OSDN Git Service

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