mining: Export block template fields. (#659)

This simply exports and adds some comments to the fields of the
BlockTemplate struct.

This is primarily being done as a step toward being able to separate the
mining code into its own package, but also it makes sense on its own
because code that requests new block template necessarily examines the
returned fields which implies they should be exported.
This commit is contained in:
Dave Collins 2016-04-11 10:27:29 -05:00
parent cab74feb59
commit a3fa066745
3 changed files with 50 additions and 31 deletions

View file

@ -318,8 +318,8 @@ out:
// with false when conditions that trigger a stale block, so
// a new block template can be generated. When the return is
// true a solution was found, so submit the solved block.
if m.solveBlock(template.block, curHeight+1, ticker, quit) {
block := btcutil.NewBlock(template.block)
if m.solveBlock(template.Block, curHeight+1, ticker, quit) {
block := btcutil.NewBlock(template.Block)
m.submitBlock(block)
}
}
@ -580,8 +580,8 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*wire.ShaHash, error) {
// with false when conditions that trigger a stale block, so
// a new block template can be generated. When the return is
// true a solution was found, so submit the solved block.
if m.solveBlock(template.block, curHeight+1, ticker, nil) {
block := btcutil.NewBlock(template.block)
if m.solveBlock(template.Block, curHeight+1, ticker, nil) {
block := btcutil.NewBlock(template.Block)
m.submitBlock(block)
blockHashes[i] = block.Sha()
i++

View file

@ -156,11 +156,30 @@ func newTxPriorityQueue(reserve int, sortByFee bool) *txPriorityQueue {
// details about the fees and the number of signature operations for each
// transaction in the block.
type BlockTemplate struct {
block *wire.MsgBlock
fees []int64
sigOpCounts []int64
height int32
validPayAddress bool
// Block is a block that is ready to be solved by miners. Thus, it is
// completely valid with the exception of satisfying the proof-of-work
// requirement.
Block *wire.MsgBlock
// Fees contains the amount of fees each transaction in the generated
// template pays in base units. Since the first transaction is the
// coinbase, the first entry (offset 0) will contain the negative of the
// sum of the fees of all other transactions.
Fees []int64
// SigOpCounts contains the number of signature operations each
// transaction in the generated template performs.
SigOpCounts []int64
// Height is the height at which the block template connects to the main
// chain.
Height int32
// ValidPayAddress indicates whether or not the template coinbase pays
// to an address or is redeemable by anyone. See the documentation on
// NewBlockTemplate for details on which this can be useful to generate
// templates without a coinbase payment address.
ValidPayAddress bool
}
// mergeTxStore adds all of the transactions in txStoreB to txStoreA. The
@ -750,11 +769,11 @@ mempoolLoop:
blockSize, blockchain.CompactToBig(msgBlock.Header.Bits))
return &BlockTemplate{
block: &msgBlock,
fees: txFees,
sigOpCounts: txSigOpCounts,
height: nextBlockHeight,
validPayAddress: payToAddress != nil,
Block: &msgBlock,
Fees: txFees,
SigOpCounts: txSigOpCounts,
Height: nextBlockHeight,
ValidPayAddress: payToAddress != nil,
}, nil
}

View file

@ -1534,7 +1534,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bo
"template: "+err.Error(), "")
}
template = blkTemplate
msgBlock = template.block
msgBlock = template.Block
targetDifficulty = fmt.Sprintf("%064x",
blockchain.CompactToBig(msgBlock.Header.Bits))
@ -1577,7 +1577,7 @@ func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bo
// template if it doesn't already have one. Since this requires
// mining addresses to be specified via the config, an error is
// returned if none have been specified.
if !useCoinbaseValue && !template.validPayAddress {
if !useCoinbaseValue && !template.ValidPayAddress {
// Choose a payment address at random.
payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
@ -1588,17 +1588,17 @@ func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bo
context := "Failed to create pay-to-addr script"
return internalRPCError(err.Error(), context)
}
template.block.Transactions[0].TxOut[0].PkScript = pkScript
template.validPayAddress = true
template.Block.Transactions[0].TxOut[0].PkScript = pkScript
template.ValidPayAddress = true
// Update the merkle root.
block := btcutil.NewBlock(template.block)
block := btcutil.NewBlock(template.Block)
merkles := blockchain.BuildMerkleTreeStore(block.Transactions())
template.block.Header.MerkleRoot = *merkles[len(merkles)-1]
template.Block.Header.MerkleRoot = *merkles[len(merkles)-1]
}
// Set locals for convenience.
msgBlock = template.block
msgBlock = template.Block
targetDifficulty = fmt.Sprintf("%064x",
blockchain.CompactToBig(msgBlock.Header.Bits))
@ -1627,7 +1627,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
// after the template is generated, but it's important to avoid serving
// invalid block templates.
template := state.template
msgBlock := template.block
msgBlock := template.Block
header := &msgBlock.Header
adjustedTime := state.timeSource.AdjustedTime()
maxTime := adjustedTime.Add(time.Second * blockchain.MaxTimeOffsetSeconds)
@ -1684,8 +1684,8 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
Data: hex.EncodeToString(txBuf.Bytes()),
Hash: txHash.String(),
Depends: depends,
Fee: template.fees[i],
SigOps: template.sigOpCounts[i],
Fee: template.Fees[i],
SigOps: template.SigOpCounts[i],
}
transactions = append(transactions, resultTx)
}
@ -1699,7 +1699,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
reply := btcjson.GetBlockTemplateResult{
Bits: strconv.FormatInt(int64(header.Bits), 16),
CurTime: header.Timestamp.Unix(),
Height: int64(template.height),
Height: int64(template.Height),
PreviousHash: header.PrevBlock.String(),
SigOpLimit: blockchain.MaxSigOpsPerBlock,
SizeLimit: wire.MaxBlockPayload,
@ -1720,7 +1720,7 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
} else {
// Ensure the template has a valid payment address associated
// with it when a full coinbase is requested.
if !template.validPayAddress {
if !template.ValidPayAddress {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInternal.Code,
Message: "A coinbase transaction has been " +
@ -1742,8 +1742,8 @@ func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld
Data: hex.EncodeToString(txBuf.Bytes()),
Hash: tx.TxSha().String(),
Depends: []int64{},
Fee: template.fees[0],
SigOps: template.sigOpCounts[0],
Fee: template.Fees[0],
SigOps: template.SigOpCounts[0],
}
reply.CoinbaseTxn = &resultTx
@ -1791,7 +1791,7 @@ func handleGetBlockTemplateLongPoll(s *rpcServer, longPollID string, useCoinbase
// Return the block template now if the specific block template
// identified by the long poll ID no longer matches the current block
// template as this means the provided template is stale.
prevTemplateHash := &state.template.block.Header.PrevBlock
prevTemplateHash := &state.template.Block.Header.PrevBlock
if !prevHash.IsEqual(prevTemplateHash) ||
lastGenerated != state.lastGenerated.Unix() {
@ -1839,7 +1839,7 @@ func handleGetBlockTemplateLongPoll(s *rpcServer, longPollID string, useCoinbase
// Include whether or not it is valid to submit work against the old
// block template depending on whether or not a solution has already
// been found and added to the block chain.
submitOld := prevHash.IsEqual(&state.template.block.Header.PrevBlock)
submitOld := prevHash.IsEqual(&state.template.Block.Header.PrevBlock)
result, err := state.blockTemplateResult(useCoinbaseValue, &submitOld)
if err != nil {
return nil, err
@ -2723,7 +2723,7 @@ func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
context := "Failed to create new block template"
return nil, internalRPCError(err.Error(), context)
}
msgBlock = template.block
msgBlock = template.Block
// Update work state to ensure another block template isn't
// generated until needed.