OSDN Git Service

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