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.
11 "github.com/bytom/blockchain/txbuilder"
12 "github.com/bytom/consensus"
13 "github.com/bytom/errors"
14 "github.com/bytom/protocol"
15 "github.com/bytom/protocol/bc"
16 "github.com/bytom/protocol/bc/legacy"
17 "github.com/bytom/protocol/state"
18 "github.com/bytom/protocol/validation"
19 "github.com/bytom/protocol/vm"
20 "github.com/bytom/protocol/vm/vmutil"
23 // standardCoinbaseScript returns a standard script suitable for use as the
24 // signature script of the coinbase transaction of a new block.
25 func standardCoinbaseScript(blockHeight uint64) ([]byte, error) {
26 //TODO: add verify conditions, block heigh & sign
27 scriptBuild := vmutil.NewBuilder()
28 scriptBuild.AddOp(vm.OP_TRUE)
29 return scriptBuild.Build()
32 // createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
33 // based on the passed block height to the provided address. When the address
34 // is nil, the coinbase transaction will instead be redeemable by anyone.
35 func createCoinbaseTx(amount uint64, blockHeight uint64, addr []byte) (*legacy.Tx, error) {
36 //TODO: make sure things works
37 amount += consensus.BlockSubsidy(blockHeight)
38 cbScript, err := standardCoinbaseScript(blockHeight)
43 builder := txbuilder.NewBuilder(time.Now())
44 builder.AddOutput(legacy.NewTxOutput(*consensus.BTMAssetID, amount, cbScript, nil))
45 _, txData, err := builder.Build()
48 Tx: legacy.MapTx(txData),
53 // NewBlockTemplate returns a new block template that is ready to be solved
54 func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, addr []byte) (*legacy.Block, error) {
55 // Extend the most recently known best block.
57 preBlock, snap := c.State()
58 newSnap := state.Copy(snap)
60 nextBlockHeight := preBlock.BlockHeader.Height + 1
61 preBcBlock := legacy.MapBlock(preBlock)
62 txDescs := txPool.GetTransactions()
63 txEntries := make([]*bc.Tx, 0, len(txDescs))
64 blockWeight := uint64(0)
68 BlockHeader: legacy.BlockHeader{
70 Height: nextBlockHeight,
71 PreviousBlockHash: preBlock.Hash(),
72 TimestampMS: bc.Millis(time.Now()),
73 BlockCommitment: legacy.BlockCommitment{},
74 Bits: consensus.CalcNextRequiredDifficulty(nil, nil),
76 Transactions: make([]*legacy.Tx, 0, len(txDescs)),
78 newSnap.PruneNonces(b.BlockHeader.TimestampMS)
80 appendTx := func(tx *legacy.Tx, weight, fee uint64) {
81 b.Transactions = append([]*legacy.Tx{tx}, b.Transactions...)
82 txEntries = append([]*bc.Tx{tx.Tx}, txEntries...)
87 for _, txDesc := range txDescs {
89 if blockWeight+txDesc.Weight > consensus.MaxBlockSzie-consensus.MaxTxSize {
92 if err := newSnap.ApplyTx(tx); err != nil {
93 fmt.Println("mining block generate skip tx due to %v", err)
94 txPool.RemoveTransaction(&tx.ID)
97 if _, err := validation.ValidateTx(tx, preBcBlock); err != nil {
98 fmt.Println("mining block generate skip tx due to %v", err)
99 txPool.RemoveTransaction(&tx.ID)
103 appendTx(txDesc.Tx, txDesc.Weight, txDesc.Fee)
106 cbTx, _ := createCoinbaseTx(txFee, nextBlockHeight, addr)
107 if err := newSnap.ApplyTx(cbTx.Tx); err != nil {
108 return nil, errors.Wrap(err, "fail on append coinbase transaction to snap")
112 b.BlockHeader.BlockCommitment.AssetsMerkleRoot = newSnap.Tree.RootHash()
113 b.BlockHeader.BlockCommitment.TransactionsMerkleRoot, err = bc.MerkleRoot(txEntries)
115 return nil, errors.Wrap(err, "calculating tx merkle root")