Modify NewBlockTemplate to accept nil pay addr.
There are certain cases such as getblocktemplate which allow external callers to be repsonsible for creating their own coinbase to replace the generated one. By allowing the pay address to be nil in such cases, the need to specify mining addresses via --miningaddr can be avoided thereby leaving the payment address management up to the caller.
This commit is contained in:
parent
d40cff64b0
commit
0c9c005c33
3 changed files with 54 additions and 32 deletions
|
@ -298,7 +298,7 @@ out:
|
||||||
// Create a new block template using the available transactions
|
// Create a new block template using the available transactions
|
||||||
// in the memory pool as a source of transactions to potentially
|
// in the memory pool as a source of transactions to potentially
|
||||||
// include in the block.
|
// include in the block.
|
||||||
template, err := NewBlockTemplate(payToAddr, m.server.txMemPool)
|
template, err := NewBlockTemplate(m.server.txMemPool, payToAddr)
|
||||||
m.submitBlockLock.Unlock()
|
m.submitBlockLock.Unlock()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := fmt.Sprintf("Failed to create new block "+
|
errStr := fmt.Sprintf("Failed to create new block "+
|
||||||
|
|
82
mining.go
82
mining.go
|
@ -165,9 +165,11 @@ func newTxPriorityQueue(reserve int, sortByFee bool) *txPriorityQueue {
|
||||||
// details about the fees and the number of signature operations for each
|
// details about the fees and the number of signature operations for each
|
||||||
// transaction in the block.
|
// transaction in the block.
|
||||||
type BlockTemplate struct {
|
type BlockTemplate struct {
|
||||||
block *btcwire.MsgBlock
|
block *btcwire.MsgBlock
|
||||||
fees []int64
|
fees []int64
|
||||||
sigOpCounts []int64
|
sigOpCounts []int64
|
||||||
|
height int64
|
||||||
|
validPayAddress bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// minInt is a helper function to return the minimum of two ints. This avoids
|
// minInt is a helper function to return the minimum of two ints. This avoids
|
||||||
|
@ -203,16 +205,25 @@ func standardCoinbaseScript(nextBlockHeight int64, extraNonce uint64) []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
// createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
|
// createCoinbaseTx returns a coinbase transaction paying an appropriate subsidy
|
||||||
// based on the passed block height to the passed public key. It also accepts
|
// based on the passed block height to the provided address. When the address
|
||||||
// an extra nonce value for the signature script. This extra nonce helps ensure
|
// is nil, the coinbase transaction will instead be redeemable by anyone.
|
||||||
// the transaction is not a duplicate transaction (paying the same value to the
|
//
|
||||||
// same public key address would otherwise be an identical transaction for
|
// See the comment for NewBlockTemplate for more information about why the nil
|
||||||
// block version 1).
|
// address handling is useful.
|
||||||
func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int64, addr btcutil.Address) (*btcutil.Tx, error) {
|
func createCoinbaseTx(coinbaseScript []byte, nextBlockHeight int64, addr btcutil.Address) (*btcutil.Tx, error) {
|
||||||
// Create a script to pay to the specific address.
|
// Create the script to pay to the provided payment address if one was
|
||||||
pkScript, err := btcscript.PayToAddrScript(addr)
|
// specified. Otherwise create a script that allows the coinbase to be
|
||||||
if err != nil {
|
// redeemable by anyone.
|
||||||
return nil, err
|
var pkScript []byte
|
||||||
|
if addr != nil {
|
||||||
|
var err error
|
||||||
|
pkScript, err = btcscript.PayToAddrScript(addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
scriptBuilder := btcscript.NewScriptBuilder()
|
||||||
|
pkScript = scriptBuilder.AddOp(btcscript.OP_TRUE).Script()
|
||||||
}
|
}
|
||||||
|
|
||||||
tx := btcwire.NewMsgTx()
|
tx := btcwire.NewMsgTx()
|
||||||
|
@ -332,16 +343,22 @@ func medianAdjustedTime(chainState *chainState) (time.Time, error) {
|
||||||
return newTimestamp, nil
|
return newTimestamp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewBlockTemplate returns a new block template using the transactions from the
|
// NewBlockTemplate returns a new block template that is ready to be solved
|
||||||
// passed transaction memory pool with a coinbase that pays to the passed
|
// using the transactions from the passed transaction memory pool and a coinbase
|
||||||
// address and is ready to be solved. The transactions selected and included
|
// that either pays to the passed address if it is not nil, or a coinbase that
|
||||||
// are prioritized according to several factors. First, each transaction has a
|
// is redeemable by anyone if the passed address is nil. The nil address
|
||||||
// priority calculated based on its value, age of inputs, and size.
|
// functionality is useful since there are cases such as the getblocktemplate
|
||||||
// Transactions which consist of larger amounts, older inputs, and small sizes
|
// RPC where external mining software is responsible for creating their own
|
||||||
// have the highest priority. Second, a fee per kilobyte is calculated for each
|
// coinbase which will replace the one generated for the block template. Thus
|
||||||
// transaction. Transactions with a higher fee per kilobyte are preferred.
|
// the need to have configured address can be avoided.
|
||||||
// Finally, the block generation related configuration options are all taken
|
//
|
||||||
// into account.
|
// The transactions selected and included are prioritized according to several
|
||||||
|
// factors. First, each transaction has a priority calculated based on its
|
||||||
|
// value, age of inputs, and size. Transactions which consist of larger
|
||||||
|
// amounts, older inputs, and small sizes have the highest priority. Second, a
|
||||||
|
// fee per kilobyte is calculated for each transaction. Transactions with a
|
||||||
|
// higher fee per kilobyte are preferred. Finally, the block generation related
|
||||||
|
// configuration options are all taken into account.
|
||||||
//
|
//
|
||||||
// Transactions which only spend outputs from other transactions already in the
|
// Transactions which only spend outputs from other transactions already in the
|
||||||
// block chain are immediately added to a priority queue which either
|
// block chain are immediately added to a priority queue which either
|
||||||
|
@ -387,7 +404,7 @@ func medianAdjustedTime(chainState *chainState) (time.Time, error) {
|
||||||
// | transactions (while block size | |
|
// | transactions (while block size | |
|
||||||
// | <= cfg.BlockMinSize) | |
|
// | <= cfg.BlockMinSize) | |
|
||||||
// ----------------------------------- --
|
// ----------------------------------- --
|
||||||
func NewBlockTemplate(payToAddress btcutil.Address, mempool *txMemPool) (*BlockTemplate, error) {
|
func NewBlockTemplate(mempool *txMemPool, payToAddress btcutil.Address) (*BlockTemplate, error) {
|
||||||
blockManager := mempool.server.blockManager
|
blockManager := mempool.server.blockManager
|
||||||
chainState := &blockManager.chainState
|
chainState := &blockManager.chainState
|
||||||
chain := blockManager.blockChain
|
chain := blockManager.blockChain
|
||||||
|
@ -402,7 +419,10 @@ func NewBlockTemplate(payToAddress btcutil.Address, mempool *txMemPool) (*BlockT
|
||||||
// address. NOTE: The coinbase value will be updated to include the
|
// address. NOTE: The coinbase value will be updated to include the
|
||||||
// fees from the selected transactions later after they have actually
|
// fees from the selected transactions later after they have actually
|
||||||
// been selected. It is created here to detect any errors early
|
// been selected. It is created here to detect any errors early
|
||||||
// before potentially doing a lot of work below.
|
// before potentially doing a lot of work below. The extra nonce helps
|
||||||
|
// ensure the transaction is not a duplicate transaction (paying the
|
||||||
|
// same value to the same public key address would otherwise be an
|
||||||
|
// identical transaction for block version 1).
|
||||||
extraNonce := uint64(0)
|
extraNonce := uint64(0)
|
||||||
coinbaseScript := standardCoinbaseScript(nextBlockHeight, extraNonce)
|
coinbaseScript := standardCoinbaseScript(nextBlockHeight, extraNonce)
|
||||||
coinbaseTx, err := createCoinbaseTx(coinbaseScript, nextBlockHeight,
|
coinbaseTx, err := createCoinbaseTx(coinbaseScript, nextBlockHeight,
|
||||||
|
@ -444,8 +464,8 @@ func NewBlockTemplate(payToAddress btcutil.Address, mempool *txMemPool) (*BlockT
|
||||||
// a transaction as it is selected for inclusion in the final block.
|
// a transaction as it is selected for inclusion in the final block.
|
||||||
// However, since the total fees aren't known yet, use a dummy value for
|
// However, since the total fees aren't known yet, use a dummy value for
|
||||||
// the coinbase fee which will be updated later.
|
// the coinbase fee which will be updated later.
|
||||||
txFees := make([]int64, len(mempoolTxns))
|
txFees := make([]int64, 0, len(mempoolTxns))
|
||||||
txSigOpCounts := make([]int64, len(mempoolTxns))
|
txSigOpCounts := make([]int64, 0, len(mempoolTxns))
|
||||||
txFees = append(txFees, -1) // Updated once known
|
txFees = append(txFees, -1) // Updated once known
|
||||||
txSigOpCounts = append(txSigOpCounts, numCoinbaseSigOps)
|
txSigOpCounts = append(txSigOpCounts, numCoinbaseSigOps)
|
||||||
|
|
||||||
|
@ -776,9 +796,11 @@ mempoolLoop:
|
||||||
blockSize, btcchain.CompactToBig(msgBlock.Header.Bits))
|
blockSize, btcchain.CompactToBig(msgBlock.Header.Bits))
|
||||||
|
|
||||||
return &BlockTemplate{
|
return &BlockTemplate{
|
||||||
block: &msgBlock,
|
block: &msgBlock,
|
||||||
fees: txFees,
|
fees: txFees,
|
||||||
sigOpCounts: txSigOpCounts,
|
sigOpCounts: txSigOpCounts,
|
||||||
|
height: nextBlockHeight,
|
||||||
|
validPayAddress: payToAddress != nil,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -813,7 +835,7 @@ func UpdateBlockTime(msgBlock *btcwire.MsgBlock, bManager *blockManager) error {
|
||||||
|
|
||||||
// UpdateExtraNonce updates the extra nonce in the coinbase script of the passed
|
// UpdateExtraNonce updates the extra nonce in the coinbase script of the passed
|
||||||
// block by regenerating the coinbase script with the passed value and block
|
// block by regenerating the coinbase script with the passed value and block
|
||||||
// height. It also recalculates and updates the new merkle root the results
|
// height. It also recalculates and updates the new merkle root that results
|
||||||
// from changing the coinbase script.
|
// from changing the coinbase script.
|
||||||
func UpdateExtraNonce(msgBlock *btcwire.MsgBlock, blockHeight int64, extraNonce uint64) error {
|
func UpdateExtraNonce(msgBlock *btcwire.MsgBlock, blockHeight int64, extraNonce uint64) error {
|
||||||
coinbaseScript := standardCoinbaseScript(blockHeight, extraNonce)
|
coinbaseScript := standardCoinbaseScript(blockHeight, extraNonce)
|
||||||
|
|
|
@ -1621,7 +1621,7 @@ func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
|
||||||
rand.Seed(time.Now().UnixNano())
|
rand.Seed(time.Now().UnixNano())
|
||||||
payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
|
payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
|
||||||
|
|
||||||
template, err := NewBlockTemplate(payToAddr, s.server.txMemPool)
|
template, err := NewBlockTemplate(s.server.txMemPool, payToAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr := fmt.Sprintf("Failed to create new block "+
|
errStr := fmt.Sprintf("Failed to create new block "+
|
||||||
"template: %v", err)
|
"template: %v", err)
|
||||||
|
|
Loading…
Reference in a new issue