mining+config: modify GBT mining to limit by weight, add witness commitment

This commit modifies the existing block selection logic to limit
preferentially by weight instead of serialized block size, and also to
adhere to the new sig-op cost limits which are weighted according to
the witness discount.
This commit is contained in:
Olaoluwa Osuntokun 2016-10-19 09:57:23 -07:00 committed by Dave Collins
parent 8b130ec4ea
commit 1244c45b88
5 changed files with 172 additions and 72 deletions

View file

@ -1473,6 +1473,7 @@ func newBlockManager(s *server, indexManager blockchain.IndexManager) (*blockMan
Notifications: bm.handleNotifyMsg, Notifications: bm.handleNotifyMsg,
SigCache: s.sigCache, SigCache: s.sigCache,
IndexManager: indexManager, IndexManager: indexManager,
HashCache: s.hashCache,
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View file

@ -20,13 +20,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/btcsuite/btcd/blockchain"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/connmgr" "github.com/btcsuite/btcd/connmgr"
"github.com/btcsuite/btcd/database" "github.com/btcsuite/btcd/database"
_ "github.com/btcsuite/btcd/database/ffldb" _ "github.com/btcsuite/btcd/database/ffldb"
"github.com/btcsuite/btcd/mempool" "github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/go-socks/socks" "github.com/btcsuite/go-socks/socks"
flags "github.com/jessevdk/go-flags" flags "github.com/jessevdk/go-flags"
@ -49,8 +49,12 @@ const (
defaultFreeTxRelayLimit = 15.0 defaultFreeTxRelayLimit = 15.0
defaultBlockMinSize = 0 defaultBlockMinSize = 0
defaultBlockMaxSize = 750000 defaultBlockMaxSize = 750000
defaultBlockMinWeight = 0
defaultBlockMaxWeight = 3000000
blockMaxSizeMin = 1000 blockMaxSizeMin = 1000
blockMaxSizeMax = wire.MaxBlockPayload - 1000 blockMaxSizeMax = blockchain.MaxBlockBaseSize - 1000
blockMaxWeightMin = 4000
blockMaxWeightMax = blockchain.MaxBlockWeight - 4000
defaultGenerate = false defaultGenerate = false
defaultMaxOrphanTransactions = 100 defaultMaxOrphanTransactions = 100
defaultMaxOrphanTxSize = 100000 defaultMaxOrphanTxSize = 100000
@ -140,6 +144,8 @@ type config struct {
MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"` MiningAddrs []string `long:"miningaddr" description:"Add the specified payment address to the list of addresses to use for generated blocks -- At least one address is required if the generate option is set"`
BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"` BlockMinSize uint32 `long:"blockminsize" description:"Mininum block size in bytes to be used when creating a block"`
BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"` BlockMaxSize uint32 `long:"blockmaxsize" description:"Maximum block size in bytes to be used when creating a block"`
BlockMinWeight uint32 `long:"blockminweight" description:"Mininum block weight to be used when creating a block"`
BlockMaxWeight uint32 `long:"blockmaxweight" description:"Maximum block weight to be used when creating a block"`
BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"` BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."` UserAgentComments []string `long:"uacomment" description:"Comment to add to the user agent -- See BIP 14 for more information."`
NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"` NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
@ -407,6 +413,8 @@ func loadConfig() (*config, []string, error) {
FreeTxRelayLimit: defaultFreeTxRelayLimit, FreeTxRelayLimit: defaultFreeTxRelayLimit,
BlockMinSize: defaultBlockMinSize, BlockMinSize: defaultBlockMinSize,
BlockMaxSize: defaultBlockMaxSize, BlockMaxSize: defaultBlockMaxSize,
BlockMinWeight: defaultBlockMinWeight,
BlockMaxWeight: defaultBlockMaxWeight,
BlockPrioritySize: mempool.DefaultBlockPrioritySize, BlockPrioritySize: mempool.DefaultBlockPrioritySize,
MaxOrphanTxs: defaultMaxOrphanTransactions, MaxOrphanTxs: defaultMaxOrphanTransactions,
SigCacheMaxSize: defaultSigCacheMaxSize, SigCacheMaxSize: defaultSigCacheMaxSize,
@ -531,8 +539,8 @@ func loadConfig() (*config, []string, error) {
cfg.DisableDNSSeed = true cfg.DisableDNSSeed = true
} }
if numNets > 1 { if numNets > 1 {
str := "%s: The testnet, regtest, and simnet params can't be " + str := "%s: The testnet, regtest, segnet, and simnet params " +
"used together -- choose one of the three" "can't be used together -- choose one of the four"
err := fmt.Errorf(str, funcName) err := fmt.Errorf(str, funcName)
fmt.Fprintln(os.Stderr, err) fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage) fmt.Fprintln(os.Stderr, usageMessage)
@ -723,7 +731,20 @@ func loadConfig() (*config, []string, error) {
return nil, nil, err return nil, nil, err
} }
// Limit the max orphan count to a sane value. // Limit the max block weight to a sane value.
if cfg.BlockMaxWeight < blockMaxWeightMin ||
cfg.BlockMaxWeight > blockMaxWeightMax {
str := "%s: The blockmaxweight option must be in between %d " +
"and %d -- parsed [%d]"
err := fmt.Errorf(str, funcName, blockMaxWeightMin,
blockMaxWeightMax, cfg.BlockMaxWeight)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
// Limit the max orphan count to a sane vlue.
if cfg.MaxOrphanTxs < 0 { if cfg.MaxOrphanTxs < 0 {
str := "%s: The maxorphantx option may not be less than 0 " + str := "%s: The maxorphantx option may not be less than 0 " +
"-- parsed [%d]" "-- parsed [%d]"
@ -736,6 +757,24 @@ func loadConfig() (*config, []string, error) {
// Limit the block priority and minimum block sizes to max block size. // Limit the block priority and minimum block sizes to max block size.
cfg.BlockPrioritySize = minUint32(cfg.BlockPrioritySize, cfg.BlockMaxSize) cfg.BlockPrioritySize = minUint32(cfg.BlockPrioritySize, cfg.BlockMaxSize)
cfg.BlockMinSize = minUint32(cfg.BlockMinSize, cfg.BlockMaxSize) cfg.BlockMinSize = minUint32(cfg.BlockMinSize, cfg.BlockMaxSize)
cfg.BlockMinWeight = minUint32(cfg.BlockMinWeight, cfg.BlockMaxWeight)
switch {
// If the max block size isn't set, but the max weight is, then we'll
// set the limit for the max block size to a safe limit so weight takes
// precedence.
case cfg.BlockMaxSize == defaultBlockMaxSize &&
cfg.BlockMaxWeight != defaultBlockMaxWeight:
cfg.BlockMaxSize = blockchain.MaxBlockBaseSize - 1000
// If the max block weight isn't set, but the block size is, then we'll
// scale the set weight accordingly based on the max block size value.
case cfg.BlockMaxSize != defaultBlockMaxSize &&
cfg.BlockMaxWeight == defaultBlockMaxWeight:
cfg.BlockMaxWeight = cfg.BlockMaxSize * blockchain.WitnessScaleFactor
}
// Look for illegal characters in the user agent comments. // Look for illegal characters in the user agent comments.
for _, uaComment := range cfg.UserAgentComments { for _, uaComment := range cfg.UserAgentComments {

View file

@ -197,9 +197,9 @@ type BlockTemplate struct {
// sum of the fees of all other transactions. // sum of the fees of all other transactions.
Fees []int64 Fees []int64
// SigOpCounts contains the number of signature operations each // SigOpCosts contains the number of signature operations each
// transaction in the generated template performs. // transaction in the generated template performs.
SigOpCounts []int64 SigOpCosts []int64
// Height is the height at which the block template connects to the main // Height is the height at which the block template connects to the main
// chain. // chain.
@ -210,6 +210,12 @@ type BlockTemplate struct {
// NewBlockTemplate for details on which this can be useful to generate // NewBlockTemplate for details on which this can be useful to generate
// templates without a coinbase payment address. // templates without a coinbase payment address.
ValidPayAddress bool ValidPayAddress bool
// WitnessCommitment is a commitment to the witness data (if any)
// within the block. This field will only be populted once segregated
// witness has been activated, and the block contains a transaction
// which has witness data.
WitnessCommitment []byte
} }
// mergeUtxoView adds all of the entries in view to viewA. The result is that // mergeUtxoView adds all of the entries in view to viewA. The result is that
@ -347,6 +353,7 @@ type BlkTmplGenerator struct {
chain *blockchain.BlockChain chain *blockchain.BlockChain
timeSource blockchain.MedianTimeSource timeSource blockchain.MedianTimeSource
sigCache *txscript.SigCache sigCache *txscript.SigCache
hashCache *txscript.HashCache
} }
// NewBlkTmplGenerator returns a new block template generator for the given // NewBlkTmplGenerator returns a new block template generator for the given
@ -358,7 +365,8 @@ type BlkTmplGenerator struct {
func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params, func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params,
txSource TxSource, chain *blockchain.BlockChain, txSource TxSource, chain *blockchain.BlockChain,
timeSource blockchain.MedianTimeSource, timeSource blockchain.MedianTimeSource,
sigCache *txscript.SigCache) *BlkTmplGenerator { sigCache *txscript.SigCache,
hashCache *txscript.HashCache) *BlkTmplGenerator {
return &BlkTmplGenerator{ return &BlkTmplGenerator{
policy: policy, policy: policy,
@ -367,6 +375,7 @@ func NewBlkTmplGenerator(policy *Policy, params *chaincfg.Params,
chain: chain, chain: chain,
timeSource: timeSource, timeSource: timeSource,
sigCache: sigCache, sigCache: sigCache,
hashCache: hashCache,
} }
} }
@ -451,12 +460,13 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*Bloc
if err != nil { if err != nil {
return nil, err return nil, err
} }
// TODO(roasbeef): add witnesss commitment output
coinbaseTx, err := createCoinbaseTx(g.chainParams, coinbaseScript, coinbaseTx, err := createCoinbaseTx(g.chainParams, coinbaseScript,
nextBlockHeight, payToAddress) nextBlockHeight, payToAddress)
if err != nil { if err != nil {
return nil, err return nil, err
} }
numCoinbaseSigOps := int64(blockchain.CountSigOps(coinbaseTx)) coinbaseSigOpCost := int64(blockchain.CountSigOps(coinbaseTx)) * blockchain.WitnessScaleFactor
// Get the current source transactions and create a priority queue to // Get the current source transactions and create a priority queue to
// hold the transactions which are ready for inclusion into a block // hold the transactions which are ready for inclusion into a block
@ -490,9 +500,9 @@ func (g *BlkTmplGenerator) NewBlockTemplate(payToAddress btcutil.Address) (*Bloc
// 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, 0, len(sourceTxns)) txFees := make([]int64, 0, len(sourceTxns))
txSigOpCounts := make([]int64, 0, len(sourceTxns)) txSigOpCosts := make([]int64, 0, len(sourceTxns))
txFees = append(txFees, -1) // Updated once known txFees = append(txFees, -1) // Updated once known
txSigOpCounts = append(txSigOpCounts, numCoinbaseSigOps) txSigOpCosts = append(txSigOpCosts, coinbaseSigOpCost)
log.Debugf("Considering %d transactions for inclusion to new block", log.Debugf("Considering %d transactions for inclusion to new block",
len(sourceTxns)) len(sourceTxns))
@ -570,6 +580,7 @@ mempoolLoop:
nextBlockHeight) nextBlockHeight)
// Calculate the fee in Satoshi/kB. // Calculate the fee in Satoshi/kB.
// TODO(roasbeef): cost accounting by weight
prioItem.feePerKB = txDesc.FeePerKB prioItem.feePerKB = txDesc.FeePerKB
prioItem.fee = txDesc.Fee prioItem.fee = txDesc.Fee
@ -591,10 +602,14 @@ mempoolLoop:
// The starting block size is the size of the block header plus the max // The starting block size is the size of the block header plus the max
// possible transaction count size, plus the size of the coinbase // possible transaction count size, plus the size of the coinbase
// transaction. // transaction.
blockSize := blockHeaderOverhead + uint32(coinbaseTx.MsgTx().SerializeSize()) blockWeight := uint32((blockHeaderOverhead * (blockchain.WitnessScaleFactor - 1)) + blockchain.GetTransactionWeight(coinbaseTx))
blockSigOps := numCoinbaseSigOps blockSigOpCost := coinbaseSigOpCost
totalFees := int64(0) totalFees := int64(0)
// TODO(roasbeef): should be guarded by version bits state check
var witnessIncluded bool
includeWitness := true
// Choose which transactions make it into the block. // Choose which transactions make it into the block.
for priorityQueue.Len() > 0 { for priorityQueue.Len() > 0 {
// Grab the highest priority (or highest fee per kilobyte // Grab the highest priority (or highest fee per kilobyte
@ -602,45 +617,73 @@ mempoolLoop:
prioItem := heap.Pop(priorityQueue).(*txPrioItem) prioItem := heap.Pop(priorityQueue).(*txPrioItem)
tx := prioItem.tx tx := prioItem.tx
switch {
// If segregated witness has not been activated yet, then we
// shouldn't include any witness transactions in the block.
case tx.HasWitness() && !segwitActive:
continue
// Otherwise, Keep track of if we've included a transaction
// with witness data or not. If so, then we'll need to include
// the witness commitment as the last output in the coinbase
// transaction.
case tx.HasWitness() && segwitActive:
// If we're about to include a transaction bearing
// witness data, then we'll also need to include a
// witness commitment in the coinbase transaction.
// Therefore, we account for the additional weight
// within the block.
if !witnessIncluded {
// First we account for the additional witness
// data in the witness nonce of the coinbaes
// transaction: 32-bytes of zeroes.
blockWeight += 2 + 32
// Next we account for the additional flag and
// marker bytes in the transaction
// serialization.
blockWeight += (1 + 1) * blockchain.WitnessScaleFactor
// Finally we account for the weight of the
// additional OP_RETURN output: 8-bytes (value)
// + 1-byte (var-int) + 38-bytes (pkScript),
// scaling up the weight as it's non-witness
// data.
blockWeight += (8 + 1 + 38) * blockchain.WitnessScaleFactor
}
witnessIncluded = true
}
// Grab any transactions which depend on this one. // Grab any transactions which depend on this one.
deps := dependers[*tx.Hash()] deps := dependers[*tx.Hash()]
// Enforce maximum block size. Also check for overflow. // Enforce maximum block size. Also check for overflow.
txSize := uint32(tx.MsgTx().SerializeSize()) txWeight := uint32(blockchain.GetTransactionWeight(tx))
blockPlusTxSize := blockSize + txSize blockPlusTxWeight := uint32(blockWeight + txWeight)
if blockPlusTxSize < blockSize || if blockPlusTxWeight < blockWeight ||
blockPlusTxSize >= g.policy.BlockMaxSize { blockPlusTxWeight >= g.policy.BlockMaxWeight {
log.Tracef("Skipping tx %s because it would exceed "+ log.Tracef("Skipping tx %s because it would exceed "+
"the max block size", tx.Hash()) "the max block weight", tx.Hash())
logSkippedDeps(tx, deps) logSkippedDeps(tx, deps)
continue continue
} }
// Enforce maximum signature operations per block. Also check // Enforce maximum signature operation cost per block. Also
// for overflow. // check for overflow.
numSigOps := int64(blockchain.CountSigOps(tx)) sigOpCost, err := blockchain.GetSigOpCost(tx, false,
if blockSigOps+numSigOps < blockSigOps || blockUtxos, true, includeWitness)
blockSigOps+numSigOps > blockchain.MaxSigOpsPerBlock {
log.Tracef("Skipping tx %s because it would exceed "+
"the maximum sigops per block", tx.Hash())
logSkippedDeps(tx, deps)
continue
}
numP2SHSigOps, err := blockchain.CountP2SHSigOps(tx, false,
blockUtxos)
if err != nil { if err != nil {
log.Tracef("Skipping tx %s due to error in "+ log.Tracef("Skipping tx %s due to error in "+
"CountP2SHSigOps: %v", tx.Hash(), err) "GetSigOpCost: %v", tx.Hash(), err)
logSkippedDeps(tx, deps) logSkippedDeps(tx, deps)
continue continue
} }
numSigOps += int64(numP2SHSigOps) if blockSigOpCost+int64(sigOpCost) < blockSigOpCost ||
if blockSigOps+numSigOps < blockSigOps || blockSigOpCost+int64(sigOpCost) > blockchain.MaxBlockSigOpsCost {
blockSigOps+numSigOps > blockchain.MaxSigOpsPerBlock { log.Tracef("Skipping tx %s because it would "+
log.Tracef("Skipping tx %s because it would exceed "+ "exceed the maximum sigops per block", tx.Hash())
"the maximum sigops per block (p2sh)",
tx.Hash())
logSkippedDeps(tx, deps) logSkippedDeps(tx, deps)
continue continue
} }
@ -649,13 +692,13 @@ mempoolLoop:
// minimum block size. // minimum block size.
if sortedByFee && if sortedByFee &&
prioItem.feePerKB < int64(g.policy.TxMinFreeFee) && prioItem.feePerKB < int64(g.policy.TxMinFreeFee) &&
blockPlusTxSize >= g.policy.BlockMinSize { blockPlusTxWeight >= g.policy.BlockMinWeight {
log.Tracef("Skipping tx %s with feePerKB %.2f "+ log.Tracef("Skipping tx %s with feePerKB %d "+
"< TxMinFreeFee %d and block size %d >= "+ "< TxMinFreeFee %d and block weight %d >= "+
"minBlockSize %d", tx.Hash(), prioItem.feePerKB, "minBlockWeight %d", tx.Hash(), prioItem.feePerKB,
g.policy.TxMinFreeFee, blockPlusTxSize, g.policy.TxMinFreeFee, blockPlusTxWeight,
g.policy.BlockMinSize) g.policy.BlockMinWeight)
logSkippedDeps(tx, deps) logSkippedDeps(tx, deps)
continue continue
} }
@ -663,13 +706,13 @@ mempoolLoop:
// Prioritize by fee per kilobyte once the block is larger than // Prioritize by fee per kilobyte once the block is larger than
// the priority size or there are no more high-priority // the priority size or there are no more high-priority
// transactions. // transactions.
if !sortedByFee && (blockPlusTxSize >= g.policy.BlockPrioritySize || if !sortedByFee && (blockPlusTxWeight >= g.policy.BlockPrioritySize ||
prioItem.priority <= MinHighPriority) { prioItem.priority <= MinHighPriority) {
log.Tracef("Switching to sort by fees per kilobyte "+ log.Tracef("Switching to sort by fees per "+
"blockSize %d >= BlockPrioritySize %d || "+ "kilobyte blockSize %d >= BlockPrioritySize "+
"priority %.2f <= minHighPriority %.2f", "%d || priority %.2f <= minHighPriority %.2f",
blockPlusTxSize, g.policy.BlockPrioritySize, blockPlusTxWeight, g.policy.BlockPrioritySize,
prioItem.priority, MinHighPriority) prioItem.priority, MinHighPriority)
sortedByFee = true sortedByFee = true
@ -677,11 +720,11 @@ mempoolLoop:
// Put the transaction back into the priority queue and // Put the transaction back into the priority queue and
// skip it so it is re-priortized by fees if it won't // skip it so it is re-priortized by fees if it won't
// fit into the high-priority section or the priority is // fit into the high-priority section or the priority
// too low. Otherwise this transaction will be the // is too low. Otherwise this transaction will be the
// final one in the high-priority section, so just fall // final one in the high-priority section, so just fall
// though to the code below so it is added now. // though to the code below so it is added now.
if blockPlusTxSize > g.policy.BlockPrioritySize || if blockPlusTxWeight > g.policy.BlockPrioritySize ||
prioItem.priority < MinHighPriority { prioItem.priority < MinHighPriority {
heap.Push(priorityQueue, prioItem) heap.Push(priorityQueue, prioItem)
@ -700,11 +743,11 @@ mempoolLoop:
continue continue
} }
err = blockchain.ValidateTransactionScripts(tx, blockUtxos, err = blockchain.ValidateTransactionScripts(tx, blockUtxos,
txscript.StandardVerifyFlags, g.sigCache) txscript.StandardVerifyFlags, g.sigCache,
g.hashCache)
if err != nil { if err != nil {
log.Tracef("Skipping tx %s due to error in "+ log.Tracef("Skipping tx %s due to error in "+
"ValidateTransactionScripts: %v", tx.Hash(), "ValidateTransactionScripts: %v", tx.Hash(), err)
err)
logSkippedDeps(tx, deps) logSkippedDeps(tx, deps)
continue continue
} }
@ -719,11 +762,11 @@ mempoolLoop:
// save the fees and signature operation counts to the block // save the fees and signature operation counts to the block
// template. // template.
blockTxns = append(blockTxns, tx) blockTxns = append(blockTxns, tx)
blockSize += txSize blockWeight += txWeight
blockSigOps += numSigOps blockSigOpCost += int64(sigOpCost)
totalFees += prioItem.fee totalFees += prioItem.fee
txFees = append(txFees, prioItem.fee) txFees = append(txFees, prioItem.fee)
txSigOpCounts = append(txSigOpCounts, numSigOps) txSigOpCosts = append(txSigOpCosts, int64(sigOpCost))
log.Tracef("Adding tx %s (priority %.2f, feePerKB %.2f)", log.Tracef("Adding tx %s (priority %.2f, feePerKB %.2f)",
prioItem.tx.Hash(), prioItem.priority, prioItem.feePerKB) prioItem.tx.Hash(), prioItem.priority, prioItem.feePerKB)
@ -742,13 +785,18 @@ mempoolLoop:
} }
// Now that the actual transactions have been selected, update the // Now that the actual transactions have been selected, update the
// block size for the real transaction count and coinbase value with // block weight for the real transaction count and coinbase value with
// the total fees accordingly. // the total fees accordingly.
blockSize -= wire.MaxVarIntPayload - blockWeight -= wire.MaxVarIntPayload -
uint32(wire.VarIntSerializeSize(uint64(len(blockTxns)))) (uint32(wire.VarIntSerializeSize(uint64(len(blockTxns)))) *
(blockchain.WitnessScaleFactor - 1))
coinbaseTx.MsgTx().TxOut[0].Value += totalFees coinbaseTx.MsgTx().TxOut[0].Value += totalFees
txFees[0] = -totalFees txFees[0] = -totalFees
// TODO(roasbeef): add witness commitment
if witnessIncluded {
}
// Calculate the required difficulty for the block. The timestamp // Calculate the required difficulty for the block. The timestamp
// is potentially adjusted to ensure it comes after the median time of // is potentially adjusted to ensure it comes after the median time of
// the last several blocks per the chain consensus rules. // the last several blocks per the chain consensus rules.
@ -766,7 +814,7 @@ mempoolLoop:
} }
// Create a new block ready to be solved. // Create a new block ready to be solved.
merkles := blockchain.BuildMerkleTreeStore(blockTxns) merkles := blockchain.BuildMerkleTreeStore(blockTxns, false)
var msgBlock wire.MsgBlock var msgBlock wire.MsgBlock
msgBlock.Header = wire.BlockHeader{ msgBlock.Header = wire.BlockHeader{
Version: nextBlockVersion, Version: nextBlockVersion,
@ -790,15 +838,15 @@ mempoolLoop:
return nil, err return nil, err
} }
log.Debugf("Created new block template (%d transactions, %d in fees, "+ log.Debugf("Created new block template (%d transactions, %d in "+
"%d signature operations, %d bytes, target difficulty %064x)", "fees, %d signature operations cost, %d weight, target difficulty "+
len(msgBlock.Transactions), totalFees, blockSigOps, blockSize, "%064x)", len(msgBlock.Transactions), totalFees, blockSigOpCost,
blockchain.CompactToBig(msgBlock.Header.Bits)) blockWeight, blockchain.CompactToBig(msgBlock.Header.Bits))
return &BlockTemplate{ return &BlockTemplate{
Block: &msgBlock, Block: &msgBlock,
Fees: txFees, Fees: txFees,
SigOpCounts: txSigOpCounts, SigOpCosts: txSigOpCosts,
Height: nextBlockHeight, Height: nextBlockHeight,
ValidPayAddress: payToAddress != nil, ValidPayAddress: payToAddress != nil,
}, nil }, nil
@ -852,7 +900,7 @@ func (g *BlkTmplGenerator) UpdateExtraNonce(msgBlock *wire.MsgBlock, blockHeight
// Recalculate the merkle root with the updated extra nonce. // Recalculate the merkle root with the updated extra nonce.
block := btcutil.NewBlock(msgBlock) block := btcutil.NewBlock(msgBlock)
merkles := blockchain.BuildMerkleTreeStore(block.Transactions()) merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false)
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1] msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
return nil return nil
} }

View file

@ -21,12 +21,20 @@ const (
// the generation of block templates. See the documentation for // the generation of block templates. See the documentation for
// NewBlockTemplate for more details on each of these parameters are used. // NewBlockTemplate for more details on each of these parameters are used.
type Policy struct { type Policy struct {
// BlockMinSize is the minimum block size in bytes to be used when // BlockMinWeight is the minimum block weight to be used when
// generating a block template. // generating a block template.
BlockMinWeight uint32
// BlockMaxWeight is the maximum block weight to be used when
// generating a block template.
BlockMaxWeight uint32
// BlockMinWeight is the minimum block size to be used when generating
// a block template.
BlockMinSize uint32 BlockMinSize uint32
// BlockMaxSize is the maximum block size in bytes to be used when // BlockMaxSize is the maximum block size to be used when generating a
// generating a block template. // block template.
BlockMaxSize uint32 BlockMaxSize uint32
// BlockPrioritySize is the size in bytes for high-priority / low-fee // BlockPrioritySize is the size in bytes for high-priority / low-fee

View file

@ -173,6 +173,7 @@ type server struct {
addrManager *addrmgr.AddrManager addrManager *addrmgr.AddrManager
connManager *connmgr.ConnManager connManager *connmgr.ConnManager
sigCache *txscript.SigCache sigCache *txscript.SigCache
hashCache *txscript.HashCache
rpcServer *rpcServer rpcServer *rpcServer
blockManager *blockManager blockManager *blockManager
txMemPool *mempool.TxPool txMemPool *mempool.TxPool
@ -2412,6 +2413,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
timeSource: blockchain.NewMedianTime(), timeSource: blockchain.NewMedianTime(),
services: services, services: services,
sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize), sigCache: txscript.NewSigCache(cfg.SigCacheMaxSize),
hashCache: txscript.NewHashCache(cfg.SigCacheMaxSize),
} }
// Create the transaction and address indexes if needed. // Create the transaction and address indexes if needed.
@ -2459,7 +2461,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
FreeTxRelayLimit: cfg.FreeTxRelayLimit, FreeTxRelayLimit: cfg.FreeTxRelayLimit,
MaxOrphanTxs: cfg.MaxOrphanTxs, MaxOrphanTxs: cfg.MaxOrphanTxs,
MaxOrphanTxSize: defaultMaxOrphanTxSize, MaxOrphanTxSize: defaultMaxOrphanTxSize,
MaxSigOpsPerTx: blockchain.MaxSigOpsPerBlock / 5, MaxSigOpCostPerTx: blockchain.MaxBlockSigOpsCost / 4,
MinRelayTxFee: cfg.minRelayTxFee, MinRelayTxFee: cfg.minRelayTxFee,
MaxTxVersion: 2, MaxTxVersion: 2,
}, },
@ -2483,6 +2485,8 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
// NOTE: The CPU miner relies on the mempool, so the mempool has to be // NOTE: The CPU miner relies on the mempool, so the mempool has to be
// created before calling the function to create the CPU miner. // created before calling the function to create the CPU miner.
policy := mining.Policy{ policy := mining.Policy{
BlockMinWeight: cfg.BlockMinWeight,
BlockMaxWeight: cfg.BlockMaxWeight,
BlockMinSize: cfg.BlockMinSize, BlockMinSize: cfg.BlockMinSize,
BlockMaxSize: cfg.BlockMaxSize, BlockMaxSize: cfg.BlockMaxSize,
BlockPrioritySize: cfg.BlockPrioritySize, BlockPrioritySize: cfg.BlockPrioritySize,
@ -2490,7 +2494,7 @@ func newServer(listenAddrs []string, db database.DB, chainParams *chaincfg.Param
} }
blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy, blockTemplateGenerator := mining.NewBlkTmplGenerator(&policy,
s.chainParams, s.txMemPool, s.blockManager.chain, s.timeSource, s.chainParams, s.txMemPool, s.blockManager.chain, s.timeSource,
s.sigCache) s.sigCache, s.hashCache)
s.cpuMiner = cpuminer.New(&cpuminer.Config{ s.cpuMiner = cpuminer.New(&cpuminer.Config{
ChainParams: chainParams, ChainParams: chainParams,
BlockTemplateGenerator: blockTemplateGenerator, BlockTemplateGenerator: blockTemplateGenerator,