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"
16 func TestCheckBlockTime(t *testing.T) {
24 blockTime: 1520000001,
25 parentTime: []uint64{1520000000},
29 desc: "timestamp less than past median time (blocktest#1005)",
30 blockTime: 1510000094,
31 parentTime: []uint64{1520000000, 1510000099, 1510000098, 1510000097, 1510000096, 1510000095, 1510000094, 1510000093, 1510000092, 1510000091, 1510000090},
35 desc: "timestamp greater than max limit (blocktest#1006)",
36 blockTime: 9999999999,
37 parentTime: []uint64{1520000000},
41 desc: "timestamp of the block and the parent block are both greater than max limit (blocktest#1007)",
42 blockTime: uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 2,
43 parentTime: []uint64{uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 1},
48 parent := &state.BlockNode{Version: 1}
50 BlockHeader: &bc.BlockHeader{Version: 1},
53 for i, c := range cases {
54 parent.Timestamp = c.parentTime[0]
55 parentSuccessor := parent
56 for i := 1; i < len(c.parentTime); i++ {
57 parentSuccessor.Parent = &state.BlockNode{Version: 1, Timestamp: c.parentTime[i]}
58 parentSuccessor = parentSuccessor.Parent
61 block.Timestamp = c.blockTime
62 if err := checkBlockTime(block, parent); rootErr(err) != c.err {
63 t.Errorf("case %d got error %s, want %s", i, err, c.err)
68 func TestCheckCoinbaseAmount(t *testing.T) {
76 types.NewTx(types.TxData{
77 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
78 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
86 types.NewTx(types.TxData{
87 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
88 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
92 err: ErrWrongCoinbaseTransaction,
97 err: ErrWrongCoinbaseTransaction,
101 block := new(types.Block)
102 for i, c := range cases {
103 block.Transactions = c.txs
104 if err := checkCoinbaseAmount(types.MapBlock(block), c.amount); rootErr(err) != c.err {
105 t.Errorf("case %d got error %s, want %s", i, err, c.err)
110 func TestValidateBlockHeader(t *testing.T) {
114 parent *state.BlockNode
118 block: &bc.Block{BlockHeader: &bc.BlockHeader{
121 parent: &state.BlockNode{
124 err: errVersionRegression,
127 block: &bc.Block{BlockHeader: &bc.BlockHeader{
131 parent: &state.BlockNode{
135 err: errMisorderedBlockHeight,
138 desc: "the prev block hash not equals to the hash of parent (blocktest#1004)",
139 block: &bc.Block{BlockHeader: &bc.BlockHeader{
142 PreviousBlockId: &bc.Hash{V0: 18},
144 parent: &state.BlockNode{
147 Hash: bc.Hash{V0: 19},
149 err: errMismatchedBlock,
154 BlockHeader: &bc.BlockHeader{
157 Timestamp: 1523352601,
158 PreviousBlockId: &bc.Hash{V0: 0},
161 parent: &state.BlockNode{
164 Timestamp: 1523352600,
165 Hash: bc.Hash{V0: 0},
170 desc: "version greater than 1 (blocktest#1001)",
173 BlockHeader: &bc.BlockHeader{
177 parent: &state.BlockNode{
180 err: errVersionRegression,
183 desc: "version equals 0 (blocktest#1002)",
186 BlockHeader: &bc.BlockHeader{
190 parent: &state.BlockNode{
193 err: errVersionRegression,
196 desc: "version equals max uint64 (blocktest#1003)",
199 BlockHeader: &bc.BlockHeader{
200 Version: math.MaxUint64,
203 parent: &state.BlockNode{
206 err: errVersionRegression,
210 for i, c := range cases {
211 if err := ValidateBlockHeader(c.block, c.parent); rootErr(err) != c.err {
212 t.Errorf("case %d (%s) got error %s, want %s", i, c.desc, err, c.err)
217 // TestValidateBlock test the ValidateBlock function
218 func TestValidateBlock(t *testing.T) {
219 cp, _ := vmutil.DefaultCoinbaseProgram()
223 parent *state.BlockNode
227 desc: "The calculated transaction merkel root hash is not equals to the hash of the block header (blocktest#1009)",
230 BlockHeader: &bc.BlockHeader{
233 Timestamp: 1523352601,
234 PreviousBlockId: &bc.Hash{V0: 0},
235 TransactionsRoot: &bc.Hash{V0: 1},
237 Transactions: []*bc.Tx{
238 types.MapTx(&types.TxData{
241 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
242 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
246 parent: &state.BlockNode{
249 Timestamp: 1523352600,
250 Hash: bc.Hash{V0: 0},
252 err: errMismatchedMerkleRoot,
255 desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header (blocktest#1009)",
258 BlockHeader: &bc.BlockHeader{
261 Timestamp: 1523352601,
262 PreviousBlockId: &bc.Hash{V0: 0},
263 TransactionsRoot: &bc.Hash{V0: 6294987741126419124, V1: 12520373106916389157, V2: 5040806596198303681, V3: 1151748423853876189},
264 TransactionStatusHash: &bc.Hash{V0: 1},
266 Transactions: []*bc.Tx{
267 types.MapTx(&types.TxData{
270 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
271 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
275 parent: &state.BlockNode{
278 Timestamp: 1523352600,
279 Hash: bc.Hash{V0: 0},
281 err: errMismatchedMerkleRoot,
284 desc: "the coinbase amount is less than the real coinbase amount (txtest#1014)",
287 BlockHeader: &bc.BlockHeader{
290 Timestamp: 1523352601,
291 PreviousBlockId: &bc.Hash{V0: 0},
293 Transactions: []*bc.Tx{
294 types.MapTx(&types.TxData{
297 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
298 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
300 types.MapTx(&types.TxData{
303 Inputs: []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
304 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp)},
308 parent: &state.BlockNode{
311 Timestamp: 1523352600,
312 Hash: bc.Hash{V0: 0},
314 err: ErrWrongCoinbaseTransaction,
318 for i, c := range cases {
319 err := ValidateBlock(c.block, c.parent)
320 if rootErr(err) != c.err {
321 t.Errorf("case #%d (%s) got error %s, want %s", i, c.desc, err, c.err)
326 // TestGasOverBlockLimit check if the gas of the block has the max limit (blocktest#1012)
327 func TestGasOverBlockLimit(t *testing.T) {
328 cp, _ := vmutil.DefaultCoinbaseProgram()
329 parent := &state.BlockNode{
332 Timestamp: 1523352600,
333 Hash: bc.Hash{V0: 0},
337 BlockHeader: &bc.BlockHeader{
340 Timestamp: 1523352601,
341 PreviousBlockId: &bc.Hash{V0: 0},
342 TransactionsRoot: &bc.Hash{V0: 1},
344 Transactions: []*bc.Tx{
345 types.MapTx(&types.TxData{
348 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
349 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
354 for i := 0; i < 100; i++ {
355 block.Transactions = append(block.Transactions, types.MapTx(&types.TxData{
357 SerializedSize: 100000,
358 Inputs: []*types.TxInput{
359 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 10000000000, 0, cp),
361 Outputs: []*types.TxOutput{
362 types.NewTxOutput(*consensus.BTMAssetID, 9000000000, cp),
367 if err := ValidateBlock(block, parent); err != errOverBlockLimit {
368 t.Errorf("got error %s, want %s", err, errOverBlockLimit)
372 // TestSetTransactionStatus verify the transaction status is set correctly (blocktest#1010)
373 func TestSetTransactionStatus(t *testing.T) {
374 cp, _ := vmutil.DefaultCoinbaseProgram()
375 parent := &state.BlockNode{
378 Timestamp: 1523352600,
379 Hash: bc.Hash{V0: 0},
383 BlockHeader: &bc.BlockHeader{
386 Timestamp: 1523352601,
387 PreviousBlockId: &bc.Hash{V0: 0},
388 TransactionsRoot: &bc.Hash{V0: 3413931728524254295, V1: 300490676707850231, V2: 1886132055969225110, V3: 10216139531293906088},
389 TransactionStatusHash: &bc.Hash{V0: 8682965660674182538, V1: 8424137560837623409, V2: 6979974817894224946, V3: 4673809519342015041},
391 Transactions: []*bc.Tx{
392 types.MapTx(&types.TxData{
395 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
396 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41449998224, cp)},
398 types.MapTx(&types.TxData{
401 Inputs: []*types.TxInput{
402 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
403 types.NewSpendInput([][]byte{}, *newHash(8), bc.AssetID{V0: 1}, 1000, 0, []byte{byte(vm.OP_FALSE)}),
405 Outputs: []*types.TxOutput{
406 types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
407 types.NewTxOutput(bc.AssetID{V0: 1}, 1000, cp),
410 types.MapTx(&types.TxData{
413 Inputs: []*types.TxInput{
414 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
416 Outputs: []*types.TxOutput{
417 types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
423 if err := ValidateBlock(block, parent); err != nil {
427 expectTxStatuses := []bool{false, true, false}
428 txStatuses := block.GetTransactionStatus().VerifyStatus
429 if len(expectTxStatuses) != len(txStatuses) {
430 t.Error("the size of expect tx status is not equals to size of got tx status")
433 for i, status := range txStatuses {
434 if expectTxStatuses[i] != status.StatusFail {
435 t.Errorf("got tx status: %v, expect tx status: %v\n", status.StatusFail, expectTxStatuses[i])