OSDN Git Service

63de5162836ccbdf90bc6bfb0086b75130581031
[bytom/vapor.git] / protocol / validation / block_test.go
1 package validation
2
3 import (
4         "math"
5         "testing"
6         "time"
7
8         "github.com/vapor/consensus"
9         "github.com/vapor/protocol/bc"
10         "github.com/vapor/protocol/bc/types"
11         "github.com/vapor/protocol/state"
12         "github.com/vapor/protocol/vm"
13         "github.com/vapor/protocol/vm/vmutil"
14         "github.com/vapor/testutil"
15 )
16
17 func TestCheckBlockTime(t *testing.T) {
18         cases := []struct {
19                 desc       string
20                 blockTime  uint64
21                 parentTime []uint64
22                 err        error
23         }{
24                 {
25                         blockTime:  1520000500,
26                         parentTime: []uint64{1520000000},
27                         err:        nil,
28                 },
29                 {
30                         desc:       "timestamp less than past median time",
31                         blockTime:  1520005500,
32                         parentTime: []uint64{1520000000, 1520000500, 1520001000, 1520001500, 1520002000, 1520002500, 1520003000, 1520003500, 1520004000, 1520004500, 1520005000},
33                         err:        nil,
34                 },
35                 {
36                         desc:       "timestamp greater than max limit",
37                         blockTime:  99999999990000,
38                         parentTime: []uint64{15200000000000},
39                         err:        errBadTimestamp,
40                 },
41                 {
42                         desc:       "timestamp of the block and the parent block are both greater than max limit",
43                         blockTime:  uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 2000,
44                         parentTime: []uint64{uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 1000},
45                         err:        errBadTimestamp,
46                 },
47         }
48
49         parent := &types.BlockHeader{Version: 1}
50         block := &bc.Block{
51                 BlockHeader: &bc.BlockHeader{Version: 1},
52         }
53
54         for i, c := range cases {
55                 parent.Timestamp = c.parentTime[0]
56                 parentSuccessor := parent
57                 for i := 1; i < len(c.parentTime); i++ {
58                         Previous := &types.BlockHeader{Version: 1, Timestamp: c.parentTime[i]}
59                         parentSuccessor.PreviousBlockHash = Previous.Hash()
60                         parentSuccessor = Previous
61                 }
62
63                 block.Timestamp = c.blockTime
64                 if err := checkBlockTime(block, parent); rootErr(err) != c.err {
65                         t.Errorf("case %d got error %s, want %s", i, err, c.err)
66                 }
67         }
68 }
69
70 func TestCheckCoinbaseTx(t *testing.T) {
71         cases := []struct {
72                 desc    string
73                 txs     []*types.Tx
74                 rewards []state.CoinbaseReward
75                 err     error
76         }{
77                 {
78                         desc: "zero coinbase amount",
79                         txs: []*types.Tx{
80                                 types.NewTx(types.TxData{
81                                         Inputs:  []*types.TxInput{types.NewCoinbaseInput(nil)},
82                                         Outputs: []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51})},
83                                 }),
84                         },
85                         rewards: []state.CoinbaseReward{},
86                         err:     nil,
87                 },
88                 {
89                         desc: "zero coinbase amount and aggregate rewards",
90                         txs: []*types.Tx{
91                                 types.NewTx(types.TxData{
92                                         Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
93                                         Outputs: []*types.TxOutput{
94                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
95                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
96                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
97                                         },
98                                 }),
99                         },
100                         rewards: []state.CoinbaseReward{
101                                 state.CoinbaseReward{
102                                         Amount:         20000,
103                                         ControlProgram: []byte{0x51},
104                                 },
105                                 state.CoinbaseReward{
106                                         Amount:         10000,
107                                         ControlProgram: []byte{0x52},
108                                 },
109                         },
110                         err: nil,
111                 },
112                 {
113                         desc:    "wrong coinbase transaction with block is empty",
114                         txs:     []*types.Tx{},
115                         rewards: []state.CoinbaseReward{},
116                         err:     ErrWrongCoinbaseTransaction,
117                 },
118                 {
119                         desc: "wrong coinbase transaction with dismatch number of outputs",
120                         txs: []*types.Tx{
121                                 types.NewTx(types.TxData{
122                                         Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
123                                         Outputs: []*types.TxOutput{
124                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
125                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
126                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
127                                         },
128                                 }),
129                         },
130                         rewards: []state.CoinbaseReward{
131                                 state.CoinbaseReward{
132                                         Amount:         20000,
133                                         ControlProgram: []byte{0x51},
134                                 },
135                         },
136                         err: ErrWrongCoinbaseTransaction,
137                 },
138                 {
139                         desc: "wrong coinbase transaction with dismatch output amount",
140                         txs: []*types.Tx{
141                                 types.NewTx(types.TxData{
142                                         Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
143                                         Outputs: []*types.TxOutput{
144                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
145                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
146                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
147                                         },
148                                 }),
149                         },
150                         rewards: []state.CoinbaseReward{
151                                 state.CoinbaseReward{
152                                         Amount:         10000,
153                                         ControlProgram: []byte{0x51},
154                                 },
155                                 state.CoinbaseReward{
156                                         Amount:         10000,
157                                         ControlProgram: []byte{0x52},
158                                 },
159                         },
160                         err: ErrWrongCoinbaseTransaction,
161                 },
162                 {
163                         desc: "wrong coinbase transaction with dismatch output control_program",
164                         txs: []*types.Tx{
165                                 types.NewTx(types.TxData{
166                                         Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
167                                         Outputs: []*types.TxOutput{
168                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
169                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
170                                                 types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
171                                         },
172                                 }),
173                         },
174                         rewards: []state.CoinbaseReward{
175                                 state.CoinbaseReward{
176                                         Amount:         20000,
177                                         ControlProgram: []byte{0x51},
178                                 },
179                                 state.CoinbaseReward{
180                                         Amount:         10000,
181                                         ControlProgram: []byte{0x53},
182                                 },
183                         },
184                         err: ErrWrongCoinbaseTransaction,
185                 },
186         }
187
188         block := new(types.Block)
189         for i, c := range cases {
190                 block.Transactions = c.txs
191                 if err := checkCoinbaseTx(types.MapBlock(block), c.rewards); rootErr(err) != c.err {
192                         t.Errorf("case %d got error %s, want %T", i, err, c.err)
193                 }
194         }
195 }
196
197 func TestValidateBlockHeader(t *testing.T) {
198         parent := &types.BlockHeader{
199                 Version:   1,
200                 Height:    0,
201                 Timestamp: 1523352600000,
202         }
203         parentHash := parent.Hash()
204
205         cases := []struct {
206                 desc   string
207                 block  *bc.Block
208                 parent *types.BlockHeader
209                 err    error
210         }{
211                 {
212                         desc: "dismatch version",
213                         block: &bc.Block{BlockHeader: &bc.BlockHeader{
214                                 Version: 2,
215                         }},
216                         parent: &types.BlockHeader{
217                                 Version: 1,
218                         },
219                         err: errVersionRegression,
220                 },
221                 {
222                         desc: "misordered block height",
223                         block: &bc.Block{BlockHeader: &bc.BlockHeader{
224                                 Version: 1,
225                                 Height:  20,
226                         }},
227                         parent: &types.BlockHeader{
228                                 Version: 1,
229                                 Height:  18,
230                         },
231                         err: errMisorderedBlockHeight,
232                 },
233                 {
234                         desc: "the prev block hash not equals to the hash of parent",
235                         block: &bc.Block{BlockHeader: &bc.BlockHeader{
236                                 Version:         1,
237                                 Height:          20,
238                                 PreviousBlockId: &bc.Hash{V0: 20},
239                         }},
240                         parent: &types.BlockHeader{
241                                 Version:           1,
242                                 Height:            19,
243                                 PreviousBlockHash: bc.Hash{V0: 19},
244                         },
245                         err: errMismatchedBlock,
246                 },
247                 {
248                         desc: "normal block",
249                         block: &bc.Block{
250                                 ID: bc.Hash{V0: 1},
251                                 BlockHeader: &bc.BlockHeader{
252                                         Version:         1,
253                                         Height:          1,
254                                         Timestamp:       1523352601000,
255                                         PreviousBlockId: &parentHash,
256                                 },
257                         },
258                         parent: parent,
259                         err:    nil,
260                 },
261                 {
262                         desc: "version greater than 1",
263                         block: &bc.Block{
264                                 ID: bc.Hash{V0: 1},
265                                 BlockHeader: &bc.BlockHeader{
266                                         Version: 2,
267                                 },
268                         },
269                         parent: &types.BlockHeader{
270                                 Version: 1,
271                         },
272                         err: errVersionRegression,
273                 },
274                 {
275                         desc: "version equals 0",
276                         block: &bc.Block{
277                                 ID: bc.Hash{V0: 1},
278                                 BlockHeader: &bc.BlockHeader{
279                                         Version: 0,
280                                 },
281                         },
282                         parent: &types.BlockHeader{
283                                 Version: 1,
284                         },
285                         err: errVersionRegression,
286                 },
287                 {
288                         desc: "version equals max uint64",
289                         block: &bc.Block{
290                                 ID: bc.Hash{V0: 1},
291                                 BlockHeader: &bc.BlockHeader{
292                                         Version: math.MaxUint64,
293                                 },
294                         },
295                         parent: &types.BlockHeader{
296                                 Version: 1,
297                         },
298                         err: errVersionRegression,
299                 },
300         }
301
302         for i, c := range cases {
303                 if err := ValidateBlockHeader(c.block, c.parent); rootErr(err) != c.err {
304                         t.Errorf("case %d (%s) got error %s, want %s", i, c.desc, err, c.err)
305                 }
306         }
307 }
308
309 func TestValidateBlock(t *testing.T) {
310         cp, _ := vmutil.DefaultCoinbaseProgram()
311         parent := &types.BlockHeader{
312                 Version:           1,
313                 Height:            0,
314                 Timestamp:         1523352600000,
315                 PreviousBlockHash: bc.Hash{V0: 0},
316         }
317         parentHash := parent.Hash()
318         txsRoot := testutil.MustDecodeHash("001e21b9618c503d909c1e0b32bab9ccf80c538b35d49ac7fffcef98eb373b23")
319         txStatusHash := testutil.MustDecodeHash("6978a65b4ee5b6f4914fe5c05000459a803ecf59132604e5d334d64249c5e50a")
320
321         txs := []*bc.Tx{
322                 types.MapTx(&types.TxData{
323                         Version:        1,
324                         SerializedSize: 1,
325                         Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
326                         Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
327                 }),
328         }
329
330         for i := 1; i <= 100; i++ {
331                 txs = append(txs, types.MapTx(&types.TxData{
332                         Version:        1,
333                         SerializedSize: 100000,
334                         Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, bc.Hash{V0: uint64(i)}, *consensus.BTMAssetID, 10000000000, 0, cp)},
335                         Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, cp)},
336                 }))
337         }
338
339         cases := []struct {
340                 desc    string
341                 block   *bc.Block
342                 parent  *types.BlockHeader
343                 rewards []state.CoinbaseReward
344                 err     error
345         }{
346                 {
347                         desc: "validate transactions with output amount great than input amount",
348                         block: &bc.Block{
349                                 ID: bc.Hash{V0: 1},
350                                 BlockHeader: &bc.BlockHeader{
351                                         Version:               1,
352                                         Height:                1,
353                                         Timestamp:             1523352601000,
354                                         PreviousBlockId:       &parentHash,
355                                         TransactionsRoot:      &bc.Hash{V0: 16229071813194843118, V1: 7413717724217377663, V2: 10255217553502780716, V3: 17975900656333257644},
356                                         TransactionStatusHash: &txStatusHash,
357                                 },
358                                 Transactions: []*bc.Tx{
359                                         types.MapTx(&types.TxData{
360                                                 Version:        1,
361                                                 SerializedSize: 1,
362                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
363                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
364                                         }),
365                                         types.MapTx(&types.TxData{
366                                                 Version:        1,
367                                                 SerializedSize: 528,
368                                                 Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
369                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 100000000, cp)},
370                                         }),
371                                         types.MapTx(&types.TxData{
372                                                 Version:        1,
373                                                 SerializedSize: 528,
374                                                 Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
375                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 200000000, cp)},
376                                         }),
377                                 },
378                         },
379                         parent: parent,
380                         err:    ErrGasCalculate,
381                 },
382                 {
383                         desc: "validate block with the total transations used gas is over than the limit",
384                         block: &bc.Block{
385                                 ID: bc.Hash{V0: 1},
386                                 BlockHeader: &bc.BlockHeader{
387                                         Version:               1,
388                                         Height:                1,
389                                         Timestamp:             1523352601000,
390                                         PreviousBlockId:       &parentHash,
391                                         TransactionsRoot:      &bc.Hash{V0: 11799591616144015196, V1: 10485585098288308103, V2: 9819002243760462505, V3: 10203115105872271656},
392                                         TransactionStatusHash: &txStatusHash,
393                                 },
394                                 Transactions: txs,
395                         },
396                         parent: parent,
397                         err:    errOverBlockLimit,
398                 },
399                 {
400                         desc: "The calculated transaction merkel root hash is not equals to the hash of the block header",
401                         block: &bc.Block{
402                                 ID: bc.Hash{V0: 1},
403                                 BlockHeader: &bc.BlockHeader{
404                                         Version:          1,
405                                         Height:           1,
406                                         Timestamp:        1523352601000,
407                                         PreviousBlockId:  &parentHash,
408                                         TransactionsRoot: &bc.Hash{V0: 1},
409                                 },
410                                 Transactions: []*bc.Tx{
411                                         types.MapTx(&types.TxData{
412                                                 Version:        1,
413                                                 SerializedSize: 1,
414                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
415                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
416                                         }),
417                                 },
418                         },
419                         parent: parent,
420                         err:    errMismatchedMerkleRoot,
421                 },
422                 {
423                         desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header",
424                         block: &bc.Block{
425                                 ID: bc.Hash{V0: 1},
426                                 BlockHeader: &bc.BlockHeader{
427                                         Version:               1,
428                                         Height:                1,
429                                         Timestamp:             1523352601000,
430                                         PreviousBlockId:       &parentHash,
431                                         TransactionsRoot:      &bc.Hash{V0: 6294987741126419124, V1: 12520373106916389157, V2: 5040806596198303681, V3: 1151748423853876189},
432                                         TransactionStatusHash: &bc.Hash{V0: 1},
433                                 },
434                                 Transactions: []*bc.Tx{
435                                         types.MapTx(&types.TxData{
436                                                 Version:        1,
437                                                 SerializedSize: 1,
438                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
439                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
440                                         }),
441                                 },
442                         },
443                         parent: parent,
444                         err:    errMismatchedMerkleRoot,
445                 },
446                 {
447                         desc: "the coinbase amount is not equal to the real coinbase outputs",
448                         block: &bc.Block{
449                                 ID: bc.Hash{V0: 1},
450                                 BlockHeader: &bc.BlockHeader{
451                                         Version:               1,
452                                         Height:                1,
453                                         Timestamp:             1523352601000,
454                                         PreviousBlockId:       &parentHash,
455                                         TransactionsRoot:      &txsRoot,
456                                         TransactionStatusHash: &txStatusHash,
457                                 },
458                                 Transactions: []*bc.Tx{
459                                         types.MapTx(&types.TxData{
460                                                 Version:        1,
461                                                 SerializedSize: 1,
462                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
463                                                 Outputs: []*types.TxOutput{
464                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
465                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
466                                                 },
467                                         }),
468                                 },
469                         },
470                         parent: parent,
471                         rewards: []state.CoinbaseReward{
472                                 state.CoinbaseReward{
473                                         Amount:         20000,
474                                         ControlProgram: []byte{0x51},
475                                 },
476                                 state.CoinbaseReward{
477                                         Amount:         10000,
478                                         ControlProgram: []byte{0x52},
479                                 },
480                         },
481                         err: ErrWrongCoinbaseTransaction,
482                 },
483                 {
484                         desc: "the coinbase program is not equal to the real coinbase outputs",
485                         block: &bc.Block{
486                                 ID: bc.Hash{V0: 1},
487                                 BlockHeader: &bc.BlockHeader{
488                                         Version:               1,
489                                         Height:                1,
490                                         Timestamp:             1523352601000,
491                                         PreviousBlockId:       &parentHash,
492                                         TransactionsRoot:      &txsRoot,
493                                         TransactionStatusHash: &txStatusHash,
494                                 },
495                                 Transactions: []*bc.Tx{
496                                         types.MapTx(&types.TxData{
497                                                 Version:        1,
498                                                 SerializedSize: 1,
499                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
500                                                 Outputs: []*types.TxOutput{
501                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
502                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
503                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x61}),
504                                                 },
505                                         }),
506                                 },
507                         },
508                         parent: parent,
509                         rewards: []state.CoinbaseReward{
510                                 state.CoinbaseReward{
511                                         Amount:         20000,
512                                         ControlProgram: []byte{0x51},
513                                 },
514                                 state.CoinbaseReward{
515                                         Amount:         10000,
516                                         ControlProgram: []byte{0x52},
517                                 },
518                         },
519                         err: ErrWrongCoinbaseTransaction,
520                 },
521                 {
522                         desc: "the coinbase amount is equal to the real coinbase amount",
523                         block: &bc.Block{
524                                 ID: bc.Hash{V0: 1},
525                                 BlockHeader: &bc.BlockHeader{
526                                         Version:               1,
527                                         Height:                1,
528                                         Timestamp:             1523352601000,
529                                         PreviousBlockId:       &parentHash,
530                                         TransactionsRoot:      &bc.Hash{V0: 16229071813194843118, V1: 7413717724217377663, V2: 10255217553502780716, V3: 17975900656333257644},
531                                         TransactionStatusHash: &txStatusHash,
532                                 },
533                                 Transactions: []*bc.Tx{
534                                         types.MapTx(&types.TxData{
535                                                 Version:        1,
536                                                 SerializedSize: 1,
537                                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
538                                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
539                                         }),
540                                         types.MapTx(&types.TxData{
541                                                 Version:        1,
542                                                 SerializedSize: 1,
543                                                 Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
544                                                 Outputs: []*types.TxOutput{
545                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
546                                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 100000000, cp),
547                                                 },
548                                         }),
549                                 },
550                         },
551                         parent: parent,
552                         err:    nil,
553                 },
554         }
555
556         for i, c := range cases {
557                 err := ValidateBlock(c.block, c.parent, c.rewards)
558                 if rootErr(err) != c.err {
559                         t.Errorf("case #%d (%s) got error %s, want %s", i, c.desc, err, c.err)
560                 }
561         }
562 }
563
564 // TestSetTransactionStatus verify the transaction status is set correctly (blocktest#1010)
565 func TestSetTransactionStatus(t *testing.T) {
566         cp, _ := vmutil.DefaultCoinbaseProgram()
567         parent := &types.BlockHeader{
568                 Version:           1,
569                 Height:            0,
570                 Timestamp:         1523352600000,
571                 PreviousBlockHash: bc.Hash{V0: 0},
572         }
573         parentHash := parent.Hash()
574
575         block := &bc.Block{
576                 ID: bc.Hash{V0: 1},
577                 BlockHeader: &bc.BlockHeader{
578                         Version:               1,
579                         Height:                1,
580                         Timestamp:             1523352601000,
581                         PreviousBlockId:       &parentHash,
582                         TransactionsRoot:      &bc.Hash{V0: 8176741810667217458, V1: 14830712230021600370, V2: 8921661778795432162, V3: 3391855546006364086},
583                         TransactionStatusHash: &bc.Hash{V0: 8682965660674182538, V1: 8424137560837623409, V2: 6979974817894224946, V3: 4673809519342015041},
584                 },
585                 Transactions: []*bc.Tx{
586                         types.MapTx(&types.TxData{
587                                 Version:        1,
588                                 SerializedSize: 1,
589                                 Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
590                                 Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
591                         }),
592                         types.MapTx(&types.TxData{
593                                 Version:        1,
594                                 SerializedSize: 1,
595                                 Inputs: []*types.TxInput{
596                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
597                                         types.NewSpendInput([][]byte{}, *newHash(8), bc.AssetID{V0: 1}, 1000, 0, []byte{byte(vm.OP_FALSE)}),
598                                 },
599                                 Outputs: []*types.TxOutput{
600                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
601                                         types.NewIntraChainOutput(bc.AssetID{V0: 1}, 1000, cp),
602                                 },
603                         }),
604                         types.MapTx(&types.TxData{
605                                 Version:        1,
606                                 SerializedSize: 1,
607                                 Inputs: []*types.TxInput{
608                                         types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
609                                 },
610                                 Outputs: []*types.TxOutput{
611                                         types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
612                                 },
613                         }),
614                 },
615         }
616
617         if err := ValidateBlock(block, parent, []state.CoinbaseReward{}); err != nil {
618                 t.Fatal(err)
619         }
620
621         expectTxStatuses := []bool{false, true, false}
622         txStatuses := block.GetTransactionStatus().VerifyStatus
623         if len(expectTxStatuses) != len(txStatuses) {
624                 t.Error("the size of expect tx status is not equals to size of got tx status")
625         }
626
627         for i, status := range txStatuses {
628                 if expectTxStatuses[i] != status.StatusFail {
629                         t.Errorf("got tx status: %v, expect tx status: %v\n", status.StatusFail, expectTxStatuses[i])
630                 }
631         }
632 }