OSDN Git Service

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