OSDN Git Service

validateBlock unit test (#346)
[bytom/vapor.git] / protocol / validation / block_test.go
index d82f119..63de516 100644 (file)
@@ -6,7 +6,6 @@ import (
        "time"
 
        "github.com/vapor/consensus"
-       "github.com/vapor/mining/tensority"
        "github.com/vapor/protocol/bc"
        "github.com/vapor/protocol/bc/types"
        "github.com/vapor/protocol/state"
@@ -23,31 +22,31 @@ func TestCheckBlockTime(t *testing.T) {
                err        error
        }{
                {
-                       blockTime:  1520000001,
+                       blockTime:  1520000500,
                        parentTime: []uint64{1520000000},
                        err:        nil,
                },
                {
-                       desc:       "timestamp less than past median time (blocktest#1005)",
-                       blockTime:  1510000094,
-                       parentTime: []uint64{1520000000, 1510000099, 1510000098, 1510000097, 1510000096, 1510000095, 1510000094, 1510000093, 1510000092, 1510000091, 1510000090},
-                       err:        errBadTimestamp,
+                       desc:       "timestamp less than past median time",
+                       blockTime:  1520005500,
+                       parentTime: []uint64{1520000000, 1520000500, 1520001000, 1520001500, 1520002000, 1520002500, 1520003000, 1520003500, 1520004000, 1520004500, 1520005000},
+                       err:        nil,
                },
                {
-                       desc:       "timestamp greater than max limit (blocktest#1006)",
-                       blockTime:  9999999999,
-                       parentTime: []uint64{1520000000},
+                       desc:       "timestamp greater than max limit",
+                       blockTime:  99999999990000,
+                       parentTime: []uint64{15200000000000},
                        err:        errBadTimestamp,
                },
                {
-                       desc:       "timestamp of the block and the parent block are both greater than max limit (blocktest#1007)",
-                       blockTime:  uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 2,
-                       parentTime: []uint64{uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 1},
+                       desc:       "timestamp of the block and the parent block are both greater than max limit",
+                       blockTime:  uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 2000,
+                       parentTime: []uint64{uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 1000},
                        err:        errBadTimestamp,
                },
        }
 
-       parent := &state.BlockNode{Version: 1}
+       parent := &types.BlockHeader{Version: 1}
        block := &bc.Block{
                BlockHeader: &bc.BlockHeader{Version: 1},
        }
@@ -56,8 +55,9 @@ func TestCheckBlockTime(t *testing.T) {
                parent.Timestamp = c.parentTime[0]
                parentSuccessor := parent
                for i := 1; i < len(c.parentTime); i++ {
-                       parentSuccessor.Parent = &state.BlockNode{Version: 1, Timestamp: c.parentTime[i]}
-                       parentSuccessor = parentSuccessor.Parent
+                       Previous := &types.BlockHeader{Version: 1, Timestamp: c.parentTime[i]}
+                       parentSuccessor.PreviousBlockHash = Previous.Hash()
+                       parentSuccessor = Previous
                }
 
                block.Timestamp = c.blockTime
@@ -67,183 +67,232 @@ func TestCheckBlockTime(t *testing.T) {
        }
 }
 
-func TestCheckCoinbaseAmount(t *testing.T) {
+func TestCheckCoinbaseTx(t *testing.T) {
        cases := []struct {
-               txs    []*types.Tx
-               amount uint64
-               err    error
+               desc    string
+               txs     []*types.Tx
+               rewards []state.CoinbaseReward
+               err     error
        }{
                {
+                       desc: "zero coinbase amount",
                        txs: []*types.Tx{
                                types.NewTx(types.TxData{
                                        Inputs:  []*types.TxInput{types.NewCoinbaseInput(nil)},
-                                       Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
+                                       Outputs: []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51})},
                                }),
                        },
-                       amount: 5000,
-                       err:    nil,
+                       rewards: []state.CoinbaseReward{},
+                       err:     nil,
                },
                {
+                       desc: "zero coinbase amount and aggregate rewards",
                        txs: []*types.Tx{
                                types.NewTx(types.TxData{
-                                       Inputs:  []*types.TxInput{types.NewCoinbaseInput(nil)},
-                                       Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
+                                       Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                       Outputs: []*types.TxOutput{
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
+                                       },
+                               }),
+                       },
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x52},
+                               },
+                       },
+                       err: nil,
+               },
+               {
+                       desc:    "wrong coinbase transaction with block is empty",
+                       txs:     []*types.Tx{},
+                       rewards: []state.CoinbaseReward{},
+                       err:     ErrWrongCoinbaseTransaction,
+               },
+               {
+                       desc: "wrong coinbase transaction with dismatch number of outputs",
+                       txs: []*types.Tx{
+                               types.NewTx(types.TxData{
+                                       Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                       Outputs: []*types.TxOutput{
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
+                                       },
+                               }),
+                       },
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                       },
+                       err: ErrWrongCoinbaseTransaction,
+               },
+               {
+                       desc: "wrong coinbase transaction with dismatch output amount",
+                       txs: []*types.Tx{
+                               types.NewTx(types.TxData{
+                                       Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                       Outputs: []*types.TxOutput{
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
+                                       },
                                }),
                        },
-                       amount: 6000,
-                       err:    ErrWrongCoinbaseTransaction,
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x52},
+                               },
+                       },
+                       err: ErrWrongCoinbaseTransaction,
                },
                {
-                       txs:    []*types.Tx{},
-                       amount: 5000,
-                       err:    ErrWrongCoinbaseTransaction,
+                       desc: "wrong coinbase transaction with dismatch output control_program",
+                       txs: []*types.Tx{
+                               types.NewTx(types.TxData{
+                                       Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                       Outputs: []*types.TxOutput{
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 0, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                               types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x52}),
+                                       },
+                               }),
+                       },
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x53},
+                               },
+                       },
+                       err: ErrWrongCoinbaseTransaction,
                },
        }
 
        block := new(types.Block)
        for i, c := range cases {
                block.Transactions = c.txs
-               if err := checkCoinbaseAmount(types.MapBlock(block), c.amount); rootErr(err) != c.err {
-                       t.Errorf("case %d got error %s, want %s", i, err, c.err)
+               if err := checkCoinbaseTx(types.MapBlock(block), c.rewards); rootErr(err) != c.err {
+                       t.Errorf("case %d got error %s, want %T", i, err, c.err)
                }
        }
 }
 
 func TestValidateBlockHeader(t *testing.T) {
-       iniTtensority()
+       parent := &types.BlockHeader{
+               Version:   1,
+               Height:    0,
+               Timestamp: 1523352600000,
+       }
+       parentHash := parent.Hash()
 
        cases := []struct {
                desc   string
                block  *bc.Block
-               parent *state.BlockNode
+               parent *types.BlockHeader
                err    error
        }{
                {
+                       desc: "dismatch version",
                        block: &bc.Block{BlockHeader: &bc.BlockHeader{
                                Version: 2,
                        }},
-                       parent: &state.BlockNode{
+                       parent: &types.BlockHeader{
                                Version: 1,
                        },
                        err: errVersionRegression,
                },
                {
+                       desc: "misordered block height",
                        block: &bc.Block{BlockHeader: &bc.BlockHeader{
                                Version: 1,
                                Height:  20,
                        }},
-                       parent: &state.BlockNode{
+                       parent: &types.BlockHeader{
                                Version: 1,
                                Height:  18,
                        },
                        err: errMisorderedBlockHeight,
                },
                {
-                       desc: "the difficulty of the block is not equals to the next difficulty of parent block (blocktest#1008)",
-                       block: &bc.Block{BlockHeader: &bc.BlockHeader{
-                               Version: 1,
-                               Height:  20,
-                               Bits:    0,
-                       }},
-                       parent: &state.BlockNode{
-                               Version: 1,
-                               Height:  19,
-                               Bits:    2305843009214532812,
-                       },
-                       err: errBadBits,
-               },
-               {
-                       desc: "the prev block hash not equals to the hash of parent (blocktest#1004)",
+                       desc: "the prev block hash not equals to the hash of parent",
                        block: &bc.Block{BlockHeader: &bc.BlockHeader{
                                Version:         1,
                                Height:          20,
-                               PreviousBlockId: &bc.Hash{V0: 18},
+                               PreviousBlockId: &bc.Hash{V0: 20},
                        }},
-                       parent: &state.BlockNode{
-                               Version: 1,
-                               Height:  19,
-                               Hash:    bc.Hash{V0: 19},
+                       parent: &types.BlockHeader{
+                               Version:           1,
+                               Height:            19,
+                               PreviousBlockHash: bc.Hash{V0: 19},
                        },
                        err: errMismatchedBlock,
                },
                {
-                       desc: "check work proof fail (blocktest#1011)",
-                       block: &bc.Block{
-                               ID: bc.Hash{V0: 0},
-                               BlockHeader: &bc.BlockHeader{
-                                       Version:         1,
-                                       Height:          1,
-                                       Timestamp:       1523352601,
-                                       PreviousBlockId: &bc.Hash{V0: 0},
-                                       Bits:            2305843009214532812,
-                               },
-                       },
-                       parent: &state.BlockNode{
-                               Version:   1,
-                               Height:    0,
-                               Timestamp: 1523352600,
-                               Hash:      bc.Hash{V0: 0},
-                               Seed:      &bc.Hash{V1: 1},
-                               Bits:      2305843009214532812,
-                       },
-                       err: errWorkProof,
-               },
-               {
+                       desc: "normal block",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version:         1,
                                        Height:          1,
-                                       Timestamp:       1523352601,
-                                       PreviousBlockId: &bc.Hash{V0: 0},
-                                       Bits:            2305843009214532812,
+                                       Timestamp:       1523352601000,
+                                       PreviousBlockId: &parentHash,
                                },
                        },
-                       parent: &state.BlockNode{
-                               Version:   1,
-                               Height:    0,
-                               Timestamp: 1523352600,
-                               Hash:      bc.Hash{V0: 0},
-                               Seed:      &bc.Hash{V1: 1},
-                               Bits:      2305843009214532812,
-                       },
-                       err: nil,
+                       parent: parent,
+                       err:    nil,
                },
                {
-                       desc: "version greater than 1 (blocktest#1001)",
+                       desc: "version greater than 1",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version: 2,
                                },
                        },
-                       parent: &state.BlockNode{
+                       parent: &types.BlockHeader{
                                Version: 1,
                        },
                        err: errVersionRegression,
                },
                {
-                       desc: "version equals 0 (blocktest#1002)",
+                       desc: "version equals 0",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version: 0,
                                },
                        },
-                       parent: &state.BlockNode{
+                       parent: &types.BlockHeader{
                                Version: 1,
                        },
                        err: errVersionRegression,
                },
                {
-                       desc: "version equals max uint64 (blocktest#1003)",
+                       desc: "version equals max uint64",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version: math.MaxUint64,
                                },
                        },
