handlers.go raw

   1  package chainrpc
   2  
   3  import (
   4  	"bytes"
   5  	"encoding/base64"
   6  	"encoding/hex"
   7  	"errors"
   8  	"fmt"
   9  	"github.com/p9c/p9/pkg/amt"
  10  	block2 "github.com/p9c/p9/pkg/block"
  11  	"github.com/p9c/p9/pkg/btcaddr"
  12  	"github.com/p9c/p9/pkg/fork"
  13  	"github.com/p9c/p9/pkg/log"
  14  	"math/big"
  15  	"net"
  16  	"strconv"
  17  	"strings"
  18  	"time"
  19  	
  20  	"github.com/p9c/p9/pkg/qu"
  21  	
  22  	"github.com/p9c/p9/pkg/blockchain"
  23  	"github.com/p9c/p9/pkg/btcjson"
  24  	"github.com/p9c/p9/pkg/chainhash"
  25  	"github.com/p9c/p9/pkg/database"
  26  	"github.com/p9c/p9/pkg/ecc"
  27  	"github.com/p9c/p9/pkg/interrupt"
  28  	"github.com/p9c/p9/pkg/mempool"
  29  	"github.com/p9c/p9/pkg/txscript"
  30  	"github.com/p9c/p9/pkg/util"
  31  	"github.com/p9c/p9/pkg/wire"
  32  )
  33  
  34  // HandleAddNode handles addnode commands.
  35  func HandleAddNode(s *Server, cmd interface{}, closeChan qu.C) (ifc interface{}, e error) {
  36  	var msg string
  37  	c, ok := cmd.(*btcjson.AddNodeCmd)
  38  	if !ok {
  39  		var h string
  40  		h, e = s.HelpCacher.RPCMethodHelp("addnode")
  41  		D.Ln(h, e)
  42  		if e != nil {
  43  			msg = e.Error() + "\n\n"
  44  		}
  45  		msg += h
  46  		return nil, &btcjson.RPCError{
  47  			Code:    btcjson.ErrRPCInvalidParameter,
  48  			Message: msg,
  49  			// "invalid subcommand for addnode",
  50  		}
  51  	}
  52  	addr := NormalizeAddress(c.Addr, s.Cfg.ChainParams.DefaultPort)
  53  	switch c.SubCmd {
  54  	case "add":
  55  		e = s.Cfg.ConnMgr.Connect(addr, true)
  56  	case "remove":
  57  		e = s.Cfg.ConnMgr.RemoveByAddr(addr)
  58  	case "onetry":
  59  		e = s.Cfg.ConnMgr.Connect(addr, false)
  60  	default:
  61  		return nil, &btcjson.RPCError{
  62  			Code:    btcjson.ErrRPCInvalidParameter,
  63  			Message: "invalid subcommand for addnode",
  64  		}
  65  	}
  66  	if e != nil {
  67  		E.Ln(e)
  68  		return nil, &btcjson.RPCError{
  69  			Code:    btcjson.ErrRPCInvalidParameter,
  70  			Message: e.Error(),
  71  		}
  72  	}
  73  	// no data returned unless an error.
  74  	return nil, nil
  75  }
  76  
  77  // HandleAskWallet is the handler for commands that are recognized as valid, but are unable to answer correctly since it
  78  // involves wallet state.
  79  func HandleAskWallet(
  80  	s *Server,
  81  	cmd interface{},
  82  	closeChan qu.C,
  83  ) (interface{}, error) {
  84  	return nil, ErrRPCNoWallet
  85  }
  86  
  87  // HandleCreateRawTransaction handles createrawtransaction commands.
  88  func HandleCreateRawTransaction(
  89  	s *Server,
  90  	cmd interface{},
  91  	closeChan qu.C,
  92  ) (interface{}, error) {
  93  	var msg string
  94  	var e error
  95  	c, ok := cmd.(*btcjson.CreateRawTransactionCmd)
  96  	if !ok {
  97  		var h string
  98  		h, e = s.HelpCacher.RPCMethodHelp("createrawtransaction")
  99  		D.Ln(h, e)
 100  		if e != nil {
 101  			msg = e.Error() + "\n\n"
 102  		}
 103  		msg += h
 104  		return nil, &btcjson.RPCError{
 105  			Code:    btcjson.ErrRPCInvalidParameter,
 106  			Message: msg,
 107  			// "invalid subcommand for addnode",
 108  		}
 109  	}
 110  	// Validate the locktime, if given.
 111  	if c.LockTime != nil &&
 112  		(*c.LockTime < 0 || *c.LockTime > int64(wire.MaxTxInSequenceNum)) {
 113  		return nil, &btcjson.RPCError{
 114  			Code:    btcjson.ErrRPCInvalidParameter,
 115  			Message: "Locktime out of range",
 116  		}
 117  	}
 118  	// Add all transaction inputs to a new transaction after performing some validity checks.
 119  	mtx := wire.NewMsgTx(wire.TxVersion)
 120  	for _, input := range c.Inputs {
 121  		var txHash *chainhash.Hash
 122  		txHash, e = chainhash.NewHashFromStr(input.Txid)
 123  		if e != nil {
 124  			E.Ln(e)
 125  			return nil, DecodeHexError(input.Txid)
 126  		}
 127  		prevOut := wire.NewOutPoint(txHash, input.Vout)
 128  		txIn := wire.NewTxIn(prevOut, []byte{}, nil)
 129  		if c.LockTime != nil && *c.LockTime != 0 {
 130  			txIn.Sequence = wire.MaxTxInSequenceNum - 1
 131  		}
 132  		mtx.AddTxIn(txIn)
 133  	}
 134  	// Add all transaction outputs to the transaction after performing some validity checks.
 135  	params := s.Cfg.ChainParams
 136  	for encodedAddr, amount := range c.Amounts {
 137  		// Ensure amount is in the valid range for monetary amounts.
 138  		if amount <= 0 || amount > amt.MaxSatoshi.ToDUO() {
 139  			return nil, &btcjson.RPCError{
 140  				Code:    btcjson.ErrRPCType,
 141  				Message: "Invalid amount",
 142  			}
 143  		}
 144  		// Decode the provided address.
 145  		var addr btcaddr.Address
 146  		addr, e = btcaddr.Decode(encodedAddr, params)
 147  		if e != nil {
 148  			E.Ln(e)
 149  			return nil, &btcjson.RPCError{
 150  				Code:    btcjson.ErrRPCInvalidAddressOrKey,
 151  				Message: "Invalid address or key: " + e.Error(),
 152  			}
 153  		}
 154  		// Ensure the address is one of the supported types and that the network encoded with the address matches the
 155  		// network the Server is currently on.
 156  		switch addr.(type) {
 157  		case *btcaddr.PubKeyHash:
 158  		case *btcaddr.ScriptHash:
 159  		default:
 160  			return nil, &btcjson.RPCError{
 161  				Code:    btcjson.ErrRPCInvalidAddressOrKey,
 162  				Message: "Invalid address or key",
 163  			}
 164  		}
 165  		if !addr.IsForNet(params) {
 166  			return nil, &btcjson.RPCError{
 167  				Code: btcjson.ErrRPCInvalidAddressOrKey,
 168  				Message: "Invalid address: " + encodedAddr +
 169  					" is for the wrong network",
 170  			}
 171  		}
 172  		// Create a new script which pays to the provided address.
 173  		var pkScript []byte
 174  		pkScript, e = txscript.PayToAddrScript(addr)
 175  		if e != nil {
 176  			E.Ln(e)
 177  			context := "Failed to generate pay-to-address script"
 178  			return nil, InternalRPCError(e.Error(), context)
 179  		}
 180  		// Convert the amount to satoshi.
 181  		var satoshi amt.Amount
 182  		satoshi, e = amt.NewAmount(amount)
 183  		if e != nil {
 184  			E.Ln(e)
 185  			context := "Failed to convert amount"
 186  			return nil, InternalRPCError(e.Error(), context)
 187  		}
 188  		txOut := wire.NewTxOut(int64(satoshi), pkScript)
 189  		mtx.AddTxOut(txOut)
 190  	}
 191  	// Set the Locktime, if given.
 192  	if c.LockTime != nil {
 193  		mtx.LockTime = uint32(*c.LockTime)
 194  	}
 195  	// Return the serialized and hex-encoded transaction. Note that this is intentionally not directly returning because
 196  	// the first return value is a string and it would result in returning an empty string to the client instead of
 197  	// nothing (nil) in the case of an error.
 198  	mtxHex, e := MessageToHex(mtx)
 199  	if e != nil {
 200  		E.Ln(e)
 201  		return nil, e
 202  	}
 203  	return mtxHex, nil
 204  }
 205  
 206  // HandleDecodeRawTransaction handles decoderawtransaction commands.
 207  func HandleDecodeRawTransaction(
 208  	s *Server,
 209  	cmd interface{},
 210  	closeChan qu.C,
 211  ) (interface{}, error) {
 212  	var msg string
 213  	var e error
 214  	c, ok := cmd.(*btcjson.DecodeRawTransactionCmd)
 215  	if !ok {
 216  		var h string
 217  		h, e = s.HelpCacher.RPCMethodHelp("decoderawtransaction")
 218  		D.Ln(h, e)
 219  		if e != nil {
 220  			msg = e.Error() + "\n\n"
 221  		}
 222  		msg += h
 223  		return nil, &btcjson.RPCError{
 224  			Code:    btcjson.ErrRPCInvalidParameter,
 225  			Message: msg,
 226  			// "invalid subcommand for addnode",
 227  		}
 228  	}
 229  	// Deserialize the transaction.
 230  	hexStr := c.HexTx
 231  	if len(hexStr)%2 != 0 {
 232  		hexStr = "0" + hexStr
 233  	}
 234  	serializedTx, e := hex.DecodeString(hexStr)
 235  	if e != nil {
 236  		E.Ln(e)
 237  		return nil, DecodeHexError(hexStr)
 238  	}
 239  	var mtx wire.MsgTx
 240  	e = mtx.Deserialize(bytes.NewReader(serializedTx))
 241  	if e != nil {
 242  		E.Ln(e)
 243  		return nil, &btcjson.RPCError{
 244  			Code:    btcjson.ErrRPCDeserialization,
 245  			Message: "TX decode failed: " + e.Error(),
 246  		}
 247  	}
 248  	// Create and return the result.
 249  	txReply := btcjson.TxRawDecodeResult{
 250  		Txid:     mtx.TxHash().String(),
 251  		Version:  mtx.Version,
 252  		Locktime: mtx.LockTime,
 253  		Vin:      CreateVinList(&mtx),
 254  		Vout:     CreateVoutList(&mtx, s.Cfg.ChainParams, nil),
 255  	}
 256  	return txReply, nil
 257  }
 258  
 259  // HandleDecodeScript handles decodescript commands.
 260  func HandleDecodeScript(
 261  	s *Server,
 262  	cmd interface{},
 263  	closeChan qu.C,
 264  ) (interface{}, error) {
 265  	var msg string
 266  	var e error
 267  	c, ok := cmd.(*btcjson.DecodeScriptCmd)
 268  	if !ok {
 269  		var h string
 270  		h, e = s.HelpCacher.RPCMethodHelp("decodescript")
 271  		D.Ln(h, e)
 272  		if e != nil {
 273  			msg = e.Error() + "\n\n"
 274  		}
 275  		msg += h
 276  		return nil, &btcjson.RPCError{
 277  			Code:    btcjson.ErrRPCInvalidParameter,
 278  			Message: msg,
 279  			// "invalid subcommand for addnode",
 280  		}
 281  	}
 282  	// Convert the hex script to bytes.
 283  	hexStr := c.HexScript
 284  	if len(hexStr)%2 != 0 {
 285  		hexStr = "0" + hexStr
 286  	}
 287  	script, e := hex.DecodeString(hexStr)
 288  	if e != nil {
 289  		E.Ln(e)
 290  		return nil, DecodeHexError(hexStr)
 291  	}
 292  	// The disassembled string will contain [error] inline if the script doesn't fully parse, so ignore the error here.
 293  	disbuf, _ := txscript.DisasmString(script)
 294  	// Get information about the script. Ignore the error here since an error means the script couldn't parse and there
 295  	// is no additinal information about it anyways.
 296  	scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(
 297  		script,
 298  		s.Cfg.ChainParams,
 299  	)
 300  	addresses := make([]string, len(addrs))
 301  	for i, addr := range addrs {
 302  		addresses[i] = addr.EncodeAddress()
 303  	}
 304  	// Convert the script itself to a pay-to-script-hash address.
 305  	p2sh, e := btcaddr.NewScriptHash(script, s.Cfg.ChainParams)
 306  	if e != nil {
 307  		E.Ln(e)
 308  		context := "Failed to convert script to pay-to-script-hash"
 309  		return nil, InternalRPCError(e.Error(), context)
 310  	}
 311  	// Generate and return the reply.
 312  	reply := btcjson.DecodeScriptResult{
 313  		Asm:       disbuf,
 314  		ReqSigs:   int32(reqSigs),
 315  		Type:      scriptClass.String(),
 316  		Addresses: addresses,
 317  	}
 318  	if scriptClass != txscript.ScriptHashTy {
 319  		reply.P2sh = p2sh.EncodeAddress()
 320  	}
 321  	return reply, nil
 322  }
 323  
 324  // HandleEstimateFee handles estimatefee commands.
 325  func HandleEstimateFee(
 326  	s *Server,
 327  	cmd interface{},
 328  	closeChan qu.C,
 329  ) (interface{}, error) {
 330  	var msg string
 331  	var e error
 332  	c, ok := cmd.(*btcjson.EstimateFeeCmd)
 333  	if !ok {
 334  		var h string
 335  		h, e = s.HelpCacher.RPCMethodHelp("estimatefee")
 336  		D.Ln(h, e)
 337  		if e != nil {
 338  			msg = e.Error() + "\n\n"
 339  		}
 340  		msg += h
 341  		return nil, &btcjson.RPCError{
 342  			Code:    btcjson.ErrRPCInvalidParameter,
 343  			Message: msg,
 344  			// "invalid subcommand for addnode",
 345  		}
 346  	}
 347  	if s.Cfg.FeeEstimator == nil {
 348  		return nil, errors.New("fee estimation disabled")
 349  	}
 350  	if c.NumBlocks <= 0 {
 351  		return -1.0, errors.New("parameter NumBlocks must be positive")
 352  	}
 353  	feeRate, e := s.Cfg.FeeEstimator.EstimateFee(uint32(c.NumBlocks))
 354  	if e != nil {
 355  		E.Ln(e)
 356  		return -1.0, e
 357  	}
 358  	// Convert to satoshis per kb.
 359  	return float64(feeRate), nil
 360  }
 361  
 362  // HandleGenerate handles generate commands.
 363  func HandleGenerate(
 364  	s *Server,
 365  	cmd interface{},
 366  	closeChan qu.C,
 367  ) (interface{}, error) {
 368  	// Respond with an error if there are no addresses to pay the created blocks to.
 369  	if len(s.StateCfg.ActiveMiningAddrs) == 0 {
 370  		return nil, &btcjson.RPCError{
 371  			Code:    btcjson.ErrRPCInternal.Code,
 372  			Message: "No payment addresses specified via --miningaddr",
 373  		}
 374  	}
 375  	// Respond with an error if there's virtually 0 chance of mining a block with the CPU.
 376  	if !s.Cfg.ChainParams.GenerateSupported {
 377  		return nil, &btcjson.RPCError{
 378  			Code: btcjson.ErrRPCDifficulty,
 379  			Message: fmt.Sprintf(
 380  				"No support for `generate` on the current"+
 381  					" network, %s, as it's unlikely to be possible to mine a block"+
 382  					" with the CPU.", s.Cfg.ChainParams.Net,
 383  			),
 384  		}
 385  	}
 386  	D.Ln("cpu miner stuff is missing here")
 387  	// Set the algorithm according to the port we were called on
 388  	// s.Cfg.CPUMiner.SetAlgo(s.Cfg.Algo)
 389  	// c := cmd.(*btcjson.GenerateCmd)
 390  	// // Respond with an error if the client is requesting 0 blocks to be
 391  	// // generated.
 392  	// if c.NumBlocks == 0 {
 393  	// 	return nil, &btcjson.RPCError{
 394  	// 		Code:    btcjson.ErrRPCInternal.Code,
 395  	// 		Message: "Please request a nonzero number of blocks to generate.",
 396  	// 	}
 397  	// }
 398  	// // Create a reply
 399  	// reply := make([]string, c.NumBlocks)
 400  	// blockHashes, e := s.Cfg.CPUMiner.GenerateNBlocks(0, c.NumBlocks,
 401  	// 	s.Cfg.Algo)
 402  	// if e != nil  {
 403  	// 	L.Script	// 	return nil, &btcjson.RPCError{
 404  	// 		Code:    btcjson.ErrRPCInternal.Code,
 405  	// 		Message: err.ScriptError(),
 406  	// 	}
 407  	// }
 408  	// // Mine the correct number of blocks, assigning the hex representation of
 409  	// // the hash of each one to its place in the reply.
 410  	// for i, hash := range blockHashes {
 411  	// 	reply[i] = hash.String()
 412  	// }
 413  	// return reply, nil
 414  	return nil, nil
 415  }
 416  
 417  // HandleGetAddedNodeInfo handles getaddednodeinfo commands.
 418  func HandleGetAddedNodeInfo(
 419  	s *Server,
 420  	cmd interface{},
 421  	closeChan qu.C,
 422  ) (interface{}, error) {
 423  	var msg string
 424  	var e error
 425  	c, ok := cmd.(*btcjson.GetAddedNodeInfoCmd)
 426  	if !ok {
 427  		var h string
 428  		h, e = s.HelpCacher.RPCMethodHelp("getaddednodeinfo")
 429  		if e != nil {
 430  			msg = e.Error() + "\n\n"
 431  		}
 432  		msg += h
 433  		return nil, &btcjson.RPCError{
 434  			Code:    btcjson.ErrRPCInvalidParameter,
 435  			Message: msg,
 436  			// "invalid subcommand for addnode",
 437  		}
 438  	}
 439  	// Retrieve a list of persistent (added) peers from the Server and filter the list of peers per the specified
 440  	// address (if any).
 441  	peers := s.Cfg.ConnMgr.PersistentPeers()
 442  	if c.Node != nil {
 443  		node := *c.Node
 444  		found := false
 445  		for i, peer := range peers {
 446  			if peer.ToPeer().Addr() == node {
 447  				peers = peers[i : i+1]
 448  				found = true
 449  			}
 450  		}
 451  		if !found {
 452  			return nil, &btcjson.RPCError{
 453  				Code:    btcjson.ErrRPCClientNodeNotAdded,
 454  				Message: "Node has not been added",
 455  			}
 456  		}
 457  	}
 458  	// Without the dns flag, the result is just a slice of the addresses as strings.
 459  	if !c.DNS {
 460  		results := make([]string, 0, len(peers))
 461  		for _, peer := range peers {
 462  			results = append(results, peer.ToPeer().Addr())
 463  		}
 464  		return results, nil
 465  	}
 466  	// With the dns flag, the result is an array of JSON objects which include the result of DNS lookups for each peer.
 467  	results := make([]*btcjson.GetAddedNodeInfoResult, 0, len(peers))
 468  	for _, rpcPeer := range peers {
 469  		// Set the "address" of the peer which could be an ip address or a domain name.
 470  		peer := rpcPeer.ToPeer()
 471  		var result btcjson.GetAddedNodeInfoResult
 472  		result.AddedNode = peer.Addr()
 473  		result.Connected = btcjson.Bool(peer.Connected())
 474  		// Split the address into host and port portions so we can do a DNS lookup against the host. When no port is
 475  		// specified in the address, just use the address as the host.
 476  		var host string
 477  		host, _, e = net.SplitHostPort(peer.Addr())
 478  		if e != nil {
 479  			host = peer.Addr()
 480  		}
 481  		var ipList []string
 482  		switch {
 483  		case net.ParseIP(host) != nil, strings.HasSuffix(host, ".onion"):
 484  			ipList = make([]string, 1)
 485  			ipList[0] = host
 486  		default:
 487  			// Do a DNS lookup for the address. If the lookup fails, just use the host.
 488  			ips, e := Lookup(s.StateCfg)(host)
 489  			if e != nil {
 490  				ipList = make([]string, 1)
 491  				ipList[0] = host
 492  				break
 493  			}
 494  			ipList = make([]string, 0, len(ips))
 495  			for _, ip := range ips {
 496  				ipList = append(ipList, ip.String())
 497  			}
 498  		}
 499  		// Add the addresses and connection info to the result.
 500  		addrs := make([]btcjson.GetAddedNodeInfoResultAddr, 0, len(ipList))
 501  		for _, ip := range ipList {
 502  			var addr btcjson.GetAddedNodeInfoResultAddr
 503  			addr.Address = ip
 504  			addr.Connected = "false"
 505  			if ip == host && peer.Connected() {
 506  				addr.Connected = log.DirectionString(peer.Inbound())
 507  			}
 508  			addrs = append(addrs, addr)
 509  		}
 510  		result.Addresses = &addrs
 511  		results = append(results, &result)
 512  	}
 513  	return results, nil
 514  }
 515  
 516  // HandleGetBestBlock implements the getbestblock command.
 517  func HandleGetBestBlock(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
 518  	// All other "get block" commands give either the height, the hash, or both but require the block SHA. This gets
 519  	// both for the best block.
 520  	best := s.Cfg.Chain.BestSnapshot()
 521  	result := &btcjson.GetBestBlockResult{
 522  		Hash:   best.Hash.String(),
 523  		Height: best.Height,
 524  	}
 525  	return result, nil
 526  }
 527  
 528  // HandleGetBestBlockHash implements the getbestblockhash command.
 529  func HandleGetBestBlockHash(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
 530  	best := s.Cfg.Chain.BestSnapshot()
 531  	return best.Hash.String(), nil
 532  }
 533  
 534  // HandleGetBlock implements the getblock command.
 535  func HandleGetBlock(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
 536  	var msg string
 537  	var e error
 538  	c, ok := cmd.(*btcjson.GetBlockCmd)
 539  	if !ok {
 540  		var h string
 541  		h, e = s.HelpCacher.RPCMethodHelp("getblock")
 542  		if e != nil {
 543  			msg = e.Error() + "\n\n"
 544  		}
 545  		msg += h
 546  		return nil, &btcjson.RPCError{
 547  			Code:    btcjson.ErrRPCInvalidParameter,
 548  			Message: msg,
 549  			// "invalid subcommand for addnode",
 550  		}
 551  	}
 552  	// Load the raw block bytes from the database.
 553  	hash, e := chainhash.NewHashFromStr(c.Hash)
 554  	if e != nil {
 555  		return nil, DecodeHexError(c.Hash)
 556  	}
 557  	var blkBytes []byte
 558  	e = s.Cfg.DB.View(
 559  		func(dbTx database.Tx) (e error) {
 560  			blkBytes, e = dbTx.FetchBlock(hash)
 561  			return e
 562  		},
 563  	)
 564  	if e != nil {
 565  		return nil, &btcjson.RPCError{
 566  			Code:    btcjson.ErrRPCBlockNotFound,
 567  			Message: "Block not found",
 568  		}
 569  	}
 570  	// When the verbose flag isn't set, simply return the serialized block as a hex-encoded string.
 571  	if c.Verbose != nil && !*c.Verbose {
 572  		return hex.EncodeToString(blkBytes), nil
 573  	}
 574  	// The verbose flag is set, so generate the JSON object and return it. Deserialize the block.
 575  	blk, e := block2.NewFromBytes(blkBytes)
 576  	if e != nil {
 577  		context := "Failed to deserialize block"
 578  		return nil, InternalRPCError(e.Error(), context)
 579  	}
 580  	// Get the block height from chain.
 581  	blockHeight, e := s.Cfg.Chain.BlockHeightByHash(hash)
 582  	if e != nil {
 583  		context := blockheightfail
 584  		return nil, InternalRPCError(e.Error(), context)
 585  	}
 586  	blk.SetHeight(blockHeight)
 587  	best := s.Cfg.Chain.BestSnapshot()
 588  	// Get next block hash unless there are none.
 589  	var nextHashString string
 590  	if blockHeight < best.Height {
 591  		nextHash, e := s.Cfg.Chain.BlockHashByHeight(blockHeight + 1)
 592  		if e != nil {
 593  			context := "No next block"
 594  			return nil, InternalRPCError(e.Error(), context)
 595  		}
 596  		nextHashString = nextHash.String()
 597  	}
 598  	params := s.Cfg.ChainParams
 599  	blockHeader := &blk.WireBlock().Header
 600  	algoname := fork.GetAlgoName(blockHeader.Version, blockHeight)
 601  	a := fork.GetAlgoVer(algoname, blockHeight)
 602  	algoid := fork.GetAlgoID(algoname, blockHeight)
 603  	blockReply := btcjson.GetBlockVerboseResult{
 604  		Hash:          c.Hash,
 605  		Version:       blockHeader.Version,
 606  		VersionHex:    fmt.Sprintf("%08x", blockHeader.Version),
 607  		PowAlgoID:     algoid,
 608  		PowAlgo:       algoname,
 609  		PowHash:       blk.WireBlock().BlockHashWithAlgos(blockHeight).String(),
 610  		MerkleRoot:    blockHeader.MerkleRoot.String(),
 611  		PreviousHash:  blockHeader.PrevBlock.String(),
 612  		Nonce:         blockHeader.Nonce,
 613  		Time:          blockHeader.Timestamp.Unix(),
 614  		Confirmations: int64(1 + best.Height - blockHeight),
 615  		Height:        int64(blockHeight),
 616  		TxNum:         len(blk.Transactions()),
 617  		Size:          int32(len(blkBytes)),
 618  		StrippedSize:  int32(blk.WireBlock().SerializeSizeStripped()),
 619  		Weight:        int32(blockchain.GetBlockWeight(blk)),
 620  		Bits:          strconv.FormatInt(int64(blockHeader.Bits), 16),
 621  		Difficulty:    GetDifficultyRatio(blockHeader.Bits, params, a),
 622  		NextHash:      nextHashString,
 623  	}
 624  	if c.VerboseTx == nil || !*c.VerboseTx {
 625  		transactions := blk.Transactions()
 626  		txNames := make([]string, len(transactions))
 627  		for i, tx := range transactions {
 628  			txNames[i] = tx.Hash().String()
 629  		}
 630  		blockReply.Tx = txNames
 631  	} else {
 632  		txns := blk.Transactions()
 633  		rawTxns := make([]btcjson.TxRawResult, len(txns))
 634  		for i, tx := range txns {
 635  			rawTxn, e := CreateTxRawResult(
 636  				params, tx.MsgTx(),
 637  				tx.Hash().String(), blockHeader, hash.String(),
 638  				blockHeight, best.Height,
 639  			)
 640  			if e != nil {
 641  				return nil, e
 642  			}
 643  			rawTxns[i] = *rawTxn
 644  		}
 645  		blockReply.RawTx = rawTxns
 646  	}
 647  	return blockReply, nil
 648  }
 649  
 650  // HandleGetBlockChainInfo implements the getblockchaininfo command.
 651  func HandleGetBlockChainInfo(
 652  	s *Server,
 653  	cmd interface{},
 654  	closeChan qu.C,
 655  ) (interface{}, error) {
 656  	// Obtain a snapshot of the current best known blockchain state. We'll populate the response to this call primarily
 657  	// from this snapshot.
 658  	params := s.Cfg.ChainParams
 659  	chain := s.Cfg.Chain
 660  	chainSnapshot := chain.BestSnapshot()
 661  	chainInfo := &btcjson.GetBlockChainInfoResult{
 662  		Chain:         params.Name,
 663  		Blocks:        chainSnapshot.Height,
 664  		Headers:       chainSnapshot.Height,
 665  		BestBlockHash: chainSnapshot.Hash.String(),
 666  		Difficulty:    GetDifficultyRatio(chainSnapshot.Bits, params, 2),
 667  		MedianTime:    chainSnapshot.MedianTime.Unix(),
 668  		Pruned:        false,
 669  		// Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription),
 670  	}
 671  	// Next, populate the response with information describing the current status of soft-forks deployed via the
 672  	// super-majority block signalling mechanism.
 673  	// height := chainSnapshot.Height
 674  	// chainInfo.SoftForks = []*btcjson.SoftForkDescription{
 675  	// 	{
 676  	// 		ID:      "bip34",
 677  	// 		Version: 2,
 678  	// 		Reject: struct {
 679  	// 			Status bool `json:"status"`
 680  	// 		}{
 681  	// 			Status: height >= params.BIP0034Height,
 682  	// 		},
 683  	// 	},
 684  	// 	{
 685  	// 		ID:      "bip66",
 686  	// 		Version: 3,
 687  	// 		Reject: struct {
 688  	// 			Status bool `json:"status"`
 689  	// 		}{
 690  	// 			Status: height >= params.BIP0066Height,
 691  	// 		},
 692  	// 	},
 693  	// 	{
 694  	// 		ID:      "bip65",
 695  	// 		Version: 4,
 696  	// 		Reject: struct {
 697  	// 			Status bool `json:"status"`
 698  	// 		}{
 699  	// 			Status: height >= params.BIP0065Height,
 700  	// 		},
 701  	// 	},
 702  	// }
 703  	// // Finally, query the BIP0009 version bits state for all currently defined BIP0009 soft-fork deployments.
 704  	// for deployment, deploymentDetails := range params.Deployments {
 705  	// 	// Map the integer deployment ID into a human readable fork-name.
 706  	// 	var forkName string
 707  	// 	switch deployment {
 708  	// 	case chaincfg.DeploymentTestDummy:
 709  	// 		forkName = "dummy"
 710  	// 	case chaincfg.DeploymentCSV:
 711  	// 		forkName = "csv"
 712  	// 	case chaincfg.DeploymentSegwit:
 713  	// 		forkName = "segwit"
 714  	// 	default:
 715  	// 		return nil, &btcjson.RPCError{
 716  	// 			Code: btcjson.ErrRPCInternal.Code,
 717  	// 			Message: fmt.Sprintf(
 718  	// 				"Unknown deployment %v "+
 719  	// 					"detected", deployment,
 720  	// 			),
 721  	// 		}
 722  	// 	}
 723  	// 	// Query the chain for the current status of the deployment as identified by its deployment ID.
 724  	// 	deploymentStatus, e := chain.ThresholdState(uint32(deployment))
 725  	// 	if e != nil  {
 726  	// 		General	// 		context := "Failed to obtain deployment status"
 727  	// 		return nil, InternalRPCError(err.GeneralError(), context)
 728  	// 	}
 729  	// 	// Attempt to convert the current deployment status into a human readable string. If the status is unrecognized,
 730  	// 	// then a non-nil error is returned.
 731  	// 	statusString, e := SoftForkStatus(deploymentStatus)
 732  	// 	if e != nil  {
 733  	// 		General	// 		return nil, &btcjson.RPCError{
 734  	// 			Code: btcjson.ErrRPCInternal.Code,
 735  	// 			Message: fmt.Sprintf(
 736  	// 				"unknown deployment status: %v",
 737  	// 				deploymentStatus,
 738  	// 			),
 739  	// 		}
 740  	// 	}
 741  	// 	// Finally, populate the soft-fork description with all the information gathered above.
 742  	// 	chainInfo.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{
 743  	// 		Status:    strings.ToLower(statusString),
 744  	// 		Bit:       deploymentDetails.BitNumber,
 745  	// 		StartTime: int64(deploymentDetails.StartTime),
 746  	// 		Timeout:   int64(deploymentDetails.ExpireTime),
 747  	// 	}
 748  	// }
 749  	return chainInfo, nil
 750  }
 751  
 752  // HandleGetBlockCount implements the getblockcount command.
 753  func HandleGetBlockCount(
 754  	s *Server,
 755  	cmd interface{},
 756  	closeChan qu.C,
 757  ) (interface{}, error) {
 758  	best := s.Cfg.Chain.BestSnapshot()
 759  	return int64(best.Height), nil
 760  }
 761  
 762  // HandleGetBlockHash implements the getblockhash command.
 763  func HandleGetBlockHash(
 764  	s *Server,
 765  	cmd interface{},
 766  	closeChan qu.C,
 767  ) (interface{}, error) {
 768  	var msg string
 769  	var e error
 770  	c, ok := cmd.(*btcjson.GetBlockHashCmd)
 771  	if !ok {
 772  		var h string
 773  		h, e = s.HelpCacher.RPCMethodHelp("getblockhash")
 774  		if e != nil {
 775  			msg = e.Error() + "\n\n"
 776  		}
 777  		msg += h
 778  		return nil, &btcjson.RPCError{
 779  			Code:    btcjson.ErrRPCInvalidParameter,
 780  			Message: msg,
 781  			// "invalid subcommand for addnode",
 782  		}
 783  	}
 784  	hash, e := s.Cfg.Chain.BlockHashByHeight(int32(c.Index))
 785  	if e != nil {
 786  		return nil, &btcjson.RPCError{
 787  			Code:    btcjson.ErrRPCOutOfRange,
 788  			Message: "Block number out of range",
 789  		}
 790  	}
 791  	return hash.String(), nil
 792  }
 793  
 794  // HandleGetBlockHeader implements the getblockheader command.
 795  func HandleGetBlockHeader(
 796  	s *Server,
 797  	cmd interface{},
 798  	closeChan qu.C,
 799  ) (interface{}, error) {
 800  	var msg string
 801  	var e error
 802  	c, ok := cmd.(*btcjson.GetBlockHeaderCmd)
 803  	if !ok {
 804  		var h string
 805  		h, e = s.HelpCacher.RPCMethodHelp("getblockheader")
 806  		if e != nil {
 807  			msg = e.Error() + "\n\n"
 808  		}
 809  		msg += h
 810  		return nil, &btcjson.RPCError{
 811  			Code:    btcjson.ErrRPCInvalidParameter,
 812  			Message: msg,
 813  			// "invalid subcommand for addnode",
 814  		}
 815  	}
 816  	// Fetch the header from chain.
 817  	hash, e := chainhash.NewHashFromStr(c.Hash)
 818  	if e != nil {
 819  		return nil, DecodeHexError(c.Hash)
 820  	}
 821  	blockHeader, e := s.Cfg.Chain.HeaderByHash(hash)
 822  	if e != nil {
 823  		return nil, &btcjson.RPCError{
 824  			Code:    btcjson.ErrRPCBlockNotFound,
 825  			Message: "Block not found",
 826  		}
 827  	}
 828  	// When the verbose flag isn't set, simply return the serialized block header as a hex-encoded string.
 829  	if c.Verbose != nil && !*c.Verbose {
 830  		var headerBuf bytes.Buffer
 831  		e = blockHeader.Serialize(&headerBuf)
 832  		if e != nil {
 833  			context := "Failed to serialize block header"
 834  			return nil, InternalRPCError(e.Error(), context)
 835  		}
 836  		return hex.EncodeToString(headerBuf.Bytes()), nil
 837  	}
 838  	// The verbose flag is set, so generate the JSON object and return it. Get the block height from chain.
 839  	blockHeight, e := s.Cfg.Chain.BlockHeightByHash(hash)
 840  	if e != nil {
 841  		context := blockheightfail
 842  		return nil, InternalRPCError(e.Error(), context)
 843  	}
 844  	best := s.Cfg.Chain.BestSnapshot()
 845  	// Get next block hash unless there are none.
 846  	var nextHashString string
 847  	if blockHeight < best.Height {
 848  		nextHash, e := s.Cfg.Chain.BlockHashByHeight(blockHeight + 1)
 849  		if e != nil {
 850  			context := "No next block"
 851  			return nil, InternalRPCError(e.Error(), context)
 852  		}
 853  		nextHashString = nextHash.String()
 854  	}
 855  	var a int32 = 2
 856  	if blockHeader.Version == 514 {
 857  		a = 514
 858  	}
 859  	params := s.Cfg.ChainParams
 860  	blockHeaderReply := btcjson.GetBlockHeaderVerboseResult{
 861  		Hash:          c.Hash,
 862  		Confirmations: int64(1 + best.Height - blockHeight),
 863  		Height:        blockHeight,
 864  		Version:       blockHeader.Version,
 865  		VersionHex:    fmt.Sprintf("%08x", blockHeader.Version),
 866  		MerkleRoot:    blockHeader.MerkleRoot.String(),
 867  		NextHash:      nextHashString,
 868  		PreviousHash:  blockHeader.PrevBlock.String(),
 869  		Nonce:         uint64(blockHeader.Nonce),
 870  		Time:          blockHeader.Timestamp.Unix(),
 871  		Bits:          strconv.FormatInt(int64(blockHeader.Bits), 16),
 872  		Difficulty:    GetDifficultyRatio(blockHeader.Bits, params, a),
 873  	}
 874  	return blockHeaderReply, nil
 875  }
 876  
 877  // HandleGetBlockTemplate implements the getblocktemplate command. See https:// en.bitcoin.it/wiki/BIP_0022 and
 878  // https://en.bitcoin.it/wiki/BIP_0023 for more details.
 879  func HandleGetBlockTemplate(
 880  	s *Server,
 881  	cmd interface{},
 882  	closeChan qu.C,
 883  ) (interface{}, error) {
 884  	var msg string
 885  	var e error
 886  	c, ok := cmd.(*btcjson.GetBlockTemplateCmd)
 887  	if !ok {
 888  		var h string
 889  		h, e = s.HelpCacher.RPCMethodHelp("getblocktemplate")
 890  		if e != nil {
 891  			msg = e.Error() + "\n\n"
 892  		}
 893  		msg += h
 894  		return nil, &btcjson.RPCError{
 895  			Code:    btcjson.ErrRPCInvalidParameter,
 896  			Message: msg,
 897  			// "invalid subcommand for addnode",
 898  		}
 899  	}
 900  	request := c.Request
 901  	// Set the default mode and override it if supplied.
 902  	mode := "template"
 903  	if request != nil && request.Mode != "" {
 904  		mode = request.Mode
 905  	}
 906  	switch mode {
 907  	case "template":
 908  		return HandleGetBlockTemplateRequest(s, request, closeChan)
 909  	case "proposal":
 910  		return HandleGetBlockTemplateProposal(s, request)
 911  	}
 912  	return nil, &btcjson.RPCError{
 913  		Code:    btcjson.ErrRPCInvalidParameter,
 914  		Message: "Invalid mode",
 915  	}
 916  }
 917  
 918  // HandleGetBlockTemplateLongPoll is a helper for handleGetBlockTemplateRequest which deals with handling long polling
 919  // for block templates. When a caller sends a request with a long poll ID that was previously returned, a response is
 920  // not sent until the caller should stop working on the previous block template in favor of the new one.
 921  //
 922  // In particular, this is the case when the old block template is no longer valid due to a solution already being found
 923  // and added to the block chain, or new transactions have shown up and some time has passed without finding a solution.
 924  // See https://en.bitcoin.it/wiki/ BIP_0022 for more details.
 925  func HandleGetBlockTemplateLongPoll(
 926  	s *Server,
 927  	longPollID string,
 928  	useCoinbaseValue bool, closeChan qu.C,
 929  ) (interface{}, error) {
 930  	state := s.GBTWorkState
 931  	state.Lock()
 932  	// The state unlock is intentionally not deferred here since it needs to be manually unlocked before waiting for a
 933  	// notification about block template changes.
 934  	if e := state.UpdateBlockTemplate(s, useCoinbaseValue); E.Chk(e) {
 935  		state.Unlock()
 936  		return nil, e
 937  	}
 938  	// Just return the current block template if the long poll ID provided by the caller is invalid.
 939  	prevHash, lastGenerated, e := DecodeTemplateID(longPollID)
 940  	var result *btcjson.GetBlockTemplateResult
 941  	if e != nil {
 942  		result, e = state.BlockTemplateResult(useCoinbaseValue, nil)
 943  		if e != nil {
 944  			state.Unlock()
 945  			return nil, e
 946  		}
 947  		state.Unlock()
 948  		return result, nil
 949  	}
 950  	// Return the block template now if the specific block template/ identified by the long poll ID no longer matches
 951  	// the current block template as this means the provided template is stale.
 952  	prevTemplateHash := &state.Template.Block.Header.PrevBlock
 953  	if !prevHash.IsEqual(prevTemplateHash) ||
 954  		lastGenerated != state.LastGenerated.Unix() {
 955  		// Include whether or not it is valid to submit work against the old block template depending on whether or not
 956  		// a solution has already been found and added to the block chain.
 957  		submitOld := prevHash.IsEqual(prevTemplateHash)
 958  		result, e = state.BlockTemplateResult(
 959  			useCoinbaseValue,
 960  			&submitOld,
 961  		)
 962  		if e != nil {
 963  			state.Unlock()
 964  			return nil, e
 965  		}
 966  		state.Unlock()
 967  		return result, nil
 968  	}
 969  	// Register the previous hash and last generated time for notifications Get a channel that will be notified when the
 970  	// template associated with the provided ID is stale and a new block template should be returned to the caller.
 971  	longPollChan := state.TemplateUpdateChan(prevHash, lastGenerated)
 972  	state.Unlock()
 973  	select {
 974  	// When the client closes before it's time to send a reply, just return now so the goroutine doesn't hang around.
 975  	case <-closeChan.Wait():
 976  		return nil, ErrClientQuit
 977  	// Wait until signal received to send the reply.
 978  	case <-longPollChan.Wait():
 979  		// Fallthrough
 980  	}
 981  	// Get the lastest block template
 982  	state.Lock()
 983  	defer state.Unlock()
 984  	if e = state.UpdateBlockTemplate(s, useCoinbaseValue); E.Chk(e) {
 985  		return nil, e
 986  	}
 987  	// Include whether or not it is valid to submit work against the old block template depending on whether or not a
 988  	// solution has already been found and added to the block chain.
 989  	submitOld := prevHash.IsEqual(&state.Template.Block.Header.PrevBlock)
 990  	result, e = state.BlockTemplateResult(useCoinbaseValue, &submitOld)
 991  	if e != nil {
 992  		return nil, e
 993  	}
 994  	return result, nil
 995  }
 996  
 997  // HandleGetBlockTemplateProposal is a helper for handleGetBlockTemplate which deals with block proposals. See
 998  // https://en.bitcoin.it/wiki/BIP_0023 for more details.
 999  func HandleGetBlockTemplateProposal(
1000  	s *Server,
1001  	request *btcjson.TemplateRequest,
1002  ) (interface{}, error) {
1003  	hexData := request.Data
1004  	if hexData == "" {
1005  		return false, &btcjson.RPCError{
1006  			Code:    btcjson.ErrRPCType,
1007  			Message: fmt.Sprintf("Data must contain the hex-encoded serialized block that is being proposed"),
1008  		}
1009  	}
1010  	// Ensure the provided data is sane and deserialize the proposed block.
1011  	if len(hexData)%2 != 0 {
1012  		hexData = "0" + hexData
1013  	}
1014  	dataBytes, e := hex.DecodeString(hexData)
1015  	if e != nil {
1016  		return false, &btcjson.RPCError{
1017  			Code: btcjson.ErrRPCDeserialization,
1018  			Message: fmt.Sprintf(
1019  				"data must be hexadecimal string (not %q)",
1020  				hexData,
1021  			),
1022  		}
1023  	}
1024  	var msgBlock wire.Block
1025  	if e := msgBlock.Deserialize(bytes.NewReader(dataBytes)); E.Chk(e) {
1026  		return nil, &btcjson.RPCError{
1027  			Code:    btcjson.ErrRPCDeserialization,
1028  			Message: "block decode failed: " + e.Error(),
1029  		}
1030  	}
1031  	block := block2.NewBlock(&msgBlock)
1032  	// Ensure the block is building from the expected previous block.
1033  	expectedPrevHash := s.Cfg.Chain.BestSnapshot().Hash
1034  	prevHash := &block.WireBlock().Header.PrevBlock
1035  	if !expectedPrevHash.IsEqual(prevHash) {
1036  		return "bad-prevblk", nil
1037  	}
1038  	if e := s.Cfg.Chain.CheckConnectBlockTemplate(block); E.Chk(e) {
1039  		if _, ok := e.(blockchain.RuleError); !ok {
1040  			errStr := fmt.Sprintf("failed to process block proposal: %v", e)
1041  			E.Ln(errStr)
1042  			
1043  			return nil, &btcjson.RPCError{
1044  				Code:    btcjson.ErrRPCVerify,
1045  				Message: errStr,
1046  			}
1047  		}
1048  		I.Ln("rejected block proposal:", e)
1049  		
1050  		return ChainErrToGBTErrString(e), nil
1051  	}
1052  	return nil, nil
1053  }
1054  
1055  // HandleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which deals with generating and returning block
1056  // templates to the caller. It handles both long poll requests as specified by BIP 0022 as well as regular requests.
1057  //
1058  // In addition, it detects the capabilities reported by the caller in regards to whether or not it supports creating its
1059  // own coinbase (the coinbasetxn and coinbasevalue capabilities) and modifies the returned block template accordingly.
1060  func HandleGetBlockTemplateRequest(
1061  	s *Server,
1062  	request *btcjson.TemplateRequest,
1063  	closeChan qu.C,
1064  ) (interface{}, error) {
1065  	// Extract the relevant passed capabilities and restrict the result to either a coinbase value or a coinbase
1066  	// transaction object depending on the request. Default to only providing a coinbase value.
1067  	useCoinbaseValue := true
1068  	if request != nil {
1069  		var hasCoinbaseValue, hasCoinbaseTxn bool
1070  		for _, capability := range request.Capabilities {
1071  			switch capability {
1072  			case "coinbasetxn":
1073  				hasCoinbaseTxn = true
1074  			case "coinbasevalue":
1075  				hasCoinbaseValue = true
1076  			}
1077  		}
1078  		if hasCoinbaseTxn && !hasCoinbaseValue {
1079  			useCoinbaseValue = false
1080  		}
1081  	}
1082  	// When a coinbase transaction has been requested, respond with an error if there are no addresses to pay the
1083  	// created block template to.
1084  	if !useCoinbaseValue && len(s.StateCfg.ActiveMiningAddrs) == 0 {
1085  		return nil, &btcjson.RPCError{
1086  			Code: btcjson.ErrRPCInternal.Code,
1087  			Message: "A coinbase transaction has been requested, " +
1088  				"but the Server has not been configured with " +
1089  				"any payment addresses via --miningaddr",
1090  		}
1091  	}
1092  	// Return an error if there are no peers connected since there is no way to relay a found block or receive
1093  	// transactions to work on. However, allow this workState when running in the regression test or simulation test
1094  	// mode.
1095  	netwk := (s.Config.Network.V())[0]
1096  	if !(netwk == 'r' || netwk == 's') &&
1097  		s.Cfg.ConnMgr.ConnectedCount() == 0 {
1098  		return nil, &btcjson.RPCError{
1099  			Code:    btcjson.ErrRPCClientNotConnected,
1100  			Message: "Pod is not connected to network",
1101  		}
1102  	}
1103  	// No point in generating or accepting work before the chain is synced.
1104  	currentHeight := s.Cfg.Chain.BestSnapshot().Height
1105  	if currentHeight != 0 && !s.Cfg.SyncMgr.IsCurrent() {
1106  		return nil, &btcjson.RPCError{
1107  			Code:    btcjson.ErrRPCClientInInitialDownload,
1108  			Message: "Pod is not yet synchronised...",
1109  		}
1110  	}
1111  	// When a long poll ID was provided, this is a long poll request by the client to be notified when block template
1112  	// referenced by the ID should be replaced with a new one.
1113  	if request != nil && request.LongPollID != "" {
1114  		return HandleGetBlockTemplateLongPoll(
1115  			s, request.LongPollID,
1116  			useCoinbaseValue, closeChan,
1117  		)
1118  	}
1119  	// Protect concurrent access when updating block templates.
1120  	workState := s.GBTWorkState
1121  	workState.Lock()
1122  	defer workState.Unlock()
1123  	// Get and return a block template. A new block template will be generated when the current best block has changed
1124  	// or the transactions in the memory pool have been updated and it has been at least five seconds since the last
1125  	// template was generated.
1126  	//
1127  	// Otherwise, the timestamp for the existing block template is updated (and possibly the difficulty on testnet per
1128  	// the consesus rules).
1129  	if e := workState.UpdateBlockTemplate(s, useCoinbaseValue); E.Chk(e) {
1130  		return nil, e
1131  	}
1132  	return workState.BlockTemplateResult(useCoinbaseValue, nil)
1133  }
1134  
1135  // HandleGetCFilter implements the getcfilter command.
1136  func HandleGetCFilter(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1137  	if s.Cfg.CfIndex == nil {
1138  		return nil, &btcjson.RPCError{
1139  			Code:    btcjson.ErrRPCNoCFIndex,
1140  			Message: "The CF index must be enabled for this command",
1141  		}
1142  	}
1143  	var msg string
1144  	var e error
1145  	c, ok := cmd.(*btcjson.GetCFilterCmd)
1146  	if !ok {
1147  		var h string
1148  		h, e = s.HelpCacher.RPCMethodHelp("getfilter")
1149  		if e != nil {
1150  			msg = e.Error() + "\n\n"
1151  		}
1152  		msg += h
1153  		return nil, &btcjson.RPCError{
1154  			Code:    btcjson.ErrRPCInvalidParameter,
1155  			Message: msg,
1156  			// "invalid subcommand for addnode",
1157  		}
1158  	}
1159  	hash, e := chainhash.NewHashFromStr(c.Hash)
1160  	if e != nil {
1161  		return nil, DecodeHexError(c.Hash)
1162  	}
1163  	filterBytes, e := s.Cfg.CfIndex.FilterByBlockHash(hash, c.FilterType)
1164  	if e != nil {
1165  		D.F("could not find committed filter for %v: %v", hash, e)
1166  		
1167  		return nil, &btcjson.RPCError{
1168  			Code:    btcjson.ErrRPCBlockNotFound,
1169  			Message: "block not found",
1170  		}
1171  	}
1172  	T.Ln("found committed filter for", hash)
1173  	return hex.EncodeToString(filterBytes), nil
1174  }
1175  
1176  // HandleGetCFilterHeader implements the getcfilterheader command.
1177  func HandleGetCFilterHeader(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1178  	if s.Cfg.CfIndex == nil {
1179  		return nil, &btcjson.RPCError{
1180  			Code:    btcjson.ErrRPCNoCFIndex,
1181  			Message: "The CF index must be enabled for this command",
1182  		}
1183  	}
1184  	var msg string
1185  	var e error
1186  	c, ok := cmd.(*btcjson.GetCFilterHeaderCmd)
1187  	if !ok {
1188  		var h string
1189  		h, e = s.HelpCacher.RPCMethodHelp("getcfilterheader")
1190  		if e != nil {
1191  			msg = e.Error() + "\n\n"
1192  		}
1193  		msg += h
1194  		return nil, &btcjson.RPCError{
1195  			Code:    btcjson.ErrRPCInvalidParameter,
1196  			Message: msg,
1197  			// "invalid subcommand for addnode",
1198  		}
1199  	}
1200  	hash, e := chainhash.NewHashFromStr(c.Hash)
1201  	if e != nil {
1202  		return nil, DecodeHexError(c.Hash)
1203  	}
1204  	headerBytes, e := s.Cfg.CfIndex.FilterHeaderByBlockHash(hash, c.FilterType)
1205  	if len(headerBytes) > 0 {
1206  		D.Ln("found header of committed filter for", hash)
1207  		
1208  	} else {
1209  		D.F(
1210  			"could not find header of committed filter for %v: %v",
1211  			hash,
1212  			e,
1213  		)
1214  		
1215  		return nil, &btcjson.RPCError{
1216  			Code:    btcjson.ErrRPCBlockNotFound,
1217  			Message: "Block not found",
1218  		}
1219  	}
1220  	
1221  	e = hash.SetBytes(headerBytes)
1222  	if e != nil {
1223  		D.Ln(e)
1224  		
1225  	}
1226  	return hash.String(), nil
1227  }
1228  
1229  // HandleGetConnectionCount implements the getconnectioncount command.
1230  func HandleGetConnectionCount(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1231  	return s.Cfg.ConnMgr.ConnectedCount(), nil
1232  }
1233  
1234  // HandleGetCurrentNet implements the getcurrentnet command.
1235  func HandleGetCurrentNet(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1236  	return s.Cfg.ChainParams.Net, nil
1237  }
1238  
1239  // HandleGetDifficulty implements the getdifficulty command.
1240  // TODO: This command should default to the configured algo for cpu mining
1241  //  and take an optional parameter to query by algo
1242  func HandleGetDifficulty(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1243  	var msg string
1244  	var e error
1245  	c, ok := cmd.(*btcjson.GetDifficultyCmd)
1246  	if !ok {
1247  		var h string
1248  		h, e = s.HelpCacher.RPCMethodHelp("getdifficulty")
1249  		if e != nil {
1250  			msg = e.Error() + "\n\n"
1251  		}
1252  		msg += h
1253  		return nil, &btcjson.RPCError{
1254  			Code:    btcjson.ErrRPCInvalidParameter,
1255  			Message: msg,
1256  			// "invalid subcommand for addnode",
1257  		}
1258  	}
1259  	best := s.Cfg.Chain.BestSnapshot()
1260  	prev, e := s.Cfg.Chain.BlockByHash(&best.Hash)
1261  	if e != nil {
1262  		E.Ln("ERROR", e)
1263  		
1264  	}
1265  	var algo = prev.WireBlock().Header.Version
1266  	if algo != 514 {
1267  		algo = 2
1268  	}
1269  	bestbits := best.Bits
1270  	if c.Algo == fork.Scrypt && algo != 514 {
1271  		algo = 514
1272  		for {
1273  			if prev.WireBlock().Header.Version != 514 {
1274  				ph := prev.WireBlock().Header.PrevBlock
1275  				prev, e = s.Cfg.Chain.BlockByHash(&ph)
1276  				if e != nil {
1277  					E.Ln("ERROR", e)
1278  					
1279  				}
1280  				continue
1281  			}
1282  			bestbits = prev.WireBlock().Header.Bits
1283  			break
1284  		}
1285  	}
1286  	if c.Algo == fork.SHA256d && algo != 2 {
1287  		algo = 2
1288  		for {
1289  			if prev.WireBlock().Header.Version == 514 {
1290  				ph := prev.WireBlock().Header.PrevBlock
1291  				prev, e = s.Cfg.Chain.BlockByHash(&ph)
1292  				if e != nil {
1293  					E.Ln("ERROR", e)
1294  					
1295  				}
1296  				continue
1297  			}
1298  			bestbits = prev.WireBlock().Header.Bits
1299  			break
1300  		}
1301  	}
1302  	return GetDifficultyRatio(bestbits, s.Cfg.ChainParams, algo), nil
1303  }
1304  
1305  // HandleGetGenerate implements the getgenerate command.
1306  func HandleGetGenerate(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) { // cpuminer
1307  	_, ok := cmd.(*btcjson.GetGenerateCmd)
1308  	if ok {
1309  		result := *s.Config.Controller
1310  		return &result, nil
1311  	}
1312  	// generating := s.StateCfg.Miner != nil
1313  	// if generating {
1314  	//	D.Ln("miner is running internally")
1315  	// } else {
1316  	//	D.Ln("miner is not running")
1317  	// }
1318  	// return nil, nil
1319  	// return s.Cfg.CPUMiner.IsMining(), nil
1320  	return false, errors.New("command was not a btcjson.GetGenerateCmd")
1321  }
1322  
1323  // var startTime = time.Now()
1324  
1325  // HandleGetHashesPerSec implements the gethashespersec command.
1326  func HandleGetHashesPerSec(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) { // cpuminer
1327  	// return int64(s.,
1328  	// Cfg.CPUMiner.HashesPerSecond()), nil
1329  	// TODO: finish this - needs generator for momentary rate (ewma)
1330  	D.Ln("miner hashes per second - multicast thing TODO")
1331  	// simple average for now
1332  	return int(s.Cfg.Hashrate.Load()), nil
1333  }
1334  
1335  // HandleGetHeaders implements the getheaders command.
1336  //
1337  // NOTE: This is a btcsuite extension originally ported from github.com/decred/dcrd.
1338  func HandleGetHeaders(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1339  	var msg string
1340  	var e error
1341  	c, ok := cmd.(*btcjson.GetHeadersCmd)
1342  	if !ok {
1343  		var h string
1344  		h, e = s.HelpCacher.RPCMethodHelp("getheaders")
1345  		if e != nil {
1346  			msg = e.Error() + "\n\n"
1347  		}
1348  		msg += h
1349  		return nil, &btcjson.RPCError{
1350  			Code:    btcjson.ErrRPCInvalidParameter,
1351  			Message: msg,
1352  			// "invalid subcommand for addnode",
1353  		}
1354  	}
1355  	// Fetch the requested headers from chain while respecting the provided block locators and stop hash.
1356  	blockLocators := make([]*chainhash.Hash, len(c.BlockLocators))
1357  	for i := range c.BlockLocators {
1358  		blockLocator, e := chainhash.NewHashFromStr(c.BlockLocators[i])
1359  		if e != nil {
1360  			return nil, DecodeHexError(c.BlockLocators[i])
1361  		}
1362  		blockLocators[i] = blockLocator
1363  	}
1364  	var hashStop chainhash.Hash
1365  	if c.HashStop != "" {
1366  		e := chainhash.Decode(&hashStop, c.HashStop)
1367  		if e != nil {
1368  			return nil, DecodeHexError(c.HashStop)
1369  		}
1370  	}
1371  	headers := s.Cfg.SyncMgr.LocateHeaders(blockLocators, &hashStop)
1372  	// Return the serialized block headers as hex-encoded strings.
1373  	hexBlockHeaders := make([]string, len(headers))
1374  	var buf bytes.Buffer
1375  	for i, h := range headers {
1376  		e := h.Serialize(&buf)
1377  		if e != nil {
1378  			return nil, InternalRPCError(
1379  				e.Error(),
1380  				"Failed to serialize block header",
1381  			)
1382  		}
1383  		hexBlockHeaders[i] = hex.EncodeToString(buf.Bytes())
1384  		buf.Reset()
1385  	}
1386  	return hexBlockHeaders, nil
1387  }
1388  
1389  // HandleGetInfo implements the getinfo command. We only return the fields that are not related to wallet functionality.
1390  // TODO: simplify this, break it up
1391  func HandleGetInfo(
1392  	s *Server,
1393  	cmd interface{},
1394  	closeChan qu.C,
1395  ) (ret interface{}, e error) {
1396  	var Difficulty, dBlake2b, dBlake14lr, dBlake2s, dKeccak, dScrypt, dSHA256D,
1397  	dSkein, dStribog, dX11 float64
1398  	var lastbitsScrypt, lastbitsSHA256D uint32
1399  	best := s.
1400  		Cfg.
1401  		Chain.
1402  		BestSnapshot()
1403  	v := s.Cfg.Chain.Index.LookupNode(&best.Hash)
1404  	foundcount, height := 0, best.Height
1405  	switch fork.GetCurrent(height) {
1406  	case 0:
1407  		for foundcount < 9 && height > 0 {
1408  			switch fork.GetAlgoName(v.Header().Version, height) {
1409  			case fork.SHA256d:
1410  				if lastbitsSHA256D == 0 {
1411  					foundcount++
1412  					lastbitsSHA256D = v.Header().Bits
1413  					dSHA256D = GetDifficultyRatio(
1414  						lastbitsSHA256D,
1415  						s.Cfg.ChainParams, v.Header().Version,
1416  					)
1417  				}
1418  			case fork.Scrypt:
1419  				if lastbitsScrypt == 0 {
1420  					foundcount++
1421  					lastbitsScrypt = v.Header().Bits
1422  					dScrypt = GetDifficultyRatio(
1423  						lastbitsScrypt,
1424  						s.Cfg.ChainParams, v.Header().Version,
1425  					)
1426  				}
1427  			default:
1428  			}
1429  			v = v.RelativeAncestor(1)
1430  			height--
1431  		}
1432  		switch s.Cfg.Algo {
1433  		case fork.SHA256d:
1434  			Difficulty = dSHA256D
1435  		case fork.Scrypt:
1436  			Difficulty = dScrypt
1437  		default:
1438  		}
1439  		ret = &btcjson.InfoChainResult0{
1440  			// Version: int32(
1441  			// version.Tag,
1442  			// 1000000*version.AppMajor +
1443  			// 	10000*version.AppMinor +
1444  			// 	100*version.AppPatch,
1445  			// ),
1446  			ProtocolVersion:   int32(MaxProtocolVersion),
1447  			Blocks:            best.Height,
1448  			TimeOffset:        int64(s.Cfg.TimeSource.Offset().Seconds()),
1449  			Connections:       s.Cfg.ConnMgr.ConnectedCount(),
1450  			Proxy:             s.Config.ProxyAddress.V(),
1451  			PowAlgoID:         fork.GetAlgoID(s.Cfg.Algo, height),
1452  			PowAlgo:           s.Cfg.Algo,
1453  			Difficulty:        Difficulty,
1454  			DifficultySHA256D: dSHA256D,
1455  			DifficultyScrypt:  dScrypt,
1456  			TestNet:           (s.Config.Network.V())[0] == 't',
1457  			RelayFee:          s.StateCfg.ActiveMinRelayTxFee.ToDUO(),
1458  		}
1459  	case 1:
1460  		foundcount, height := 0, best.Height
1461  		for foundcount < 9 &&
1462  			height > fork.List[fork.GetCurrent(height)].ActivationHeight-512 {
1463  			switch fork.GetAlgoName(v.Header().Version, height) {
1464  			case fork.Scrypt:
1465  				if lastbitsScrypt == 0 {
1466  					foundcount++
1467  					lastbitsScrypt = v.Header().Bits
1468  					dScrypt = GetDifficultyRatio(
1469  						lastbitsScrypt,
1470  						s.Cfg.ChainParams, v.Header().Version,
1471  					)
1472  				}
1473  			case fork.SHA256d:
1474  				if lastbitsSHA256D == 0 {
1475  					foundcount++
1476  					lastbitsSHA256D = v.Header().Bits
1477  					dSHA256D = GetDifficultyRatio(
1478  						lastbitsSHA256D,
1479  						s.Cfg.ChainParams, v.Header().Version,
1480  					)
1481  				}
1482  			default:
1483  			}
1484  			v = v.RelativeAncestor(1)
1485  			height--
1486  		}
1487  		switch s.Cfg.Algo {
1488  		case fork.Scrypt:
1489  			Difficulty = dScrypt
1490  		case fork.SHA256d:
1491  			Difficulty = dSHA256D
1492  		default:
1493  		}
1494  		ret = &btcjson.InfoChainResult{
1495  			// Version: int32(
1496  			// 	1000000*version.AppMajor +
1497  			// 		10000*version.AppMinor +
1498  			// 		100*version.AppPatch,
1499  			// ),
1500  			ProtocolVersion:     int32(MaxProtocolVersion),
1501  			Blocks:              best.Height,
1502  			TimeOffset:          int64(s.Cfg.TimeSource.Offset().Seconds()),
1503  			Connections:         s.Cfg.ConnMgr.ConnectedCount(),
1504  			Proxy:               s.Config.ProxyAddress.V(),
1505  			PowAlgoID:           fork.GetAlgoID(s.Cfg.Algo, height),
1506  			PowAlgo:             s.Cfg.Algo,
1507  			Difficulty:          Difficulty,
1508  			DifficultyBlake2b:   dBlake2b,
1509  			DifficultyBlake14lr: dBlake14lr,
1510  			DifficultyBlake2s:   dBlake2s,
1511  			DifficultyKeccak:    dKeccak,
1512  			DifficultyScrypt:    dScrypt,
1513  			DifficultySHA256D:   dSHA256D,
1514  			DifficultySkein:     dSkein,
1515  			DifficultyStribog:   dStribog,
1516  			DifficultyX11:       dX11,
1517  			TestNet:             (s.Config.Network.V())[0] == 't',
1518  			RelayFee:            s.StateCfg.ActiveMinRelayTxFee.ToDUO(),
1519  		}
1520  	}
1521  	return ret, nil
1522  }
1523  
1524  // HandleGetMempoolInfo implements the getmempoolinfo command.
1525  func HandleGetMempoolInfo(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1526  	mempoolTxns := s.Cfg.TxMemPool.TxDescs()
1527  	var numBytes int64
1528  	for _, txD := range mempoolTxns {
1529  		numBytes += int64(txD.Tx.MsgTx().SerializeSize())
1530  	}
1531  	ret := &btcjson.GetMempoolInfoResult{
1532  		Size:  int64(len(mempoolTxns)),
1533  		Bytes: numBytes,
1534  	}
1535  	return ret, nil
1536  }
1537  
1538  // HandleGetMiningInfo implements the getmininginfo command. We only return the fields that are not related to wallet
1539  // functionality. This function returns more information than parallelcoind. TODO: simplify this, break it up
1540  func HandleGetMiningInfo(
1541  	s *Server, cmd interface{},
1542  	closeChan qu.C,
1543  ) (ret interface{}, e error) {
1544  	// cpuminer
1545  	// Create a default getnetworkhashps command to use defaults and make use of the existing getnetworkhashps handler.
1546  	gnhpsCmd := btcjson.NewGetNetworkHashPSCmd(nil, nil)
1547  	networkHashesPerSecIface, e := HandleGetNetworkHashPS(s, gnhpsCmd, closeChan)
1548  	if e != nil {
1549  		return nil, e
1550  	}
1551  	networkHashesPerSec, ok := networkHashesPerSecIface.(int64)
1552  	if !ok {
1553  		return nil, &btcjson.RPCError{
1554  			Code:    btcjson.ErrRPCInternal.Code,
1555  			Message: "networkHashesPerSec is not an int64",
1556  		}
1557  	}
1558  	var Difficulty, dScrypt, dSHA256D float64
1559  	var lastbitsScrypt, lastbitsSHA256D uint32
1560  	best := s.Cfg.Chain.BestSnapshot()
1561  	v := s.Cfg.Chain.Index.LookupNode(&best.Hash)
1562  	foundCount, height := 0, best.Height
1563  	switch fork.GetCurrent(height) {
1564  	case 0:
1565  		for foundCount < 2 && height > 0 {
1566  			switch fork.GetAlgoName(v.Header().Version, height) {
1567  			case fork.SHA256d:
1568  				if lastbitsSHA256D == 0 {
1569  					foundCount++
1570  					lastbitsSHA256D = v.Header().Bits
1571  					dSHA256D = GetDifficultyRatio(
1572  						lastbitsSHA256D,
1573  						s.Cfg.ChainParams, v.Header().Version,
1574  					)
1575  				}
1576  			case fork.Scrypt:
1577  				if lastbitsScrypt == 0 {
1578  					foundCount++
1579  					lastbitsScrypt = v.Header().Bits
1580  					dScrypt = GetDifficultyRatio(
1581  						lastbitsScrypt,
1582  						s.Cfg.ChainParams, v.Header().Version,
1583  					)
1584  				}
1585  			default:
1586  			}
1587  			v = v.RelativeAncestor(1)
1588  			height--
1589  		}
1590  		switch s.Cfg.Algo {
1591  		case fork.SHA256d:
1592  			Difficulty = dSHA256D
1593  		case fork.Scrypt:
1594  			Difficulty = dScrypt
1595  		default:
1596  		}
1597  		D.Ln("missing generate stats in here")
1598  		ret = &btcjson.GetMiningInfoResult0{
1599  			Blocks:             int64(best.Height),
1600  			CurrentBlockSize:   best.BlockSize,
1601  			CurrentBlockWeight: best.BlockWeight,
1602  			CurrentBlockTx:     best.NumTxns,
1603  			PowAlgoID:          fork.GetAlgoID(s.Cfg.Algo, height),
1604  			PowAlgo:            s.Cfg.Algo,
1605  			Difficulty:         Difficulty,
1606  			DifficultySHA256D:  dSHA256D,
1607  			DifficultyScrypt:   dScrypt,
1608  			// Generate:           s.Cfg.CPUMiner.IsMining(),
1609  			// GenProcLimit:       s.Cfg.CPUMiner.NumWorkers(),
1610  			// HashesPerSec:       int64(s.Cfg.CPUMiner.HashesPerSecond()),
1611  			NetworkHashPS: networkHashesPerSec,
1612  			PooledTx:      uint64(s.Cfg.TxMemPool.Count()),
1613  			TestNet:       (s.Config.Network.V())[0] == 't',
1614  		}
1615  	case 1:
1616  		fc, height := 0, best.Height
1617  		for fc < 9 && height > fork.List[fork.GetCurrent(height)].ActivationHeight-512 {
1618  			switch fork.GetAlgoName(v.Header().Version, height) {
1619  			case fork.Scrypt:
1620  				if lastbitsScrypt == 0 {
1621  					fc++
1622  					lastbitsScrypt = v.Header().Bits
1623  					dScrypt = GetDifficultyRatio(
1624  						lastbitsScrypt,
1625  						s.Cfg.ChainParams, v.Header().Version,
1626  					)
1627  				}
1628  			case fork.SHA256d:
1629  				if lastbitsSHA256D == 0 {
1630  					fc++
1631  					lastbitsSHA256D = v.Header().Bits
1632  					dSHA256D = GetDifficultyRatio(
1633  						lastbitsSHA256D,
1634  						s.Cfg.ChainParams, v.Header().Version,
1635  					)
1636  				}
1637  			default:
1638  			}
1639  			v = v.RelativeAncestor(1)
1640  			height--
1641  		}
1642  		switch s.Cfg.Algo {
1643  		case fork.Scrypt:
1644  			Difficulty = dScrypt
1645  		case fork.SHA256d:
1646  			Difficulty = dSHA256D
1647  		default:
1648  		}
1649  		D.Ln("missing cpu miner stuff in here") // cpuminer
1650  		ret = &btcjson.GetMiningInfoResult{
1651  			Blocks:             int64(best.Height),
1652  			CurrentBlockSize:   best.BlockSize,
1653  			CurrentBlockWeight: best.BlockWeight,
1654  			CurrentBlockTx:     best.NumTxns,
1655  			PowAlgoID:          fork.GetAlgoID(s.Cfg.Algo, height),
1656  			PowAlgo:            s.Cfg.Algo,
1657  			Difficulty:         Difficulty,
1658  			DifficultyScrypt:   dScrypt,
1659  			DifficultySHA256D:  dSHA256D,
1660  			NetworkHashPS:      networkHashesPerSec,
1661  			PooledTx:           uint64(s.Cfg.TxMemPool.Count()),
1662  			TestNet:            (s.Config.Network.V())[0] == 't',
1663  		}
1664  	}
1665  	return ret, nil
1666  }
1667  
1668  // HandleGetNetTotals implements the getnettotals command.
1669  func HandleGetNetTotals(
1670  	s *Server,
1671  	cmd interface{},
1672  	closeChan qu.C,
1673  ) (interface{}, error) {
1674  	totalBytesRecv, totalBytesSent := s.Cfg.ConnMgr.NetTotals()
1675  	reply := &btcjson.GetNetTotalsResult{
1676  		TotalBytesRecv: totalBytesRecv,
1677  		TotalBytesSent: totalBytesSent,
1678  		TimeMillis:     time.Now().UTC().UnixNano() / int64(time.Millisecond),
1679  	}
1680  	return reply, nil
1681  }
1682  
1683  // HandleGetNetworkHashPS implements the getnetworkhashps command. This command does not default to the same end block
1684  // as the parallelcoind. TODO: Really this needs to be expanded to show per-algorithm hashrates
1685  func HandleGetNetworkHashPS(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1686  	var msg string
1687  	var e error
1688  	c, ok := cmd.(*btcjson.GetNetworkHashPSCmd)
1689  	if !ok {
1690  		var h string
1691  		h, e = s.HelpCacher.RPCMethodHelp("getnetworkhashps")
1692  		if e != nil {
1693  			msg = e.Error() + "\n\n"
1694  		}
1695  		msg += h
1696  		return nil, &btcjson.RPCError{
1697  			Code:    btcjson.ErrRPCInvalidParameter,
1698  			Message: msg,
1699  			// "invalid subcommand for addnode",
1700  		}
1701  	}
1702  	// Note: All valid error return paths should return an int64. Literal zeros are inferred as int, and won't coerce to
1703  	// int64 because the return value is an interface{}.
1704  	//
1705  	// When the passed height is too high or zero, just return 0 now since we can't reasonably calculate the number of
1706  	// network hashes per second from invalid values. When it's negative, use the current best block height.
1707  	best := s.Cfg.Chain.BestSnapshot()
1708  	endHeight := int32(-1)
1709  	if c.Height != nil {
1710  		endHeight = int32(*c.Height)
1711  	}
1712  	if endHeight > best.Height || endHeight == 0 {
1713  		return int64(0), nil
1714  	}
1715  	if endHeight < 0 {
1716  		endHeight = best.Height
1717  	}
1718  	// Calculate the number of blocks per retarget interval based on the chain parameters.
1719  	blocksPerRetarget := int32(
1720  		s.Cfg.ChainParams.TargetTimespan / s.Cfg.
1721  			ChainParams.TargetTimePerBlock,
1722  	)
1723  	// Calculate the starting block height based on the passed number of blocks.
1724  	//
1725  	// When the passed value is negative, use the last block the difficulty changed as the starting height. Also make
1726  	// sure the starting height is not before the beginning of the chain.
1727  	numBlocks := int32(120)
1728  	if c.Blocks != nil {
1729  		numBlocks = int32(*c.Blocks)
1730  	}
1731  	var startHeight int32
1732  	if numBlocks <= 0 {
1733  		startHeight = endHeight - ((endHeight % blocksPerRetarget) + 1)
1734  	} else {
1735  		startHeight = endHeight - numBlocks
1736  	}
1737  	if startHeight < 0 {
1738  		startHeight = 0
1739  	}
1740  	T.F(
1741  		"calculating network hashes per second from %d to %d",
1742  		startHeight,
1743  		endHeight,
1744  	)
1745  	
1746  	// Find the min and max block timestamps as well as calculate the total amount of work that happened between the
1747  	// start and end blocks.
1748  	var minTimestamp, maxTimestamp time.Time
1749  	totalWork := big.NewInt(0)
1750  	for curHeight := startHeight; curHeight <= endHeight; curHeight++ {
1751  		hash, e := s.Cfg.Chain.BlockHashByHeight(curHeight)
1752  		if e != nil {
1753  			context := "Failed to fetch block hash"
1754  			return nil, InternalRPCError(e.Error(), context)
1755  		}
1756  		// Fetch the header from chain.
1757  		header, e := s.Cfg.Chain.HeaderByHash(hash)
1758  		if e != nil {
1759  			context := "Failed to fetch block header"
1760  			return nil, InternalRPCError(e.Error(), context)
1761  		}
1762  		if curHeight == startHeight {
1763  			minTimestamp = header.Timestamp
1764  			maxTimestamp = minTimestamp
1765  		} else {
1766  			totalWork.Add(
1767  				totalWork, blockchain.CalcWork(
1768  					header.Bits,
1769  					best.Height+1, header.Version,
1770  				),
1771  			)
1772  			if minTimestamp.After(header.Timestamp) {
1773  				minTimestamp = header.Timestamp
1774  			}
1775  			if maxTimestamp.Before(header.Timestamp) {
1776  				maxTimestamp = header.Timestamp
1777  			}
1778  		}
1779  	}
1780  	// Calculate the difference in seconds between the min and max block timestamps and avoid division by zero in the
1781  	// case where there is no time difference.
1782  	timeDiff := int64(maxTimestamp.Sub(minTimestamp) / time.Second)
1783  	if timeDiff == 0 {
1784  		return int64(0), nil
1785  	}
1786  	hashesPerSec := new(big.Int).Div(totalWork, big.NewInt(timeDiff))
1787  	return hashesPerSec.Int64(), nil
1788  }
1789  
1790  // HandleGetPeerInfo implements the getpeerinfo command.
1791  func HandleGetPeerInfo(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1792  	peers := s.Cfg.ConnMgr.ConnectedPeers()
1793  	syncPeerID := s.Cfg.SyncMgr.SyncPeerID()
1794  	infos := make([]*btcjson.GetPeerInfoResult, 0, len(peers))
1795  	for _, p := range peers {
1796  		statsSnap := p.ToPeer().StatsSnapshot()
1797  		var addr, addrLocal string
1798  		if statsSnap.Inbound {
1799  			addr =
1800  				statsSnap.Addr
1801  			addrLocal =
1802  				p.ToPeer().LocalAddr().String()
1803  			// (*s.Config.P2PConnect)[0]
1804  		} else {
1805  			addr =
1806  				statsSnap.Addr
1807  			addrLocal =
1808  			// (*s.Config.P2PConnect)[0]
1809  				p.ToPeer().LocalAddr().String()
1810  		}
1811  		info := &btcjson.GetPeerInfoResult{
1812  			ID:             statsSnap.ID,
1813  			Addr:           addr,
1814  			AddrLocal:      addrLocal,
1815  			Services:       fmt.Sprintf("%08d", uint64(statsSnap.Services)),
1816  			RelayTxes:      !p.IsTxRelayDisabled(),
1817  			LastSend:       statsSnap.LastSend.Unix(),
1818  			LastRecv:       statsSnap.LastRecv.Unix(),
1819  			BytesSent:      statsSnap.BytesSent,
1820  			BytesRecv:      statsSnap.BytesRecv,
1821  			ConnTime:       statsSnap.ConnTime.Unix(),
1822  			PingTime:       float64(statsSnap.LastPingMicros),
1823  			TimeOffset:     statsSnap.TimeOffset,
1824  			Version:        statsSnap.Version,
1825  			SubVer:         statsSnap.UserAgent,
1826  			Inbound:        statsSnap.Inbound,
1827  			StartingHeight: statsSnap.StartingHeight,
1828  			CurrentHeight:  statsSnap.LastBlock,
1829  			BanScore:       int32(p.GetBanScore()),
1830  			FeeFilter:      p.GetFeeFilter(),
1831  			SyncNode:       statsSnap.ID == syncPeerID,
1832  		}
1833  		if p.ToPeer().LastPingNonce() != 0 {
1834  			wait := float64(time.Since(statsSnap.LastPingTime).Nanoseconds())
1835  			// We actually want microseconds.
1836  			info.PingWait = wait / 1000
1837  		}
1838  		infos = append(infos, info)
1839  	}
1840  	return infos, nil
1841  }
1842  
1843  // HandleGetRawMempool implements the getrawmempool command.
1844  func HandleGetRawMempool(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1845  	c := cmd.(*btcjson.GetRawMempoolCmd)
1846  	mp := s.Cfg.TxMemPool
1847  	if c.Verbose != nil && *c.Verbose {
1848  		return mp.RawMempoolVerbose(), nil
1849  	}
1850  	// The response is simply an array of the transaction hashes if the verbose flag is not set.
1851  	descs := mp.TxDescs()
1852  	hashStrings := make([]string, len(descs))
1853  	for i := range hashStrings {
1854  		hashStrings[i] = descs[i].Tx.Hash().String()
1855  	}
1856  	return hashStrings, nil
1857  }
1858  
1859  // HandleGetRawTransaction implements the getrawtransaction command.
1860  func HandleGetRawTransaction(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1861  	var msg string
1862  	var e error
1863  	c, ok := cmd.(*btcjson.GetRawTransactionCmd)
1864  	if !ok {
1865  		var h string
1866  		h, e = s.HelpCacher.RPCMethodHelp("getrawtransaction")
1867  		if e != nil {
1868  			msg = e.Error() + "\n\n"
1869  		}
1870  		msg += h
1871  		return nil, &btcjson.RPCError{
1872  			Code:    btcjson.ErrRPCInvalidParameter,
1873  			Message: msg,
1874  			// "invalid subcommand for addnode",
1875  		}
1876  	}
1877  	// Convert the provided transaction hash hex to a Hash.
1878  	txHash, e := chainhash.NewHashFromStr(c.Txid)
1879  	if e != nil {
1880  		return nil, DecodeHexError(c.Txid)
1881  	}
1882  	verbose := false
1883  	if c.Verbose != nil {
1884  		verbose = *c.Verbose != 0
1885  	}
1886  	// Try to fetch the transaction from the memory pool and if that fails, try the block database.
1887  	var mtx *wire.MsgTx
1888  	var blkHash *chainhash.Hash
1889  	var blkHeight int32
1890  	tx, e := s.Cfg.TxMemPool.FetchTransaction(txHash)
1891  	if e != nil {
1892  		if s.Cfg.TxIndex == nil {
1893  			return nil, &btcjson.RPCError{
1894  				Code: btcjson.ErrRPCNoTxInfo,
1895  				Message: "The transaction index must be " +
1896  					"enabled to query the blockchain " +
1897  					"(specify --txindex)",
1898  			}
1899  		}
1900  		// Look up the location of the transaction.
1901  		var blockRegion *database.BlockRegion
1902  		blockRegion, e = s.Cfg.TxIndex.TxBlockRegion(txHash)
1903  		if e != nil {
1904  			context := "Failed to retrieve transaction location"
1905  			return nil, InternalRPCError(e.Error(), context)
1906  		}
1907  		if blockRegion == nil {
1908  			return nil, NoTxInfoError(txHash)
1909  		}
1910  		// Load the raw transaction bytes from the database.
1911  		var txBytes []byte
1912  		e = s.Cfg.DB.View(
1913  			func(dbTx database.Tx) (e error) {
1914  				txBytes, e = dbTx.FetchBlockRegion(blockRegion)
1915  				return e
1916  			},
1917  		)
1918  		if e != nil {
1919  			return nil, NoTxInfoError(txHash)
1920  		}
1921  		// When the verbose flag isn't set, simply return the serialized transaction as a hex-encoded string. This is
1922  		// done here to avoid deserializing it only to reserialize it again later.
1923  		if !verbose {
1924  			return hex.EncodeToString(txBytes), nil
1925  		}
1926  		// Grab the block height.
1927  		blkHash = blockRegion.Hash
1928  		blkHeight, e = s.Cfg.Chain.BlockHeightByHash(blkHash)
1929  		if e != nil {
1930  			context := "Failed to retrieve block height"
1931  			return nil, InternalRPCError(e.Error(), context)
1932  		}
1933  		// Deserialize the transaction
1934  		var msgTx wire.MsgTx
1935  		e = msgTx.Deserialize(bytes.NewReader(txBytes))
1936  		if e != nil {
1937  			context := deserialfail
1938  			return nil, InternalRPCError(e.Error(), context)
1939  		}
1940  		mtx = &msgTx
1941  	} else {
1942  		// When the verbose flag isn't set, simply return the network-serialized transaction as a hex-encoded string.
1943  		if !verbose {
1944  			// Note that this is intentionally not directly returning because the first return value is a string and it
1945  			// would result in returning an empty string to the client instead of nothing (nil) in the case of an error.
1946  			var mtxHex string
1947  			mtxHex, e = MessageToHex(tx.MsgTx())
1948  			if e != nil {
1949  				return nil, e
1950  			}
1951  			return mtxHex, nil
1952  		}
1953  		mtx = tx.MsgTx()
1954  	}
1955  	// The verbose flag is set, so generate the JSON object and return it.
1956  	var blkHeader *wire.BlockHeader
1957  	var blkHashStr string
1958  	var chainHeight int32
1959  	if blkHash != nil {
1960  		// Fetch the header from chain.
1961  		var header wire.BlockHeader
1962  		header, e = s.Cfg.Chain.HeaderByHash(blkHash)
1963  		if e != nil {
1964  			context := "Failed to fetch block header"
1965  			return nil, InternalRPCError(e.Error(), context)
1966  		}
1967  		blkHeader = &header
1968  		blkHashStr = blkHash.String()
1969  		chainHeight = s.Cfg.Chain.BestSnapshot().Height
1970  	}
1971  	rawTxn, e := CreateTxRawResult(
1972  		s.Cfg.ChainParams, mtx, txHash.String(),
1973  		blkHeader, blkHashStr, blkHeight, chainHeight,
1974  	)
1975  	if e != nil {
1976  		return nil, e
1977  	}
1978  	return *rawTxn, nil
1979  }
1980  
1981  // HandleGetTxOut handles gettxout commands.
1982  func HandleGetTxOut(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
1983  	var msg string
1984  	var e error
1985  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
1986  	c, ok := cmd.(*btcjson.GetTxOutCmd)
1987  	if !ok {
1988  		var h string
1989  		h, e = s.HelpCacher.RPCMethodHelp("gettxout")
1990  		if e != nil {
1991  			msg = e.Error() + "\n\n"
1992  		}
1993  		msg += h
1994  		return nil, &btcjson.RPCError{
1995  			Code:    btcjson.ErrRPCInvalidParameter,
1996  			Message: msg,
1997  			// "invalid subcommand for addnode",
1998  		}
1999  	}
2000  	// Convert the provided transaction hash hex to a Hash.
2001  	txHash, e := chainhash.NewHashFromStr(c.Txid)
2002  	if e != nil {
2003  		return nil, DecodeHexError(c.Txid)
2004  	}
2005  	// If requested and the tx is available in the mempool try to fetch it from there, otherwise attempt to fetch from
2006  	// the block database.
2007  	var bestBlockHash string
2008  	var confirmations int32
2009  	var value int64
2010  	var pkScript []byte
2011  	var isCoinbase bool
2012  	includeMempool := true
2013  	if c.IncludeMempool != nil {
2014  		includeMempool = *c.IncludeMempool
2015  	}
2016  	// TODO: This is racy.  It should attempt to fetch it directly and check the error.
2017  	if includeMempool && s.Cfg.TxMemPool.HaveTransaction(txHash) {
2018  		tx, e := s.Cfg.TxMemPool.FetchTransaction(txHash)
2019  		if e != nil {
2020  			return nil, NoTxInfoError(txHash)
2021  		}
2022  		mtx := tx.MsgTx()
2023  		if c.Vout > uint32(len(mtx.TxOut)-1) {
2024  			return nil, &btcjson.RPCError{
2025  				Code: btcjson.ErrRPCInvalidTxVout,
2026  				Message: "Output index number (vout) does not " +
2027  					"exist for transaction.",
2028  			}
2029  		}
2030  		txOut := mtx.TxOut[c.Vout]
2031  		if txOut == nil {
2032  			errStr := fmt.Sprintf(
2033  				"Output index: %d for txid: %s "+
2034  					"does not exist", c.Vout, txHash,
2035  			)
2036  			return nil, InternalRPCError(errStr, "")
2037  		}
2038  		best := s.Cfg.Chain.BestSnapshot()
2039  		bestBlockHash = best.Hash.String()
2040  		confirmations = 0
2041  		value = txOut.Value
2042  		pkScript = txOut.PkScript
2043  		isCoinbase = blockchain.IsCoinBaseTx(mtx)
2044  	} else {
2045  		out := wire.OutPoint{Hash: *txHash, Index: c.Vout}
2046  		entry, e := s.Cfg.Chain.FetchUtxoEntry(out)
2047  		if e != nil {
2048  			return nil, NoTxInfoError(txHash)
2049  		}
2050  		// To match the behavior of the reference client, return nil (JSON null) if the transaction output is spent by
2051  		// another transaction already in the main chain. Mined transactions that are spent by a mempool transaction are
2052  		// not affected by this.
2053  		if entry == nil || entry.IsSpent() {
2054  			return nil, nil
2055  		}
2056  		best := s.Cfg.Chain.BestSnapshot()
2057  		bestBlockHash = best.Hash.String()
2058  		confirmations = 1 + best.Height - entry.BlockHeight()
2059  		value = entry.Amount()
2060  		pkScript = entry.PkScript()
2061  		isCoinbase = entry.IsCoinBase()
2062  	}
2063  	// Disassemble script into single line printable format. The disassembled string will contain [error] inline if the
2064  	// script doesn't fully parse, so ignore the error here.
2065  	disbuf, _ := txscript.DisasmString(pkScript)
2066  	// Get further info about the script. Ignore the error here since an error means the script couldn't parse and there
2067  	// is no additional information about it anyways.
2068  	scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(pkScript, s.Cfg.ChainParams)
2069  	addresses := make([]string, len(addrs))
2070  	for i, addr := range addrs {
2071  		addresses[i] = addr.EncodeAddress()
2072  	}
2073  	txOutReply := &btcjson.GetTxOutResult{
2074  		BestBlock:     bestBlockHash,
2075  		Confirmations: int64(confirmations),
2076  		Value:         amt.Amount(value).ToDUO(),
2077  		ScriptPubKey: btcjson.ScriptPubKeyResult{
2078  			Asm:       disbuf,
2079  			Hex:       hex.EncodeToString(pkScript),
2080  			ReqSigs:   int32(reqSigs),
2081  			Type:      scriptClass.String(),
2082  			Addresses: addresses,
2083  		},
2084  		Coinbase: isCoinbase,
2085  	}
2086  	return txOutReply, nil
2087  }
2088  
2089  // HandleHelp implements the help command.
2090  func HandleHelp(s *Server, cmd interface{}, closeChan qu.C) (
2091  	interface{}, error,
2092  ) {
2093  	var msg string
2094  	var e error
2095  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2096  	c, ok := cmd.(*btcjson.HelpCmd)
2097  	if !ok {
2098  		var h string
2099  		h, e = s.HelpCacher.RPCUsage(true)
2100  		if e != nil {
2101  			msg = e.Error() + "\n"
2102  		}
2103  		msg += h
2104  		return nil, &btcjson.RPCError{
2105  			Code:    btcjson.ErrRPCInvalidParameter,
2106  			Message: msg,
2107  			// "invalid subcommand for addnode",
2108  		}
2109  	}
2110  	// Provide a usage overview of all commands when no specific command was specified.
2111  	var command string
2112  	if c.Command != nil {
2113  		command = *c.Command
2114  	}
2115  	if command == "" {
2116  		var usage string
2117  		usage, e = s.HelpCacher.RPCUsage(false)
2118  		if e != nil {
2119  			context := "Failed to generate RPC usage"
2120  			return nil, InternalRPCError(e.Error(), context)
2121  		}
2122  		return usage, nil
2123  	}
2124  	// Chk that the command asked for is supported and implemented. Only search the main list of handlers since help
2125  	// should not be provided for commands that are unimplemented or related to wallet functionality.
2126  	if _, ok := RPCHandlers[command]; !ok {
2127  		return nil, &btcjson.RPCError{
2128  			Code:    btcjson.ErrRPCInvalidParameter,
2129  			Message: "Unknown command: " + command,
2130  		}
2131  	}
2132  	// Get the help for the command.
2133  	help, e := s.HelpCacher.RPCMethodHelp(command)
2134  	if e != nil {
2135  		context := "Failed to generate help"
2136  		return nil, InternalRPCError(e.Error(), context)
2137  	}
2138  	return help, nil
2139  }
2140  
2141  // HandleNode handles node commands.
2142  func HandleNode(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2143  	var msg string
2144  	var e error
2145  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2146  	c, ok := cmd.(*btcjson.NodeCmd)
2147  	if !ok {
2148  		var h string
2149  		h, e = s.HelpCacher.RPCMethodHelp("help")
2150  		if e != nil {
2151  			msg = e.Error() + "\n\n"
2152  		}
2153  		msg += h
2154  		return nil, &btcjson.RPCError{
2155  			Code:    btcjson.ErrRPCInvalidParameter,
2156  			Message: msg,
2157  			// "invalid subcommand for addnode",
2158  		}
2159  	}
2160  	var addr string
2161  	var nodeID uint64
2162  	var errN error
2163  	params := s.Cfg.ChainParams
2164  	switch c.SubCmd {
2165  	case "disconnect":
2166  		// If we have a valid uint disconnect by node id. Otherwise, attempt to disconnect by address, returning an
2167  		// error if a valid IP address is not supplied.
2168  		if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil {
2169  			e = s.Cfg.ConnMgr.DisconnectByID(int32(nodeID))
2170  		} else {
2171  			if _, _, errP := net.SplitHostPort(c.Target); errP == nil || net.ParseIP(c.Target) != nil {
2172  				addr = NormalizeAddress(c.Target, params.DefaultPort)
2173  				e = s.Cfg.ConnMgr.DisconnectByAddr(addr)
2174  			} else {
2175  				return nil, &btcjson.RPCError{
2176  					Code:    btcjson.ErrRPCInvalidParameter,
2177  					Message: "invalid address or node ID",
2178  				}
2179  			}
2180  		}
2181  		if e != nil && PeerExists(s.Cfg.ConnMgr, addr, int32(nodeID)) {
2182  			return nil, &btcjson.RPCError{
2183  				Code:    btcjson.ErrRPCMisc,
2184  				Message: "can't disconnect a permanent peer, use remove",
2185  			}
2186  		}
2187  	case "remove":
2188  		// If we have a valid uint disconnect by node id. Otherwise, attempt to disconnect by address, returning an
2189  		// error if a valid IP address is not supplied.
2190  		if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil {
2191  			e = s.Cfg.ConnMgr.RemoveByID(int32(nodeID))
2192  		} else {
2193  			if _, _, errP := net.SplitHostPort(c.Target); errP == nil || net.ParseIP(c.Target) != nil {
2194  				addr = NormalizeAddress(c.Target, params.DefaultPort)
2195  				e = s.Cfg.ConnMgr.RemoveByAddr(addr)
2196  			} else {
2197  				return nil, &btcjson.RPCError{
2198  					Code:    btcjson.ErrRPCInvalidParameter,
2199  					Message: "invalid address or node ID",
2200  				}
2201  			}
2202  		}
2203  		if e != nil && PeerExists(s.Cfg.ConnMgr, addr, int32(nodeID)) {
2204  			return nil, &btcjson.RPCError{
2205  				Code:    btcjson.ErrRPCMisc,
2206  				Message: "can't remove a temporary peer, use disconnect",
2207  			}
2208  		}
2209  	case "connect":
2210  		addr = NormalizeAddress(c.Target, params.DefaultPort)
2211  		// Default to temporary connections.
2212  		subCmd := "temp"
2213  		if c.ConnectSubCmd != nil {
2214  			subCmd = *c.ConnectSubCmd
2215  		}
2216  		switch subCmd {
2217  		case "perm", "temp":
2218  			e = s.Cfg.ConnMgr.Connect(addr, subCmd == "perm")
2219  		default:
2220  			return nil, &btcjson.RPCError{
2221  				Code:    btcjson.ErrRPCInvalidParameter,
2222  				Message: "invalid subcommand for node connect",
2223  			}
2224  		}
2225  	default:
2226  		return nil, &btcjson.RPCError{
2227  			Code:    btcjson.ErrRPCInvalidParameter,
2228  			Message: "invalid subcommand for node",
2229  		}
2230  	}
2231  	if e != nil {
2232  		return nil, &btcjson.RPCError{
2233  			Code:    btcjson.ErrRPCInvalidParameter,
2234  			Message: e.Error(),
2235  		}
2236  	}
2237  	// no data returned unless an error.
2238  	return nil, nil
2239  }
2240  
2241  // HandlePing implements the ping command.
2242  func HandlePing(s *Server, cmd interface{}, closeChan qu.C) (
2243  	interface{}, error,
2244  ) {
2245  	// Ask Server to ping \o_
2246  	nonce, e := wire.RandomUint64()
2247  	if e != nil {
2248  		return nil, InternalRPCError(
2249  			"Not sending ping - failed to generate nonce: "+e.Error(), "",
2250  		)
2251  	}
2252  	s.Cfg.ConnMgr.BroadcastMessage(wire.NewMsgPing(nonce))
2253  	return nil, nil
2254  }
2255  
2256  // HandleSearchRawTransactions implements the searchrawtransactions command.
2257  // TODO: simplify this, break it up
2258  func HandleSearchRawTransactions(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2259  	// Respond with an error if the address index is not enabled.
2260  	addrIndex := s.Cfg.AddrIndex
2261  	if addrIndex == nil {
2262  		return nil, &btcjson.RPCError{
2263  			Code:    btcjson.ErrRPCMisc,
2264  			Message: "Address index must be enabled (--addrindex)",
2265  		}
2266  	}
2267  	// Override the flag for including extra previous output information in each input if needed.
2268  	c := cmd.(*btcjson.SearchRawTransactionsCmd)
2269  	vinExtra := false
2270  	if c.VinExtra != nil {
2271  		vinExtra = *c.VinExtra != 0
2272  	}
2273  	// Including the extra previous output information requires the transaction index. Currently the address index
2274  	// relies on the transaction index, so this check is redundant, but it's better to be safe in case the address index
2275  	// is ever changed to not rely on it.
2276  	if vinExtra && s.Cfg.TxIndex == nil {
2277  		return nil, &btcjson.RPCError{
2278  			Code:    btcjson.ErrRPCMisc,
2279  			Message: "Transaction index must be enabled (--txindex)",
2280  		}
2281  	}
2282  	// Attempt to decode the supplied address.
2283  	params := s.Cfg.ChainParams
2284  	addr, e := btcaddr.Decode(c.Address, params)
2285  	if e != nil {
2286  		return nil, &btcjson.RPCError{
2287  			Code:    btcjson.ErrRPCInvalidAddressOrKey,
2288  			Message: "Invalid address or key: " + e.Error(),
2289  		}
2290  	}
2291  	// Override the default number of requested entries if needed. Also, just return now if the number of requested
2292  	// entries is zero to avoid extra work.
2293  	numRequested := 100
2294  	if c.Count != nil {
2295  		numRequested = *c.Count
2296  		if numRequested < 0 {
2297  			numRequested = 1
2298  		}
2299  	}
2300  	if numRequested == 0 {
2301  		return nil, nil
2302  	}
2303  	// Override the default number of entries to skip if needed.
2304  	var numToSkip int
2305  	if c.Skip != nil {
2306  		numToSkip = *c.Skip
2307  		if numToSkip < 0 {
2308  			numToSkip = 0
2309  		}
2310  	}
2311  	// Override the reverse flag if needed.
2312  	var reverse bool
2313  	if c.Reverse != nil {
2314  		reverse = *c.Reverse
2315  	}
2316  	// Add transactions from mempool first if client asked for reverse order. Otherwise, they will be added last (as
2317  	// needed depending on the requested counts). NOTE: This code doesn't txsort by dependency. This might be something to
2318  	// do in the future for the client's convenience, or leave it to the client.
2319  	numSkipped := uint32(0)
2320  	addressTxns := make([]RetrievedTx, 0, numRequested)
2321  	if reverse {
2322  		// Transactions in the mempool are not in a block header yet, so the block header field in the retrieved
2323  		// transaction struct is left nil.
2324  		mpTxns, mpSkipped := FetchMempoolTxnsForAddress(
2325  			s, addr,
2326  			uint32(numToSkip), uint32(numRequested),
2327  		)
2328  		numSkipped += mpSkipped
2329  		for _, tx := range mpTxns {
2330  			addressTxns = append(addressTxns, RetrievedTx{Tx: tx})
2331  		}
2332  	}
2333  	// Fetch transactions from the database in the desired order if more are needed.
2334  	if len(addressTxns) < numRequested {
2335  		e = s.Cfg.DB.View(
2336  			func(dbTx database.Tx) (e error) {
2337  				regions, dbSkipped, e := addrIndex.TxRegionsForAddress(
2338  					dbTx, addr,
2339  					uint32(numToSkip)-numSkipped, uint32(numRequested-len(addressTxns)),
2340  					reverse,
2341  				)
2342  				if e != nil {
2343  					return e
2344  				}
2345  				// Load the raw transaction bytes from the database.
2346  				serializedTxns, e := dbTx.FetchBlockRegions(regions)
2347  				if e != nil {
2348  					return e
2349  				}
2350  				// Add the transaction and the hash of the block it is contained in to the list. Note that the transaction
2351  				// is left serialized here since the caller might have requested non-verbose output and hence there would
2352  				// be/ no point in deserializing it just to reserialize it later.
2353  				for i, serializedTx := range serializedTxns {
2354  					addressTxns = append(
2355  						addressTxns, RetrievedTx{
2356  							TxBytes: serializedTx,
2357  							BlkHash: regions[i].Hash,
2358  						},
2359  					)
2360  				}
2361  				numSkipped += dbSkipped
2362  				return nil
2363  			},
2364  		)
2365  		if e != nil {
2366  			context := "Failed to load address index entries"
2367  			return nil, InternalRPCError(e.Error(), context)
2368  		}
2369  	}
2370  	// Add transactions from mempool last if client did not request reverse order and the number of results is still
2371  	// under the number requested.
2372  	if !reverse && len(addressTxns) < numRequested {
2373  		// Transactions in the mempool are not in a block header yet, so the block header field in the retrieved
2374  		// transaction struct is left nil.
2375  		mpTxns, mpSkipped := FetchMempoolTxnsForAddress(
2376  			s, addr,
2377  			uint32(numToSkip)-numSkipped, uint32(numRequested-len(addressTxns)),
2378  		)
2379  		numSkipped += mpSkipped
2380  		for _, tx := range mpTxns {
2381  			addressTxns = append(addressTxns, RetrievedTx{Tx: tx})
2382  		}
2383  	}
2384  	// Address has never been used if neither source yielded any results.
2385  	if len(addressTxns) == 0 {
2386  		return nil, &btcjson.RPCError{
2387  			Code:    btcjson.ErrRPCNoTxInfo,
2388  			Message: "No information available about address",
2389  		}
2390  	}
2391  	// Serialize all of the transactions to hex.
2392  	hexTxns := make([]string, len(addressTxns))
2393  	for i := range addressTxns {
2394  		// Simply encode the raw bytes to hex when the retrieved transaction is already in serialized form.
2395  		rtx := &addressTxns[i]
2396  		if rtx.TxBytes != nil {
2397  			hexTxns[i] = hex.EncodeToString(rtx.TxBytes)
2398  			continue
2399  		}
2400  		// Serialize the transaction first and convert to hex when the retrieved transaction is the deserialized
2401  		// structure.
2402  		hexTxns[i], e = MessageToHex(rtx.Tx.MsgTx())
2403  		if e != nil {
2404  			return nil, e
2405  		}
2406  	}
2407  	// When not in verbose mode, simply return a list of serialized txns.
2408  	if c.Verbose != nil && *c.Verbose == 0 {
2409  		return hexTxns, nil
2410  	}
2411  	// Normalize the provided filter addresses (if any) to ensure there are no duplicates.
2412  	filterAddrMap := make(map[string]struct{})
2413  	if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 {
2414  		for _, addr := range *c.FilterAddrs {
2415  			filterAddrMap[addr] = struct{}{}
2416  		}
2417  	}
2418  	// The verbose flag is set, so generate the JSON object and return it.
2419  	best := s.Cfg.Chain.BestSnapshot()
2420  	srtList := make([]btcjson.SearchRawTransactionsResult, len(addressTxns))
2421  	for i := range addressTxns {
2422  		// The deserialized transaction is needed, so deserialize the retrieved transaction if it's in serialized form
2423  		// (which will be the case when it was lookup up from the database). Otherwise, use the existing deserialized
2424  		// transaction.
2425  		var rtx *RetrievedTx
2426  		rtx = &addressTxns[i]
2427  		var mtx *wire.MsgTx
2428  		if rtx.Tx == nil {
2429  			// Deserialize the transaction.
2430  			mtx = new(wire.MsgTx)
2431  			e = mtx.Deserialize(bytes.NewReader(rtx.TxBytes))
2432  			if e != nil {
2433  				context := deserialfail
2434  				return nil, InternalRPCError(e.Error(), context)
2435  			}
2436  		} else {
2437  			mtx = rtx.Tx.MsgTx()
2438  		}
2439  		result := &srtList[i]
2440  		result.Hex = hexTxns[i]
2441  		result.TxID = mtx.TxHash().String()
2442  		result.Vin, e = CreateVinListPrevOut(
2443  			s, mtx, params, vinExtra,
2444  			filterAddrMap,
2445  		)
2446  		if e != nil {
2447  			return nil, e
2448  		}
2449  		result.VOut = CreateVoutList(mtx, params, filterAddrMap)
2450  		result.Version = mtx.Version
2451  		result.LockTime = mtx.LockTime
2452  		// Transactions grabbed from the mempool aren't yet in a block, so conditionally fetch block details here. This
2453  		// will be reflected in the final JSON output (mempool won't have confirmations or block information).
2454  		var blkHeader *wire.BlockHeader
2455  		var blkHashStr string
2456  		var blkHeight int32
2457  		if blkHash := rtx.BlkHash; blkHash != nil {
2458  			// Fetch the header from chain.
2459  			header, e := s.Cfg.Chain.HeaderByHash(blkHash)
2460  			if e != nil {
2461  				return nil, &btcjson.RPCError{
2462  					Code:    btcjson.ErrRPCBlockNotFound,
2463  					Message: "Block not found",
2464  				}
2465  			}
2466  			// Get the block height from chain.
2467  			height, e := s.Cfg.Chain.BlockHeightByHash(blkHash)
2468  			if e != nil {
2469  				context := blockheightfail
2470  				return nil, InternalRPCError(e.Error(), context)
2471  			}
2472  			blkHeader = &header
2473  			blkHashStr = blkHash.String()
2474  			blkHeight = height
2475  		}
2476  		// Add the block information to the result if there is any.
2477  		if blkHeader != nil {
2478  			// This is not a typo, they are identical in Bitcoin Core as well.
2479  			result.Time = blkHeader.Timestamp.Unix()
2480  			result.Blocktime = blkHeader.Timestamp.Unix()
2481  			result.BlockHash = blkHashStr
2482  			result.Confirmations = uint64(1 + best.Height - blkHeight)
2483  		}
2484  	}
2485  	return srtList, nil
2486  }
2487  
2488  // HandleSendRawTransaction implements the sendrawtransaction command.
2489  func HandleSendRawTransaction(
2490  	s *Server,
2491  	cmd interface{},
2492  	closeChan qu.C,
2493  ) (interface{}, error) {
2494  	var msg string
2495  	var e error
2496  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2497  	c, ok := cmd.(*btcjson.SendRawTransactionCmd)
2498  	if !ok {
2499  		var h string
2500  		h, e = s.HelpCacher.RPCMethodHelp("sendrawtransaction")
2501  		if e != nil {
2502  			msg = e.Error() + "\n\n"
2503  		}
2504  		msg += h
2505  		return nil, &btcjson.RPCError{
2506  			Code:    btcjson.ErrRPCInvalidParameter,
2507  			Message: msg,
2508  			// "invalid subcommand for addnode",
2509  		}
2510  	}
2511  	// Deserialize and send off to tx relay
2512  	hexStr := c.HexTx
2513  	if len(hexStr)%2 != 0 {
2514  		hexStr = "0" + hexStr
2515  	}
2516  	serializedTx, e := hex.DecodeString(hexStr)
2517  	if e != nil {
2518  		return nil, DecodeHexError(hexStr)
2519  	}
2520  	var msgTx wire.MsgTx
2521  	e = msgTx.Deserialize(bytes.NewReader(serializedTx))
2522  	if e != nil {
2523  		return nil, &btcjson.RPCError{
2524  			Code:    btcjson.ErrRPCDeserialization,
2525  			Message: "TX decode failed: " + e.Error(),
2526  		}
2527  	}
2528  	// Use 0 for the tag to represent local node.
2529  	tx := util.NewTx(&msgTx)
2530  	acceptedTxs, e := s.Cfg.TxMemPool.ProcessTransaction(s.Cfg.Chain, tx, false, false, 0)
2531  	if e != nil {
2532  		// When the error is a rule error, it means the transaction was simply rejected as opposed to something actually
2533  		// going wrong, so log such. Otherwise, something really did go wrong, so log an actual error. In both cases, a
2534  		// JSON-RPC error is returned to the client with the deserialization error code (to match bitcoind behavior).
2535  		if _, ok := e.(mempool.RuleError); ok {
2536  			D.F("rejected transaction %v: %v", tx.Hash(), e)
2537  			
2538  		} else {
2539  			E.F(
2540  				"failed to process transaction %v: %v", tx.Hash(), e,
2541  			)
2542  		}
2543  		return nil, &btcjson.RPCError{
2544  			Code:    btcjson.ErrRPCDeserialization,
2545  			Message: "TX rejected: " + e.Error(),
2546  		}
2547  	}
2548  	// When the transaction was accepted it should be the first item in the returned array of accepted transactions.
2549  	//
2550  	// The only way this will not be true is if the API for ProcessTransaction changes and this code is not properly
2551  	// updated, but ensure the condition holds as a safeguard.
2552  	//
2553  	// Also, since an error is being returned to the caller, ensure the transaction is removed from the memory pool.
2554  	if len(acceptedTxs) == 0 || !acceptedTxs[0].Tx.Hash().IsEqual(tx.Hash()) {
2555  		s.Cfg.TxMemPool.RemoveTransaction(tx, true)
2556  		errStr := fmt.Sprintf("transaction %v is not in accepted list", tx.Hash())
2557  		return nil, InternalRPCError(errStr, "")
2558  	}
2559  	// Generate and relay inventory vectors for all newly accepted transactions into the memory pool due to the original
2560  	// being accepted.
2561  	s.Cfg.ConnMgr.RelayTransactions(acceptedTxs)
2562  	// Notify both websocket and getblocktemplate long poll clients of all newly accepted transactions.
2563  	s.NotifyNewTransactions(acceptedTxs)
2564  	// Keep track of all the sendrawtransaction request txns so that they can be rebroadcast if they don't make their
2565  	// way into a block.
2566  	txD := acceptedTxs[0]
2567  	iv := wire.NewInvVect(wire.InvTypeTx, txD.Tx.Hash())
2568  	s.Cfg.ConnMgr.AddRebroadcastInventory(iv, txD)
2569  	return tx.Hash().String(), nil
2570  }
2571  
2572  // HandleSetGenerate implements the setgenerate command.
2573  func HandleSetGenerate(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) { // cpuminer
2574  	c, ok := cmd.(*btcjson.SetGenerateCmd)
2575  	if ok {
2576  		if c.Generate {
2577  			s.Cfg.StartController.Signal()
2578  		} else {
2579  			s.Cfg.StopController.Signal()
2580  		}
2581  		return &struct{}{}, nil
2582  	}
2583  	return nil, errors.New("command was not a btcjson.SetGenerateCmd")
2584  	// var msg string
2585  	// var e error
2586  	// // c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2587  	// c, ok := cmd.(*btcjson.SetGenerateCmd)
2588  	// if !ok {
2589  	//	var h string
2590  	//	h, e = s.HelpCacher.RPCMethodHelp("setgenerate")
2591  	//	if e != nil  {
2592  	//		msg = err.E.Ln() + "\n\n"
2593  	//	}
2594  	//	msg += h
2595  	//	return nil, &btcjson.RPCError{
2596  	//		Code:    btcjson.ErrRPCInvalidParameter,
2597  	//		Message: msg,
2598  	//		// "invalid subcommand for addnode",
2599  	//	}
2600  	// }
2601  	// D.S(c)
2602  	// // Disable generation regardless of the provided generate flag if the maximum number of threads (goroutines for our
2603  	// // purposes) is 0. Otherwise enable or disable it depending on the provided flag. l.ScriptError(*c.GenProcLimit,
2604  	// // c.Generate)
2605  	// generate := c.Generate
2606  	// genProcLimit := *s.Config.GenThreads
2607  	// if c.GenProcLimit != nil {
2608  	//	genProcLimit = *c.GenProcLimit
2609  	//	if !generate {
2610  	//		*c.GenProcLimit = 0
2611  	//	}
2612  	//	if *c.GenProcLimit == 0 {
2613  	//		generate = false
2614  	//	}
2615  	// }
2616  	// D.Ln("generating", generate, "threads", genProcLimit)
2617  	// // if s.Cfg.CPUMiner.IsMining() {
2618  	// // 	// if s.cfg.CPUMiner.GetAlgo() != s.cfg.Algo {
2619  	// // 	s.Cfg.CPUMiner.Stop()
2620  	// // 	generate = true
2621  	// // 	// }
2622  	// // }
2623  	// // if !generate {
2624  	// // 	s.Cfg.CPUMiner.Stop()
2625  	// // } else {
2626  	// // 	// Respond with an error if there are no addresses to pay the created
2627  	// // 	// blocks to.
2628  	// // 	if len(s.StateCfg.ActiveMiningAddrs) == 0 {
2629  	// // 		return nil, &btcjson.RPCError{
2630  	// // 			Code:    btcjson.ErrRPCInternal.Code,
2631  	// // 			Message: "no payment addresses specified via --miningaddr",
2632  	// // 		}
2633  	// // 	}
2634  	// // 	// It's safe to call start even if it's already started.
2635  	// // 	s.Cfg.CPUMiner.SetNumWorkers(int32(genProcLimit))
2636  	// // 	s.Cfg.CPUMiner.Start()
2637  	// // }
2638  	// //*s.Config.Generate = generate
2639  	// //*s.Config.GenThreads = genProcLimit
2640  	// //if s.StateCfg.Miner != nil {
2641  	// //	D.Ln("stopping existing miner")
2642  	// //	consume.Kill(s.StateCfg.Miner)
2643  	// //	s.StateCfg.Miner = nil
2644  	// //}
2645  	// D.Ln("saving configuration")
2646  	// save.Pod(s.Config)
2647  	// //if *s.Config.Generate && *s.Config.GenThreads != 0 {
2648  	// //	D.Ln("starting miner")
2649  	// //	args := []string{os.Args[0], "-D", *s.Config.DataDir}
2650  	// //	if *s.Config.KopachGUI {
2651  	// //		args = append(args, "--kopachgui")
2652  	// //	}
2653  	// //	args = append(args, "kopach")
2654  	// //	// args = apputil.PrependForWindows(args)
2655  	// //	s.StateCfg.Miner = consume.Log(s.Quit, func(ent *log.Entry) (e error) {
2656  	// //		D.Ln(ent.Level, ent.Time, ent.Text, ent.CodeLocation)
2657  	// //		return
2658  	// //	}, func(pkg string) (out bool) {
2659  	// //		return false
2660  	// //	}, args...)
2661  	// //	consume.Start(s.StateCfg.Miner)
2662  	// //} else {
2663  	// //	consume.Kill(s.StateCfg.Miner)
2664  	// //}
2665  	// return nil, nil
2666  }
2667  
2668  // HandleStop implements the stop command.
2669  func HandleStop(s *Server, cmd interface{}, closeChan qu.C) (
2670  	interface{}, error,
2671  ) {
2672  	interrupt.Request()
2673  	return nil, nil
2674  }
2675  
2676  // HandleRestart implements the restart command.
2677  func HandleRestart(s *Server, cmd interface{}, closeChan qu.C) (
2678  	interface{}, error,
2679  ) {
2680  	// select {
2681  	// case s.RequestProcessShutdown <- struct{}{}:
2682  	// default:
2683  	// }
2684  	interrupt.RequestRestart()
2685  	return nil, nil
2686  }
2687  
2688  // HandleSubmitBlock implements the submitblock command.
2689  func HandleSubmitBlock(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2690  	var msg string
2691  	var e error
2692  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2693  	c, ok := cmd.(*btcjson.SubmitBlockCmd)
2694  	if !ok {
2695  		var h string
2696  		h, e = s.HelpCacher.RPCMethodHelp("submitblock")
2697  		if e != nil {
2698  			msg = e.Error() + "\n\n"
2699  		}
2700  		msg += h
2701  		return nil, &btcjson.RPCError{
2702  			Code:    btcjson.ErrRPCInvalidParameter,
2703  			Message: msg,
2704  			// "invalid subcommand for addnode",
2705  		}
2706  	}
2707  	// Deserialize the submitted block.
2708  	hexStr := c.HexBlock
2709  	if len(hexStr)%2 != 0 {
2710  		hexStr = "0" + c.HexBlock
2711  	}
2712  	serializedBlock, e := hex.DecodeString(hexStr)
2713  	if e != nil {
2714  		return nil, DecodeHexError(hexStr)
2715  	}
2716  	block, e := block2.NewFromBytes(serializedBlock)
2717  	if e != nil {
2718  		return nil, &btcjson.RPCError{
2719  			Code:    btcjson.ErrRPCDeserialization,
2720  			Message: "Block decode failed: " + e.Error(),
2721  		}
2722  	}
2723  	// Process this block using the same rules as blocks coming from other nodes. This will in turn relay it to the
2724  	// network like normal.
2725  	_, e = s.Cfg.SyncMgr.SubmitBlock(block, blockchain.BFNone)
2726  	if e != nil {
2727  		return fmt.Sprintf("rejected: %s", e.Error()), nil
2728  	}
2729  	I.F(
2730  		"accepted block %s via submitblock", block.Hash(),
2731  	)
2732  	
2733  	return nil, nil
2734  }
2735  
2736  // HandleUnimplemented is the handler for commands that should ultimately be supported but are not yet implemented.
2737  func HandleUnimplemented(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2738  	return nil, ErrRPCUnimplemented
2739  }
2740  
2741  // HandleUptime implements the uptime command.
2742  func HandleUptime(s *Server, cmd interface{}, closeChan qu.C) (
2743  	interface{}, error,
2744  ) {
2745  	return time.Now().Unix() - s.Cfg.StartupTime, nil
2746  }
2747  
2748  // HandleValidateAddress implements the validateaddress command.
2749  func HandleValidateAddress(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2750  	var msg string
2751  	var e error
2752  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2753  	c, ok := cmd.(*btcjson.ValidateAddressCmd)
2754  	if !ok {
2755  		var h string
2756  		h, e = s.HelpCacher.RPCMethodHelp("validateaddress")
2757  		if e != nil {
2758  			msg = e.Error() + "\n\n"
2759  		}
2760  		msg += h
2761  		return nil, &btcjson.RPCError{
2762  			Code:    btcjson.ErrRPCInvalidParameter,
2763  			Message: msg,
2764  			// "invalid subcommand for addnode",
2765  		}
2766  	}
2767  	result := btcjson.ValidateAddressChainResult{}
2768  	addr, e := btcaddr.Decode(c.Address, s.Cfg.ChainParams)
2769  	if e != nil {
2770  		// Return the default value (false) for IsValid.
2771  		return result, nil
2772  	}
2773  	result.Address = addr.EncodeAddress()
2774  	result.IsValid = true
2775  	return result, nil
2776  }
2777  
2778  // HandleVerifyChain implements the verifychain command.
2779  func HandleVerifyChain(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2780  	var msg string
2781  	var e error
2782  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2783  	c, ok := cmd.(*btcjson.VerifyChainCmd)
2784  	if !ok {
2785  		var h string
2786  		h, e = s.HelpCacher.RPCMethodHelp("verifychain")
2787  		if e != nil {
2788  			msg = e.Error() + "\n\n"
2789  		}
2790  		msg += h
2791  		return nil, &btcjson.RPCError{
2792  			Code:    btcjson.ErrRPCInvalidParameter,
2793  			Message: msg,
2794  			// "invalid subcommand for addnode",
2795  		}
2796  	}
2797  	var checkLevel, checkDepth int32
2798  	if c.CheckLevel != nil {
2799  		checkLevel = *c.CheckLevel
2800  	}
2801  	if c.CheckDepth != nil {
2802  		checkDepth = *c.CheckDepth
2803  	}
2804  	e = VerifyChain(s, checkLevel, checkDepth)
2805  	return e == nil, nil
2806  }
2807  
2808  // HandleResetChain deletes the existing chain database and restarts
2809  func HandleResetChain(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2810  	// dbName := blockdb.NamePrefix + "_" + *s.Config.DbType
2811  	// if *s.Config.DbType == "sqlite" {
2812  	// 	dbName += ".db"
2813  	// }
2814  	// dbPath := filepath.Join(filepath.Join(*s.Config.DataDir, s.Cfg.ChainParams.Name), dbName)
2815  	// select {
2816  	// case s.RequestProcessShutdown <- struct{}{}:
2817  	// default:
2818  	// }
2819  	// defer interrupt.RequestRestart()
2820  	// os.RemoveAll(dbPath)
2821  	return nil, nil
2822  }
2823  
2824  // HandleVerifyMessage implements the verifymessage command.
2825  func HandleVerifyMessage(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2826  	var msg string
2827  	var e error
2828  	// c, ok := cmd.(*btcjson.GetRawTransactionCmd)
2829  	c, ok := cmd.(*btcjson.VerifyMessageCmd)
2830  	if !ok {
2831  		var h string
2832  		h, e = s.HelpCacher.RPCMethodHelp("verifymessage")
2833  		if e != nil {
2834  			msg = e.Error() + "\n\n"
2835  		}
2836  		msg += h
2837  		return nil, &btcjson.RPCError{
2838  			Code:    btcjson.ErrRPCInvalidParameter,
2839  			Message: msg,
2840  			// "invalid subcommand for addnode",
2841  		}
2842  	}
2843  	// Decode the provided address.
2844  	params := s.Cfg.ChainParams
2845  	addr, e := btcaddr.Decode(c.Address, params)
2846  	if e != nil {
2847  		return nil, &btcjson.RPCError{
2848  			Code:    btcjson.ErrRPCInvalidAddressOrKey,
2849  			Message: "Invalid address or key: " + e.Error(),
2850  		}
2851  	}
2852  	// Only P2PKH addresses are valid for signing.
2853  	if _, ok := addr.(*btcaddr.PubKeyHash); !ok {
2854  		return nil, &btcjson.RPCError{
2855  			Code:    btcjson.ErrRPCType,
2856  			Message: "Address is not a pay-to-pubkey-hash address",
2857  		}
2858  	}
2859  	// Decode base64 signature.
2860  	sig, e := base64.StdEncoding.DecodeString(c.Signature)
2861  	if e != nil {
2862  		return nil, &btcjson.RPCError{
2863  			Code:    btcjson.ErrRPCParse.Code,
2864  			Message: "Malformed base64 encoding: " + e.Error(),
2865  		}
2866  	}
2867  	// Validate the signature - this just shows that it was valid at all. we will compare it with the key next.
2868  	var buf bytes.Buffer
2869  	e = wire.WriteVarString(&buf, 0, "Bitcoin Signed Message:\n")
2870  	if e != nil {
2871  		D.Ln(e)
2872  		
2873  	}
2874  	e = wire.WriteVarString(&buf, 0, c.Message)
2875  	if e != nil {
2876  		D.Ln(e)
2877  		
2878  	}
2879  	expectedMessageHash := chainhash.DoubleHashB(buf.Bytes())
2880  	pk, wasCompressed, e := ecc.RecoverCompact(
2881  		ecc.S256(), sig,
2882  		expectedMessageHash,
2883  	)
2884  	if e != nil {
2885  		// Mirror Bitcoin Core behavior, which treats error in RecoverCompact as invalid signature.
2886  		return false, nil
2887  	}
2888  	// Reconstruct the pubkey hash.
2889  	var serializedPK []byte
2890  	if wasCompressed {
2891  		serializedPK = pk.SerializeCompressed()
2892  	} else {
2893  		serializedPK = pk.SerializeUncompressed()
2894  	}
2895  	address, e := btcaddr.NewPubKey(serializedPK, params)
2896  	if e != nil {
2897  		// Again mirror Bitcoin Core behavior, which treats error in public key reconstruction as invalid signature.
2898  		return false, nil
2899  	}
2900  	// Return boolean if addresses match.
2901  	return address.EncodeAddress() == c.Address, nil
2902  }
2903  
2904  // HandleVersion implements the version command. NOTE: This is a btcsuite extension ported from github.com/decred/dcrd.
2905  func HandleVersion(s *Server, cmd interface{}, closeChan qu.C) (interface{}, error) {
2906  	result := map[string]btcjson.VersionResult{
2907  		"podjsonrpcapi": {
2908  			VersionString: JSONRPCSemverString,
2909  			Major:         JSONRPCSemverMajor,
2910  			Minor:         JSONRPCSemverMinor,
2911  			Patch:         JSONRPCSemverPatch,
2912  		},
2913  	}
2914  	return result, nil
2915  }
2916