diff --git a/mining/cpuminer/cpuminer.go b/mining/cpuminer/cpuminer.go index 3d5b3b19..a62d5cf6 100644 --- a/mining/cpuminer/cpuminer.go +++ b/mining/cpuminer/cpuminer.go @@ -274,7 +274,7 @@ func (m *CPUMiner) solveBlock(msgBlock *wire.MsgBlock, blockHeight int32, // increment the number of hashes completed for each // attempt accordingly. header.Nonce = i - hash := header.BlockHash() + hash := header.BlockPoWHash() hashesCompleted += 2 // The block is solved when the new block hash is less @@ -544,7 +544,7 @@ func (m *CPUMiner) NumWorkers() int32 { // detecting when it is performing stale work and reacting accordingly by // generating a new block template. When a block is solved, it is submitted. // The function returns a list of the hashes of generated blocks. -func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) { +func (m *CPUMiner) GenerateNBlocks(n uint32, payToAddr btcutil.Address) ([]*chainhash.Hash, error) { m.Lock() // Respond with an error if server is already mining. @@ -590,8 +590,9 @@ func (m *CPUMiner) GenerateNBlocks(n uint32) ([]*chainhash.Hash, error) { // Choose a payment address at random. rand.Seed(time.Now().UnixNano()) - payToAddr := m.cfg.MiningAddrs[rand.Intn(len(m.cfg.MiningAddrs))] - + if payToAddr == nil { + payToAddr = m.cfg.MiningAddrs[rand.Intn(len(m.cfg.MiningAddrs))] + } // Create a new block template using the available transactions // in the memory pool as a source of transactions to potentially // include in the block. diff --git a/rpcserver.go b/rpcserver.go index 6baf2030..57000307 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -137,6 +137,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "decodescript": handleDecodeScript, "estimatefee": handleEstimateFee, "generate": handleGenerate, + "generatetoaddress": handleGenerateToAddress, "getaddednodeinfo": handleGetAddedNodeInfo, "getbestblock": handleGetBestBlock, "getbestblockhash": handleGetBestBlockHash, @@ -893,7 +894,6 @@ func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return float64(feeRate), nil } -// handleGenerate handles generate commands. func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { // Respond with an error if there are no addresses to pay the // created blocks to. @@ -930,7 +930,62 @@ func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (i // Create a reply reply := make([]string, c.NumBlocks) - blockHashes, err := s.cfg.CPUMiner.GenerateNBlocks(c.NumBlocks) + blockHashes, err := s.cfg.CPUMiner.GenerateNBlocks(c.NumBlocks, nil) + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInternal.Code, + Message: err.Error(), + } + } + + // Mine the correct number of blocks, assigning the hex representation of the + // hash of each one to its place in the reply. + for i, hash := range blockHashes { + reply[i] = hash.String() + } + + return reply, nil +} + +// handleGenerateToAddress handles generate commands. +func handleGenerateToAddress(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GenerateToAddressCmd) + payToAddr, err := btcutil.DecodeAddress(c.Address, s.cfg.ChainParams) + + // Respond with an error if there are no addresses to pay the + // created blocks to. + if err != nil { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInvalidParameter, + Message: "No payment addresses specified ", + } + } + // cfg.miningAddrs = append(cfg.miningAddrs, maddr) + + // Respond with an error if there's virtually 0 chance of mining a block + // with the CPU. + if !s.cfg.ChainParams.GenerateSupported { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCDifficulty, + Message: fmt.Sprintf("No support for `generatetoaddress` on "+ + "the current network, %s, as it's unlikely to "+ + "be possible to mine a block with the CPU.", + s.cfg.ChainParams.Net), + } + } + + // Respond with an error if the client is requesting 0 blocks to be generated. + if c.NumBlocks == 0 { + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCInternal.Code, + Message: "Please request a nonzero number of blocks to generate.", + } + } + + // Create a reply + reply := make([]string, c.NumBlocks) + + blockHashes, err := s.cfg.CPUMiner.GenerateNBlocks(uint32(c.NumBlocks), payToAddr) if err != nil { return nil, &btcjson.RPCError{ Code: btcjson.ErrRPCInternal.Code, diff --git a/rpcserverhelp.go b/rpcserverhelp.go index 13301c53..5d54fbf9 100644 --- a/rpcserverhelp.go +++ b/rpcserverhelp.go @@ -794,6 +794,7 @@ var rpcResultTypes = map[string][]interface{}{ "decodescript": {(*btcjson.DecodeScriptResult)(nil)}, "estimatefee": {(*float64)(nil)}, "generate": {(*[]string)(nil)}, + "generatetoaddress": {(*[]string)(nil)}, "getaddednodeinfo": {(*[]string)(nil), (*[]btcjson.GetAddedNodeInfoResult)(nil)}, "getbestblock": {(*btcjson.GetBestBlockResult)(nil)}, "getbestblockhash": {(*string)(nil)},