-                       parent: &state.BlockNode{
+                       parent: &types.BlockHeader{
                                Version: 1,
                        },
                        err: errVersionRegression,
@@ -257,27 +306,105 @@ func TestValidateBlockHeader(t *testing.T) {
        }
 }
 
-// TestValidateBlock test the ValidateBlock function
 func TestValidateBlock(t *testing.T) {
-       iniTtensority()
-
        cp, _ := vmutil.DefaultCoinbaseProgram()
+       parent := &types.BlockHeader{
+               Version:           1,
+               Height:            0,
+               Timestamp:         1523352600000,
+               PreviousBlockHash: bc.Hash{V0: 0},
+       }
+       parentHash := parent.Hash()
+       txsRoot := testutil.MustDecodeHash("001e21b9618c503d909c1e0b32bab9ccf80c538b35d49ac7fffcef98eb373b23")
+       txStatusHash := testutil.MustDecodeHash("6978a65b4ee5b6f4914fe5c05000459a803ecf59132604e5d334d64249c5e50a")
+
+       txs := []*bc.Tx{
+               types.MapTx(&types.TxData{
+                       Version:        1,
+                       SerializedSize: 1,
+                       Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
+                       Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
+               }),
+       }
+
+       for i := 1; i <= 100; i++ {
+               txs = append(txs, types.MapTx(&types.TxData{
+                       Version:        1,
+                       SerializedSize: 100000,
+                       Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, bc.Hash{V0: uint64(i)}, *consensus.BTMAssetID, 10000000000, 0, cp)},
+                       Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 9000000000, cp)},
+               }))
+       }
+
        cases := []struct {
-               desc   string
-               block  *bc.Block
-               parent *state.BlockNode
-               err    error
+               desc    string
+               block   *bc.Block
+               parent  *types.BlockHeader
+               rewards []state.CoinbaseReward
+               err     error
        }{
                {
-                       desc: "The calculated transaction merkel root hash is not equals to the hash of the block header (blocktest#1009)",
+                       desc: "validate transactions with output amount great than input amount",
+                       block: &bc.Block{
+                               ID: bc.Hash{V0: 1},
+                               BlockHeader: &bc.BlockHeader{
+                                       Version:               1,
+                                       Height:                1,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
+                                       TransactionsRoot:      &bc.Hash{V0: 16229071813194843118, V1: 7413717724217377663, V2: 10255217553502780716, V3: 17975900656333257644},
+                                       TransactionStatusHash: &txStatusHash,
+                               },
+                               Transactions: []*bc.Tx{
+                                       types.MapTx(&types.TxData{
+                                               Version:        1,
+                                               SerializedSize: 1,
+                                               Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
+                                       }),
+                                       types.MapTx(&types.TxData{
+                                               Version:        1,
+                                               SerializedSize: 528,
+                                               Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 100000000, cp)},
+                                       }),
+                                       types.MapTx(&types.TxData{
+                                               Version:        1,
+                                               SerializedSize: 528,
+                                               Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 200000000, cp)},
+                                       }),
+                               },
+                       },
+                       parent: parent,
+                       err:    ErrGasCalculate,
+               },
+               {
+                       desc: "validate block with the total transations used gas is over than the limit",
+                       block: &bc.Block{
+                               ID: bc.Hash{V0: 1},
+                               BlockHeader: &bc.BlockHeader{
+                                       Version:               1,
+                                       Height:                1,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
+                                       TransactionsRoot:      &bc.Hash{V0: 11799591616144015196, V1: 10485585098288308103, V2: 9819002243760462505, V3: 10203115105872271656},
+                                       TransactionStatusHash: &txStatusHash,
+                               },
+                               Transactions: txs,
+                       },
+                       parent: parent,
+                       err:    errOverBlockLimit,
+               },
+               {
+                       desc: "The calculated transaction merkel root hash is not equals to the hash of the block header",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version:          1,
                                        Height:           1,
-                                       Timestamp:        1523352601,
-                                       PreviousBlockId:  &bc.Hash{V0: 0},
-                                       Bits:             2305843009214532812,
+                                       Timestamp:        1523352601000,
+                                       PreviousBlockId:  &parentHash,
                                        TransactionsRoot: &bc.Hash{V0: 1},
                                },
                                Transactions: []*bc.Tx{
@@ -285,30 +412,22 @@ func TestValidateBlock(t *testing.T) {
                                                Version:        1,
                                                SerializedSize: 1,
                                                Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
-                                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
                                        }),
                                },
                        },
