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 }