OSDN Git Service

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