-                       parent: &state.BlockNode{
-                               Version:   1,
-                               Height:    0,
-                               Timestamp: 1523352600,
-                               Hash:      bc.Hash{V0: 0},
-                               Seed:      &bc.Hash{V1: 1},
-                               Bits:      2305843009214532812,
-                       },
-                       err: errMismatchedMerkleRoot,
+                       parent: parent,
+                       err:    errMismatchedMerkleRoot,
                },
                {
-                       desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header (blocktest#1009)",
+                       desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
                                        Version:               1,
                                        Height:                1,
-                                       Timestamp:             1523352601,
-                                       PreviousBlockId:       &bc.Hash{V0: 0},
-                                       Bits:                  2305843009214532812,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
                                        TransactionsRoot:      &bc.Hash{V0: 6294987741126419124, V1: 12520373106916389157, V2: 5040806596198303681, V3: 1151748423853876189},
                                        TransactionStatusHash: &bc.Hash{V0: 1},
                                },
@@ -317,139 +436,150 @@ func TestValidateBlock(t *testing.T) {
                                                Version:        1,
                                                SerializedSize: 1,
                                                Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
-                                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
                                        }),
                                },
                        },
-                       parent: &state.BlockNode{
-                               Version:   1,
-                               Height:    0,
-                               Timestamp: 1523352600,
-                               Hash:      bc.Hash{V0: 0},
-                               Seed:      &bc.Hash{V1: 1},
-                               Bits:      2305843009214532812,
-                       },
-                       err: errMismatchedMerkleRoot,
+                       parent: parent,
+                       err:    errMismatchedMerkleRoot,
                },
                {
-                       desc: "the coinbase amount is less than the real coinbase amount (txtest#1014)",
+                       desc: "the coinbase amount is not equal to the real coinbase outputs",
                        block: &bc.Block{
                                ID: bc.Hash{V0: 1},
                                BlockHeader: &bc.BlockHeader{
-                                       Version:         1,
-                                       Height:          1,
-                                       Timestamp:       1523352601,
-                                       PreviousBlockId: &bc.Hash{V0: 0},
-                                       Bits:            2305843009214532812,
+                                       Version:               1,
+                                       Height:                1,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
+                                       TransactionsRoot:      &txsRoot,
+                                       TransactionStatusHash: &txStatusHash,
                                },
                                Transactions: []*bc.Tx{
                                        types.MapTx(&types.TxData{
                                                Version:        1,
                                                SerializedSize: 1,
                                                Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
-                                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
+                                               Outputs: []*types.TxOutput{
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                               },
                                        }),
+                               },
+                       },
+                       parent: parent,
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x52},
+                               },
+                       },
+                       err: ErrWrongCoinbaseTransaction,
+               },
+               {
+                       desc: "the coinbase program is not equal to the real coinbase outputs",
+                       block: &bc.Block{
+                               ID: bc.Hash{V0: 1},
+                               BlockHeader: &bc.BlockHeader{
+                                       Version:               1,
+                                       Height:                1,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
+                                       TransactionsRoot:      &txsRoot,
+                                       TransactionStatusHash: &txStatusHash,
+                               },
+                               Transactions: []*bc.Tx{
                                        types.MapTx(&types.TxData{
                                                Version:        1,
                                                SerializedSize: 1,
-                                               Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
-                                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp)},
+                                               Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                               Outputs: []*types.TxOutput{
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 20000, []byte{0x51}),
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 10000, []byte{0x61}),
+                                               },
                                        }),
                                },
                        },
