OSDN Git Service

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