OSDN Git Service

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