-                       parent: &state.BlockNode{
-                               Version:   1,
-                               Height:    0,
-                               Timestamp: 1523352600,
-                               Hash:      bc.Hash{V0: 0},
-                               Seed:      &bc.Hash{V1: 1},
-                               Bits:      2305843009214532812,
+                       parent: parent,
+                       rewards: []state.CoinbaseReward{
+                               state.CoinbaseReward{
+                                       Amount:         20000,
+                                       ControlProgram: []byte{0x51},
+                               },
+                               state.CoinbaseReward{
+                                       Amount:         10000,
+                                       ControlProgram: []byte{0x52},
+                               },
                        },
                        err: ErrWrongCoinbaseTransaction,
                },
+               {
+                       desc: "the coinbase amount is equal to the real coinbase amount",
+                       block: &bc.Block{
+                               ID: bc.Hash{V0: 1},
+                               BlockHeader: &bc.BlockHeader{
+                                       Version:               1,
+                                       Height:                1,
+                                       Timestamp:             1523352601000,
+                                       PreviousBlockId:       &parentHash,
+                                       TransactionsRoot:      &bc.Hash{V0: 16229071813194843118, V1: 7413717724217377663, V2: 10255217553502780716, V3: 17975900656333257644},
+                                       TransactionStatusHash: &txStatusHash,
+                               },
+                               Transactions: []*bc.Tx{
+                                       types.MapTx(&types.TxData{
+                                               Version:        1,
+                                               SerializedSize: 1,
+                                               Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
+                                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
+                                       }),
+                                       types.MapTx(&types.TxData{
+                                               Version:        1,
+                                               SerializedSize: 1,
+                                               Inputs:         []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
+                                               Outputs: []*types.TxOutput{
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp),
+                                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 100000000, cp),
+                                               },
+                                       }),
+                               },
+                       },
+                       parent: parent,
+                       err:    nil,
+               },
        }
 
        for i, c := range cases {
-               err := ValidateBlock(c.block, c.parent)
+               err := ValidateBlock(c.block, c.parent, c.rewards)
                if rootErr(err) != c.err {
                        t.Errorf("case #%d (%s) got error %s, want %s", i, c.desc, err, c.err)
                }
        }
 }
 
