1 // Copyright (c) 2014-2016 The btcsuite developers
2 // Use of this source code is governed by an ISC
3 // license that can be found in the LICENSE file.
10 "github.com/bytom/blockchain/txbuilder"
11 "github.com/bytom/consensus"
12 "github.com/bytom/errors"
13 "github.com/bytom/protocol"
14 "github.com/bytom/protocol/bc"
15 "github.com/bytom/protocol/bc/legacy"
16 "github.com/bytom/protocol/state"
17 "github.com/bytom/protocol/validation"
18 "github.com/bytom/protocol/vm"
19 "github.com/bytom/protocol/vm/vmutil"
22 // standardCoinbaseScript returns a standard script suitable for use as the
23 // signature script of the coinbase transaction of a new block.
24 func standardCoinbaseScript(blockHeight uint64) ([]byte, error) {
25 //TODO: add verify conditions, block heigh & sign
26 scriptBuild := vmutil.NewBuilder()
27 scriptBuild.AddOp(vm.OP_TRUE)
28 return scriptBuild.Build()
31 // createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
32 // based on the passed block height to the provided address. When the address
33 // is nil, the coinbase transaction will instead be redeemable by anyone.
34 func createCoinbaseTx(amount uint64, blockHeight uint64, addr []byte) (*legacy.Tx, error) {
35 //TODO: make sure things works
36 amount += consensus.BlockSubsidy(blockHeight)
37 cbScript, err := standardCoinbaseScript(blockHeight)
42 builder := txbuilder.NewBuilder(time.Now())
43 builder.AddOutput(legacy.NewTxOutput(*validation.BTMAssetID, amount, cbScript, nil))
44 _, txData, err := builder.Build()
47 Tx: legacy.MapTx(txData),
52 // NewBlockTemplate returns a new block template that is ready to be solved
53 func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, addr []byte) (*legacy.Block, error) {
54 // Extend the most recently known best block.
56 newSnap := state.Empty()
57 var blockData *bc.Block
58 nextBlockHeight := uint64(1)
59 preBlockHash := bc.Hash{}
61 block, snap := c.State()
63 nextBlockHeight = block.BlockHeader.Height + 1
64 preBlockHash = block.Hash()
65 newSnap = state.Copy(snap)
66 blockData = legacy.MapBlock(block)
69 txDescs := txPool.GetTransactions()
70 blockTxns := make([]*legacy.Tx, 0, len(txDescs))
71 blockWeight := uint64(0)
75 BlockHeader: legacy.BlockHeader{
77 Height: nextBlockHeight,
78 PreviousBlockHash: preBlockHash,
79 TimestampMS: bc.Millis(time.Now()),
80 BlockCommitment: legacy.BlockCommitment{},
81 Bits: consensus.CalcNextRequiredDifficulty(),
84 newSnap.PruneNonces(b.BlockHeader.TimestampMS)
86 var txEntries []*bc.Tx
87 for _, txDesc := range txDescs {
89 blockPlusTxWeight := blockWeight + txDesc.Weight
90 if blockPlusTxWeight > validation.MaxBlockSzie {
94 if err := newSnap.ApplyTx(tx); err != nil {
95 txPool.RemoveTransaction(&tx.ID)
99 if _, err := validation.ValidateTx(tx, blockData); err != nil {
100 txPool.RemoveTransaction(&tx.ID)
104 blockTxns = append(blockTxns, txDesc.Tx)
105 txEntries = append(txEntries, tx)
106 blockWeight = blockPlusTxWeight
110 cbTx, _ := createCoinbaseTx(txFee, nextBlockHeight, addr)
111 newSnap.ApplyTx(cbTx.Tx)
112 blockTxns = append([]*legacy.Tx{cbTx}, blockTxns...)
114 b.Transactions = blockTxns
116 b.BlockHeader.BlockCommitment.TransactionsMerkleRoot, err = bc.MerkleRoot(txEntries)
117 b.BlockHeader.BlockCommitment.AssetsMerkleRoot = newSnap.Tree.RootHash()
119 return nil, errors.Wrap(err, "calculating tx merkle root")