7 "github.com/bytom/consensus"
8 "github.com/bytom/database/storage"
9 "github.com/bytom/event"
10 "github.com/bytom/protocol/bc"
11 "github.com/bytom/protocol/bc/types"
12 "github.com/bytom/protocol/state"
13 "github.com/bytom/testutil"
16 var testTxs = []*types.Tx{
17 types.NewTx(types.TxData{
19 Inputs: []*types.TxInput{
20 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
22 Outputs: []*types.TxOutput{
23 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}),
26 types.NewTx(types.TxData{
28 Inputs: []*types.TxInput{
29 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
31 Outputs: []*types.TxOutput{
32 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
35 types.NewTx(types.TxData{
38 Inputs: []*types.TxInput{
39 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
40 types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}),
42 Outputs: []*types.TxOutput{
43 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
44 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}),
47 types.NewTx(types.TxData{
49 Inputs: []*types.TxInput{
50 types.NewSpendInput(nil, testutil.MustDecodeHash("dbea684b5c5153ed7729669a53d6c59574f26015a3e1eb2a0e8a1c645425a764"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}),
52 Outputs: []*types.TxOutput{
53 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}),
54 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}),
57 types.NewTx(types.TxData{
59 Inputs: []*types.TxInput{
60 types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}),
62 Outputs: []*types.TxOutput{
63 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}),
64 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}),
69 type mockStore struct{}
71 func (s *mockStore) BlockExist(hash *bc.Hash) bool { return false }
72 func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error) { return nil, nil }
73 func (s *mockStore) GetStoreStatus() *BlockStoreState { return nil }
74 func (s *mockStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil }
75 func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error { return nil }
76 func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { return nil, nil }
77 func (s *mockStore) LoadBlockIndex(uint64) (*state.BlockIndex, error) { return nil, nil }
78 func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil }
79 func (s *mockStore) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil }
81 func TestAddOrphan(t *testing.T) {
86 requireParents []*bc.Hash
90 orphans: map[bc.Hash]*orphanTx{},
91 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
94 orphans: map[bc.Hash]*orphanTx{
101 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
102 testTxs[0].SpentOutputIDs[0]: {
111 addOrphan: &TxDesc{Tx: testTxs[0]},
112 requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]},
116 orphans: map[bc.Hash]*orphanTx{
123 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
124 testTxs[0].SpentOutputIDs[0]: {
134 orphans: map[bc.Hash]*orphanTx{
146 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
147 testTxs[0].SpentOutputIDs[0]: {
161 addOrphan: &TxDesc{Tx: testTxs[1]},
162 requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]},
166 orphans: map[bc.Hash]*orphanTx{},
167 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
170 orphans: map[bc.Hash]*orphanTx{
177 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
178 testTxs[2].SpentOutputIDs[1]: {
187 addOrphan: &TxDesc{Tx: testTxs[2]},
188 requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]},
192 for i, c := range cases {
193 c.before.addOrphan(c.addOrphan, c.requireParents)
194 for _, orphan := range c.before.orphans {
195 orphan.expiration = time.Time{}
197 for _, orphans := range c.before.orphansByPrev {
198 for _, orphan := range orphans {
199 orphan.expiration = time.Time{}
202 if !testutil.DeepEqual(c.before, c.after) {
203 t.Errorf("case %d: got %v want %v", i, c.before, c.after)
208 func TestAddTransaction(t *testing.T) {
209 dispatcher := event.NewDispatcher()
217 pool: map[bc.Hash]*TxDesc{},
218 utxo: map[bc.Hash]*types.Tx{},
219 eventDispatcher: dispatcher,
222 pool: map[bc.Hash]*TxDesc{
228 utxo: map[bc.Hash]*types.Tx{
229 *testTxs[2].ResultIds[0]: testTxs[2],
230 *testTxs[2].ResultIds[1]: testTxs[2],
240 pool: map[bc.Hash]*TxDesc{},
241 utxo: map[bc.Hash]*types.Tx{},
242 eventDispatcher: dispatcher,
245 pool: map[bc.Hash]*TxDesc{
251 utxo: map[bc.Hash]*types.Tx{
252 *testTxs[2].ResultIds[0]: testTxs[2],
262 for i, c := range cases {
263 c.before.addTransaction(c.addTx)
264 for _, txD := range c.before.pool {
265 txD.Added = time.Time{}
267 if !testutil.DeepEqual(c.before.pool, c.after.pool) {
268 t.Errorf("case %d: got %v want %v", i, c.before.pool, c.after.pool)
270 if !testutil.DeepEqual(c.before.utxo, c.after.utxo) {
271 t.Errorf("case %d: got %v want %v", i, c.before.utxo, c.after.utxo)
276 func TestExpireOrphan(t *testing.T) {
278 orphans: map[bc.Hash]*orphanTx{
280 expiration: time.Unix(1533489701, 0),
286 expiration: time.Unix(1633489701, 0),
292 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
293 testTxs[0].SpentOutputIDs[0]: {
295 expiration: time.Unix(1533489701, 0),
301 expiration: time.Unix(1633489701, 0),
311 orphans: map[bc.Hash]*orphanTx{
313 expiration: time.Unix(1633489701, 0),
319 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
320 testTxs[0].SpentOutputIDs[0]: {
322 expiration: time.Unix(1633489701, 0),
331 before.ExpireOrphan(time.Unix(1633479701, 0))
332 if !testutil.DeepEqual(before, want) {
333 t.Errorf("got %v want %v", before, want)
337 func TestProcessOrphans(t *testing.T) {
338 dispatcher := event.NewDispatcher()
346 pool: map[bc.Hash]*TxDesc{},
347 utxo: map[bc.Hash]*types.Tx{},
348 eventDispatcher: dispatcher,
349 orphans: map[bc.Hash]*orphanTx{
356 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
357 testTxs[3].SpentOutputIDs[0]: {
367 pool: map[bc.Hash]*TxDesc{
373 utxo: map[bc.Hash]*types.Tx{
374 *testTxs[3].ResultIds[0]: testTxs[3],
375 *testTxs[3].ResultIds[1]: testTxs[3],
377 eventDispatcher: dispatcher,
378 orphans: map[bc.Hash]*orphanTx{},
379 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
381 processTx: &TxDesc{Tx: testTxs[2]},
385 pool: map[bc.Hash]*TxDesc{},
386 utxo: map[bc.Hash]*types.Tx{},
387 eventDispatcher: dispatcher,
388 orphans: map[bc.Hash]*orphanTx{
400 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
401 testTxs[3].SpentOutputIDs[0]: {
408 testTxs[4].SpentOutputIDs[0]: {
418 pool: map[bc.Hash]*TxDesc{
428 utxo: map[bc.Hash]*types.Tx{
429 *testTxs[3].ResultIds[0]: testTxs[3],
430 *testTxs[3].ResultIds[1]: testTxs[3],
431 *testTxs[4].ResultIds[0]: testTxs[4],
432 *testTxs[4].ResultIds[1]: testTxs[4],
434 eventDispatcher: dispatcher,
435 orphans: map[bc.Hash]*orphanTx{},
436 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
438 processTx: &TxDesc{Tx: testTxs[2]},
442 for i, c := range cases {
443 c.before.store = &mockStore{}
444 c.before.addTransaction(c.processTx)
445 c.before.processOrphans(c.processTx)
446 c.before.RemoveTransaction(&c.processTx.Tx.ID)
448 c.before.lastUpdated = 0
449 for _, txD := range c.before.pool {
450 txD.Added = time.Time{}
453 if !testutil.DeepEqual(c.before, c.after) {
454 t.Errorf("case %d: got %v want %v", i, c.before, c.after)
459 func TestRemoveOrphan(t *testing.T) {
463 removeHashes []*bc.Hash
467 orphans: map[bc.Hash]*orphanTx{
469 expiration: time.Unix(1533489701, 0),
475 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
476 testTxs[0].SpentOutputIDs[0]: {
478 expiration: time.Unix(1533489701, 0),
487 orphans: map[bc.Hash]*orphanTx{},
488 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
490 removeHashes: []*bc.Hash{
496 orphans: map[bc.Hash]*orphanTx{
498 expiration: time.Unix(1533489701, 0),
504 expiration: time.Unix(1533489701, 0),
510 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
511 testTxs[0].SpentOutputIDs[0]: {
513 expiration: time.Unix(1533489701, 0),
519 expiration: time.Unix(1533489701, 0),
528 orphans: map[bc.Hash]*orphanTx{
530 expiration: time.Unix(1533489701, 0),
536 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
537 testTxs[0].SpentOutputIDs[0]: {
539 expiration: time.Unix(1533489701, 0),
547 removeHashes: []*bc.Hash{
553 for i, c := range cases {
554 for _, hash := range c.removeHashes {
555 c.before.removeOrphan(hash)
557 if !testutil.DeepEqual(c.before, c.after) {
558 t.Errorf("case %d: got %v want %v", i, c.before, c.after)