-// TestGasOverBlockLimit check if the gas of the block has the max limit (blocktest#1012)
-func TestGasOverBlockLimit(t *testing.T) {
-       iniTtensority()
-
-       cp, _ := vmutil.DefaultCoinbaseProgram()
-       parent := &state.BlockNode{
-               Version:   1,
-               Height:    0,
-               Timestamp: 1523352600,
-               Hash:      bc.Hash{V0: 0},
-               Seed:      &bc.Hash{V1: 1},
-               Bits:      2305843009214532812,
-       }
-       block := &bc.Block{
-               ID: bc.Hash{V0: 1},
-               BlockHeader: &bc.BlockHeader{
-                       Version:          1,
-                       Height:           1,
-                       Timestamp:        1523352601,
-                       PreviousBlockId:  &bc.Hash{V0: 0},
-                       Bits:             2305843009214532812,
-                       TransactionsRoot: &bc.Hash{V0: 1},
-               },
-               Transactions: []*bc.Tx{
-                       types.MapTx(&types.TxData{
-                               Version:        1,
-                               SerializedSize: 1,
-                               Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
-                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
-                       }),
-               },
-       }
-
-       for i := 0; i < 100; i++ {
-               block.Transactions = append(block.Transactions, types.MapTx(&types.TxData{
-                       Version:        1,
-                       SerializedSize: 100000,
-                       Inputs: []*types.TxInput{
-                               types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 10000000000, 0, cp),
-                       },
-                       Outputs: []*types.TxOutput{
-                               types.NewTxOutput(*consensus.BTMAssetID, 9000000000, cp),
-                       },
-               }))
-       }
-
-       if err := ValidateBlock(block, parent); err != errOverBlockLimit {
-               t.Errorf("got error %s, want %s", err, errOverBlockLimit)
-       }
-}
-
 // TestSetTransactionStatus verify the transaction status is set correctly (blocktest#1010)
 func TestSetTransactionStatus(t *testing.T) {
-       iniTtensority()
-
        cp, _ := vmutil.DefaultCoinbaseProgram()
-       parent := &state.BlockNode{
-               Version:   1,
-               Height:    0,
-               Timestamp: 1523352600,
-               Hash:      bc.Hash{V0: 0},
-               Seed:      &bc.Hash{V1: 1},
-               Bits:      2305843009214532812,
+       parent := &types.BlockHeader{
+               Version:           1,
+               Height:            0,
+               Timestamp:         1523352600000,
+               PreviousBlockHash: bc.Hash{V0: 0},
        }
+       parentHash := parent.Hash()
+
        block := &bc.Block{
                ID: bc.Hash{V0: 1},
                BlockHeader: &bc.BlockHeader{
                        Version:               1,
                        Height:                1,
-                       Timestamp:             1523352601,
-                       PreviousBlockId:       &bc.Hash{V0: 0},
-                       Bits:                  2305843009214532812,
-                       TransactionsRoot:      &bc.Hash{V0: 3413931728524254295, V1: 300490676707850231, V2: 1886132055969225110, V3: 10216139531293906088},
+                       Timestamp:             1523352601000,
+                       PreviousBlockId:       &parentHash,
+                       TransactionsRoot:      &bc.Hash{V0: 8176741810667217458, V1: 14830712230021600370, V2: 8921661778795432162, V3: 3391855546006364086},
                        TransactionStatusHash: &bc.Hash{V0: 8682965660674182538, V1: 8424137560837623409, V2: 6979974817894224946, V3: 4673809519342015041},
                },
                Transactions: []*bc.Tx{
@@ -457,7 +587,7 @@ func TestSetTransactionStatus(t *testing.T) {
                                Version:        1,
                                SerializedSize: 1,
                                Inputs:         []*types.TxInput{types.NewCoinbaseInput(nil)},
-                               Outputs:        []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41449998224, cp)},
+                               Outputs:        []*types.TxOutput{types.NewIntraChainOutput(*consensus.BTMAssetID, 0, cp)},
                        }),
                        types.MapTx(&types.TxData{
                                Version:        1,
@@ -467,8 +597,8 @@ func TestSetTransactionStatus(t *testing.T) {
                                        types.NewSpendInput([][]byte{}, *newHash(8), bc.AssetID{V0: 1}, 1000, 0, []byte{byte(vm.OP_FALSE)}),
                                },
                                Outputs: []*types.TxOutput{
-                                       types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
-                                       types.NewTxOutput(bc.AssetID{V0: 1}, 1000, cp),
+                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
+                                       types.NewIntraChainOutput(bc.AssetID{V0: 1}, 1000, cp),
                                },
                        }),
                        types.MapTx(&types.TxData{
@@ -478,13 +608,13 @@ func TestSetTransactionStatus(t *testing.T) {
                                        types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
                                },
                                Outputs: []*types.TxOutput{
-                                       types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
+                                       types.NewIntraChainOutput(*consensus.BTMAssetID, 888, cp),
                                },
                        }),
                },
        }
 
-       if err := ValidateBlock(block, parent); err != nil {
+       if err := ValidateBlock(block, parent, []state.CoinbaseReward{}); err != nil {
                t.Fatal(err)
        }
 
@@ -500,11 +630,3 @@ func TestSetTransactionStatus(t *testing.T) {
                }
        }
 }
-
-func iniTtensority() {
-       // add (hash, seed) --> (tensority hash) to the  tensority cache for avoid
-       // real matrix calculate cost.
-       tensority.AIHash.AddCache(&bc.Hash{V0: 0}, &bc.Hash{}, testutil.MaxHash)
-       tensority.AIHash.AddCache(&bc.Hash{V0: 1}, &bc.Hash{}, testutil.MinHash)
-       tensority.AIHash.AddCache(&bc.Hash{V0: 1}, consensus.InitialSeed, testutil.MinHash)
-}