github.com/bytom/bytom@v1.1.2-0.20221014091027-bbcba3df6075/protocol/validation/block_test.go (about)

     1  package validation
     2  
     3  import (
     4  	"encoding/hex"
     5  	"math"
     6  	"testing"
     7  	"time"
     8  
     9  	"github.com/bytom/bytom/consensus"
    10  	"github.com/bytom/bytom/protocol/bc"
    11  	"github.com/bytom/bytom/protocol/bc/types"
    12  	"github.com/bytom/bytom/protocol/state"
    13  )
    14  
    15  func TestCheckBlockTime(t *testing.T) {
    16  	cases := []struct {
    17  		desc       string
    18  		blockTime  uint64
    19  		parentTime []uint64
    20  		err        error
    21  	}{
    22  		{
    23  			blockTime:  1520006000,
    24  			parentTime: []uint64{1520000000},
    25  			err:        nil,
    26  		},
    27  		{
    28  			desc:       "timestamp less than past median time",
    29  			blockTime:  1520006000,
    30  			parentTime: []uint64{1520000000, 1520000500, 1520001000, 1520001500, 1520002000, 1520002500, 1520003000, 1520003500, 1520004000, 1520004500, 1520005000},
    31  			err:        nil,
    32  		},
    33  		{
    34  			desc:       "timestamp greater than max limit",
    35  			blockTime:  99999999990000,
    36  			parentTime: []uint64{15200000000000},
    37  			err:        errBadTimestamp,
    38  		},
    39  		{
    40  			desc:       "timestamp of the block and the parent block are both greater than max limit",
    41  			blockTime:  uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 2000,
    42  			parentTime: []uint64{uint64(time.Now().UnixNano()/int64(time.Millisecond)) + consensus.ActiveNetParams.MaxTimeOffsetMs + 1000},
    43  			err:        errBadTimestamp,
    44  		},
    45  	}
    46  
    47  	parent := &types.BlockHeader{Version: 1}
    48  	block := &types.BlockHeader{Version: 1}
    49  	for i, c := range cases {
    50  		parent.Timestamp = c.parentTime[0]
    51  		parentSuccessor := parent
    52  		for i := 1; i < len(c.parentTime); i++ {
    53  			Previous := &types.BlockHeader{Version: 1, Timestamp: c.parentTime[i]}
    54  			parentSuccessor.PreviousBlockHash = Previous.Hash()
    55  			parentSuccessor = Previous
    56  		}
    57  
    58  		block.Timestamp = c.blockTime
    59  		if err := checkBlockTime(block, parent); rootErr(err) != c.err {
    60  			t.Errorf("case %d got error %s, want %s", i, err, c.err)
    61  		}
    62  	}
    63  }
    64  
    65  func TestCheckCoinbaseAmount(t *testing.T) {
    66  	cases := []struct {
    67  		block      *types.Block
    68  		checkpoint *state.Checkpoint
    69  		err        error
    70  	}{
    71  		{
    72  			block: &types.Block{
    73  				BlockHeader: types.BlockHeader{Height: 0},
    74  				Transactions: []*types.Tx{
    75  					types.NewTx(types.TxData{
    76  						Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
    77  						Outputs: []*types.TxOutput{
    78  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte("controlProgram"), nil),
    79  						},
    80  					}),
    81  				},
    82  			},
    83  			checkpoint: &state.Checkpoint{
    84  				Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
    85  			},
    86  			err: nil,
    87  		},
    88  		{
    89  			block: &types.Block{
    90  				BlockHeader: types.BlockHeader{Height: consensus.ActiveNetParams.BlocksOfEpoch + 1},
    91  				Transactions: []*types.Tx{
    92  					types.NewTx(types.TxData{
    93  						Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
    94  						Outputs: []*types.TxOutput{
    95  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil),
    96  						},
    97  					}),
    98  				},
    99  			},
   100  			checkpoint: &state.Checkpoint{
   101  				Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
   102  			},
   103  			err: nil,
   104  		},
   105  		{
   106  			block: &types.Block{
   107  				BlockHeader: types.BlockHeader{Height: consensus.ActiveNetParams.BlocksOfEpoch + 1},
   108  				Transactions: []*types.Tx{
   109  					types.NewTx(types.TxData{
   110  						Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
   111  						Outputs: []*types.TxOutput{
   112  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 0, []byte("controlProgramX1"), nil),
   113  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil),
   114  						},
   115  					}),
   116  				},
   117  			},
   118  			checkpoint: &state.Checkpoint{
   119  				Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
   120  			},
   121  			err: nil,
   122  		},
   123  		{
   124  			block: &types.Block{
   125  				BlockHeader: types.BlockHeader{Height: consensus.ActiveNetParams.BlocksOfEpoch + 1},
   126  				Transactions: []*types.Tx{
   127  					types.NewTx(types.TxData{
   128  						Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
   129  						Outputs: []*types.TxOutput{
   130  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 1000, []byte("controlProgram"), nil),
   131  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram"), nil),
   132  						},
   133  					}),
   134  				},
   135  			},
   136  			checkpoint: &state.Checkpoint{
   137  				Rewards: map[string]uint64{hex.EncodeToString([]byte("controlProgram")): 5000},
   138  			},
   139  			err: ErrWrongCoinbaseTransaction,
   140  		},
   141  		{
   142  			block: &types.Block{
   143  				BlockHeader: types.BlockHeader{Height: consensus.ActiveNetParams.BlocksOfEpoch + 1},
   144  				Transactions: []*types.Tx{
   145  					types.NewTx(types.TxData{
   146  						Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
   147  						Outputs: []*types.TxOutput{
   148  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram1"), nil),
   149  							types.NewOriginalTxOutput(*consensus.BTMAssetID, 5000, []byte("controlProgram2"), nil),
   150  						},
   151  					}),
   152  				},
   153  			},
   154  			checkpoint: &state.Checkpoint{
   155  				Rewards: map[string]uint64{
   156  					hex.EncodeToString([]byte("controlProgram1")): 5000,
   157  					hex.EncodeToString([]byte("controlProgram2")): 5000},
   158  			},
   159  			err: nil,
   160  		},
   161  		{
   162  			block: &types.Block{
   163  				BlockHeader:  types.BlockHeader{},
   164  				Transactions: []*types.Tx{},
   165  			},
   166  			checkpoint: &state.Checkpoint{
   167  				Rewards: map[string]uint64{"controlProgram": 5000},
   168  			},
   169  			err: ErrWrongCoinbaseTransaction,
   170  		},
   171  	}
   172  
   173  	for i, c := range cases {
   174  		if err := checkCoinbaseAmount(c.block, c.checkpoint); rootErr(err) != c.err {
   175  			t.Errorf("case %d got error %v, want %v", i, err, c.err)
   176  		}
   177  	}
   178  }
   179  
   180  func TestValidateBlockHeader(t *testing.T) {
   181  	cases := []struct {
   182  		desc   string
   183  		bh     *types.BlockHeader
   184  		parent *types.BlockHeader
   185  		err    error
   186  	}{
   187  		{
   188  			bh: &types.BlockHeader{
   189  				Version: 2,
   190  			},
   191  			parent: &types.BlockHeader{
   192  				Version: 1,
   193  			},
   194  			err: errVersionRegression,
   195  		},
   196  		{
   197  			bh: &types.BlockHeader{
   198  				Version: 1,
   199  				Height:  20,
   200  			},
   201  			parent: &types.BlockHeader{
   202  				Version: 1,
   203  				Height:  18,
   204  			},
   205  			err: errMisorderedBlockHeight,
   206  		},
   207  		{
   208  			desc: "the prev block hash not equals to the hash of parent (blocktest#1004)",
   209  			bh: &types.BlockHeader{
   210  				Version:           1,
   211  				Height:            20,
   212  				Timestamp:         1523358600,
   213  				PreviousBlockHash: bc.Hash{V0: 0},
   214  			},
   215  			parent: &types.BlockHeader{
   216  				Version: 1,
   217  				Height:  19,
   218  			},
   219  			err: errMismatchedBlock,
   220  		},
   221  		{
   222  			desc: "version greater than 1 (blocktest#1001)",
   223  			bh: &types.BlockHeader{
   224  				Version: 2,
   225  			},
   226  			parent: &types.BlockHeader{
   227  				Version: 1,
   228  			},
   229  			err: errVersionRegression,
   230  		},
   231  		{
   232  			desc: "version equals 0 (blocktest#1002)",
   233  			bh: &types.BlockHeader{
   234  				Version: 0,
   235  			},
   236  			parent: &types.BlockHeader{
   237  				Version: 1,
   238  			},
   239  			err: errVersionRegression,
   240  		},
   241  		{
   242  			desc: "version equals max uint64 (blocktest#1003)",
   243  			bh: &types.BlockHeader{
   244  				Version: math.MaxUint64,
   245  			},
   246  			parent: &types.BlockHeader{
   247  				Version: 1,
   248  			},
   249  			err: errVersionRegression,
   250  		},
   251  	}
   252  
   253  	for i, c := range cases {
   254  		if err := ValidateBlockHeader(c.bh, c.parent, nil); rootErr(err) != c.err {
   255  			t.Errorf("case %d (%s) got error %s, want %s", i, c.desc, err, c.err)
   256  		}
   257  	}
   258  }