From a3fa06674512523f61a50c67a4a8f315749fcd1e Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Mon, 11 Apr 2016 10:27:29 -0500 Subject: [PATCH] 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. --- cpuminer.go | 8 ++++---- mining.go | 39 +++++++++++++++++++++++++++++---------- rpcserver.go | 34 +++++++++++++++++----------------- 3 files changed, 50 insertions(+), 31 deletions(-) diff --git a/cpuminer.go b/cpuminer.go index 78fb8193..587288d3 100644 --- a/cpuminer.go +++ b/cpuminer.go @@ -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++ diff --git a/mining.go b/mining.go index 8314099a..4359fa47 100644 --- a/mining.go +++ b/mining.go @@ -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 } diff --git a/rpcserver.go b/rpcserver.go index 6194e672..8a4d3b8e 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -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.