6 "github.com/vapor/consensus"
7 "github.com/vapor/database/storage"
8 "github.com/vapor/protocol/bc"
9 "github.com/vapor/testutil"
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},
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},
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,
40 bc.Hash{V1: 1}: &bc.IntraChainOutput{
41 Source: &bc.ValueSource{
42 Value: &bc.AssetAmount{
43 AssetId: &bc.AssetID{V0: 999},
49 func TestApplyBlock(t *testing.T) {
52 inputView *UtxoViewpoint
53 fetchView *UtxoViewpoint
58 // can't find prevout in tx entries
60 BlockHeader: &bc.BlockHeader{
61 TransactionStatus: bc.NewTransactionStatus(),
63 Transactions: []*bc.Tx{
65 SpentOutputIDs: []bc.Hash{
68 Entries: defaultEntry,
72 inputView: &UtxoViewpoint{
73 Entries: map[bc.Hash]*storage.UtxoEntry{
74 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
77 fetchView: NewUtxoViewpoint(),
82 BlockHeader: &bc.BlockHeader{
83 TransactionStatus: bc.NewTransactionStatus(),
85 Transactions: []*bc.Tx{
87 SpentOutputIDs: []bc.Hash{
90 Entries: defaultEntry,
94 inputView: NewUtxoViewpoint(),
95 fetchView: NewUtxoViewpoint(),
100 BlockHeader: &bc.BlockHeader{
101 TransactionStatus: bc.NewTransactionStatus(),
103 Transactions: []*bc.Tx{
105 SpentOutputIDs: []bc.Hash{
108 Entries: defaultEntry,
112 inputView: &UtxoViewpoint{
113 Entries: map[bc.Hash]*storage.UtxoEntry{
114 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
121 BlockHeader: &bc.BlockHeader{
122 TransactionStatus: bc.NewTransactionStatus(),
124 Transactions: []*bc.Tx{
126 TxHeader: &bc.TxHeader{
127 ResultIds: []*bc.Hash{},
129 SpentOutputIDs: []bc.Hash{
132 Entries: defaultEntry,
136 inputView: &UtxoViewpoint{
137 Entries: map[bc.Hash]*storage.UtxoEntry{
138 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
141 fetchView: &UtxoViewpoint{
142 Entries: map[bc.Hash]*storage.UtxoEntry{
143 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
150 BlockHeader: &bc.BlockHeader{
152 TransactionStatus: bc.NewTransactionStatus(),
154 Transactions: []*bc.Tx{
156 TxHeader: &bc.TxHeader{
157 ResultIds: []*bc.Hash{},
159 SpentOutputIDs: []bc.Hash{
162 Entries: defaultEntry,
166 inputView: &UtxoViewpoint{
167 Entries: map[bc.Hash]*storage.UtxoEntry{
168 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
171 fetchView: &UtxoViewpoint{
172 Entries: map[bc.Hash]*storage.UtxoEntry{
173 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, true),
180 BlockHeader: &bc.BlockHeader{
182 TransactionStatus: bc.NewTransactionStatus(),
184 Transactions: []*bc.Tx{
186 TxHeader: &bc.TxHeader{
187 ResultIds: []*bc.Hash{},
189 SpentOutputIDs: []bc.Hash{
192 Entries: defaultEntry,
196 inputView: &UtxoViewpoint{
197 Entries: map[bc.Hash]*storage.UtxoEntry{
198 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
201 fetchView: &UtxoViewpoint{
202 Entries: map[bc.Hash]*storage.UtxoEntry{
203 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, true),
209 // output will be store
211 BlockHeader: &bc.BlockHeader{
212 TransactionStatus: bc.NewTransactionStatus(),
214 Transactions: []*bc.Tx{
216 TxHeader: &bc.TxHeader{
217 ResultIds: []*bc.Hash{
221 SpentOutputIDs: []bc.Hash{},
222 Entries: defaultEntry,
226 inputView: NewUtxoViewpoint(),
227 fetchView: &UtxoViewpoint{
228 Entries: map[bc.Hash]*storage.UtxoEntry{
229 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
235 // apply gas only tx, non-btm asset spent input will not be spent
237 BlockHeader: &bc.BlockHeader{
238 TransactionStatus: bc.NewTransactionStatus(),
240 Transactions: []*bc.Tx{
242 TxHeader: &bc.TxHeader{
243 ResultIds: []*bc.Hash{},
245 SpentOutputIDs: []bc.Hash{
249 Entries: gasOnlyTxEntry,
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),
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),
269 // apply gas only tx, non-btm asset spent output will not be store
271 BlockHeader: &bc.BlockHeader{
272 TransactionStatus: bc.NewTransactionStatus(),
274 Transactions: []*bc.Tx{
276 TxHeader: &bc.TxHeader{
277 ResultIds: []*bc.Hash{
282 SpentOutputIDs: []bc.Hash{},
283 Entries: gasOnlyTxEntry,
287 inputView: NewUtxoViewpoint(),
288 fetchView: &UtxoViewpoint{
289 Entries: map[bc.Hash]*storage.UtxoEntry{
290 bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.CoinbaseUTXOType, 0, false),
298 BlockHeader: &bc.BlockHeader{
299 TransactionStatus: bc.NewTransactionStatus(),
301 Transactions: []*bc.Tx{
303 TxHeader: &bc.TxHeader{
304 ResultIds: []*bc.Hash{},
306 SpentOutputIDs: []bc.Hash{
313 inputView: &UtxoViewpoint{
314 Entries: map[bc.Hash]*storage.UtxoEntry{
315 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
318 fetchView: &UtxoViewpoint{
319 Entries: map[bc.Hash]*storage.UtxoEntry{
320 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, true),
327 BlockHeader: &bc.BlockHeader{
329 TransactionStatus: bc.NewTransactionStatus(),
331 Transactions: []*bc.Tx{
333 TxHeader: &bc.TxHeader{
334 ResultIds: []*bc.Hash{},
336 SpentOutputIDs: []bc.Hash{
343 inputView: &UtxoViewpoint{
344 Entries: map[bc.Hash]*storage.UtxoEntry{
345 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, false),
348 fetchView: &UtxoViewpoint{
349 Entries: map[bc.Hash]*storage.UtxoEntry{
350 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 1, true),
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)
365 if !testutil.DeepEqual(c.inputView, c.fetchView) {
366 t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)
371 func TestDetachBlock(t *testing.T) {
374 inputView *UtxoViewpoint
375 fetchView *UtxoViewpoint
381 BlockHeader: &bc.BlockHeader{
382 TransactionStatus: bc.NewTransactionStatus(),
384 Transactions: []*bc.Tx{
386 TxHeader: &bc.TxHeader{
387 ResultIds: []*bc.Hash{},
389 SpentOutputIDs: []bc.Hash{
392 Entries: defaultEntry,
396 inputView: NewUtxoViewpoint(),
397 fetchView: &UtxoViewpoint{
398 Entries: map[bc.Hash]*storage.UtxoEntry{
399 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
406 BlockHeader: &bc.BlockHeader{
407 TransactionStatus: bc.NewTransactionStatus(),
409 Transactions: []*bc.Tx{
411 TxHeader: &bc.TxHeader{
412 ResultIds: []*bc.Hash{
416 SpentOutputIDs: []bc.Hash{},
417 Entries: defaultEntry,
421 inputView: NewUtxoViewpoint(),
422 fetchView: &UtxoViewpoint{
423 Entries: map[bc.Hash]*storage.UtxoEntry{
424 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
431 BlockHeader: &bc.BlockHeader{
432 TransactionStatus: bc.NewTransactionStatus(),
434 Transactions: []*bc.Tx{
436 TxHeader: &bc.TxHeader{
437 ResultIds: []*bc.Hash{},
439 SpentOutputIDs: []bc.Hash{
442 Entries: defaultEntry,
446 inputView: &UtxoViewpoint{
447 Entries: map[bc.Hash]*storage.UtxoEntry{
448 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
455 BlockHeader: &bc.BlockHeader{
456 TransactionStatus: bc.NewTransactionStatus(),
458 Transactions: []*bc.Tx{
460 TxHeader: &bc.TxHeader{
461 ResultIds: []*bc.Hash{},
463 SpentOutputIDs: []bc.Hash{
466 Entries: defaultEntry,
470 inputView: &UtxoViewpoint{
471 Entries: map[bc.Hash]*storage.UtxoEntry{
472 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
475 fetchView: &UtxoViewpoint{
476 Entries: map[bc.Hash]*storage.UtxoEntry{
477 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, false),
484 BlockHeader: &bc.BlockHeader{
485 TransactionStatus: bc.NewTransactionStatus(),
487 Transactions: []*bc.Tx{
489 TxHeader: &bc.TxHeader{
490 ResultIds: []*bc.Hash{},
492 SpentOutputIDs: []bc.Hash{
496 Entries: gasOnlyTxEntry,
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),
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),
517 BlockHeader: &bc.BlockHeader{
518 TransactionStatus: bc.NewTransactionStatus(),
520 Transactions: []*bc.Tx{
522 TxHeader: &bc.TxHeader{
523 ResultIds: []*bc.Hash{
528 SpentOutputIDs: []bc.Hash{},
529 Entries: gasOnlyTxEntry,
533 inputView: NewUtxoViewpoint(),
534 fetchView: &UtxoViewpoint{
535 Entries: map[bc.Hash]*storage.UtxoEntry{
536 bc.Hash{V1: 0}: storage.NewUtxoEntry(storage.NormalUTXOType, 0, true),
544 BlockHeader: &bc.BlockHeader{
545 TransactionStatus: bc.NewTransactionStatus(),
547 Transactions: []*bc.Tx{
549 TxHeader: &bc.TxHeader{
550 ResultIds: []*bc.Hash{},
552 SpentOutputIDs: []bc.Hash{
559 inputView: NewUtxoViewpoint(),
560 fetchView: &UtxoViewpoint{
561 Entries: map[bc.Hash]*storage.UtxoEntry{
562 bc.Hash{V0: 0}: storage.NewUtxoEntry(storage.VoteUTXOType, 0, false),
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)
577 if !testutil.DeepEqual(c.inputView, c.fetchView) {
578 t.Errorf("test case %d, want %v, get %v", i, c.fetchView, c.inputView)