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 // with false when conditions that trigger a stale block, so
// a new block template can be generated. When the return is // a new block template can be generated. When the return is
// true a solution was found, so submit the solved block. // true a solution was found, so submit the solved block.
if m.solveBlock(template.block, curHeight+1, ticker, quit) { if m.solveBlock(template.Block, curHeight+1, ticker, quit) {
block := btcutil.NewBlock(template.block) block := btcutil.NewBlock(template.Block)
m.submitBlock(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 // with false when conditions that trigger a stale block, so
// a new block template can be generated. When the return is // a new block template can be generated. When the return is
// true a solution was found, so submit the solved block. // true a solution was found, so submit the solved block.
if m.solveBlock(template.block, curHeight+1, ticker, nil) { if m.solveBlock(template.Block, curHeight+1, ticker, nil) {
block := btcutil.NewBlock(template.block) block := btcutil.NewBlock(template.Block)
m.submitBlock(block) m.submitBlock(block)
blockHashes[i] = block.Sha() blockHashes[i] = block.Sha()
i++ 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 // 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 *wire.MsgBlock // Block is a block that is ready to be solved by miners. Thus, it is
fees []int64 // completely valid with the exception of satisfying the proof-of-work
sigOpCounts []int64 // requirement.
height int32 Block *wire.MsgBlock
validPayAddress bool
// 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 // mergeTxStore adds all of the transactions in txStoreB to txStoreA. The
@ -750,11 +769,11 @@ mempoolLoop:
blockSize, blockchain.CompactToBig(msgBlock.Header.Bits)) blockSize, blockchain.CompactToBig(msgBlock.Header.Bits))
return &BlockTemplate{ return &BlockTemplate{
block: &msgBlock, Block: &msgBlock,
fees: txFees, Fees: txFees,
sigOpCounts: txSigOpCounts, SigOpCounts: txSigOpCounts,
height: nextBlockHeight, Height: nextBlockHeight,
validPayAddress: payToAddress != nil, ValidPayAddress: payToAddress != nil,
}, nil }, nil
} }

View file

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