getwork.go raw

   1  package chainrpc
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/binary"
   6  	"encoding/hex"
   7  	"fmt"
   8  	"math/big"
   9  	"math/rand"
  10  	"time"
  11  
  12  	"github.com/p9c/p9/pkg/bits"
  13  	block2 "github.com/p9c/p9/pkg/block"
  14  	"github.com/p9c/p9/pkg/fork"
  15  
  16  	"github.com/p9c/p9/pkg/qu"
  17  
  18  	"github.com/conformal/fastsha256"
  19  
  20  	"github.com/p9c/p9/pkg/blockchain"
  21  	"github.com/p9c/p9/pkg/btcjson"
  22  	"github.com/p9c/p9/pkg/chainhash"
  23  	"github.com/p9c/p9/pkg/wire"
  24  )
  25  
  26  // Uint256Size is the number of bytes needed to represent an unsigned 256-bit integer.
  27  const Uint256Size = 32
  28  
  29  // GetworkDataLen is the length of the data field of the getwork RPC.
  30  //
  31  // It consists of the serialized block header plus the internal sha256 padding. The internal sha256 padding consists of
  32  // a single 1 bit followed by enough zeros to pad the message out to 56 bytes followed by length of the message in bits
  33  // encoded as a big-endian uint64 (8 bytes). Thus, the resulting length is a multiple of the sha256 block size (64
  34  // bytes).
  35  var GetworkDataLen = (1 + ((wire.MaxBlockHeaderPayload + 8) / fastsha256.
  36  	BlockSize)) * fastsha256.BlockSize
  37  
  38  // Hash1Len is the length of the hash1 field of the getwork RPC.
  39  //
  40  // It consists of a zero hash plus the internal sha256 padding. See the getworkDataLen comment for details about the
  41  // internal sha256 padding format.
  42  var Hash1Len = (1 + ((chainhash.HashSize + 8) / fastsha256.
  43  	BlockSize)) * fastsha256.BlockSize
  44  
  45  // BigToLEUint256 returns the passed big integer as an unsigned 256-bit integer encoded as little-endian bytes.
  46  //
  47  // Numbers which are larger than the max unsigned 256-bit integer are truncated.
  48  func BigToLEUint256(n *big.Int) [Uint256Size]byte {
  49  	// Pad or truncate the big-endian big int to correct number of bytes.
  50  	nBytes := n.Bytes()
  51  	nlen := len(nBytes)
  52  	pad := 0
  53  	start := 0
  54  	if nlen <= Uint256Size {
  55  		pad = Uint256Size - nlen
  56  	} else {
  57  		start = nlen - Uint256Size
  58  	}
  59  	var buf [Uint256Size]byte
  60  	copy(buf[pad:], nBytes[start:])
  61  	// Reverse the bytes to little endian and return them.
  62  	for i := 0; i < Uint256Size/2; i++ {
  63  		buf[i], buf[Uint256Size-1-i] = buf[Uint256Size-1-i], buf[i]
  64  	}
  65  	return buf
  66  }
  67  
  68  // HandleGetWork handles the getwork call
  69  func HandleGetWork(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
  70  	c := cmd.(*btcjson.GetWorkCmd)
  71  	if len(s.StateCfg.ActiveMiningAddrs) == 0 {
  72  		return nil, &btcjson.RPCError{
  73  			Code:    btcjson.ErrRPCInternal.Code,
  74  			Message: "No payment addresses specified via --miningaddr",
  75  		}
  76  	}
  77  	netwk := (s.Config.Network.V())[0]
  78  	if !((netwk == 'r') || (netwk == 's')) &&
  79  		s.Cfg.ConnMgr.ConnectedCount() == 0 {
  80  		return nil, &btcjson.RPCError{
  81  			Code:    btcjson.ErrRPCClientNotConnected,
  82  			Message: "Pod is not connected to network",
  83  		}
  84  	}
  85  	// No point in generating or accepting work before the chain is synced.
  86  	latestHeight := s.Cfg.Chain.BestSnapshot().Height
  87  	if latestHeight != 0 && !s.Cfg.SyncMgr.IsCurrent() {
  88  		return nil, &btcjson.RPCError{
  89  			Code:    btcjson.ErrRPCClientInInitialDownload,
  90  			Message: "Pod is not yet synchronised...",
  91  		}
  92  	}
  93  	state := s.GBTWorkState
  94  	state.Lock()
  95  	defer state.Unlock()
  96  	if c.Data != nil {
  97  		return HandleGetWorkSubmission(s, *c.Data)
  98  	}
  99  	// Choose a payment address at random.
 100  	rand.Seed(time.Now().UnixNano())
 101  	payToAddr := s.StateCfg.ActiveMiningAddrs[rand.Intn(len(s.StateCfg.ActiveMiningAddrs))]
 102  	lastTxUpdate := s.GBTWorkState.LastTxUpdate
 103  	latestHash := &s.Cfg.Chain.BestSnapshot().Hash
 104  	generator := s.Cfg.Generator
 105  	if state.Template == nil {
 106  		var e error
 107  		state.Template, e = generator.NewBlockTemplate(payToAddr, s.Cfg.Algo)
 108  		if e != nil {
 109  			return nil, e
 110  		}
 111  	}
 112  	msgBlock := state.Template.Block
 113  	if msgBlock == nil || state.prevHash == nil ||
 114  		!state.prevHash.IsEqual(latestHash) ||
 115  		(state.LastTxUpdate != lastTxUpdate &&
 116  			time.Now().After(state.LastGenerated.Add(time.Minute))) {
 117  		//	Reset the extra nonce and clear all cached template variations if the best block changed.
 118  		if state.prevHash != nil && !state.prevHash.IsEqual(latestHash) {
 119  			e := state.UpdateBlockTemplate(s, false)
 120  			if e != nil {
 121  				W.Ln("failed to update block template", e)
 122  			}
 123  		}
 124  		//	Reset the previous best hash the block template was generated against so any errors below cause the next
 125  		//	invocation to try again.
 126  		state.prevHash = nil
 127  		var e error
 128  		state.Template, e = generator.NewBlockTemplate(payToAddr, s.Cfg.Algo)
 129  		if e != nil {
 130  			errStr := fmt.Sprintf("Failed to create new block template: %v", e)
 131  			E.Ln(errStr)
 132  			return nil, &btcjson.RPCError{
 133  				Code:    btcjson.ErrRPCInternal.Code,
 134  				Message: errStr,
 135  			}
 136  		}
 137  		msgBlock = state.Template.Block
 138  		// Update work state to ensure another block template isn't generated until needed.
 139  		state.Template.Block = msgBlock
 140  		state.LastGenerated = time.Now()
 141  		state.LastTxUpdate = lastTxUpdate
 142  		state.prevHash = latestHash
 143  		D.C(
 144  			func() string {
 145  				return fmt.Sprintf(
 146  					"generated block template (timestamp %v, target %064x, "+
 147  						"merkle root %s, signature script %x)",
 148  					msgBlock.Header.Timestamp, bits.CompactToBig(
 149  						msgBlock.Header.
 150  							Bits,
 151  					), msgBlock.Header.MerkleRoot,
 152  					msgBlock.Transactions[0].TxIn[0].SignatureScript,
 153  				)
 154  			},
 155  		)
 156  	} else {
 157  		// At this point, there is a saved block template and a new request for work was made but either the available
 158  		// transactions haven't change or it hasn't been long enough to trigger a new block template to be generated.
 159  		//
 160  		// So, update the existing block template and track the variations so each variation can be regenerated if a
 161  		// caller finds an answer and makes a submission against it. Update the time of the block template to the
 162  		// current time while accounting for the median time of the past several blocks per the chain consensus rules.
 163  		e := generator.UpdateBlockTime(0, msgBlock)
 164  		if e != nil {
 165  			W.Ln("failed to update block time", e)
 166  		}
 167  		// Increment the extra nonce and update the block template with the new value by regenerating the coinbase
 168  		// script and setting the merkle root to the new value.
 169  		D.F(
 170  			"updated block template (timestamp %v, target %064x, "+
 171  				"merkle root %s, signature script %x)",
 172  			msgBlock.Header.Timestamp, bits.CompactToBig(msgBlock.Header.Bits),
 173  			msgBlock.Header.MerkleRoot, msgBlock.Transactions[0].TxIn[0].
 174  				SignatureScript,
 175  		)
 176  	}
 177  	// In order to efficiently store the variations of block templates that have been provided to callers save a pointer
 178  	// to the block as well as the modified signature script keyed by the merkle root. This information, along with the
 179  	// data that is included in a work submission, is used to rebuild the block before checking the submitted solution.
 180  	/*
 181  		coinbaseTx := msgBlock.Transactions[0]
 182  		state.blockInfo[msgBlock.Header.MerkleRoot] = &workStateBlockInfo{
 183  			msgBlock:        msgBlock,
 184  			signatureScript: coinbaseTx.TxIn[0].SignatureScript,
 185  		}
 186  	*/
 187  	// Serialize the block header into a buffer large enough to hold the the block header and the internal sha256
 188  	// padding that is added and returned as part of the data below.
 189  	data := make([]byte, 0, GetworkDataLen)
 190  	buf := bytes.NewBuffer(data)
 191  	e := msgBlock.Header.Serialize(buf)
 192  	if e != nil {
 193  		errStr := fmt.Sprintf("Failed to serialize data: %v", e)
 194  		W.Ln(errStr)
 195  		return nil, &btcjson.RPCError{
 196  			Code:    btcjson.ErrRPCInternal.Code,
 197  			Message: errStr,
 198  		}
 199  	}
 200  	// Calculate the midstate for the block header. The midstate here is the internal state of the sha256 algorithm for
 201  	// the first chunk of the block header (sha256 operates on 64-byte chunks) which is before the nonce.
 202  	//
 203  	// This allows sophisticated callers to avoid hashing the first chunk over and over while iterating the nonce range.
 204  	data = data[:buf.Len()]
 205  	midstate := fastsha256.MidState256(data)
 206  	// Expand the data slice to include the full data buffer and apply the internal sha256 padding which consists of a
 207  	// single 1 bit followed by enough zeros to pad the message out to 56 bytes followed by the length of the message in
 208  	// bits encoded as a big-endian uint64 (8 bytes).
 209  	//
 210  	// Thus, the resulting length is a multiple of the sha256 block size (64 bytes). This makes the data ready for
 211  	// sophisticated caller to make use of only the second chunk along with the midstate for the first chunk.
 212  	data = data[:GetworkDataLen]
 213  	data[wire.MaxBlockHeaderPayload] = 0x80
 214  	binary.BigEndian.PutUint64(
 215  		data[len(data)-8:],
 216  		wire.MaxBlockHeaderPayload*8,
 217  	)
 218  	// Create the hash1 field which is a zero hash along with the internal sha256 padding as described above. This field
 219  	// is really quite useless, but it is required for compatibility with the reference implementation.
 220  	var hash1 = make([]byte, Hash1Len)
 221  	hash1[chainhash.HashSize] = 0x80
 222  	binary.BigEndian.PutUint64(hash1[len(hash1)-8:], chainhash.HashSize*8)
 223  	// The final result reverses the each of the fields to little endian. In particular, the data, hash1, and midstate
 224  	// fields are treated as arrays of uint32s (per the internal sha256 hashing state) which are in big endian, and thus
 225  	// each 4 bytes is byte swapped.
 226  	//
 227  	// The target is also in big endian, but it is treated as a uint256 and byte swapped to little endian accordingly.
 228  	//
 229  	// The fact the fields are reversed in this way is rather odd and likely an artifact of some legacy internal state
 230  	// in the reference implementation, but it is required for compatibility.
 231  	ReverseUint32Array(data)
 232  	ReverseUint32Array(hash1)
 233  	ReverseUint32Array(midstate[:])
 234  	target := BigToLEUint256(bits.CompactToBig(msgBlock.Header.Bits))
 235  	reply := &btcjson.GetWorkResult{
 236  		Data:     hex.EncodeToString(data),
 237  		Hash1:    hex.EncodeToString(hash1),
 238  		Midstate: hex.EncodeToString(midstate[:]),
 239  		Target:   hex.EncodeToString(target[:]),
 240  	}
 241  	return reply, nil
 242  }
 243  
 244  // HandleGetWorkSubmission is a helper for handleGetWork which deals with the calling submitting work to be verified and
 245  // processed.
 246  //
 247  // This function MUST be called with the RPC workstate locked.
 248  func HandleGetWorkSubmission(s *Server, hexData string) (interface{}, error) {
 249  	// Ensure the provided data is sane.
 250  	if len(hexData)%2 != 0 {
 251  		hexData = "0" + hexData
 252  	}
 253  	data, e := hex.DecodeString(hexData)
 254  	if e != nil {
 255  		return nil, &btcjson.RPCError{
 256  			Code: btcjson.ErrRPCInvalidParameter,
 257  			Message: fmt.Sprintf(
 258  				"argument must be "+
 259  					"hexadecimal string (not %q)", hexData,
 260  			),
 261  		}
 262  	}
 263  	if len(data) != GetworkDataLen {
 264  		return false, &btcjson.RPCError{
 265  			Code: btcjson.ErrRPCInvalidParameter,
 266  			Message: fmt.Sprintf(
 267  				"argument must be "+
 268  					"%d bytes (not %d)", GetworkDataLen,
 269  				len(data),
 270  			),
 271  		}
 272  	}
 273  	// Reverse the data as if it were an array of 32-bit unsigned integers. The fact the getwork request and submission
 274  	// data is reversed in this way is rather odd and likely an artifact of some legacy internal state in the reference
 275  	// implementation, but it is required for compatibility.
 276  	ReverseUint32Array(data)
 277  	// Deserialize the block header from the data.
 278  	var submittedHeader wire.BlockHeader
 279  	bhBuf := bytes.NewBuffer(data[0:wire.MaxBlockHeaderPayload])
 280  	e = submittedHeader.Deserialize(bhBuf)
 281  	if e != nil {
 282  		return false, &btcjson.RPCError{
 283  			Code: btcjson.ErrRPCInvalidParameter,
 284  			Message: fmt.Sprintf(
 285  				"argument does not "+
 286  					"contain a valid block header: %v", e,
 287  			),
 288  		}
 289  	}
 290  	// Look up the full block for the provided data based on the merkle root.
 291  	//
 292  	// Return false to indicate the solve failed if it's not available.
 293  	state := s.GBTWorkState
 294  
 295  	if state.Template.Block.Header.MerkleRoot.String() == "" {
 296  		D.Ln(
 297  			"Block submitted via getwork has no matching template for merkle root",
 298  			submittedHeader.MerkleRoot,
 299  		)
 300  		return false, nil
 301  	}
 302  	// Reconstruct the block using the submitted header stored block info.
 303  	msgBlock := state.Template.Block
 304  	block := block2.NewBlock(msgBlock)
 305  	msgBlock.Header.Timestamp = submittedHeader.Timestamp
 306  	msgBlock.Header.Nonce = submittedHeader.Nonce
 307  	msgBlock.Transactions[0].TxIn[0].SignatureScript = state.Template.Block.
 308  		Transactions[0].TxIn[0].SignatureScript
 309  	merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false)
 310  	msgBlock.Header.MerkleRoot = *merkles.GetRoot()
 311  	// Ensure the submitted block hash is less than the target difficulty.
 312  	pl := fork.GetMinDiff(s.Cfg.Algo, s.Cfg.Chain.BestSnapshot().Height)
 313  	e = blockchain.CheckProofOfWork(block, pl, s.Cfg.Chain.BestSnapshot().Height)
 314  	if e != nil {
 315  		// Anything other than a rule violation is an unexpected error, so return that error as an internal error.
 316  		if _, ok := e.(blockchain.RuleError); !ok {
 317  			return nil, &btcjson.RPCError{
 318  				Code: btcjson.ErrRPCInternal.Code,
 319  				Message: fmt.Sprintf(
 320  					"Unexpected error while checking proof"+
 321  						" of work: %v", e,
 322  				),
 323  			}
 324  		}
 325  		D.Ln("block submitted via getwork does not meet the required proof of work:", e)
 326  		return false, nil
 327  	}
 328  	latestHash := &s.Cfg.Chain.BestSnapshot().Hash
 329  	if !msgBlock.Header.PrevBlock.IsEqual(latestHash) {
 330  		D.F("block submitted via getwork with previous block %s is stale", msgBlock.Header.PrevBlock)
 331  		return false, nil
 332  	}
 333  	// Process this block using the same rules as blocks coming from other nodes. This will in turn relay it to the
 334  	// network like normal.
 335  	_, isOrphan, e := s.Cfg.Chain.ProcessBlock(
 336  		0, block, 0,
 337  		s.Cfg.Chain.BestSnapshot().Height,
 338  	)
 339  	if e != nil || isOrphan {
 340  		// Anything other than a rule violation is an unexpected error, so return that error as an internal error.
 341  		if _, ok := e.(blockchain.RuleError); !ok {
 342  			return nil, &btcjson.RPCError{
 343  				Code:    btcjson.ErrRPCInternal.Code,
 344  				Message: fmt.Sprintf("Unexpected error while processing block: %v", e),
 345  			}
 346  		}
 347  		I.Ln("block submitted via getwork rejected:", e)
 348  		return false, nil
 349  	}
 350  	// The block was accepted.
 351  	blockSha := block.Hash()
 352  	I.Ln("block submitted via getwork accepted:", blockSha)
 353  	return true, nil
 354  }
 355  
 356  // ReverseUint32Array treats the passed bytes as a series of uint32s and reverses the byte order of each uint32.
 357  //
 358  // The passed byte slice must be a multiple of 4 for a correct result.
 359  //
 360  // The passed bytes slice is modified.
 361  func ReverseUint32Array(b []byte) {
 362  	bLen := len(b)
 363  	for i := 0; i < bLen; i += 4 {
 364  		b[i], b[i+3] = b[i+3], b[i]
 365  		b[i+1], b[i+2] = b[i+2], b[i+1]
 366  	}
 367  }
 368