OSDN Git Service

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