OSDN Git Service

modify utxo pending number and consensus node vote restrict (#285)
[bytom/vapor.git] / protocol / state / utxo_view_test.go
1 package state
2
3 import (
4         "testing"
5
6         "github.com/vapor/consensus"
7         "github.com/vapor/database/storage"
8         "github.com/vapor/protocol/bc"
9         "github.com/vapor/testutil"
10 )
11
12 var defaultEntry = map[bc.Hash]bc.Entry{
13         bc.Hash{V0: 0}: &bc.IntraChainOutput{
14                 Source: &bc.ValueSource{
15                         Value: &bc.AssetAmount{
16                                 AssetId: &bc.AssetID{V0: 0},
17                         },
18                 },
19         },
20 }
21
22 var coinbaseEntry = map[bc.Hash]bc.Entry{
23         bc.Hash{V0: 0}: &bc.IntraChainOutput{
24                 Source: &bc.ValueSource{
25                         Value: &bc.AssetAmount{
26                                 AssetId: consensus.BTMAssetID,
27                         },
28                 },
29         },
30         bc.Hash{V0: 1}: &bc.IntraChainOutput{
31                 Source: &bc.ValueSource{
32                         Value: &bc.AssetAmount{
33                                 AssetId: consensus.BTMAssetID,
34                                 Amount:  uint64(100),
35                         },
36                 },
37         },
38 }
39
40 var voteEntry = map[bc.Hash]bc.Entry{
41         bc.Hash{V0: 0}: &bc.VoteOutput{
42                 Source: &bc.ValueSource{
43                         Value: &bc.AssetAmount{
44                                 AssetId: &bc.AssetID{V0: 0},
45                         },
46                 },
47         },
48 }
49
50 var gasOnlyTxEntry = map[bc.Hash]bc.Entry{
51         bc.Hash{V1: 0}: &bc.IntraChainOutput{
52                 Source: &bc.ValueSource{
53                         Value: &bc.AssetAmount{
54                                 AssetId: consensus.BTMAssetID,
55                         },
56                 },
57         },
58         bc.Hash{V1: 1}: &bc.IntraChainOutput{
59                 Source: &bc.ValueSource{
60                         Value: &bc.AssetAmount{
61                                 AssetId: &bc.AssetID{V0: 999},
62                         },
63                 },
64         },
65 }
66
67 func TestApplyBlock(t *testing.T) {
68         cases := []struct {
69                 block     *bc.Block
70                 inputView *UtxoViewpoint
71                 fetchView *UtxoViewpoint
72                 gasOnlyTx bool
73                 err       bool
74         }{
75                 {
76                         // can't find prevout in tx entries
77                         block: &bc.Block{
78                                 BlockHeader: &bc.BlockHeader{
79                                         TransactionStatus: bc.NewTransactionStatus(),
80                                 },
81                                 Transactions: []*bc.Tx{
82                                         &bc.Tx{
83                                                 SpentOutputIDs: []bc.Hash{
84                                                         bc.Hash{V0: 1},
85                                                 },
86                                                 Entries: defaultEntry,
87                                         },
88                                 },
89                         },
90                         inputView: &UtxoViewpoint{
91                                 Entries: map[bc.Hash]*storage.UtxoEntry{
92                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
93                                 },
94                         },
95                         fetchView: NewUtxoViewpoint(),
96                         err:       true,
97                 },
98                 {
99                         block: &bc.Block{
100                                 BlockHeader: &bc.BlockHeader{
101                                         TransactionStatus: bc.NewTransactionStatus(),
102                                 },
103                                 Transactions: []*bc.Tx{
104                                         &bc.Tx{
105                                                 SpentOutputIDs: []bc.Hash{
106                                                         bc.Hash{V0: 0},
107                                                 },
108                                                 Entries: defaultEntry,
109                                         },
110                                 },
111                         },
112                         inputView: NewUtxoViewpoint(),
113                         fetchView: NewUtxoViewpoint(),
114                         err:       true,
115                 },
116                 {
117                         block: &bc.Block{
118                                 BlockHeader: &bc.BlockHeader{
119                                         TransactionStatus: bc.NewTransactionStatus(),
120                                 },
121                                 Transactions: []*bc.Tx{
122                                         &bc.Tx{
123                                                 SpentOutputIDs: []bc.Hash{
124                                                         bc.Hash{V0: 0},
125                                                 },
126                                                 Entries: defaultEntry,
127                                         },
128                                 },
129                         },
130                         inputView: &UtxoViewpoint{
131                                 Entries: map[bc.Hash]*storage.UtxoEntry{
132                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
133                                 },
134                         },
135                         err: true,
136                 },
137                 {
138                         block: &bc.Block{
139                                 BlockHeader: &bc.BlockHeader{
140                                         TransactionStatus: bc.NewTransactionStatus(),
141                                 },
142                                 Transactions: []*bc.Tx{
143                                         &bc.Tx{
144                                                 TxHeader: &bc.TxHeader{
145                                                         ResultIds: []*bc.Hash{},
146                                                 },
147                                                 SpentOutputIDs: []bc.Hash{
148                                                         bc.Hash{V0: 0},
149                                                 },
150                                                 Entries: defaultEntry,
151                                         },
152                                 },
153                         },
154                         inputView: &UtxoViewpoint{
155                                 Entries: map[bc.Hash]*storage.UtxoEntry{
156                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
157                                 },
158                         },
159                         fetchView: &UtxoViewpoint{
160                                 Entries: map[bc.Hash]*storage.UtxoEntry{
161                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
162                                 },
163                         },
164                         err: false,
165                 },
166                 {
167                         block: &bc.Block{
168                                 BlockHeader: &bc.BlockHeader{
169                                         Height:            consensus.MainNetParams.CoinbasePendingBlockNumber + 1,
170                                         TransactionStatus: bc.NewTransactionStatus(),
171                                 },
172                                 Transactions: []*bc.Tx{
173                                         &bc.Tx{
174                                                 TxHeader: &bc.TxHeader{
175                                                         ResultIds: []*bc.Hash{},
176                                                 },
177                                                 SpentOutputIDs: []bc.Hash{
178                                                         bc.Hash{V0: 0},
179                                                 },
180                                                 Entries: defaultEntry,
181                                         },
182                                 },
183                         },
184                         inputView: &UtxoViewpoint{
185                                 Entries: map[bc.Hash]*storage.UtxoEntry{
186                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
187                                 },
188                         },
189                         fetchView: &UtxoViewpoint{
190                                 Entries: map[bc.Hash]*storage.UtxoEntry{
191                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, true),
192                                 },
193                         },
194                         err: false,
195                 },
196                 {
197                         block: &bc.Block{
198                                 BlockHeader: &bc.BlockHeader{
199                                         Height:            0,
200                                         TransactionStatus: bc.NewTransactionStatus(),
201                                 },
202                                 Transactions: []*bc.Tx{
203                                         &bc.Tx{
204                                                 TxHeader: &bc.TxHeader{
205                                                         ResultIds: []*bc.Hash{},
206                                                 },
207                                                 SpentOutputIDs: []bc.Hash{
208                                                         bc.Hash{V0: 0},
209                                                 },
210                                                 Entries: defaultEntry,
211                                         },
212                                 },
213                         },
214                         inputView: &UtxoViewpoint{
215                                 Entries: map[bc.Hash]*storage.UtxoEntry{
216                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
217                                 },
218                         },
219                         fetchView: &UtxoViewpoint{
220                                 Entries: map[bc.Hash]*storage.UtxoEntry{
221                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, true),
222                                 },
223                         },
224                         err: true,
225                 },
226                 {
227                         // output will be store
228                         block: &bc.Block{
229                                 BlockHeader: &bc.BlockHeader{
230                                         TransactionStatus: bc.NewTransactionStatus(),
231                                 },
232                                 Transactions: []*bc.Tx{
233                                         &bc.Tx{
234                                                 TxHeader: &bc.TxHeader{
235                                                         ResultIds: []*bc.Hash{
236                                                                 &bc.Hash{V0: 0},
237                                                                 &bc.Hash{V0: 1},
238                                                         },
239                                                 },
240                                                 SpentOutputIDs: []bc.Hash{},
241                                                 Entries:        coinbaseEntry,
242                                         },
243                                 },
244                         },
245                         inputView: NewUtxoViewpoint(),
246                         fetchView: &UtxoViewpoint{
247                                 Entries: map[bc.Hash]*storage.UtxoEntry{
248                                         bc.Hash{V0: 1}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
249                                 },
250                         },
251                         err: false,
252                 },
253                 {
254                         // apply gas only tx, non-btm asset spent input will not be spent
255                         block: &bc.Block{
256                                 BlockHeader: &bc.BlockHeader{
257                                         TransactionStatus: bc.NewTransactionStatus(),
258                                 },
259                                 Transactions: []*bc.Tx{
260                                         &bc.Tx{
261                                                 TxHeader: &bc.TxHeader{
262                                                         ResultIds: []*bc.Hash{},
263                                                 },
264                                                 SpentOutputIDs: []bc.Hash{
265                                                         bc.Hash{V1: 0},
266                                                         bc.Hash{V1: 1},
267                                                 },
268                                                 Entries: gasOnlyTxEntry,
269                                         },
270                                 },
271                         },
272                         inputView: &UtxoViewpoint{
273                                 Entries: map[bc.Hash]*storage.UtxoEntry{
274                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
275                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
276                                 },
277                         },
278                         fetchView: &UtxoViewpoint{
279                                 Entries: map[bc.Hash]*storage.UtxoEntry{
280                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
281                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
282                                 },
283                         },
284                         gasOnlyTx: true,
285                         err:       false,
286                 },
287                 {
288                         // apply gas only tx, non-btm asset spent output will not be store
289                         block: &bc.Block{
290                                 BlockHeader: &bc.BlockHeader{
291                                         TransactionStatus: bc.NewTransactionStatus(),
292                                 },
293                                 Transactions: []*bc.Tx{
294                                         &bc.Tx{
295                                                 TxHeader: &bc.TxHeader{
296                                                         ResultIds: []*bc.Hash{
297                                                                 &bc.Hash{V1: 0},
298                                                                 &bc.Hash{V1: 1},
299                                                         },
300                                                 },
301                                                 SpentOutputIDs: []bc.Hash{},
302                                                 Entries:        gasOnlyTxEntry,
303                                         },
304                                 },
305                         },
306                         inputView: NewUtxoViewpoint(),
307                         fetchView: NewUtxoViewpoint(),
308                         gasOnlyTx: true,
309                         err:       false,
310                 },
311                 {
312                         block: &bc.Block{
313                                 BlockHeader: &bc.BlockHeader{
314                                         TransactionStatus: bc.NewTransactionStatus(),
315                                 },
316                                 Transactions: []*bc.Tx{
317                                         &bc.Tx{
318                                                 TxHeader: &bc.TxHeader{
319                                                         ResultIds: []*bc.Hash{},
320                                                 },
321                                                 SpentOutputIDs: []bc.Hash{
322                                                         bc.Hash{V0: 0},
323                                                 },
324                                                 Entries: voteEntry,
325                                         },
326                                 },
327                         },
328                         inputView: &UtxoViewpoint{
329                                 Entries: map[bc.Hash]*storage.UtxoEntry{
330                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
331                                 },
332                         },
333                         fetchView: &UtxoViewpoint{
334                                 Entries: map[bc.Hash]*storage.UtxoEntry{
335                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, true),
336                                 },
337                         },
338                         err: true,
339                 },
340                 {
341                         block: &bc.Block{
342                                 BlockHeader: &bc.BlockHeader{
343                                         Height:            consensus.MainNetParams.VotePendingBlockNumber + 1,
344                                         TransactionStatus: bc.NewTransactionStatus(),
345                                 },
346                                 Transactions: []*bc.Tx{
347                                         &bc.Tx{
348                                                 TxHeader: &bc.TxHeader{
349                                                         ResultIds: []*bc.Hash{},
350                                                 },
351                                                 SpentOutputIDs: []bc.Hash{
352                                                         bc.Hash{V0: 0},
353                                                 },
354                                                 Entries: voteEntry,
355                                         },
356                                 },
357                         },
358                         inputView: &UtxoViewpoint{
359                                 Entries: map[bc.Hash]*storage.UtxoEntry{
360                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, false),
361                                 },
362                         },
363                         fetchView: &UtxoViewpoint{
364                                 Entries: map[bc.Hash]*storage.UtxoEntry{
365                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, true),
366                                 },
367                         },
368                         err: false,
369                 },
370         }
371
372         for i, c := range cases {
373                 c.block.TransactionStatus.SetStatus(0, c.gasOnlyTx)
374                 if err := c.inputView.ApplyBlock(c.block, c.block.TransactionStatus); c.err != (err != nil) {
375                         t.Errorf("case #%d want err = %v, get err = %v", i, c.err, err)
376                 }
377                 if c.err {
378                         continue
379                 }
380                 if !testutil.DeepEqual(c.inputView, c.fetchView) {
381                         t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
382                 }
383         }
384 }
385
386 func TestDetachBlock(t *testing.T) {
387         cases := []struct {
388                 block     *bc.Block
389                 inputView *UtxoViewpoint
390                 fetchView *UtxoViewpoint
391                 gasOnlyTx bool
392                 err       bool
393         }{
394                 {
395                         block: &bc.Block{
396                                 BlockHeader: &bc.BlockHeader{
397                                         TransactionStatus: bc.NewTransactionStatus(),
398                                 },
399                                 Transactions: []*bc.Tx{
400                                         &bc.Tx{
401                                                 TxHeader: &bc.TxHeader{
402                                                         ResultIds: []*bc.Hash{},
403                                                 },
404                                                 SpentOutputIDs: []bc.Hash{
405                                                         bc.Hash{V0: 0},
406                                                 },
407                                                 Entries: defaultEntry,
408                                         },
409                                 },
410                         },
411                         inputView: NewUtxoViewpoint(),
412                         fetchView: &UtxoViewpoint{
413                                 Entries: map[bc.Hash]*storage.UtxoEntry{
414                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
415                                 },
416                         },
417                         err: false,
418                 },
419                 {
420                         block: &bc.Block{
421                                 BlockHeader: &bc.BlockHeader{
422                                         TransactionStatus: bc.NewTransactionStatus(),
423                                 },
424                                 Transactions: []*bc.Tx{
425                                         &bc.Tx{
426                                                 TxHeader: &bc.TxHeader{
427                                                         ResultIds: []*bc.Hash{
428                                                                 &bc.Hash{V0: 0},
429                                                                 &bc.Hash{V0: 1},
430                                                         },
431                                                 },
432                                                 SpentOutputIDs: []bc.Hash{},
433                                                 Entries:        coinbaseEntry,
434                                         },
435                                 },
436                         },
437                         inputView: &UtxoViewpoint{
438                                 Entries: map[bc.Hash]*storage.UtxoEntry{
439                                         bc.Hash{V0: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
440                                 },
441                         },
442                         fetchView: &UtxoViewpoint{
443                                 Entries: map[bc.Hash]*storage.UtxoEntry{
444                                         bc.Hash{V0: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
445                                 },
446                         },
447                         err: false,
448                 },
449                 {
450                         block: &bc.Block{
451                                 BlockHeader: &bc.BlockHeader{
452                                         TransactionStatus: bc.NewTransactionStatus(),
453                                 },
454                                 Transactions: []*bc.Tx{
455                                         &bc.Tx{
456                                                 TxHeader: &bc.TxHeader{
457                                                         ResultIds: []*bc.Hash{},
458                                                 },
459                                                 SpentOutputIDs: []bc.Hash{
460                                                         bc.Hash{V0: 0},
461                                                 },
462                                                 Entries: defaultEntry,
463                                         },
464                                 },
465                         },
466                         inputView: &UtxoViewpoint{
467                                 Entries: map[bc.Hash]*storage.UtxoEntry{
468                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
469                                 },
470                         },
471                         err: true,
472                 },
473                 {
474                         block: &bc.Block{
475                                 BlockHeader: &bc.BlockHeader{
476                                         TransactionStatus: bc.NewTransactionStatus(),
477                                 },
478                                 Transactions: []*bc.Tx{
479                                         &bc.Tx{
480                                                 TxHeader: &bc.TxHeader{
481                                                         ResultIds: []*bc.Hash{},
482                                                 },
483                                                 SpentOutputIDs: []bc.Hash{
484                                                         bc.Hash{V0: 0},
485                                                 },
486                                                 Entries: defaultEntry,
487                                         },
488                                 },
489                         },
490                         inputView: &UtxoViewpoint{
491                                 Entries: map[bc.Hash]*storage.UtxoEntry{
492                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
493                                 },
494                         },
495                         fetchView: &UtxoViewpoint{
496                                 Entries: map[bc.Hash]*storage.UtxoEntry{
497                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
498                                 },
499                         },
500                         err: false,
501                 },
502                 {
503                         block: &bc.Block{
504                                 BlockHeader: &bc.BlockHeader{
505                                         TransactionStatus: bc.NewTransactionStatus(),
506                                 },
507                                 Transactions: []*bc.Tx{
508                                         &bc.Tx{
509                                                 TxHeader: &bc.TxHeader{
510                                                         ResultIds: []*bc.Hash{},
511                                                 },
512                                                 SpentOutputIDs: []bc.Hash{
513                                                         bc.Hash{V1: 0},
514                                                         bc.Hash{V1: 1},
515                                                 },
516                                                 Entries: gasOnlyTxEntry,
517                                         },
518                                 },
519                         },
520                         inputView: &UtxoViewpoint{
521                                 Entries: map[bc.Hash]*storage.UtxoEntry{
522                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
523                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
524                                 },
525                         },
526                         fetchView: &UtxoViewpoint{
527                                 Entries: map[bc.Hash]*storage.UtxoEntry{
528                                         bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
529                                         bc.Hash{V1: 1}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
530                                 },
531                         },
532                         gasOnlyTx: true,
533                         err:       false,
534                 },
535                 {
536                         block: &bc.Block{
537                                 BlockHeader: &bc.BlockHeader{
538                                         TransactionStatus: bc.NewTransactionStatus(),
539                                 },
540                                 Transactions: []*bc.Tx{
541                                         &bc.Tx{
542                                                 TxHeader: &bc.TxHeader{
543                                                         ResultIds: []*bc.Hash{
544                                                                 &bc.Hash{V1: 0},
545                                                                 &bc.Hash{V1: 1},
546                                                         },
547                                                 },
548                                                 SpentOutputIDs: []bc.Hash{},
549                                                 Entries:        gasOnlyTxEntry,
550                                         },
551                                 },
552                         },
553                         inputView: NewUtxoViewpoint(),
554                         fetchView: NewUtxoViewpoint(),
555                         gasOnlyTx: true,
556                         err:       false,
557                 },
558                 {
559                         block: &bc.Block{
560                                 BlockHeader: &bc.BlockHeader{
561                                         TransactionStatus: bc.NewTransactionStatus(),
562                                 },
563                                 Transactions: []*bc.Tx{
564                                         &bc.Tx{
565                                                 TxHeader: &bc.TxHeader{
566                                                         ResultIds: []*bc.Hash{},
567                                                 },
568                                                 SpentOutputIDs: []bc.Hash{
569                                                         bc.Hash{V0: 0},
570                                                 },
571                                                 Entries: voteEntry,
572                                         },
573                                 },
574                         },
575                         inputView: NewUtxoViewpoint(),
576                         fetchView: &UtxoViewpoint{
577                                 Entries: map[bc.Hash]*storage.UtxoEntry{
578                                         bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
579                                 },
580                         },
581                         err: false,
582                 },
583         }
584
585         for i, c := range cases {
586                 c.block.TransactionStatus.SetStatus(0, c.gasOnlyTx)
587                 if err := c.inputView.DetachBlock(c.block, c.block.TransactionStatus); c.err != (err != nil) {
588                         t.Errorf("case %d want err = %v, get err = %v", i, c.err, err)
589                 }
590                 if c.err {
591                         continue
592                 }
593                 if !testutil.DeepEqual(c.inputView, c.fetchView) {
594                         t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
595                 }
596         }
597 }