6 "github.com/bytom/consensus"
7 "github.com/bytom/consensus/difficulty"
8 "github.com/bytom/protocol"
9 "github.com/bytom/protocol/bc"
10 "github.com/bytom/protocol/bc/types"
11 "github.com/bytom/protocol/validation"
12 "github.com/bytom/protocol/vm"
15 // NewBlock create block according to the current status of chain
16 func NewBlock(chain *protocol.Chain, txs []*types.Tx, controlProgram []byte) (*types.Block, error) {
19 txEntries := []*bc.Tx{nil}
20 txStatus := bc.NewTransactionStatus()
21 txStatus.SetStatus(0, false)
23 preBlockHeader := chain.BestBlockHeader()
24 var compareDiffBH *types.BlockHeader
25 if compareDiffBlock, err := chain.GetBlockByHeight(preBlockHeader.Height - consensus.BlocksPerRetarget); err == nil {
26 compareDiffBH = &compareDiffBlock.BlockHeader
30 BlockHeader: types.BlockHeader{
32 Height: preBlockHeader.Height + 1,
33 PreviousBlockHash: preBlockHeader.Hash(),
34 Timestamp: uint64(time.Now().Unix()),
35 BlockCommitment: types.BlockCommitment{},
36 Bits: difficulty.CalcNextRequiredDifficulty(preBlockHeader, compareDiffBH),
38 Transactions: []*types.Tx{nil},
41 bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: preBlockHeader.Height + 1}}
42 for _, tx := range txs {
44 gasStatus, err := validation.ValidateTx(tx.Tx, bcBlock)
46 if !gasStatus.GasVaild {
52 txStatus.SetStatus(len(b.Transactions), gasOnlyTx)
53 b.Transactions = append(b.Transactions, tx)
54 txEntries = append(txEntries, tx.Tx)
55 gasUsed += uint64(gasStatus.GasUsed)
59 coinbaseTx, err := CreateCoinbaseTx(controlProgram, preBlockHeader.Height+1, txsFee)
64 b.Transactions[0] = coinbaseTx
65 txEntries[0] = coinbaseTx.Tx
66 b.TransactionsMerkleRoot, err = bc.TxMerkleRoot(txEntries)
71 b.TransactionStatusHash, err = bc.TxStatusMerkleRoot(txStatus.VerifyStatus)
75 // ReplaceCoinbase replace the coinbase tx of block with coinbaseTx
76 func ReplaceCoinbase(block *types.Block, coinbaseTx *types.Tx) (err error) {
77 block.Transactions[0] = coinbaseTx
78 txEntires := []*bc.Tx{coinbaseTx.Tx}
79 for i := 1; i < len(block.Transactions); i++ {
80 txEntires = append(txEntires, block.Transactions[i].Tx)
83 block.TransactionsMerkleRoot, err = bc.TxMerkleRoot(txEntires)
87 // AppendBlocks append empty blocks to chain, mainly used to mature the coinbase tx
88 func AppendBlocks(chain *protocol.Chain, num uint64) error {
89 for i := uint64(0); i < num; i++ {
90 block, err := NewBlock(chain, nil, []byte{byte(vm.OP_TRUE)})
94 if err := SolveAndUpdate(chain, block); err != nil {
101 // SolveAndUpdate solve difficulty and update chain status
102 func SolveAndUpdate(chain *protocol.Chain, block *types.Block) error {
103 seed, err := chain.CalcNextSeed(&block.PreviousBlockHash)
108 _, err = chain.ProcessBlock(block)
112 // Solve solve difficulty
113 func Solve(seed *bc.Hash, block *types.Block) error {
114 header := &block.BlockHeader
115 for i := uint64(0); i < maxNonce; i++ {
117 headerHash := header.Hash()
118 if difficulty.CheckProofOfWork(&headerHash, seed, header.Bits) {