mining: drop getwork support.

Since the Midstate is no longer needed, switch to using
crypto/sha256.
This commit is contained in:
David Hill 2017-01-11 10:00:16 -05:00
parent 7c44b6472f
commit ab0f30c00d
14 changed files with 48 additions and 509 deletions

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -9,12 +9,11 @@ import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/hmac"
"crypto/sha256"
"errors"
"fmt"
"hash"
"math/big"
"github.com/btcsuite/fastsha256"
)
// Errors returned by canonicalPadding.
@ -455,7 +454,7 @@ func nonceRFC6979(privkey *big.Int, hash []byte) *big.Int {
curve := S256()
q := curve.Params().N
x := privkey
alg := fastsha256.New
alg := sha256.New
qlen := q.BitLen()
holen := alg().Size()

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -7,12 +7,11 @@ package btcec
import (
"bytes"
"crypto/rand"
"crypto/sha256"
"encoding/hex"
"fmt"
"math/big"
"testing"
"github.com/btcsuite/fastsha256"
)
type signatureTest struct {
@ -558,7 +557,7 @@ func TestRFC6979(t *testing.T) {
for i, test := range tests {
privKey, _ := PrivKeyFromBytes(S256(), decodeHex(test.key))
hash := fastsha256.Sum256([]byte(test.msg))
hash := sha256.Sum256([]byte(test.msg))
// Ensure deterministically generated nonce is the expected value.
gotNonce := nonceRFC6979(privKey.D, hash[:]).Bytes()

View file

@ -1,33 +1,33 @@
// Copyright (c) 2015 The Decred developers
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2016-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package chainhash
import "github.com/btcsuite/fastsha256"
import "crypto/sha256"
// HashB calculates hash(b) and returns the resulting bytes.
func HashB(b []byte) []byte {
hash := fastsha256.Sum256(b)
hash := sha256.Sum256(b)
return hash[:]
}
// HashH calculates hash(b) and returns the resulting bytes as a Hash.
func HashH(b []byte) Hash {
return Hash(fastsha256.Sum256(b))
return Hash(sha256.Sum256(b))
}
// DoubleHashB calculates hash(hash(b)) and returns the resulting bytes.
func DoubleHashB(b []byte) []byte {
first := fastsha256.Sum256(b)
second := fastsha256.Sum256(first[:])
first := sha256.Sum256(b)
second := sha256.Sum256(first[:])
return second[:]
}
// DoubleHashH calculates hash(hash(b)) and returns the resulting bytes as a
// Hash.
func DoubleHashH(b []byte) Hash {
first := fastsha256.Sum256(b)
return Hash(fastsha256.Sum256(first[:]))
first := sha256.Sum256(b)
return Hash(sha256.Sum256(first[:]))
}

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -137,7 +137,6 @@ type config struct {
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"`
BlockPrioritySize uint32 `long:"blockprioritysize" description:"Size in bytes for high-priority/low-fee transactions when creating a block"`
GetWorkKeys []string `long:"getworkkey" description:"DEPRECATED -- Use the --miningaddr option instead"`
NoPeerBloomFilters bool `long:"nopeerbloomfilters" description:"Disable bloom filtering support"`
SigCacheMaxSize uint `long:"sigcachemaxsize" description:"The maximum number of entries in the signature verification cache"`
BlocksOnly bool `long:"blocksonly" description:"Do not accept transactions from remote peers."`
@ -717,30 +716,8 @@ func loadConfig() (*config, []string, error) {
return nil, nil, err
}
// Check getwork keys are valid and saved parsed versions.
cfg.miningAddrs = make([]btcutil.Address, 0, len(cfg.GetWorkKeys)+
len(cfg.MiningAddrs))
for _, strAddr := range cfg.GetWorkKeys {
addr, err := btcutil.DecodeAddress(strAddr,
activeNetParams.Params)
if err != nil {
str := "%s: getworkkey '%s' failed to decode: %v"
err := fmt.Errorf(str, funcName, strAddr, err)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
if !addr.IsForNet(activeNetParams.Params) {
str := "%s: getworkkey '%s' is on the wrong network"
err := fmt.Errorf(str, funcName, strAddr)
fmt.Fprintln(os.Stderr, err)
fmt.Fprintln(os.Stderr, usageMessage)
return nil, nil, err
}
cfg.miningAddrs = append(cfg.miningAddrs, addr)
}
// Check mining addresses are valid and saved parsed versions.
cfg.miningAddrs = make([]btcutil.Address, 0, len(cfg.MiningAddrs))
for _, strAddr := range cfg.MiningAddrs {
addr, err := btcutil.DecodeAddress(strAddr, activeNetParams.Params)
if err != nil {

3
doc.go
View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -106,7 +106,6 @@ Application Options:
a block (750000)
--blockprioritysize= Size in bytes for high-priority/low-fee transactions
when creating a block (50000)
--getworkkey= DEPRECATED -- Use the --miningaddr option instead
--nopeerbloomfilters Disable bloom filtering support.
--sigcachemaxsize= The maximum number of entries in the signature
verification cache.

View file

@ -155,9 +155,8 @@ For a list of available options, run: `$ btcctl --help`
<a name="Mining" />
**2.4 Mining**<br />
btcd supports both the `getwork` and `getblocktemplate` RPCs although the
`getwork` RPC is deprecated and will likely be removed in a future release.
The limited user cannot access these RPCs.<br />
btcd supports the `getblocktemplate` RPC.
The limited user cannot access this RPC.<br />
**1. Add the payment addresses with the `miningaddr` option.**<br />

View file

@ -170,15 +170,14 @@ the method name for further details such as parameter and return information.
|20|[getpeerinfo](#getpeerinfo)|N|Returns information about each connected network peer as an array of json objects.|
|21|[getrawmempool](#getrawmempool)|Y|Returns an array of hashes for all of the transactions currently in the memory pool.|
|22|[getrawtransaction](#getrawtransaction)|Y|Returns information about a transaction given its hash.|
|23|[getwork](#getwork)|N|Returns formatted hash data to work on or checks and submits solved data.<br /><font color="orange">NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.</font>|
|24|[help](#help)|Y|Returns a list of all commands or help for a specified command.|
|25|[ping](#ping)|N|Queues a ping to be sent to each connected peer.|
|26|[sendrawtransaction](#sendrawtransaction)|Y|Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.<br /><font color="orange">btcd does not yet implement the `allowhighfees` parameter, so it has no effect</font>|
|27|[setgenerate](#setgenerate) |N|Set the server to generate coins (mine) or not.<br/>NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.|
|28|[stop](#stop)|N|Shutdown btcd.|
|29|[submitblock](#submitblock)|Y|Attempts to submit a new serialized, hex-encoded block to the network.|
|30|[validateaddress](#validateaddress)|Y|Verifies the given address is valid. NOTE: Since btcd does not have a wallet integrated, btcd will only return whether the address is valid or not.|
|31|[verifychain](#verifychain)|N|Verifies the block chain database.|
|23|[help](#help)|Y|Returns a list of all commands or help for a specified command.|
|24|[ping](#ping)|N|Queues a ping to be sent to each connected peer.|
|25|[sendrawtransaction](#sendrawtransaction)|Y|Submits the serialized, hex-encoded transaction to the local peer and relays it to the network.<br /><font color="orange">btcd does not yet implement the `allowhighfees` parameter, so it has no effect</font>|
|26|[setgenerate](#setgenerate) |N|Set the server to generate coins (mine) or not.<br/>NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.|
|27|[stop](#stop)|N|Shutdown btcd.|
|28|[submitblock](#submitblock)|Y|Attempts to submit a new serialized, hex-encoded block to the network.|
|29|[validateaddress](#validateaddress)|Y|Verifies the given address is valid. NOTE: Since btcd does not have a wallet integrated, btcd will only return whether the address is valid or not.|
|30|[verifychain](#verifychain)|N|Verifies the block chain database.|
<a name="MethodDetails" />
**5.2 Method Details**<br />
@ -442,21 +441,6 @@ Example Return|`{`<br />&nbsp;&nbsp;`"bytes": 310768,`<br />&nbsp;&nbsp;`"size":
|Example Return (verbose=1)|`{`<br />&nbsp;&nbsp;`"hex": "01000000010000000000000000000000000000000000000000000000000000000000000000f...",`<br />&nbsp;&nbsp;`"txid": "90743aad855880e517270550d2a881627d84db5265142fd1e7fb7add38b08be9",`<br />&nbsp;&nbsp;`"version": 1,`<br />&nbsp;&nbsp;`"locktime": 0,`<br />&nbsp;&nbsp;`"vin": [`<br />&nbsp;&nbsp;<font color="orange">For coinbase transactions:</font><br />&nbsp;&nbsp;&nbsp;&nbsp;`{ (json object)`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"coinbase": "03708203062f503253482f04066d605108f800080100000ea2122f6f7a636f696e4065757374726174756d2f",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"sequence": 0,`<br />&nbsp;&nbsp;&nbsp;&nbsp;`}`<br />&nbsp;&nbsp;<font color="orange">For non-coinbase transactions:</font><br />&nbsp;&nbsp;&nbsp;&nbsp;`{`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"txid": "60ac4b057247b3d0b9a8173de56b5e1be8c1d1da970511c626ef53706c66be04",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"vout": 0,`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"scriptSig": {`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"asm": "3046022100cb42f8df44eca83dd0a727988dcde9384953e830b1f8004d57485e2ede1b9c8f0...",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"hex": "493046022100cb42f8df44eca83dd0a727988dcde9384953e830b1f8004d57485e2ede1b9c8...",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`}`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"sequence": 4294967295,`<br />&nbsp;&nbsp;&nbsp;&nbsp;`}`<br />&nbsp;&nbsp;`]`<br />&nbsp;&nbsp;`"vout": [`<br />&nbsp;&nbsp;&nbsp;&nbsp;`{`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"value": 25.1394,`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"n": 0,`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"scriptPubKey": {`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"asm": "OP_DUP OP_HASH160 ea132286328cfc819457b9dec386c4b5c84faa5c OP_EQUALVERIFY OP_CHECKSIG",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"hex": "76a914ea132286328cfc819457b9dec386c4b5c84faa5c88ac",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"reqSigs": 1,`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"type": "pubkeyhash"`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"addresses": [`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`"1NLg3QJMsMQGM5KEUaEu5ADDmKQSLHwmyh",`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`]`<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;`}`<br />&nbsp;&nbsp;&nbsp;&nbsp;`}`<br />&nbsp;&nbsp;`]`<br />`}`|
[Return to Overview](#MethodOverview)<br />
***
<a name="getwork"/>
| | |
|---|---|
|Method|getwork|
|Parameters|1. data (string, optional) - The hex|
|Description|Returns information about a transaction given its hash.|
|Notes|<font color="orange">NOTE: Since btcd does not have the wallet integrated to provide payment addresses, btcd must be configured via the `--miningaddr` option to provide which payment addresses to pay created blocks to for this RPC to function.</font>
|Returns (data not specified)|`{ (json object)`<br />&nbsp;&nbsp;`"data": "hex", (string) hex-encoded block data`<br />&nbsp;&nbsp;`"hash1": "hex", (string) (DEPRECATED) hex-encoded formatted hash buffer`<br />&nbsp;&nbsp;`"midstate": "hex", (string) (DEPRECATED) hex-encoded precomputed hash state after hashing first half of the data`<br />&nbsp;&nbsp;`"target": "hex", (string) the hex-encoded little-endian hash target`<br />`}`|
|Returns (data specified)|`true` or `false` (boolean)|
|Example Return (data not specified)|`{`<br />&nbsp;&nbsp;`"data": "00000002c39b5d2b7a1e8f7356a1efce26b24bd15d7d906e85341ef9cec99b6a000000006474f...",`<br />&nbsp;&nbsp;`"hash1": "00000000000000000000000000000000000000000000000000000000000000000000008000000...",`<br />&nbsp;&nbsp;`"midstate": "ae4a80fc51476e452de855b4e20d5f33418c50fc7cae3b1ecd5badb819b8a584",`<br />&nbsp;&nbsp;`"target": "0000000000000000000000000000000000000000000000008c96010000000000",`<br />`}`|
|Example Return (data specified)|`true`|
[Return to Overview](#MethodOverview)<br />
***
<a name="help"/>

12
glide.lock generated
View file

@ -1,21 +1,19 @@
hash: ebeea81fdd8ab49cce0e295ae834f8fbb0fb6e1b8e618a5059aceff477ef6596
updated: 2016-12-09T12:53:49.172263045-05:00
hash: 3483e97fe9cd4e2c998f05ca648ce21767e1a4b955919aeffbc6bfe87d9b0648
updated: 2017-01-11T09:52:36.894361964-05:00
imports:
- name: github.com/btcsuite/btclog
version: 73889fb79bd687870312b6e40effcecffbd57d30
- name: github.com/btcsuite/btcrpcclient
version: 7903290fd9956021ed7b65463f8667df345b365e
version: 5ce0ed600997eafaed25ad4936c1d84ec6ad2b5a
- name: github.com/btcsuite/btcutil
version: 96e858f48ed95f9245e765d98be0ee01176409c7
version: bca6409ade96981b0e77a2a7d358be53b340a1a7
subpackages:
- .
- base58
- bloom
- hdkeychain
- name: github.com/btcsuite/fastsha256
version: 637e656429416087660c84436a2a035d69d54e2e
- name: github.com/btcsuite/go-socks
version: cfe8b59e565c1a5bd4e2005d77cd9aa8b2e14524
version: 4720035b7bfd2a9bb130b1c184f8bbe41b6f0d0f
subpackages:
- socks
- name: github.com/btcsuite/golangcrypto

View file

@ -8,7 +8,6 @@ import:
- base58
- hdkeychain
- package: github.com/btcsuite/btcrpcclient
- package: github.com/btcsuite/fastsha256
- package: github.com/btcsuite/go-socks
subpackages:
- socks

View file

@ -7,10 +7,10 @@ package main
import (
"bytes"
"crypto/sha256"
"crypto/subtle"
"crypto/tls"
"encoding/base64"
"encoding/binary"
"encoding/hex"
"encoding/json"
"errors"
@ -39,7 +39,6 @@ import (
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/fastsha256"
"github.com/btcsuite/websocket"
)
@ -61,23 +60,6 @@ const (
// 256-bit integer.
uint256Size = 32
// getworkDataLen is the length of the data field of the getwork RPC.
// It consists of the serialized block header plus the internal sha256
// padding. The internal sha256 padding consists of a single 1 bit
// followed by enough zeros to pad the message out to 56 bytes followed
// by length of the message in bits encoded as a big-endian uint64
// (8 bytes). Thus, the resulting length is a multiple of the sha256
// block size (64 bytes).
getworkDataLen = (1 + ((wire.MaxBlockHeaderPayload + 8) /
fastsha256.BlockSize)) * fastsha256.BlockSize
// hash1Len is the length of the hash1 field of the getwork RPC. It
// consists of a zero hash plus the internal sha256 padding. See
// the getworkDataLen comment for details about the internal sha256
// padding format.
hash1Len = (1 + ((chainhash.HashSize + 8) / fastsha256.BlockSize)) *
fastsha256.BlockSize
// gbtNonceRange is two 32-bit big-endian hexadecimal integers which
// represent the valid ranges of nonces returned by the getblocktemplate
// RPC.
@ -173,7 +155,6 @@ var rpcHandlersBeforeInit = map[string]commandHandler{
"getrawmempool": handleGetRawMempool,
"getrawtransaction": handleGetRawTransaction,
"gettxout": handleGetTxOut,
"getwork": handleGetWork,
"help": handleHelp,
"node": handleNode,
"ping": handlePing,
@ -242,6 +223,7 @@ var rpcUnimplemented = map[string]struct{}{
"estimatepriority": {},
"getchaintips": {},
"getnetworkinfo": {},
"getwork": {},
"invalidateblock": {},
"preciousblock": {},
"reconsiderblock": {},
@ -329,33 +311,6 @@ func rpcNoTxInfoError(txHash *chainhash.Hash) *btcjson.RPCError {
txHash))
}
// workStateBlockInfo houses information about how to reconstruct a block given
// its template and signature script.
type workStateBlockInfo struct {
msgBlock *wire.MsgBlock
signatureScript []byte
}
// workState houses state that is used in between multiple RPC invocations to
// getwork.
type workState struct {
sync.Mutex
lastTxUpdate time.Time
lastGenerated time.Time
prevHash *chainhash.Hash
msgBlock *wire.MsgBlock
extraNonce uint64
blockInfo map[chainhash.Hash]*workStateBlockInfo
}
// newWorkState returns a new instance of a workState with all internal fields
// initialized and ready to use.
func newWorkState() *workState {
return &workState{
blockInfo: make(map[chainhash.Hash]*workStateBlockInfo),
}
}
// gbtWorkState houses state that is used in between multiple RPC invocations to
// getblocktemplate.
type gbtWorkState struct {
@ -2590,41 +2545,6 @@ func handleGetRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan str
return *rawTxn, nil
}
// bigToLEUint256 returns the passed big integer as an unsigned 256-bit integer
// encoded as little-endian bytes. Numbers which are larger than the max
// unsigned 256-bit integer are truncated.
func bigToLEUint256(n *big.Int) [uint256Size]byte {
// Pad or truncate the big-endian big int to correct number of bytes.
nBytes := n.Bytes()
nlen := len(nBytes)
pad := 0
start := 0
if nlen <= uint256Size {
pad = uint256Size - nlen
} else {
start = nlen - uint256Size
}
var buf [uint256Size]byte
copy(buf[pad:], nBytes[start:])
// Reverse the bytes to little endian and return them.
for i := 0; i < uint256Size/2; i++ {
buf[i], buf[uint256Size-1-i] = buf[uint256Size-1-i], buf[i]
}
return buf
}
// reverseUint32Array treats the passed bytes as a series of uint32s and
// reverses the byte order of each uint32. The passed byte slice must be a
// multiple of 4 for a correct result. The passed bytes slice is modified.
func reverseUint32Array(b []byte) {
blen := len(b)
for i := 0; i < blen; i += 4 {
b[i], b[i+3] = b[i+3], b[i]
b[i+1], b[i+2] = b[i+2], b[i+1]
}
}
// handleGetTxOut handles gettxout commands.
func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.GetTxOutCmd)
@ -2734,325 +2654,6 @@ func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i
return txOutReply, nil
}
// handleGetWorkRequest is a helper for handleGetWork which deals with
// generating and returning work to the caller.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkRequest(s *rpcServer) (interface{}, error) {
state := s.workState
// Generate a new block template when the current best block has
// changed or the transactions in the memory pool have been updated
// and it has been at least one minute since the last template was
// generated.
lastTxUpdate := s.server.txMemPool.LastUpdated()
best := s.server.blockManager.chain.BestSnapshot()
latestHash, latestHeight := best.Hash, best.Height
msgBlock := state.msgBlock
if msgBlock == nil || state.prevHash == nil ||
!state.prevHash.IsEqual(latestHash) ||
(state.lastTxUpdate != lastTxUpdate &&
time.Now().After(state.lastGenerated.Add(time.Minute))) {
// Reset the extra nonce and clear all cached template
// variations if the best block changed.
if state.prevHash != nil && !state.prevHash.IsEqual(latestHash) {
state.extraNonce = 0
state.blockInfo = make(map[chainhash.Hash]*workStateBlockInfo)
}
// Reset the previous best hash the block template was generated
// against so any errors below cause the next invocation to try
// again.
state.prevHash = nil
// Choose a payment address at random.
payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))]
template, err := s.generator.NewBlockTemplate(payToAddr)
if err != nil {
context := "Failed to create new block template"
return nil, internalRPCError(err.Error(), context)
}
msgBlock = template.Block
// Update work state to ensure another block template isn't
// generated until needed.
state.msgBlock = msgBlock
state.lastGenerated = time.Now()
state.lastTxUpdate = lastTxUpdate
state.prevHash = latestHash
rpcsLog.Debugf("Generated block template (timestamp %v, extra "+
"nonce %d, target %064x, merkle root %s, signature "+
"script %x)", msgBlock.Header.Timestamp,
state.extraNonce,
blockchain.CompactToBig(msgBlock.Header.Bits),
msgBlock.Header.MerkleRoot,
msgBlock.Transactions[0].TxIn[0].SignatureScript)
} else {
// At this point, there is a saved block template and a new
// request for work was made, but either the available
// transactions haven't change or it hasn't been long enough to
// trigger a new block template to be generated. So, update the
// existing block template and track the variations so each
// variation can be regenerated if a caller finds an answer and
// makes a submission against it.
// Update the time of the block template to the current time
// while accounting for the median time of the past several
// blocks per the chain consensus rules.
s.generator.UpdateBlockTime(msgBlock)
// Increment the extra nonce and update the block template
// with the new value by regenerating the coinbase script and
// setting the merkle root to the new value.
state.extraNonce++
err := s.generator.UpdateExtraNonce(msgBlock, latestHeight+1,
state.extraNonce)
if err != nil {
errStr := fmt.Sprintf("Failed to update extra nonce: "+
"%v", err)
return nil, internalRPCError(errStr, "")
}
rpcsLog.Debugf("Updated block template (timestamp %v, extra "+
"nonce %d, target %064x, merkle root %s, signature "+
"script %x)", msgBlock.Header.Timestamp,
state.extraNonce,
blockchain.CompactToBig(msgBlock.Header.Bits),
msgBlock.Header.MerkleRoot,
msgBlock.Transactions[0].TxIn[0].SignatureScript)
}
// In order to efficiently store the variations of block templates that
// have been provided to callers, save a pointer to the block as well as
// the modified signature script keyed by the merkle root. This
// information, along with the data that is included in a work
// submission, is used to rebuild the block before checking the
// submitted solution.
coinbaseTx := msgBlock.Transactions[0]
state.blockInfo[msgBlock.Header.MerkleRoot] = &workStateBlockInfo{
msgBlock: msgBlock,
signatureScript: coinbaseTx.TxIn[0].SignatureScript,
}
// Serialize the block header into a buffer large enough to hold the
// the block header and the internal sha256 padding that is added and
// retuned as part of the data below.
data := make([]byte, 0, getworkDataLen)
buf := bytes.NewBuffer(data)
err := msgBlock.Header.Serialize(buf)
if err != nil {
errStr := fmt.Sprintf("Failed to serialize data: %v", err)
return nil, internalRPCError(errStr, "")
}
// Calculate the midstate for the block header. The midstate here is
// the internal state of the sha256 algorithm for the first chunk of the
// block header (sha256 operates on 64-byte chunks) which is before the
// nonce. This allows sophisticated callers to avoid hashing the first
// chunk over and over while iterating the nonce range.
data = data[:buf.Len()]
midstate := fastsha256.MidState256(data)
// Expand the data slice to include the full data buffer and apply the
// internal sha256 padding which consists of a single 1 bit followed
// by enough zeros to pad the message out to 56 bytes followed by the
// length of the message in bits encoded as a big-endian uint64
// (8 bytes). Thus, the resulting length is a multiple of the sha256
// block size (64 bytes). This makes the data ready for sophisticated
// caller to make use of only the second chunk along with the midstate
// for the first chunk.
data = data[:getworkDataLen]
data[wire.MaxBlockHeaderPayload] = 0x80
binary.BigEndian.PutUint64(data[len(data)-8:],
wire.MaxBlockHeaderPayload*8)
// Create the hash1 field which is a zero hash along with the internal
// sha256 padding as described above. This field is really quite
// useless, but it is required for compatibility with the reference
// implementation.
var hash1 [hash1Len]byte
hash1[chainhash.HashSize] = 0x80
binary.BigEndian.PutUint64(hash1[len(hash1)-8:], chainhash.HashSize*8)
// The final result reverses each of the fields to little endian.
// In particular, the data, hash1, and midstate fields are treated as
// arrays of uint32s (per the internal sha256 hashing state) which are
// in big endian, and thus each 4 bytes is byte swapped. The target is
// also in big endian, but it is treated as a uint256 and byte swapped
// to little endian accordingly.
//
// The fact the fields are reversed in this way is rather odd and likey
// an artifact of some legacy internal state in the reference
// implementation, but it is required for compatibility.
reverseUint32Array(data)
reverseUint32Array(hash1[:])
reverseUint32Array(midstate[:])
target := bigToLEUint256(blockchain.CompactToBig(msgBlock.Header.Bits))
reply := &btcjson.GetWorkResult{
Data: hex.EncodeToString(data),
Hash1: hex.EncodeToString(hash1[:]),
Midstate: hex.EncodeToString(midstate[:]),
Target: hex.EncodeToString(target[:]),
}
return reply, nil
}
// handleGetWorkSubmission is a helper for handleGetWork which deals with
// the calling submitting work to be verified and processed.
//
// This function MUST be called with the RPC workstate locked.
func handleGetWorkSubmission(s *rpcServer, hexData string) (interface{}, error) {
// Ensure the provided data is sane.
if len(hexData)%2 != 0 {
hexData = "0" + hexData
}
data, err := hex.DecodeString(hexData)
if err != nil {
return false, rpcDecodeHexError(hexData)
}
if len(data) != getworkDataLen {
return false, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidParameter,
Message: fmt.Sprintf("Argument must be "+
"%d bytes (not %d)", getworkDataLen,
len(data)),
}
}
// Reverse the data as if it were an array of 32-bit unsigned integers.
// The fact the getwork request and submission data is reversed in this
// way is rather odd and likey an artifact of some legacy internal state
// in the reference implementation, but it is required for
// compatibility.
reverseUint32Array(data)
// Deserialize the block header from the data.
var submittedHeader wire.BlockHeader
bhBuf := bytes.NewReader(data[0:wire.MaxBlockHeaderPayload])
err = submittedHeader.Deserialize(bhBuf)
if err != nil {
return false, &btcjson.RPCError{
Code: btcjson.ErrRPCInvalidParameter,
Message: fmt.Sprintf("Argument does not "+
"contain a valid block header: %v", err),
}
}
// Look up the full block for the provided data based on the
// merkle root. Return false to indicate the solve failed if
// it's not available.
state := s.workState
blockInfo, ok := state.blockInfo[submittedHeader.MerkleRoot]
if !ok {
rpcsLog.Debugf("Block submitted via getwork has no matching "+
"template for merkle root %s",
submittedHeader.MerkleRoot)
return false, nil
}
// Reconstruct the block using the submitted header stored block info.
msgBlock := blockInfo.msgBlock
block := btcutil.NewBlock(msgBlock)
msgBlock.Header.Timestamp = submittedHeader.Timestamp
msgBlock.Header.Nonce = submittedHeader.Nonce
msgBlock.Transactions[0].TxIn[0].SignatureScript = blockInfo.signatureScript
merkles := blockchain.BuildMerkleTreeStore(block.Transactions())
msgBlock.Header.MerkleRoot = *merkles[len(merkles)-1]
// Ensure the submitted block hash is less than the target difficulty.
err = blockchain.CheckProofOfWork(block, activeNetParams.PowLimit)
if err != nil {
// Anything other than a rule violation is an unexpected error,
// so return that error as an internal error.
if _, ok := err.(blockchain.RuleError); !ok {
return false, internalRPCError("Unexpected error "+
"while checking proof of work: "+err.Error(),
"")
}
rpcsLog.Debugf("Block submitted via getwork does not meet "+
"the required proof of work: %v", err)
return false, nil
}
latestHash := s.server.blockManager.chain.BestSnapshot().Hash
if !msgBlock.Header.PrevBlock.IsEqual(latestHash) {
rpcsLog.Debugf("Block submitted via getwork with previous "+
"block %s is stale", msgBlock.Header.PrevBlock)
return false, nil
}
// Process this block using the same rules as blocks coming from other
// nodes. This will in turn relay it to the network like normal.
isOrphan, err := s.server.blockManager.ProcessBlock(block, blockchain.BFNone)
if err != nil || isOrphan {
// Anything other than a rule violation is an unexpected error,
// so return that error as an internal error.
if _, ok := err.(blockchain.RuleError); !ok {
return false, internalRPCError("Unexpected error "+
"while processing block: "+err.Error(), "")
}
rpcsLog.Infof("Block submitted via getwork rejected: %v", err)
return false, nil
}
// The block was accepted.
rpcsLog.Infof("Block submitted via getwork accepted: %s", block.Hash())
return true, nil
}
// handleGetWork implements the getwork command.
func handleGetWork(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.GetWorkCmd)
// Respond with an error if there are no addresses to pay the created
// blocks to.
if len(cfg.miningAddrs) == 0 {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCInternal.Code,
Message: "No payment addresses specified via --miningaddr",
}
}
// Return an error if there are no peers connected since there is no
// way to relay a found block or receive transactions to work on.
// However, allow this state when running in the regression test or
// simulation test mode.
if !(cfg.RegressionTest || cfg.SimNet) && s.server.ConnectedCount() == 0 {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCClientNotConnected,
Message: "Bitcoin is not connected",
}
}
// No point in generating or accepting work before the chain is synced.
currentHeight := s.server.blockManager.chain.BestSnapshot().Height
if currentHeight != 0 && !s.server.blockManager.IsCurrent() {
return nil, &btcjson.RPCError{
Code: btcjson.ErrRPCClientInInitialDownload,
Message: "Bitcoin is downloading blocks...",
}
}
// Protect concurrent access from multiple RPC invocations for work
// requests and submission.
s.workState.Lock()
defer s.workState.Unlock()
// When the caller provides data, it is a submission of a supposedly
// solved block that needs to be checked and submitted to the network
// if valid.
if c.Data != nil && *c.Data != "" {
return handleGetWorkSubmission(s, *c.Data)
}
// No data was provided, so the caller is requesting work.
return handleGetWorkRequest(s)
}
// handleHelp implements the help command.
func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) {
c := cmd.(*btcjson.HelpCmd)
@ -3885,15 +3486,14 @@ type rpcServer struct {
generator *mining.BlkTmplGenerator
server *server
chain *blockchain.BlockChain
authsha [fastsha256.Size]byte
limitauthsha [fastsha256.Size]byte
authsha [sha256.Size]byte
limitauthsha [sha256.Size]byte
ntfnMgr *wsNotificationManager
numClients int32
statusLines map[int]string
statusLock sync.RWMutex
wg sync.WaitGroup
listeners []net.Listener
workState *workState
gbtWorkState *gbtWorkState
helpCacher *helpCacher
requestProcessShutdown chan struct{}
@ -4041,7 +3641,7 @@ func (s *rpcServer) checkAuth(r *http.Request, require bool) (bool, bool, error)
return false, false, nil
}
authsha := fastsha256.Sum256([]byte(authhdr[0]))
authsha := sha256.Sum256([]byte(authhdr[0]))
// Check for limited auth first as in environments with limited users, those
// are probably expected to have a higher volume of calls
@ -4387,7 +3987,6 @@ func newRPCServer(listenAddrs []string, generator *mining.BlkTmplGenerator, s *s
generator: generator,
chain: s.blockManager.chain,
statusLines: make(map[int]string),
workState: newWorkState(),
gbtWorkState: newGbtWorkState(s.timeSource),
helpCacher: newHelpCacher(),
requestProcessShutdown: make(chan struct{}),
@ -4396,12 +3995,12 @@ func newRPCServer(listenAddrs []string, generator *mining.BlkTmplGenerator, s *s
if cfg.RPCUser != "" && cfg.RPCPass != "" {
login := cfg.RPCUser + ":" + cfg.RPCPass
auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
rpc.authsha = fastsha256.Sum256([]byte(auth))
rpc.authsha = sha256.Sum256([]byte(auth))
}
if cfg.RPCLimitUser != "" && cfg.RPCLimitPass != "" {
login := cfg.RPCLimitUser + ":" + cfg.RPCLimitPass
auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
rpc.limitauthsha = fastsha256.Sum256([]byte(auth))
rpc.limitauthsha = sha256.Sum256([]byte(auth))
}
rpc.ntfnMgr = newWsNotificationManager(&rpc)

View file

@ -470,19 +470,6 @@ var helpDescsEnUS = map[string]string{
"gettxout-vout": "The index of the output",
"gettxout-includemempool": "Include the mempool when true",
// GetWorkResult help.
"getworkresult-data": "Hex-encoded block data",
"getworkresult-hash1": "(DEPRECATED) Hex-encoded formatted hash buffer",
"getworkresult-midstate": "(DEPRECATED) Hex-encoded precomputed hash state after hashing first half of the data",
"getworkresult-target": "Hex-encoded little-endian hash target",
// GetWorkCmd help.
"getwork--synopsis": "(DEPRECATED - Use getblocktemplate instead) Returns formatted hash data to work on or checks and submits solved data.",
"getwork-data": "Hex-encoded data to check",
"getwork--condition0": "no data provided",
"getwork--condition1": "data provided",
"getwork--result1": "Whether or not the solved data is valid and was added to the chain",
// HelpCmd help.
"help--synopsis": "Returns a list of all commands or help for a specified command.",
"help-command": "The command to retrieve help for",
@ -662,7 +649,6 @@ var rpcResultTypes = map[string][]interface{}{
"getrawmempool": {(*[]string)(nil), (*btcjson.GetRawMempoolVerboseResult)(nil)},
"getrawtransaction": {(*string)(nil), (*btcjson.TxRawResult)(nil)},
"gettxout": {(*btcjson.GetTxOutResult)(nil)},
"getwork": {(*btcjson.GetWorkResult)(nil), (*bool)(nil)},
"node": nil,
"help": {(*string)(nil), (*string)(nil)},
"ping": nil,

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -7,6 +7,7 @@ package main
import (
"bytes"
"container/list"
"crypto/sha256"
"crypto/subtle"
"encoding/base64"
"encoding/hex"
@ -25,7 +26,6 @@ import (
"github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/fastsha256"
"github.com/btcsuite/golangcrypto/ripemd160"
"github.com/btcsuite/websocket"
)
@ -1010,7 +1010,7 @@ out:
// Check credentials.
login := authCmd.Username + ":" + authCmd.Passphrase
auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
authSha := fastsha256.Sum256([]byte(auth))
authSha := sha256.Sum256([]byte(auth))
cmp := subtle.ConstantTimeCompare(authSha[:], c.server.authsha[:])
limitcmp := subtle.ConstantTimeCompare(authSha[:], c.server.limitauthsha[:])
if cmp != 1 && limitcmp != 1 {

View file

@ -293,8 +293,8 @@
; worth your while.
; generate=false
; Add addresses to pay mined blocks to for CPU mining and the block templates
; generated for the getwork RPC as desired. One address per line.
; Add addresses to pay mined blocks to for CPU mining and potentially in the
; block templates generated for the getblocktemplate RPC. One address per line.
; miningaddr=1yourbitcoinaddress
; miningaddr=1yourbitcoinaddress2
; miningaddr=1yourbitcoinaddress3

View file

@ -1,4 +1,4 @@
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2013-2017 The btcsuite developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -7,6 +7,7 @@ package txscript
import (
"bytes"
"crypto/sha1"
"crypto/sha256"
"encoding/binary"
"errors"
"fmt"
@ -15,7 +16,6 @@ import (
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/fastsha256"
"github.com/btcsuite/golangcrypto/ripemd160"
)
@ -1890,7 +1890,7 @@ func opcodeSha256(op *parsedOpcode, vm *Engine) error {
return err
}
hash := fastsha256.Sum256(buf)
hash := sha256.Sum256(buf)
vm.dstack.PushByteArray(hash[:])
return nil
}
@ -1905,7 +1905,7 @@ func opcodeHash160(op *parsedOpcode, vm *Engine) error {
return err
}
hash := fastsha256.Sum256(buf)
hash := sha256.Sum256(buf)
vm.dstack.PushByteArray(calcHash(hash[:], ripemd160.New()))
return nil
}