8 "github.com/vapor/consensus"
9 "github.com/vapor/mining/tensority"
10 "github.com/vapor/protocol/bc"
11 "github.com/vapor/protocol/bc/types"
12 "github.com/vapor/protocol/state"
13 "github.com/vapor/protocol/vm"
14 "github.com/vapor/protocol/vm/vmutil"
15 "github.com/vapor/testutil"
18 func TestCheckBlockTime(t *testing.T) {
26 blockTime: 1520000001,
27 parentTime: []uint64{1520000000},
31 desc: "timestamp less than past median time (blocktest#1005)",
32 blockTime: 1510000094,
33 parentTime: []uint64{1520000000, 1510000099, 1510000098, 1510000097, 1510000096, 1510000095, 1510000094, 1510000093, 1510000092, 1510000091, 1510000090},
37 desc: "timestamp greater than max limit (blocktest#1006)",
38 blockTime: 9999999999,
39 parentTime: []uint64{1520000000},
43 desc: "timestamp of the block and the parent block are both greater than max limit (blocktest#1007)",
44 blockTime: uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 2,
45 parentTime: []uint64{uint64(time.Now().Unix()) + consensus.MaxTimeOffsetSeconds + 1},
50 parent := &state.BlockNode{Version: 1}
52 BlockHeader: &bc.BlockHeader{Version: 1},
55 for i, c := range cases {
56 parent.Timestamp = c.parentTime[0]
57 parentSuccessor := parent
58 for i := 1; i < len(c.parentTime); i++ {
59 parentSuccessor.Parent = &state.BlockNode{Version: 1, Timestamp: c.parentTime[i]}
60 parentSuccessor = parentSuccessor.Parent
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)
70 func TestCheckCoinbaseAmount(t *testing.T) {
78 types.NewTx(types.TxData{
79 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
80 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
88 types.NewTx(types.TxData{
89 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
90 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 5000, nil)},
94 err: ErrWrongCoinbaseTransaction,
99 err: ErrWrongCoinbaseTransaction,
103 block := new(types.Block)
104 for i, c := range cases {
105 block.Transactions = c.txs
106 if err := checkCoinbaseAmount(types.MapBlock(block), c.amount); rootErr(err) != c.err {
107 t.Errorf("case %d got error %s, want %s", i, err, c.err)
112 func TestValidateBlockHeader(t *testing.T) {
118 parent *state.BlockNode
122 block: &bc.Block{BlockHeader: &bc.BlockHeader{
125 parent: &state.BlockNode{
128 err: errVersionRegression,
131 block: &bc.Block{BlockHeader: &bc.BlockHeader{
135 parent: &state.BlockNode{
139 err: errMisorderedBlockHeight,
142 desc: "the difficulty of the block is not equals to the next difficulty of parent block (blocktest#1008)",
143 block: &bc.Block{BlockHeader: &bc.BlockHeader{
148 parent: &state.BlockNode{
151 Bits: 2305843009214532812,
156 desc: "the prev block hash not equals to the hash of parent (blocktest#1004)",
157 block: &bc.Block{BlockHeader: &bc.BlockHeader{
160 PreviousBlockId: &bc.Hash{V0: 18},
162 parent: &state.BlockNode{
165 Hash: bc.Hash{V0: 19},
167 err: errMismatchedBlock,
170 desc: "check work proof fail (blocktest#1011)",
173 BlockHeader: &bc.BlockHeader{
176 Timestamp: 1523352601,
177 PreviousBlockId: &bc.Hash{V0: 0},
178 Bits: 2305843009214532812,
181 parent: &state.BlockNode{
184 Timestamp: 1523352600,
185 Hash: bc.Hash{V0: 0},
186 Seed: &bc.Hash{V1: 1},
187 Bits: 2305843009214532812,
194 BlockHeader: &bc.BlockHeader{
197 Timestamp: 1523352601,
198 PreviousBlockId: &bc.Hash{V0: 0},
199 Bits: 2305843009214532812,
202 parent: &state.BlockNode{
205 Timestamp: 1523352600,
206 Hash: bc.Hash{V0: 0},
207 Seed: &bc.Hash{V1: 1},
208 Bits: 2305843009214532812,
213 desc: "version greater than 1 (blocktest#1001)",
216 BlockHeader: &bc.BlockHeader{
220 parent: &state.BlockNode{
223 err: errVersionRegression,
226 desc: "version equals 0 (blocktest#1002)",
229 BlockHeader: &bc.BlockHeader{
233 parent: &state.BlockNode{
236 err: errVersionRegression,
239 desc: "version equals max uint64 (blocktest#1003)",
242 BlockHeader: &bc.BlockHeader{
243 Version: math.MaxUint64,
246 parent: &state.BlockNode{
249 err: errVersionRegression,
253 for i, c := range cases {
254 if err := ValidateBlockHeader(c.block, c.parent); rootErr(err) != c.err {
255 t.Errorf("case %d (%s) got error %s, want %s", i, c.desc, err, c.err)
260 // TestValidateBlock test the ValidateBlock function
261 func TestValidateBlock(t *testing.T) {
264 cp, _ := vmutil.DefaultCoinbaseProgram()
268 parent *state.BlockNode
272 desc: "The calculated transaction merkel root hash is not equals to the hash of the block header (blocktest#1009)",
275 BlockHeader: &bc.BlockHeader{
278 Timestamp: 1523352601,
279 PreviousBlockId: &bc.Hash{V0: 0},
280 Bits: 2305843009214532812,
281 TransactionsRoot: &bc.Hash{V0: 1},
283 Transactions: []*bc.Tx{
284 types.MapTx(&types.TxData{
287 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
288 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
292 parent: &state.BlockNode{
295 Timestamp: 1523352600,
296 Hash: bc.Hash{V0: 0},
297 Seed: &bc.Hash{V1: 1},
298 Bits: 2305843009214532812,
300 err: errMismatchedMerkleRoot,
303 desc: "The calculated transaction status merkel root hash is not equals to the hash of the block header (blocktest#1009)",
306 BlockHeader: &bc.BlockHeader{
309 Timestamp: 1523352601,
310 PreviousBlockId: &bc.Hash{V0: 0},
311 Bits: 2305843009214532812,
312 TransactionsRoot: &bc.Hash{V0: 6294987741126419124, V1: 12520373106916389157, V2: 5040806596198303681, V3: 1151748423853876189},
313 TransactionStatusHash: &bc.Hash{V0: 1},
315 Transactions: []*bc.Tx{
316 types.MapTx(&types.TxData{
319 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
320 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
324 parent: &state.BlockNode{
327 Timestamp: 1523352600,
328 Hash: bc.Hash{V0: 0},
329 Seed: &bc.Hash{V1: 1},
330 Bits: 2305843009214532812,
332 err: errMismatchedMerkleRoot,
335 desc: "the coinbase amount is less than the real coinbase amount (txtest#1014)",
338 BlockHeader: &bc.BlockHeader{
341 Timestamp: 1523352601,
342 PreviousBlockId: &bc.Hash{V0: 0},
343 Bits: 2305843009214532812,
345 Transactions: []*bc.Tx{
346 types.MapTx(&types.TxData{
349 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
350 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
352 types.MapTx(&types.TxData{
355 Inputs: []*types.TxInput{types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp)},
356 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 90000000, cp)},
360 parent: &state.BlockNode{
363 Timestamp: 1523352600,
364 Hash: bc.Hash{V0: 0},
365 Seed: &bc.Hash{V1: 1},
366 Bits: 2305843009214532812,
368 err: ErrWrongCoinbaseTransaction,
372 for i, c := range cases {
373 err := ValidateBlock(c.block, c.parent)
374 if rootErr(err) != c.err {
375 t.Errorf("case #%d (%s) got error %s, want %s", i, c.desc, err, c.err)
380 // TestGasOverBlockLimit check if the gas of the block has the max limit (blocktest#1012)
381 func TestGasOverBlockLimit(t *testing.T) {
384 cp, _ := vmutil.DefaultCoinbaseProgram()
385 parent := &state.BlockNode{
388 Timestamp: 1523352600,
389 Hash: bc.Hash{V0: 0},
390 Seed: &bc.Hash{V1: 1},
391 Bits: 2305843009214532812,
395 BlockHeader: &bc.BlockHeader{
398 Timestamp: 1523352601,
399 PreviousBlockId: &bc.Hash{V0: 0},
400 Bits: 2305843009214532812,
401 TransactionsRoot: &bc.Hash{V0: 1},
403 Transactions: []*bc.Tx{
404 types.MapTx(&types.TxData{
407 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
408 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41250000000, cp)},
413 for i := 0; i < 100; i++ {
414 block.Transactions = append(block.Transactions, types.MapTx(&types.TxData{
416 SerializedSize: 100000,
417 Inputs: []*types.TxInput{
418 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 10000000000, 0, cp),
420 Outputs: []*types.TxOutput{
421 types.NewTxOutput(*consensus.BTMAssetID, 9000000000, cp),
426 if err := ValidateBlock(block, parent); err != errOverBlockLimit {
427 t.Errorf("got error %s, want %s", err, errOverBlockLimit)
431 // TestSetTransactionStatus verify the transaction status is set correctly (blocktest#1010)
432 func TestSetTransactionStatus(t *testing.T) {
435 cp, _ := vmutil.DefaultCoinbaseProgram()
436 parent := &state.BlockNode{
439 Timestamp: 1523352600,
440 Hash: bc.Hash{V0: 0},
441 Seed: &bc.Hash{V1: 1},
442 Bits: 2305843009214532812,
446 BlockHeader: &bc.BlockHeader{
449 Timestamp: 1523352601,
450 PreviousBlockId: &bc.Hash{V0: 0},
451 Bits: 2305843009214532812,
452 TransactionsRoot: &bc.Hash{V0: 3413931728524254295, V1: 300490676707850231, V2: 1886132055969225110, V3: 10216139531293906088},
453 TransactionStatusHash: &bc.Hash{V0: 8682965660674182538, V1: 8424137560837623409, V2: 6979974817894224946, V3: 4673809519342015041},
455 Transactions: []*bc.Tx{
456 types.MapTx(&types.TxData{
459 Inputs: []*types.TxInput{types.NewCoinbaseInput(nil)},
460 Outputs: []*types.TxOutput{types.NewTxOutput(*consensus.BTMAssetID, 41449998224, cp)},
462 types.MapTx(&types.TxData{
465 Inputs: []*types.TxInput{
466 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
467 types.NewSpendInput([][]byte{}, *newHash(8), bc.AssetID{V0: 1}, 1000, 0, []byte{byte(vm.OP_FALSE)}),
469 Outputs: []*types.TxOutput{
470 types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
471 types.NewTxOutput(bc.AssetID{V0: 1}, 1000, cp),
474 types.MapTx(&types.TxData{
477 Inputs: []*types.TxInput{
478 types.NewSpendInput([][]byte{}, *newHash(8), *consensus.BTMAssetID, 100000000, 0, cp),
480 Outputs: []*types.TxOutput{
481 types.NewTxOutput(*consensus.BTMAssetID, 888, cp),
487 if err := ValidateBlock(block, parent); err != nil {
491 expectTxStatuses := []bool{false, true, false}
492 txStatuses := block.GetTransactionStatus().VerifyStatus
493 if len(expectTxStatuses) != len(txStatuses) {
494 t.Error("the size of expect tx status is not equals to size of got tx status")
497 for i, status := range txStatuses {
498 if expectTxStatuses[i] != status.StatusFail {
499 t.Errorf("got tx status: %v, expect tx status: %v\n", status.StatusFail, expectTxStatuses[i])
504 func iniTtensority() {
505 // add (hash, seed) --> (tensority hash) to the tensority cache for avoid
506 // real matrix calculate cost.
507 tensority.AIHash.AddCache(&bc.Hash{V0: 0}, &bc.Hash{}, testutil.MaxHash)
508 tensority.AIHash.AddCache(&bc.Hash{V0: 1}, &bc.Hash{}, testutil.MinHash)
509 tensority.AIHash.AddCache(&bc.Hash{V0: 1}, consensus.InitialSeed, testutil.MinHash)