OSDN Git Service

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