OSDN Git Service

Add the implementation for dppos
[bytom/vapor.git] / test / block_test_util.go
1 package test
2
3 import (
4         "github.com/vapor/protocol"
5         "github.com/vapor/protocol/bc"
6         "github.com/vapor/protocol/bc/types"
7         "github.com/vapor/protocol/validation"
8         "github.com/vapor/protocol/vm"
9 )
10
11 // NewBlock create block according to the current status of chain
12 func NewBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*types.Block, error) {
13         gasUsed := uint64(0)
14         txsFee := uint64(0)
15         txEntries := []*bc.Tx{nil}
16         txStatus := bc.NewTransactionStatus()
17         if err := txStatus.SetStatus(0, false); err != nil {
18                 return nil, err
19         }
20
21         preBlockHeader := chain.BestBlockHeader()
22
23         b := &types.Block{
24                 BlockHeader: types.BlockHeader{
25                         Version:           1,
26                         Height:            preBlockHeader.Height + 1,
27                         PreviousBlockHash: preBlockHeader.Hash(),
28                         Timestamp:         preBlockHeader.Timestamp + 1,
29                         BlockCommitment:   types.BlockCommitment{},
30                 },
31                 Transactions: []*types.Tx{nil},
32         }
33
34         bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: preBlockHeader.Height + 1}}
35         for _, tx := range txs {
36                 gasOnlyTx := false
37                 gasStatus, err := validation.ValidateTx(tx.Tx, bcBlock)
38                 if err != nil {
39                         if !gasStatus.GasValid {
40                                 continue
41                         }
42                         gasOnlyTx = true
43                 }
44
45                 txStatus.SetStatus(len(b.Transactions), gasOnlyTx)
46                 b.Transactions = append(b.Transactions, tx)
47                 txEntries = append(txEntries, tx.Tx)
48                 gasUsed += uint64(gasStatus.GasUsed)
49                 txsFee += txFee(tx)
50         }
51
52         coinbaseTx, err := CreateCoinbaseTx(controlProgram, preBlockHeader.Height+1, txsFee)
53         if err != nil {
54                 return nil, err
55         }
56
57         b.Transactions[0] = coinbaseTx
58         txEntries[0] = coinbaseTx.Tx
59         b.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntries)
60         if err != nil {
61                 return nil, err
62         }
63
64         b.TransactionStatusHash, err = types.TxStatusMerkleRoot(txStatus.VerifyStatus)
65         return b, err
66 }
67
68 // ReplaceCoinbase replace the coinbase tx of block with coinbaseTx
69 func ReplaceCoinbase(block *types.Block, coinbaseTx *types.Tx) (err error) {
70         block.Transactions[0] = coinbaseTx
71         txEntires := []*bc.Tx{coinbaseTx.Tx}
72         for i := 1; i < len(block.Transactions); i++ {
73                 txEntires = append(txEntires, block.Transactions[i].Tx)
74         }
75
76         block.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntires)
77         return
78 }
79
80 // AppendBlocks append empty blocks to chain, mainly used to mature the coinbase tx
81 func AppendBlocks(chain *protocol.Chain, num uint64) error {
82         for i := uint64(0); i < num; i++ {
83                 block, err := NewBlock(chain, nil, []byte{byte(vm.OP_TRUE)})
84                 if err != nil {
85                         return err
86                 }
87                 if err := SolveAndUpdate(chain, block); err != nil {
88                         return err
89                 }
90         }
91         return nil
92 }
93
94 // SolveAndUpdate solve difficulty and update chain status
95 func SolveAndUpdate(chain *protocol.Chain, block *types.Block) error {
96         _, err := chain.ProcessBlock(block)
97         return err
98 }