7 "github.com/vapor/consensus"
8 "github.com/vapor/database/storage"
9 "github.com/vapor/protocol/bc"
10 "github.com/vapor/protocol/bc/types"
11 "github.com/vapor/protocol/state"
12 "github.com/vapor/testutil"
15 var testTxs = []*types.Tx{
16 types.NewTx(types.TxData{
18 Inputs: []*types.TxInput{
19 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
21 Outputs: []*types.TxOutput{
22 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}),
25 types.NewTx(types.TxData{
27 Inputs: []*types.TxInput{
28 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
30 Outputs: []*types.TxOutput{
31 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
34 types.NewTx(types.TxData{
37 Inputs: []*types.TxInput{
38 types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
39 types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}),
41 Outputs: []*types.TxOutput{
42 types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
43 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}),
46 types.NewTx(types.TxData{
48 Inputs: []*types.TxInput{
49 types.NewSpendInput(nil, testutil.MustDecodeHash("dbea684b5c5153ed7729669a53d6c59574f26015a3e1eb2a0e8a1c645425a764"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}),
51 Outputs: []*types.TxOutput{
52 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}),
53 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}),
56 types.NewTx(types.TxData{
58 Inputs: []*types.TxInput{
59 types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}),
61 Outputs: []*types.TxOutput{
62 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}),
63 types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}),
68 type mockStore struct{}
70 func (s *mockStore) BlockExist(hash *bc.Hash) bool { return false }
71 func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error) { return nil, nil }
72 func (s *mockStore) GetStoreStatus() *BlockStoreState { return nil }
73 func (s *mockStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil }
74 func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error { return nil }
75 func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { return nil, nil }
76 func (s *mockStore) LoadBlockIndex(uint64) (*state.BlockIndex, error) { return nil, nil }
77 func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil }
78 func (s *mockStore) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil }
79 func (s *mockStore) IsWithdrawSpent(hash *bc.Hash) bool { return true }
80 func (s *mockStore) SetWithdrawSpent(hash *bc.Hash) {}
81 func (s *mockStore) Set(hash *bc.Hash, data []byte) error { return nil }
82 func (s *mockStore) Get(hash *bc.Hash) ([]byte, error) { return nil, nil }
84 func TestAddOrphan(t *testing.T) {
89 requireParents []*bc.Hash
93 orphans: map[bc.Hash]*orphanTx{},
94 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
97 orphans: map[bc.Hash]*orphanTx{
98 testTxs[0].ID: &orphanTx{
104 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
105 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
106 testTxs[0].ID: &orphanTx{
114 addOrphan: &TxDesc{Tx: testTxs[0]},
115 requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]},
119 orphans: map[bc.Hash]*orphanTx{
120 testTxs[0].ID: &orphanTx{
126 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
127 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
128 testTxs[0].ID: &orphanTx{
137 orphans: map[bc.Hash]*orphanTx{
138 testTxs[0].ID: &orphanTx{
143 testTxs[1].ID: &orphanTx{
149 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
150 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
151 testTxs[0].ID: &orphanTx{
156 testTxs[1].ID: &orphanTx{
164 addOrphan: &TxDesc{Tx: testTxs[1]},
165 requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]},
169 orphans: map[bc.Hash]*orphanTx{},
170 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
173 orphans: map[bc.Hash]*orphanTx{
174 testTxs[2].ID: &orphanTx{
180 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
181 testTxs[2].SpentOutputIDs[1]: map[bc.Hash]*orphanTx{
182 testTxs[2].ID: &orphanTx{
190 addOrphan: &TxDesc{Tx: testTxs[2]},
191 requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]},
195 for i, c := range cases {
196 c.before.addOrphan(c.addOrphan, c.requireParents)
197 for _, orphan := range c.before.orphans {
198 orphan.expiration = time.Time{}
200 for _, orphans := range c.before.orphansByPrev {
201 for _, orphan := range orphans {
202 orphan.expiration = time.Time{}
205 if !testutil.DeepEqual(c.before, c.after) {
206 t.Errorf("case %d: got %v want %v", i, c.before, c.after)
211 func TestAddTransaction(t *testing.T) {
219 pool: map[bc.Hash]*TxDesc{},
220 utxo: map[bc.Hash]*types.Tx{},
221 msgCh: make(chan *TxPoolMsg, 1),
224 pool: map[bc.Hash]*TxDesc{
225 testTxs[2].ID: &TxDesc{
230 utxo: map[bc.Hash]*types.Tx{
231 *testTxs[2].ResultIds[0]: testTxs[2],
232 *testTxs[2].ResultIds[1]: testTxs[2],
242 pool: map[bc.Hash]*TxDesc{},
243 utxo: map[bc.Hash]*types.Tx{},
244 msgCh: make(chan *TxPoolMsg, 1),
247 pool: map[bc.Hash]*TxDesc{
248 testTxs[2].ID: &TxDesc{
253 utxo: map[bc.Hash]*types.Tx{
254 *testTxs[2].ResultIds[0]: testTxs[2],
264 for i, c := range cases {
265 c.before.addTransaction(c.addTx)
266 for _, txD := range c.before.pool {
267 txD.Added = time.Time{}
269 if !testutil.DeepEqual(c.before.pool, c.after.pool) {
270 t.Errorf("case %d: got %v want %v", i, c.before.pool, c.after.pool)
272 if !testutil.DeepEqual(c.before.utxo, c.after.utxo) {
273 t.Errorf("case %d: got %v want %v", i, c.before.utxo, c.after.utxo)
278 func TestExpireOrphan(t *testing.T) {
280 orphans: map[bc.Hash]*orphanTx{
281 testTxs[0].ID: &orphanTx{
282 expiration: time.Unix(1533489701, 0),
287 testTxs[1].ID: &orphanTx{
288 expiration: time.Unix(1633489701, 0),
294 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
295 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
296 testTxs[0].ID: &orphanTx{
297 expiration: time.Unix(1533489701, 0),
302 testTxs[1].ID: &orphanTx{
303 expiration: time.Unix(1633489701, 0),
313 orphans: map[bc.Hash]*orphanTx{
314 testTxs[1].ID: &orphanTx{
315 expiration: time.Unix(1633489701, 0),
321 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
322 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
323 testTxs[1].ID: &orphanTx{
324 expiration: time.Unix(1633489701, 0),
333 before.ExpireOrphan(time.Unix(1633479701, 0))
334 if !testutil.DeepEqual(before, want) {
335 t.Errorf("got %v want %v", before, want)
339 func TestProcessOrphans(t *testing.T) {
347 pool: map[bc.Hash]*TxDesc{},
348 utxo: map[bc.Hash]*types.Tx{},
349 orphans: map[bc.Hash]*orphanTx{
350 testTxs[3].ID: &orphanTx{
356 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
357 testTxs[3].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
358 testTxs[3].ID: &orphanTx{
365 msgCh: make(chan *TxPoolMsg, 10),
368 pool: map[bc.Hash]*TxDesc{
369 testTxs[3].ID: &TxDesc{
374 utxo: map[bc.Hash]*types.Tx{
375 *testTxs[3].ResultIds[0]: testTxs[3],
376 *testTxs[3].ResultIds[1]: testTxs[3],
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 orphans: map[bc.Hash]*orphanTx{
388 testTxs[3].ID: &orphanTx{
393 testTxs[4].ID: &orphanTx{
399 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
400 testTxs[3].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
401 testTxs[3].ID: &orphanTx{
407 testTxs[4].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
408 testTxs[4].ID: &orphanTx{
415 msgCh: make(chan *TxPoolMsg, 10),
418 pool: map[bc.Hash]*TxDesc{
419 testTxs[3].ID: &TxDesc{
423 testTxs[4].ID: &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 orphans: map[bc.Hash]*orphanTx{},
435 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
437 processTx: &TxDesc{Tx: testTxs[2]},
441 for i, c := range cases {
442 c.before.store = &mockStore{}
443 c.before.addTransaction(c.processTx)
444 c.before.processOrphans(c.processTx)
445 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{
468 testTxs[0].ID: &orphanTx{
469 expiration: time.Unix(1533489701, 0),
475 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
476 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
477 testTxs[0].ID: &orphanTx{
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{
497 testTxs[0].ID: &orphanTx{
498 expiration: time.Unix(1533489701, 0),
503 testTxs[1].ID: &orphanTx{
504 expiration: time.Unix(1533489701, 0),
510 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
511 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
512 testTxs[0].ID: &orphanTx{
513 expiration: time.Unix(1533489701, 0),
518 testTxs[1].ID: &orphanTx{
519 expiration: time.Unix(1533489701, 0),
528 orphans: map[bc.Hash]*orphanTx{
529 testTxs[0].ID: &orphanTx{
530 expiration: time.Unix(1533489701, 0),
536 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
537 testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
538 testTxs[0].ID: &orphanTx{
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)