OSDN Git Service

try to fix ban peer bug (#273)
[bytom/vapor.git] / proposal / proposal.go
index 6e5387b..a4c51e4 100644 (file)
@@ -24,10 +24,8 @@ const logModule = "mining"
 // createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
 // based on the passed block height to the provided address.  When the address
 // is nil, the coinbase transaction will instead be redeemable by anyone.
-func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeight uint64) (tx *types.Tx, err error) {
-       amount += consensus.BlockSubsidy(blockHeight)
+func createCoinbaseTx(accountManager *account.Manager, blockHeight uint64) (tx *types.Tx, err error) {
        arbitrary := append([]byte{0x00}, []byte(strconv.FormatUint(blockHeight, 10))...)
-
        var script []byte
        if accountManager == nil {
                script, err = vmutil.DefaultCoinbaseProgram()
@@ -39,7 +37,7 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
                return nil, err
        }
 
-       if len(arbitrary) > consensus.CoinbaseArbitrarySizeLimit {
+       if len(arbitrary) > consensus.ActiveNetParams.CoinbaseArbitrarySizeLimit {
                return nil, validation.ErrCoinbaseArbitraryOversize
        }
 
@@ -47,19 +45,14 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
        if err = builder.AddInput(types.NewCoinbaseInput(arbitrary), &txbuilder.SigningInstruction{}); err != nil {
                return nil, err
        }
-       if err = builder.AddOutput(types.NewIntraChainOutput(*consensus.BTMAssetID, amount, script)); err != nil {
-               return nil, err
-       }
-       _, txData, err := builder.Build()
-       if err != nil {
+       if err = builder.AddOutput(types.NewIntraChainOutput(*consensus.BTMAssetID, 0, script)); err != nil {
                return nil, err
        }
 
-       byteData, err := txData.MarshalText()
+       _, txData, err := builder.Build()
        if err != nil {
                return nil, err
        }
-       txData.SerializedSize = uint64(len(byteData))
 
        tx = &types.Tx{
                TxData: *txData,
@@ -68,6 +61,22 @@ func createCoinbaseTx(accountManager *account.Manager, amount uint64, blockHeigh
        return tx, nil
 }
 
+// restructCoinbaseTx build coinbase transaction with aggregate outputs when it achieved the specified block height
+func restructCoinbaseTx(tx *types.Tx, rewards []state.CoinbaseReward) error {
+       for _, r := range rewards {
+               tx.Outputs = append(tx.Outputs, types.NewIntraChainOutput(*consensus.BTMAssetID, r.Amount, r.ControlProgram))
+       }
+
+       byteData, err := tx.TxData.MarshalText()
+       if err != nil {
+               return err
+       }
+
+       tx.TxData.SerializedSize = uint64(len(byteData))
+       tx.Tx = types.MapTx(&tx.TxData)
+       return nil
+}
+
 // NewBlockTemplate returns a new block template that is ready to be solved
 func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager *account.Manager, timestamp uint64) (b *types.Block, err error) {
        view := state.NewUtxoViewpoint()
@@ -77,7 +86,6 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
        }
        txEntries := []*bc.Tx{nil}
        gasUsed := uint64(0)
-       txFee := uint64(0)
 
        // get preblock info for generate next block
        preBlockHeader := c.BestBlockHeader()
@@ -91,7 +99,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                        PreviousBlockHash: preBlockHash,
                        Timestamp:         timestamp,
                        BlockCommitment:   types.BlockCommitment{},
-                       BlockWitness:      types.BlockWitness{Witness: make([][]byte, consensus.NumOfConsensusNode)},
+                       BlockWitness:      types.BlockWitness{Witness: make([][]byte, consensus.ActiveNetParams.NumOfConsensusNode)},
                },
        }
        bcBlock := &bc.Block{BlockHeader: &bc.BlockHeader{Height: nextBlockHeight}}
@@ -99,17 +107,20 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
 
        txs := txPool.GetTransactions()
        sort.Sort(byTime(txs))
+
+       entriesTxs := []*bc.Tx{}
        for _, txDesc := range txs {
+               entriesTxs = append(entriesTxs, txDesc.Tx.Tx)
+       }
+
+       validateResults := validation.ValidateTxs(entriesTxs, bcBlock)
+       for i, validateResult := range validateResults {
+               txDesc := txs[i]
                tx := txDesc.Tx.Tx
                gasOnlyTx := false
 
-               if err := c.GetTransactionsUtxo(view, []*bc.Tx{tx}); err != nil {
-                       blkGenSkipTxForErr(txPool, &tx.ID, err)
-                       continue
-               }
-
-               gasStatus, err := validation.ValidateTx(tx, bcBlock)
-               if err != nil {
+               gasStatus := validateResult.GetGasState()
+               if validateResult.GetError() != nil {
                        if !gasStatus.GasValid {
                                blkGenSkipTxForErr(txPool, &tx.ID, err)
                                continue
@@ -117,7 +128,12 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                        gasOnlyTx = true
                }
 
-               if gasUsed+uint64(gasStatus.GasUsed) > consensus.MaxBlockGas {
+               if err := c.GetTransactionsUtxo(view, []*bc.Tx{tx}); err != nil {
+                       blkGenSkipTxForErr(txPool, &tx.ID, err)
+                       continue
+               }
+
+               if gasUsed+uint64(gasStatus.GasUsed) > consensus.ActiveNetParams.MaxBlockGas {
                        break
                }
 
@@ -133,20 +149,38 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
                b.Transactions = append(b.Transactions, txDesc.Tx)
                txEntries = append(txEntries, tx)
                gasUsed += uint64(gasStatus.GasUsed)
-               txFee += txDesc.Fee
-
-               if gasUsed == consensus.MaxBlockGas {
+               if gasUsed == consensus.ActiveNetParams.MaxBlockGas {
                        break
                }
+
        }
 
-       // creater coinbase transaction
-       b.Transactions[0], err = createCoinbaseTx(accountManager, txFee, nextBlockHeight)
+       // create coinbase transaction
+       b.Transactions[0], err = createCoinbaseTx(accountManager, nextBlockHeight)
        if err != nil {
                return nil, errors.Wrap(err, "fail on createCoinbaseTx")
        }
-       txEntries[0] = b.Transactions[0].Tx
 
+       consensusResult, err := c.GetConsensusResultByHash(&preBlockHash)
+       if err != nil {
+               return nil, err
+       }
+
+       if err := consensusResult.AttachCoinbaseReward(b); err != nil {
+               return nil, err
+       }
+
+       rewards, err := consensusResult.GetCoinbaseRewards(nextBlockHeight)
+       if err != nil {
+               return nil, err
+       }
+
+       // restruct coinbase transaction
+       if err = restructCoinbaseTx(b.Transactions[0], rewards); err != nil {
+               return nil, errors.Wrap(err, "fail on createCoinbaseTx")
+       }
+
+       txEntries[0] = b.Transactions[0].Tx
        b.BlockHeader.BlockCommitment.TransactionsMerkleRoot, err = types.TxMerkleRoot(txEntries)
        if err != nil {
                return nil, err
@@ -154,7 +188,7 @@ func NewBlockTemplate(c *protocol.Chain, txPool *protocol.TxPool, accountManager
 
        b.BlockHeader.BlockCommitment.TransactionStatusHash, err = types.TxStatusMerkleRoot(txStatus.VerifyStatus)
 
-       _, err = c.GetBBFT().SignBlock(b)
+       _, err = c.SignBlock(b)
        return b, err
 }