OSDN Git Service

Merge pull request #27 from Bytom/dev_modify_code
[bytom/vapor.git] / protocol / txpool_test.go
1 package protocol
2
3 import (
4         "testing"
5         "time"
6
7         "github.com/vapor/consensus"
8         "github.com/vapor/database/storage"
9         "github.com/vapor/protocol/bc"
10         "github.com/vapor/protocol/bc/types"
11         "github.com/vapor/protocol/state"
12         "github.com/vapor/testutil"
13 )
14
15 var testTxs = []*types.Tx{
16         types.NewTx(types.TxData{
17                 SerializedSize: 100,
18                 Inputs: []*types.TxInput{
19                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
20                 },
21                 Outputs: []*types.TxOutput{
22                         types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6a}),
23                 },
24         }),
25         types.NewTx(types.TxData{
26                 SerializedSize: 100,
27                 Inputs: []*types.TxInput{
28                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
29                 },
30                 Outputs: []*types.TxOutput{
31                         types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
32                 },
33         }),
34         types.NewTx(types.TxData{
35                 SerializedSize: 150,
36                 TimeRange:      0,
37                 Inputs: []*types.TxInput{
38                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x01}), *consensus.BTMAssetID, 1, 1, []byte{0x51}),
39                         types.NewSpendInput(nil, bc.NewHash([32]byte{0x02}), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x51}),
40                 },
41                 Outputs: []*types.TxOutput{
42                         types.NewTxOutput(*consensus.BTMAssetID, 1, []byte{0x6b}),
43                         types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 4, []byte{0x61}),
44                 },
45         }),
46         types.NewTx(types.TxData{
47                 SerializedSize: 100,
48                 Inputs: []*types.TxInput{
49                         types.NewSpendInput(nil, testutil.MustDecodeHash("dbea684b5c5153ed7729669a53d6c59574f26015a3e1eb2a0e8a1c645425a764"), bc.NewAssetID([32]byte{0xa1}), 4, 1, []byte{0x61}),
50                 },
51                 Outputs: []*types.TxOutput{
52                         types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 3, []byte{0x62}),
53                         types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x63}),
54                 },
55         }),
56         types.NewTx(types.TxData{
57                 SerializedSize: 100,
58                 Inputs: []*types.TxInput{
59                         types.NewSpendInput(nil, testutil.MustDecodeHash("d84d0be0fd08e7341f2d127749bb0d0844d4560f53bd54861cee9981fd922cad"), bc.NewAssetID([32]byte{0xa1}), 3, 0, []byte{0x62}),
60                 },
61                 Outputs: []*types.TxOutput{
62                         types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 2, []byte{0x64}),
63                         types.NewTxOutput(bc.NewAssetID([32]byte{0xa1}), 1, []byte{0x65}),
64                 },
65         }),
66 }
67
68 type mockStore struct{}
69
70 func (s *mockStore) BlockExist(hash *bc.Hash) bool                                { return false }
71 func (s *mockStore) GetBlock(*bc.Hash) (*types.Block, error)                      { return nil, nil }
72 func (s *mockStore) GetStoreStatus() *BlockStoreState                             { return nil }
73 func (s *mockStore) GetTransactionStatus(*bc.Hash) (*bc.TransactionStatus, error) { return nil, nil }
74 func (s *mockStore) GetTransactionsUtxo(*state.UtxoViewpoint, []*bc.Tx) error     { return nil }
75 func (s *mockStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error)                 { return nil, nil }
76 func (s *mockStore) LoadBlockIndex(uint64) (*state.BlockIndex, error)             { return nil, nil }
77 func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error          { return nil }
78 func (s *mockStore) SaveChainStatus(*state.BlockNode, *state.UtxoViewpoint) error { return nil }
79 func (s *mockStore) IsWithdrawSpent(hash *bc.Hash) bool                           { return true }
80 func (s *mockStore) SetWithdrawSpent(hash *bc.Hash)                               {}
81 func (s *mockStore) Set(hash *bc.Hash, data []byte) error                         { return nil }
82 func (s *mockStore) Get(hash *bc.Hash) ([]byte, error)                            { return nil, nil }
83
84 func TestAddOrphan(t *testing.T) {
85         cases := []struct {
86                 before         *TxPool
87                 after          *TxPool
88                 addOrphan      *TxDesc
89                 requireParents []*bc.Hash
90         }{
91                 {
92                         before: &TxPool{
93                                 orphans:       map[bc.Hash]*orphanTx{},
94                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
95                         },
96                         after: &TxPool{
97                                 orphans: map[bc.Hash]*orphanTx{
98                                         testTxs[0].ID: &orphanTx{
99                                                 TxDesc: &TxDesc{
100                                                         Tx: testTxs[0],
101                                                 },
102                                         },
103                                 },
104                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
105                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
106                                                 testTxs[0].ID: &orphanTx{
107                                                         TxDesc: &TxDesc{
108                                                                 Tx: testTxs[0],
109                                                         },
110                                                 },
111                                         },
112                                 },
113                         },
114                         addOrphan:      &TxDesc{Tx: testTxs[0]},
115                         requireParents: []*bc.Hash{&testTxs[0].SpentOutputIDs[0]},
116                 },
117                 {
118                         before: &TxPool{
119                                 orphans: map[bc.Hash]*orphanTx{
120                                         testTxs[0].ID: &orphanTx{
121                                                 TxDesc: &TxDesc{
122                                                         Tx: testTxs[0],
123                                                 },
124                                         },
125                                 },
126                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
127                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
128                                                 testTxs[0].ID: &orphanTx{
129                                                         TxDesc: &TxDesc{
130                                                                 Tx: testTxs[0],
131                                                         },
132                                                 },
133                                         },
134                                 },
135                         },
136                         after: &TxPool{
137                                 orphans: map[bc.Hash]*orphanTx{
138                                         testTxs[0].ID: &orphanTx{
139                                                 TxDesc: &TxDesc{
140                                                         Tx: testTxs[0],
141                                                 },
142                                         },
143                                         testTxs[1].ID: &orphanTx{
144                                                 TxDesc: &TxDesc{
145                                                         Tx: testTxs[1],
146                                                 },
147                                         },
148                                 },
149                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
150                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
151                                                 testTxs[0].ID: &orphanTx{
152                                                         TxDesc: &TxDesc{
153                                                                 Tx: testTxs[0],
154                                                         },
155                                                 },
156                                                 testTxs[1].ID: &orphanTx{
157                                                         TxDesc: &TxDesc{
158                                                                 Tx: testTxs[1],
159                                                         },
160                                                 },
161                                         },
162                                 },
163                         },
164                         addOrphan:      &TxDesc{Tx: testTxs[1]},
165                         requireParents: []*bc.Hash{&testTxs[1].SpentOutputIDs[0]},
166                 },
167                 {
168                         before: &TxPool{
169                                 orphans:       map[bc.Hash]*orphanTx{},
170                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
171                         },
172                         after: &TxPool{
173                                 orphans: map[bc.Hash]*orphanTx{
174                                         testTxs[2].ID: &orphanTx{
175                                                 TxDesc: &TxDesc{
176                                                         Tx: testTxs[2],
177                                                 },
178                                         },
179                                 },
180                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
181                                         testTxs[2].SpentOutputIDs[1]: map[bc.Hash]*orphanTx{
182                                                 testTxs[2].ID: &orphanTx{
183                                                         TxDesc: &TxDesc{
184                                                                 Tx: testTxs[2],
185                                                         },
186                                                 },
187                                         },
188                                 },
189                         },
190                         addOrphan:      &TxDesc{Tx: testTxs[2]},
191                         requireParents: []*bc.Hash{&testTxs[2].SpentOutputIDs[1]},
192                 },
193         }
194
195         for i, c := range cases {
196                 c.before.addOrphan(c.addOrphan, c.requireParents)
197                 for _, orphan := range c.before.orphans {
198                         orphan.expiration = time.Time{}
199                 }
200                 for _, orphans := range c.before.orphansByPrev {
201                         for _, orphan := range orphans {
202                                 orphan.expiration = time.Time{}
203                         }
204                 }
205                 if !testutil.DeepEqual(c.before, c.after) {
206                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
207                 }
208         }
209 }
210
211 func TestAddTransaction(t *testing.T) {
212         cases := []struct {
213                 before *TxPool
214                 after  *TxPool
215                 addTx  *TxDesc
216         }{
217                 {
218                         before: &TxPool{
219                                 pool:  map[bc.Hash]*TxDesc{},
220                                 utxo:  map[bc.Hash]*types.Tx{},
221                                 msgCh: make(chan *TxPoolMsg, 1),
222                         },
223                         after: &TxPool{
224                                 pool: map[bc.Hash]*TxDesc{
225                                         testTxs[2].ID: &TxDesc{
226                                                 Tx:         testTxs[2],
227                                                 StatusFail: false,
228                                         },
229                                 },
230                                 utxo: map[bc.Hash]*types.Tx{
231                                         *testTxs[2].ResultIds[0]: testTxs[2],
232                                         *testTxs[2].ResultIds[1]: testTxs[2],
233                                 },
234                         },
235                         addTx: &TxDesc{
236                                 Tx:         testTxs[2],
237                                 StatusFail: false,
238                         },
239                 },
240                 {
241                         before: &TxPool{
242                                 pool:  map[bc.Hash]*TxDesc{},
243                                 utxo:  map[bc.Hash]*types.Tx{},
244                                 msgCh: make(chan *TxPoolMsg, 1),
245                         },
246                         after: &TxPool{
247                                 pool: map[bc.Hash]*TxDesc{
248                                         testTxs[2].ID: &TxDesc{
249                                                 Tx:         testTxs[2],
250                                                 StatusFail: true,
251                                         },
252                                 },
253                                 utxo: map[bc.Hash]*types.Tx{
254                                         *testTxs[2].ResultIds[0]: testTxs[2],
255                                 },
256                         },
257                         addTx: &TxDesc{
258                                 Tx:         testTxs[2],
259                                 StatusFail: true,
260                         },
261                 },
262         }
263
264         for i, c := range cases {
265                 c.before.addTransaction(c.addTx)
266                 for _, txD := range c.before.pool {
267                         txD.Added = time.Time{}
268                 }
269                 if !testutil.DeepEqual(c.before.pool, c.after.pool) {
270                         t.Errorf("case %d: got %v want %v", i, c.before.pool, c.after.pool)
271                 }
272                 if !testutil.DeepEqual(c.before.utxo, c.after.utxo) {
273                         t.Errorf("case %d: got %v want %v", i, c.before.utxo, c.after.utxo)
274                 }
275         }
276 }
277
278 func TestExpireOrphan(t *testing.T) {
279         before := &TxPool{
280                 orphans: map[bc.Hash]*orphanTx{
281                         testTxs[0].ID: &orphanTx{
282                                 expiration: time.Unix(1533489701, 0),
283                                 TxDesc: &TxDesc{
284                                         Tx: testTxs[0],
285                                 },
286                         },
287                         testTxs[1].ID: &orphanTx{
288                                 expiration: time.Unix(1633489701, 0),
289                                 TxDesc: &TxDesc{
290                                         Tx: testTxs[1],
291                                 },
292                         },
293                 },
294                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
295                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
296                                 testTxs[0].ID: &orphanTx{
297                                         expiration: time.Unix(1533489701, 0),
298                                         TxDesc: &TxDesc{
299                                                 Tx: testTxs[0],
300                                         },
301                                 },
302                                 testTxs[1].ID: &orphanTx{
303                                         expiration: time.Unix(1633489701, 0),
304                                         TxDesc: &TxDesc{
305                                                 Tx: testTxs[1],
306                                         },
307                                 },
308                         },
309                 },
310         }
311
312         want := &TxPool{
313                 orphans: map[bc.Hash]*orphanTx{
314                         testTxs[1].ID: &orphanTx{
315                                 expiration: time.Unix(1633489701, 0),
316                                 TxDesc: &TxDesc{
317                                         Tx: testTxs[1],
318                                 },
319                         },
320                 },
321                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
322                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
323                                 testTxs[1].ID: &orphanTx{
324                                         expiration: time.Unix(1633489701, 0),
325                                         TxDesc: &TxDesc{
326                                                 Tx: testTxs[1],
327                                         },
328                                 },
329                         },
330                 },
331         }
332
333         before.ExpireOrphan(time.Unix(1633479701, 0))
334         if !testutil.DeepEqual(before, want) {
335                 t.Errorf("got %v want %v", before, want)
336         }
337 }
338
339 func TestProcessOrphans(t *testing.T) {
340         cases := []struct {
341                 before    *TxPool
342                 after     *TxPool
343                 processTx *TxDesc
344         }{
345                 {
346                         before: &TxPool{
347                                 pool: map[bc.Hash]*TxDesc{},
348                                 utxo: map[bc.Hash]*types.Tx{},
349                                 orphans: map[bc.Hash]*orphanTx{
350                                         testTxs[3].ID: &orphanTx{
351                                                 TxDesc: &TxDesc{
352                                                         Tx: testTxs[3],
353                                                 },
354                                         },
355                                 },
356                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
357                                         testTxs[3].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
358                                                 testTxs[3].ID: &orphanTx{
359                                                         TxDesc: &TxDesc{
360                                                                 Tx: testTxs[3],
361                                                         },
362                                                 },
363                                         },
364                                 },
365                                 msgCh: make(chan *TxPoolMsg, 10),
366                         },
367                         after: &TxPool{
368                                 pool: map[bc.Hash]*TxDesc{
369                                         testTxs[3].ID: &TxDesc{
370                                                 Tx:         testTxs[3],
371                                                 StatusFail: false,
372                                         },
373                                 },
374                                 utxo: map[bc.Hash]*types.Tx{
375                                         *testTxs[3].ResultIds[0]: testTxs[3],
376                                         *testTxs[3].ResultIds[1]: testTxs[3],
377                                 },
378                                 orphans:       map[bc.Hash]*orphanTx{},
379                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
380                         },
381                         processTx: &TxDesc{Tx: testTxs[2]},
382                 },
383                 {
384                         before: &TxPool{
385                                 pool: map[bc.Hash]*TxDesc{},
386                                 utxo: map[bc.Hash]*types.Tx{},
387                                 orphans: map[bc.Hash]*orphanTx{
388                                         testTxs[3].ID: &orphanTx{
389                                                 TxDesc: &TxDesc{
390                                                         Tx: testTxs[3],
391                                                 },
392                                         },
393                                         testTxs[4].ID: &orphanTx{
394                                                 TxDesc: &TxDesc{
395                                                         Tx: testTxs[4],
396                                                 },
397                                         },
398                                 },
399                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
400                                         testTxs[3].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
401                                                 testTxs[3].ID: &orphanTx{
402                                                         TxDesc: &TxDesc{
403                                                                 Tx: testTxs[3],
404                                                         },
405                                                 },
406                                         },
407                                         testTxs[4].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
408                                                 testTxs[4].ID: &orphanTx{
409                                                         TxDesc: &TxDesc{
410                                                                 Tx: testTxs[4],
411                                                         },
412                                                 },
413                                         },
414                                 },
415                                 msgCh: make(chan *TxPoolMsg, 10),
416                         },
417                         after: &TxPool{
418                                 pool: map[bc.Hash]*TxDesc{
419                                         testTxs[3].ID: &TxDesc{
420                                                 Tx:         testTxs[3],
421                                                 StatusFail: false,
422                                         },
423                                         testTxs[4].ID: &TxDesc{
424                                                 Tx:         testTxs[4],
425                                                 StatusFail: false,
426                                         },
427                                 },
428                                 utxo: map[bc.Hash]*types.Tx{
429                                         *testTxs[3].ResultIds[0]: testTxs[3],
430                                         *testTxs[3].ResultIds[1]: testTxs[3],
431                                         *testTxs[4].ResultIds[0]: testTxs[4],
432                                         *testTxs[4].ResultIds[1]: testTxs[4],
433                                 },
434                                 orphans:       map[bc.Hash]*orphanTx{},
435                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
436                         },
437                         processTx: &TxDesc{Tx: testTxs[2]},
438                 },
439         }
440
441         for i, c := range cases {
442                 c.before.store = &mockStore{}
443                 c.before.addTransaction(c.processTx)
444                 c.before.processOrphans(c.processTx)
445                 c.before.RemoveTransaction(&c.processTx.Tx.ID)
446                 c.before.store = nil
447                 c.before.msgCh = nil
448                 c.before.lastUpdated = 0
449                 for _, txD := range c.before.pool {
450                         txD.Added = time.Time{}
451                 }
452
453                 if !testutil.DeepEqual(c.before, c.after) {
454                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
455                 }
456         }
457 }
458
459 func TestRemoveOrphan(t *testing.T) {
460         cases := []struct {
461                 before       *TxPool
462                 after        *TxPool
463                 removeHashes []*bc.Hash
464         }{
465                 {
466                         before: &TxPool{
467                                 orphans: map[bc.Hash]*orphanTx{
468                                         testTxs[0].ID: &orphanTx{
469                                                 expiration: time.Unix(1533489701, 0),
470                                                 TxDesc: &TxDesc{
471                                                         Tx: testTxs[0],
472                                                 },
473                                         },
474                                 },
475                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
476                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
477                                                 testTxs[0].ID: &orphanTx{
478                                                         expiration: time.Unix(1533489701, 0),
479                                                         TxDesc: &TxDesc{
480                                                                 Tx: testTxs[0],
481                                                         },
482                                                 },
483                                         },
484                                 },
485                         },
486                         after: &TxPool{
487                                 orphans:       map[bc.Hash]*orphanTx{},
488                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{},
489                         },
490                         removeHashes: []*bc.Hash{
491                                 &testTxs[0].ID,
492                         },
493                 },
494                 {
495                         before: &TxPool{
496                                 orphans: map[bc.Hash]*orphanTx{
497                                         testTxs[0].ID: &orphanTx{
498                                                 expiration: time.Unix(1533489701, 0),
499                                                 TxDesc: &TxDesc{
500                                                         Tx: testTxs[0],
501                                                 },
502                                         },
503                                         testTxs[1].ID: &orphanTx{
504                                                 expiration: time.Unix(1533489701, 0),
505                                                 TxDesc: &TxDesc{
506                                                         Tx: testTxs[1],
507                                                 },
508                                         },
509                                 },
510                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
511                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
512                                                 testTxs[0].ID: &orphanTx{
513                                                         expiration: time.Unix(1533489701, 0),
514                                                         TxDesc: &TxDesc{
515                                                                 Tx: testTxs[0],
516                                                         },
517                                                 },
518                                                 testTxs[1].ID: &orphanTx{
519                                                         expiration: time.Unix(1533489701, 0),
520                                                         TxDesc: &TxDesc{
521                                                                 Tx: testTxs[1],
522                                                         },
523                                                 },
524                                         },
525                                 },
526                         },
527                         after: &TxPool{
528                                 orphans: map[bc.Hash]*orphanTx{
529                                         testTxs[0].ID: &orphanTx{
530                                                 expiration: time.Unix(1533489701, 0),
531                                                 TxDesc: &TxDesc{
532                                                         Tx: testTxs[0],
533                                                 },
534                                         },
535                                 },
536                                 orphansByPrev: map[bc.Hash]map[bc.Hash]*orphanTx{
537                                         testTxs[0].SpentOutputIDs[0]: map[bc.Hash]*orphanTx{
538                                                 testTxs[0].ID: &orphanTx{
539                                                         expiration: time.Unix(1533489701, 0),
540                                                         TxDesc: &TxDesc{
541                                                                 Tx: testTxs[0],
542                                                         },
543                                                 },
544                                         },
545                                 },
546                         },
547                         removeHashes: []*bc.Hash{
548                                 &testTxs[1].ID,
549                         },
550                 },
551         }
552
553         for i, c := range cases {
554                 for _, hash := range c.removeHashes {
555                         c.before.removeOrphan(hash)
556                 }
557                 if !testutil.DeepEqual(c.before, c.after) {
558                         t.Errorf("case %d: got %v want %v", i, c.before, c.after)
559                 }
560         }
561 }