OSDN Git Service

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