OSDN Git Service

Add validate votetx (#64)
[bytom/vapor.git] / protocol / txpool_test.go
1 package protocol
2
3 import (
4         "testing"
5         "time"
6
7         "github.com/davecgh/go-spew/spew"
8
9         "github.com/vapor/consensus"
10         "github.com/vapor/database/storage"
11         "github.com/vapor/event"
12         "github.com/vapor/protocol/bc"
13         "github.com/vapor/protocol/bc/types"
14         "github.com/vapor/protocol/state"
15         "github.com/vapor/testutil"
16 )
17
18 var testTxs = []*types.Tx{
19         //tx0
20         types.NewTx(types.TxData{
21                 SerializedSize: 100,
22                 Inputs: []*types.TxInput{
23                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
24                 },
25                 Outputs: []*types.TxOutput{
26                         types.NewIntraChainOutput(*consensus.BTMAssetID, 1, []byte{0x6a}),
27                 },
28         }),
29         //tx1
30         types.NewTx(types.TxData{
31                 SerializedSize: 100,
32                 Inputs: []*types.TxInput{
33                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
34                 },
35                 Outputs: []*types.TxOutput{
36                         types.NewIntraChainOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
37                 },
38         }),
39         //tx2
40         types.NewTx(types.TxData{
41                 SerializedSize: 150,
42                 TimeRange:      0,
43                 Inputs: []*types.TxInput{
44                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
45                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}),
46                 },
47                 Outputs: []*types.TxOutput{
48                         types.NewIntraChainOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
49                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}),
50                 },
51         }),
52         //tx3
53         types.NewTx(types.TxData{
54
55                 SerializedSize: 100,
56                 Inputs: []*types.TxInput{
57                         types.NewSpendInput(nil, testutil.MustDecodeHash("7d3f8e8474775f9fab2a7370529f0569a2199b22a5a83d235a036f50de3e8c84"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}),
58                 },
59                 Outputs: []*types.TxOutput{
60                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}),
61                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}),
62                 },
63         }),
64         //tx4
65         types.NewTx(types.TxData{
66                 SerializedSize: 100,
67                 Inputs: []*types.TxInput{
68                         types.NewSpendInput(nil, testutil.MustDecodeHash("9a26cde504a5d7190dbed119280276f9816d9c2b7d20c768b312be57930fe840"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}),
69                 },
70                 Outputs: []*types.TxOutput{
71                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}),
72                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}),
73                 },
74         }),
75         //tx5
76         types.NewTx(types.TxData{
77                 SerializedSize: 100,
78                 Inputs: []*types.TxInput{
79                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
80                 },
81                 Outputs: []*types.TxOutput{
82                         types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
83                 },
84         }),
85         //tx6
86         types.NewTx(types.TxData{
87                 SerializedSize: 100,
88                 Inputs: []*types.TxInput{
89                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 3, 1, []byte{0x51}),
90                         types.NewSpendInput(nil, testutil.MustDecodeHash("9a26cde504a5d7190dbed119280276f9816d9c2b7d20c768b312be57930fe840"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}),
91                 },
92                 Outputs: []*types.TxOutput{
93                         types.NewIntraChainOutput(*consensus.BTMAssetID, 2, []byte{0x51}),
94                         types.NewIntraChainOutput(bc.NewAssetID([32]byte{0xa1}), 0, []byte{0x65}),
95                 },
96         }),
97         //tx7
98         types.NewTx(types.TxData{
99                 SerializedSize: 150,
100                 TimeRange:      0,
101                 Inputs: []*types.TxInput{
102                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
103                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}),
104                 },
105                 Outputs: []*types.TxOutput{
106                         types.NewIntraChainOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
107                         types.NewVoteOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}, []byte("a8f410b9f7cd9ce352d215ed17c85559c351dc8d18ed89ad403ca28cfc423f612e04a1c9584f945c286c47ec1e5b8405c65ff56e31f44a2627aca4f77e03936f")),
108                 },
109         }),
110 }
111
112 type mockStore struct{}
113
114 func (s *mockStore) BlockExist(hash *bc.Hash) bool                                { return false }
115 func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error)                      { return nil, nil }
116 func (s *mockStore) GetStoreStatus() *BlockStoreState                             { return nil }
117 func (s *mockStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil }
118 func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error     { return nil }
119 func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)                 { return nil, nil }
120 func (s *mockStore) LoadBlockIndex(uint64) (*state.BlockIndex, error)             { return nil, nil }
121 func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error          { return nil }
122 func (s *mockStore) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil }
123
124 func TestAddOrphan(t *testing.T) {
125         cases := []struct {
126                 before         *TxPool
127                 after          *TxPool
128                 addOrphan      *TxDesc
129                 requireParents []*bc.Hash
130         }{
131                 {
132                         before: &TxPool{
133                                 orphans:       map[bc.Hash]*orphanTx{},
134                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
135                         },
136                         after: &TxPool{
137                                 orphans: map[bc.Hash]*orphanTx{
138                                         testTxs[0].ID: {
139                                                 TxDesc: &TxDesc{
140                                                         Tx: testTxs[0],
141                                                 },
142                                         },
143                                 },
144                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
145                                         testTxs[0].SpentOutputIDs[0]: {
146                                                 testTxs[0].ID: {
147                                                         TxDesc: &TxDesc{
148                                                                 Tx: testTxs[0],
149                                                         },
150                                                 },
151                                         },
152                                 },
153                         },
154                         addOrphan:      &TxDesc{Tx: testTxs[0]},
155                         requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]},
156                 },
157                 {
158                         before: &TxPool{
159                                 orphans: map[bc.Hash]*orphanTx{
160                                         testTxs[0].ID: {
161                                                 TxDesc: &TxDesc{
162                                                         Tx: testTxs[0],
163                                                 },
164                                         },
165                                 },
166                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
167                                         testTxs[0].SpentOutputIDs[0]: {
168                                                 testTxs[0].ID: {
169                                                         TxDesc: &TxDesc{
170                                                                 Tx: testTxs[0],
171                                                         },
172                                                 },
173                                         },
174                                 },
175                         },
176                         after: &TxPool{
177                                 orphans: map[bc.Hash]*orphanTx{
178                                         testTxs[0].ID: {
179                                                 TxDesc: &TxDesc{
180                                                         Tx: testTxs[0],
181                                                 },
182                                         },
183                                         testTxs[1].ID: {
184                                                 TxDesc: &TxDesc{
185                                                         Tx: testTxs[1],
186                                                 },
187                                         },
188                                 },
189                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
190                                         testTxs[0].SpentOutputIDs[0]: {
191                                                 testTxs[0].ID: {
192                                                         TxDesc: &TxDesc{
193                                                                 Tx: testTxs[0],
194                                                         },
195                                                 },
196                                                 testTxs[1].ID: {
197                                                         TxDesc: &TxDesc{
198                                                                 Tx: testTxs[1],
199                                                         },
200                                                 },
201                                         },
202                                 },
203                         },
204                         addOrphan:      &TxDesc{Tx: testTxs[1]},
205                         requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]},
206                 },
207                 {
208                         before: &TxPool{
209                                 orphans:       map[bc.Hash]*orphanTx{},
210                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
211                         },
212                         after: &TxPool{
213                                 orphans: map[bc.Hash]*orphanTx{
214                                         testTxs[2].ID: {
215                                                 TxDesc: &TxDesc{
216                                                         Tx: testTxs[2],
217                                                 },
218                                         },
219                                 },
220                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
221                                         testTxs[2].SpentOutputIDs[1]: {
222                                                 testTxs[2].ID: {
223                                                         TxDesc: &TxDesc{
224                                                                 Tx: testTxs[2],
225                                                         },
226                                                 },
227                                         },
228                                 },
229                         },
230                         addOrphan:      &TxDesc{Tx: testTxs[2]},
231                         requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]},
232                 },
233         }
234
235         for i, c := range cases {
236                 c.before.addOrphan(c.addOrphan, c.requireParents)
237                 for _, orphan := range c.before.orphans {
238                         orphan.expiration = time.Time{}
239                 }
240                 for _, orphans := range c.before.orphansByPrev {
241                         for _, orphan := range orphans {
242                                 orphan.expiration = time.Time{}
243                         }
244                 }
245                 if !testutil.DeepEqual(c.before, c.after) {
246                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
247                 }
248         }
249 }
250
251 func TestAddTransaction(t *testing.T) {
252         dispatcher := event.NewDispatcher()
253         cases := []struct {
254                 before *TxPool
255                 after  *TxPool
256                 addTx  *TxDesc
257         }{
258                 {
259                         before: &TxPool{
260                                 pool:            map[bc.Hash]*TxDesc{},
261                                 utxo:            map[bc.Hash]*types.Tx{},
262                                 eventDispatcher: dispatcher,
263                         },
264                         after: &TxPool{
265                                 pool: map[bc.Hash]*TxDesc{
266                                         testTxs[2].ID: {
267                                                 Tx:         testTxs[2],
268                                                 StatusFail: false,
269                                         },
270                                 },
271                                 utxo: map[bc.Hash]*types.Tx{
272                                         *testTxs[2].ResultIds[0]: testTxs[2],
273                                         *testTxs[2].ResultIds[1]: testTxs[2],
274                                 },
275                         },
276                         addTx: &TxDesc{
277                                 Tx:         testTxs[2],
278                                 StatusFail: false,
279                         },
280                 },
281                 {
282                         before: &TxPool{
283                                 pool:            map[bc.Hash]*TxDesc{},
284                                 utxo:            map[bc.Hash]*types.Tx{},
285                                 eventDispatcher: dispatcher,
286                         },
287                         after: &TxPool{
288                                 pool: map[bc.Hash]*TxDesc{
289                                         testTxs[2].ID: {
290                                                 Tx:         testTxs[2],
291                                                 StatusFail: true,
292                                         },
293                                 },
294                                 utxo: map[bc.Hash]*types.Tx{
295                                         *testTxs[2].ResultIds[0]: testTxs[2],
296                                 },
297                         },
298                         addTx: &TxDesc{
299                                 Tx:         testTxs[2],
300                                 StatusFail: true,
301                         },
302                 },
303                 {
304                         before: &TxPool{
305                                 pool:            map[bc.Hash]*TxDesc{},
306                                 utxo:            map[bc.Hash]*types.Tx{},
307                                 eventDispatcher: dispatcher,
308                         },
309                         after: &TxPool{
310                                 pool: map[bc.Hash]*TxDesc{
311                                         testTxs[7].ID: {
312                                                 Tx:         testTxs[7],
313                                                 StatusFail: false,
314                                         },
315                                 },
316                                 utxo: map[bc.Hash]*types.Tx{
317                                         *testTxs[7].ResultIds[0]: testTxs[7],
318                                         *testTxs[7].ResultIds[1]: testTxs[7],
319                                 },
320                         },
321                         addTx: &TxDesc{
322                                 Tx:         testTxs[7],
323                                 StatusFail: false,
324                         },
325                 },
326                 {
327                         before: &TxPool{
328                                 pool:            map[bc.Hash]*TxDesc{},
329                                 utxo:            map[bc.Hash]*types.Tx{},
330                                 eventDispatcher: dispatcher,
331                         },
332                         after: &TxPool{
333                                 pool: map[bc.Hash]*TxDesc{
334                                         testTxs[7].ID: {
335                                                 Tx:         testTxs[7],
336                                                 StatusFail: true,
337                                         },
338                                 },
339                                 utxo: map[bc.Hash]*types.Tx{
340                                         *testTxs[7].ResultIds[0]: testTxs[7],
341                                 },
342                         },
343                         addTx: &TxDesc{
344                                 Tx:         testTxs[7],
345                                 StatusFail: true,
346                         },
347                 },
348         }
349
350         for i, c := range cases {
351                 c.before.addTransaction(c.addTx)
352                 for _, txD := range c.before.pool {
353                         txD.Added = time.Time{}
354                 }
355                 if !testutil.DeepEqual(c.before.pool, c.after.pool) {
356                         t.Errorf("case %d: got %v want %v", i, c.before.pool, c.after.pool)
357                 }
358                 if !testutil.DeepEqual(c.before.utxo, c.after.utxo) {
359                         t.Errorf("case %d: got %v want %v", i, c.before.utxo, c.after.utxo)
360                 }
361         }
362 }
363
364 func TestExpireOrphan(t *testing.T) {
365         before := &TxPool{
366                 orphans: map[bc.Hash]*orphanTx{
367                         testTxs[0].ID: {
368                                 expiration: time.Unix(1533489701, 0),
369                                 TxDesc: &TxDesc{
370                                         Tx: testTxs[0],
371                                 },
372                         },
373                         testTxs[1].ID: {
374                                 expiration: time.Unix(1633489701, 0),
375                                 TxDesc: &TxDesc{
376                                         Tx: testTxs[1],
377                                 },
378                         },
379                 },
380                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
381                         testTxs[0].SpentOutputIDs[0]: {
382                                 testTxs[0].ID: {
383                                         expiration: time.Unix(1533489701, 0),
384                                         TxDesc: &TxDesc{
385                                                 Tx: testTxs[0],
386                                         },
387                                 },
388                                 testTxs[1].ID: {
389                                         expiration: time.Unix(1633489701, 0),
390                                         TxDesc: &TxDesc{
391                                                 Tx: testTxs[1],
392                                         },
393                                 },
394                         },
395                 },
396         }
397
398         want := &TxPool{
399                 orphans: map[bc.Hash]*orphanTx{
400                         testTxs[1].ID: {
401                                 expiration: time.Unix(1633489701, 0),
402                                 TxDesc: &TxDesc{
403                                         Tx: testTxs[1],
404                                 },
405                         },
406                 },
407                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
408                         testTxs[0].SpentOutputIDs[0]: {
409                                 testTxs[1].ID: {
410                                         expiration: time.Unix(1633489701, 0),
411                                         TxDesc: &TxDesc{
412                                                 Tx: testTxs[1],
413                                         },
414                                 },
415                         },
416                 },
417         }
418
419         before.ExpireOrphan(time.Unix(1633479701, 0))
420         if !testutil.DeepEqual(before, want) {
421                 t.Errorf("got %v want %v", before, want)
422         }
423 }
424
425 func TestProcessOrphans(t *testing.T) {
426         dispatcher := event.NewDispatcher()
427         cases := []struct {
428                 before    *TxPool
429                 after     *TxPool
430                 processTx *TxDesc
431         }{
432                 {
433                         before: &TxPool{
434                                 pool:            map[bc.Hash]*TxDesc{},
435                                 utxo:            map[bc.Hash]*types.Tx{},
436                                 eventDispatcher: dispatcher,
437                                 orphans: map[bc.Hash]*orphanTx{
438                                         testTxs[3].ID: {
439                                                 TxDesc: &TxDesc{
440                                                         Tx: testTxs[3],
441                                                 },
442                                         },
443                                 },
444                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
445                                         testTxs[3].SpentOutputIDs[0]: {
446                                                 testTxs[3].ID: {
447                                                         TxDesc: &TxDesc{
448                                                                 Tx: testTxs[3],
449                                                         },
450                                                 },
451                                         },
452                                 },
453                         },
454                         after: &TxPool{
455                                 pool: map[bc.Hash]*TxDesc{
456                                         testTxs[3].ID: {
457                                                 Tx:         testTxs[3],
458                                                 StatusFail: false,
459                                         },
460                                 },
461                                 utxo: map[bc.Hash]*types.Tx{
462                                         *testTxs[3].ResultIds[0]: testTxs[3],
463                                         *testTxs[3].ResultIds[1]: testTxs[3],
464                                 },
465                                 eventDispatcher: dispatcher,
466                                 orphans:         map[bc.Hash]*orphanTx{},
467                                 orphansByPrev:   map[bc.Hash]map[bc.Hash]*orphanTx{},
468                         },
469                         processTx: &TxDesc{Tx: testTxs[2]},
470                 },
471                 {
472                         before: &TxPool{
473                                 pool:            map[bc.Hash]*TxDesc{},
474                                 utxo:            map[bc.Hash]*types.Tx{},
475                                 eventDispatcher: dispatcher,
476                                 orphans: map[bc.Hash]*orphanTx{
477                                         testTxs[3].ID: {
478                                                 TxDesc: &TxDesc{
479                                                         Tx: testTxs[3],
480                                                 },
481                                         },
482                                         testTxs[4].ID: {
483                                                 TxDesc: &TxDesc{
484                                                         Tx: testTxs[4],
485                                                 },
486                                         },
487                                 },
488                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
489                                         testTxs[3].SpentOutputIDs[0]: {
490                                                 testTxs[3].ID: {
491                                                         TxDesc: &TxDesc{
492                                                                 Tx: testTxs[3],
493                                                         },
494                                                 },
495                                         },
496                                         testTxs[4].SpentOutputIDs[0]: {
497                                                 testTxs[4].ID: {
498                                                         TxDesc: &TxDesc{
499                                                                 Tx: testTxs[4],
500                                                         },
501                                                 },
502                                         },
503                                 },
504                         },
505                         after: &TxPool{
506                                 pool: map[bc.Hash]*TxDesc{
507                                         testTxs[3].ID: {
508                                                 Tx:         testTxs[3],
509                                                 StatusFail: false,
510                                         },
511                                         testTxs[4].ID: {
512                                                 Tx:         testTxs[4],
513                                                 StatusFail: false,
514                                         },
515                                 },
516                                 utxo: map[bc.Hash]*types.Tx{
517                                         *testTxs[3].ResultIds[0]: testTxs[3],
518                                         *testTxs[3].ResultIds[1]: testTxs[3],
519                                         *testTxs[4].ResultIds[0]: testTxs[4],
520                                         *testTxs[4].ResultIds[1]: testTxs[4],
521                                 },
522                                 eventDispatcher: dispatcher,
523                                 orphans:         map[bc.Hash]*orphanTx{},
524                                 orphansByPrev:   map[bc.Hash]map[bc.Hash]*orphanTx{},
525                         },
526                         processTx: &TxDesc{Tx: testTxs[2]},
527                 },
528         }
529
530         for i, c := range cases {
531                 c.before.store = &mockStore{}
532                 c.before.addTransaction(c.processTx)
533                 c.before.processOrphans(c.processTx)
534                 c.before.RemoveTransaction(&c.processTx.Tx.ID)
535                 c.before.store = nil
536                 c.before.lastUpdated = 0
537                 for _, txD := range c.before.pool {
538                         txD.Added = time.Time{}
539                 }
540
541                 if !testutil.DeepEqual(c.before, c.after) {
542                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
543                 }
544         }
545 }
546
547 func TestRemoveOrphan(t *testing.T) {
548         cases := []struct {
549                 before       *TxPool
550                 after        *TxPool
551                 removeHashes []*bc.Hash
552         }{
553                 {
554                         before: &TxPool{
555                                 orphans: map[bc.Hash]*orphanTx{
556                                         testTxs[0].ID: {
557                                                 expiration: time.Unix(1533489701, 0),
558                                                 TxDesc: &TxDesc{
559                                                         Tx: testTxs[0],
560                                                 },
561                                         },
562                                 },
563                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
564                                         testTxs[0].SpentOutputIDs[0]: {
565                                                 testTxs[0].ID: {
566                                                         expiration: time.Unix(1533489701, 0),
567                                                         TxDesc: &TxDesc{
568                                                                 Tx: testTxs[0],
569                                                         },
570                                                 },
571                                         },
572                                 },
573                         },
574                         after: &TxPool{
575                                 orphans:       map[bc.Hash]*orphanTx{},
576                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
577                         },
578                         removeHashes: []*bc.Hash{
579                                 &testTxs[0].ID,
580                         },
581                 },
582                 {
583                         before: &TxPool{
584                                 orphans: map[bc.Hash]*orphanTx{
585                                         testTxs[0].ID: {
586                                                 expiration: time.Unix(1533489701, 0),
587                                                 TxDesc: &TxDesc{
588                                                         Tx: testTxs[0],
589                                                 },
590                                         },
591                                         testTxs[1].ID: {
592                                                 expiration: time.Unix(1533489701, 0),
593                                                 TxDesc: &TxDesc{
594                                                         Tx: testTxs[1],
595                                                 },
596                                         },
597                                 },
598                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
599                                         testTxs[0].SpentOutputIDs[0]: {
600                                                 testTxs[0].ID: {
601                                                         expiration: time.Unix(1533489701, 0),
602                                                         TxDesc: &TxDesc{
603                                                                 Tx: testTxs[0],
604                                                         },
605                                                 },
606                                                 testTxs[1].ID: {
607                                                         expiration: time.Unix(1533489701, 0),
608                                                         TxDesc: &TxDesc{
609                                                                 Tx: testTxs[1],
610                                                         },
611                                                 },
612                                         },
613                                 },
614                         },
615                         after: &TxPool{
616                                 orphans: map[bc.Hash]*orphanTx{
617                                         testTxs[0].ID: {
618                                                 expiration: time.Unix(1533489701, 0),
619                                                 TxDesc: &TxDesc{
620                                                         Tx: testTxs[0],
621                                                 },
622                                         },
623                                 },
624                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
625                                         testTxs[0].SpentOutputIDs[0]: {
626                                                 testTxs[0].ID: {
627                                                         expiration: time.Unix(1533489701, 0),
628                                                         TxDesc: &TxDesc{
629                                                                 Tx: testTxs[0],
630                                                         },
631                                                 },
632                                         },
633                                 },
634                         },
635                         removeHashes: []*bc.Hash{
636                                 &testTxs[1].ID,
637                         },
638                 },
639         }
640
641         for i, c := range cases {
642                 for _, hash := range c.removeHashes {
643                         c.before.removeOrphan(hash)
644                 }
645                 if !testutil.DeepEqual(c.before, c.after) {
646                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
647                 }
648         }
649 }
650
651 type mockStore1 struct{}
652
653 func (s *mockStore1) BlockExist(hash *bc.Hash) bool                                { return false }
654 func (s *mockStore1) GetBlock(*bc.Hash) (*types.Block, error)                      { return nil, nil }
655 func (s *mockStore1) GetStoreStatus() *BlockStoreState                             { return nil }
656 func (s *mockStore1) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil }
657 func (s *mockStore1) GetTransactionsUtxo(utxoView *state.UtxoViewpoint, tx []*bc.Tx) error {
658         for _, hash := range testTxs[2].SpentOutputIDs {
659                 utxoView.Entries[hash] = &storage.UtxoEntry{IsCoinBase: false, Spent: false}
660         }
661         return nil
662 }
663 func (s *mockStore1) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)                 { return nil, nil }
664 func (s *mockStore1) LoadBlockIndex(uint64) (*state.BlockIndex, error)             { return nil, nil }
665 func (s *mockStore1) SaveBlock(*types.Block, *bc.TransactionStatus) error          { return nil }
666 func (s *mockStore1) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil }
667
668 func TestProcessTransaction(t *testing.T) {
669         txPool := &TxPool{
670                 pool:            make(map[bc.Hash]*TxDesc),
671                 utxo:            make(map[bc.Hash]*types.Tx),
672                 orphans:         make(map[bc.Hash]*orphanTx),
673                 orphansByPrev:   make(map[bc.Hash]map[bc.Hash]*orphanTx),
674                 store:           &mockStore1{},
675                 eventDispatcher: event.NewDispatcher(),
676         }
677         cases := []struct {
678                 want  *TxPool
679                 addTx *TxDesc
680         }{
681                 //Dust tx
682                 {
683                         want: &TxPool{},
684                         addTx: &TxDesc{
685                                 Tx:         testTxs[3],
686                                 StatusFail: false,
687                         },
688                 },
689                 //Dust tx
690                 {
691                         want: &TxPool{},
692                         addTx: &TxDesc{
693                                 Tx:         testTxs[4],
694                                 StatusFail: false,
695                         },
696                 },
697                 //Dust tx
698                 {
699                         want: &TxPool{},
700                         addTx: &TxDesc{
701                                 Tx:         testTxs[5],
702                                 StatusFail: false,
703                         },
704                 },
705                 //Dust tx
706                 {
707                         want: &TxPool{},
708                         addTx: &TxDesc{
709                                 Tx:         testTxs[6],
710                                 StatusFail: false,
711                         },
712                 },
713                 //normal tx
714                 {
715                         want: &TxPool{
716                                 pool: map[bc.Hash]*TxDesc{
717                                         testTxs[2].ID: {
718                                                 Tx:         testTxs[2],
719                                                 StatusFail: false,
720                                                 Weight:     150,
721                                         },
722                                 },
723                                 utxo: map[bc.Hash]*types.Tx{
724                                         *testTxs[2].ResultIds[0]: testTxs[2],
725                                         *testTxs[2].ResultIds[1]: testTxs[2],
726                                 },
727                         },
728                         addTx: &TxDesc{
729                                 Tx:         testTxs[2],
730                                 StatusFail: false,
731                         },
732                 },
733         }
734
735         for i, c := range cases {
736                 txPool.ProcessTransaction(c.addTx.Tx, c.addTx.StatusFail, 0, 0)
737                 for _, txD := range txPool.pool {
738                         txD.Added = time.Time{}
739                 }
740                 for _, txD := range txPool.orphans {
741                         txD.Added = time.Time{}
742                         txD.expiration = time.Time{}
743                 }
744
745                 if !testutil.DeepEqual(txPool.pool, c.want.pool) {
746                         t.Errorf("case %d: test ProcessTransaction pool mismatch got %s want %s", i, spew.Sdump(txPool.pool), spew.Sdump(c.want.pool))
747                 }
748                 if !testutil.DeepEqual(txPool.utxo, c.want.utxo) {
749                         t.Errorf("case %d: test ProcessTransaction utxo mismatch got %s want %s", i, spew.Sdump(txPool.utxo), spew.Sdump(c.want.utxo))
750                 }
751                 if !testutil.DeepEqual(txPool.orphans, c.want.orphans) {
752                         t.Errorf("case %d: test ProcessTransaction orphans mismatch got %s want %s", i, spew.Sdump(txPool.orphans), spew.Sdump(c.want.orphans))
753                 }
754                 if !testutil.DeepEqual(txPool.orphansByPrev, c.want.orphansByPrev) {
755                         t.Errorf("case %d: test ProcessTransaction orphansByPrev mismatch got %s want %s", i, spew.Sdump(txPool.orphansByPrev), spew.Sdump(c.want.orphansByPrev))
756                 }
757         }
758 }