github.com/palcoin-project/palcd@v1.0.0/rpcserver.go (about) 1 // Copyright (c) 2013-2017 The btcsuite developers 2 // Copyright (c) 2015-2017 The Decred developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package main 7 8 import ( 9 "bytes" 10 "crypto/sha256" 11 "crypto/subtle" 12 "encoding/base64" 13 "encoding/hex" 14 "encoding/json" 15 "errors" 16 "fmt" 17 "io" 18 "io/ioutil" 19 "math/big" 20 "math/rand" 21 "net" 22 "net/http" 23 "os" 24 "strconv" 25 "strings" 26 "sync" 27 "sync/atomic" 28 "time" 29 30 "github.com/btcsuite/websocket" 31 "github.com/palcoin-project/palcd/blockchain" 32 "github.com/palcoin-project/palcd/blockchain/indexers" 33 "github.com/palcoin-project/palcd/btcec" 34 "github.com/palcoin-project/palcd/btcjson" 35 "github.com/palcoin-project/palcd/chaincfg" 36 "github.com/palcoin-project/palcd/chaincfg/chainhash" 37 "github.com/palcoin-project/palcd/database" 38 "github.com/palcoin-project/palcd/mempool" 39 "github.com/palcoin-project/palcd/mining" 40 "github.com/palcoin-project/palcd/mining/cpuminer" 41 "github.com/palcoin-project/palcd/peer" 42 "github.com/palcoin-project/palcd/txscript" 43 "github.com/palcoin-project/palcd/wire" 44 "github.com/palcoin-project/palcutil" 45 ) 46 47 // API version constants 48 const ( 49 jsonrpcSemverString = "1.3.0" 50 jsonrpcSemverMajor = 1 51 jsonrpcSemverMinor = 3 52 jsonrpcSemverPatch = 0 53 ) 54 55 const ( 56 // rpcAuthTimeoutSeconds is the number of seconds a connection to the 57 // RPC server is allowed to stay open without authenticating before it 58 // is closed. 59 rpcAuthTimeoutSeconds = 10 60 61 // uint256Size is the number of bytes needed to represent an unsigned 62 // 256-bit integer. 63 uint256Size = 32 64 65 // gbtNonceRange is two 32-bit big-endian hexadecimal integers which 66 // represent the valid ranges of nonces returned by the getblocktemplate 67 // RPC. 68 gbtNonceRange = "00000000ffffffff" 69 70 // gbtRegenerateSeconds is the number of seconds that must pass before 71 // a new template is generated when the previous block hash has not 72 // changed and there have been changes to the available transactions 73 // in the memory pool. 74 gbtRegenerateSeconds = 60 75 76 // maxProtocolVersion is the max protocol version the server supports. 77 maxProtocolVersion = 70002 78 ) 79 80 var ( 81 // gbtMutableFields are the manipulations the server allows to be made 82 // to block templates generated by the getblocktemplate RPC. It is 83 // declared here to avoid the overhead of creating the slice on every 84 // invocation for constant data. 85 gbtMutableFields = []string{ 86 "time", "transactions/add", "prevblock", "coinbase/append", 87 } 88 89 // gbtCoinbaseAux describes additional data that miners should include 90 // in the coinbase signature script. It is declared here to avoid the 91 // overhead of creating a new object on every invocation for constant 92 // data. 93 gbtCoinbaseAux = &btcjson.GetBlockTemplateResultAux{ 94 Flags: hex.EncodeToString(builderScript(txscript. 95 NewScriptBuilder(). 96 AddData([]byte(mining.CoinbaseFlags)))), 97 } 98 99 // gbtCapabilities describes additional capabilities returned with a 100 // block template generated by the getblocktemplate RPC. It is 101 // declared here to avoid the overhead of creating the slice on every 102 // invocation for constant data. 103 gbtCapabilities = []string{"proposal"} 104 105 // JSON 2.0 batched request prefix 106 batchedRequestPrefix = []byte("[") 107 ) 108 109 // Errors 110 var ( 111 // ErrRPCUnimplemented is an error returned to RPC clients when the 112 // provided command is recognized, but not implemented. 113 ErrRPCUnimplemented = &btcjson.RPCError{ 114 Code: btcjson.ErrRPCUnimplemented, 115 Message: "Command unimplemented", 116 } 117 118 // ErrRPCNoWallet is an error returned to RPC clients when the provided 119 // command is recognized as a wallet command. 120 ErrRPCNoWallet = &btcjson.RPCError{ 121 Code: btcjson.ErrRPCNoWallet, 122 Message: "This implementation does not implement wallet commands", 123 } 124 ) 125 126 type commandHandler func(*rpcServer, interface{}, <-chan struct{}) (interface{}, error) 127 128 // rpcHandlers maps RPC command strings to appropriate handler functions. 129 // This is set by init because help references rpcHandlers and thus causes 130 // a dependency loop. 131 var rpcHandlers map[string]commandHandler 132 var rpcHandlersBeforeInit = map[string]commandHandler{ 133 "addnode": handleAddNode, 134 "createrawtransaction": handleCreateRawTransaction, 135 "debuglevel": handleDebugLevel, 136 "decoderawtransaction": handleDecodeRawTransaction, 137 "decodescript": handleDecodeScript, 138 "estimatefee": handleEstimateFee, 139 "generate": handleGenerate, 140 "getaddednodeinfo": handleGetAddedNodeInfo, 141 "getbestblock": handleGetBestBlock, 142 "getbestblockhash": handleGetBestBlockHash, 143 "getblock": handleGetBlock, 144 "getblockchaininfo": handleGetBlockChainInfo, 145 "getblockcount": handleGetBlockCount, 146 "getblockhash": handleGetBlockHash, 147 "getblockheader": handleGetBlockHeader, 148 "getblocktemplate": handleGetBlockTemplate, 149 "getcfilter": handleGetCFilter, 150 "getcfilterheader": handleGetCFilterHeader, 151 "getconnectioncount": handleGetConnectionCount, 152 "getcurrentnet": handleGetCurrentNet, 153 "getdifficulty": handleGetDifficulty, 154 "getgenerate": handleGetGenerate, 155 "gethashespersec": handleGetHashesPerSec, 156 "getheaders": handleGetHeaders, 157 "getinfo": handleGetInfo, 158 "getmempoolinfo": handleGetMempoolInfo, 159 "getmininginfo": handleGetMiningInfo, 160 "getnettotals": handleGetNetTotals, 161 "getnetworkhashps": handleGetNetworkHashPS, 162 "getnodeaddresses": handleGetNodeAddresses, 163 "getpeerinfo": handleGetPeerInfo, 164 "getrawmempool": handleGetRawMempool, 165 "getrawtransaction": handleGetRawTransaction, 166 "gettxout": handleGetTxOut, 167 "help": handleHelp, 168 "node": handleNode, 169 "ping": handlePing, 170 "searchrawtransactions": handleSearchRawTransactions, 171 "sendrawtransaction": handleSendRawTransaction, 172 "setgenerate": handleSetGenerate, 173 "signmessagewithprivkey": handleSignMessageWithPrivKey, 174 "stop": handleStop, 175 "submitblock": handleSubmitBlock, 176 "uptime": handleUptime, 177 "validateaddress": handleValidateAddress, 178 "verifychain": handleVerifyChain, 179 "verifymessage": handleVerifyMessage, 180 "version": handleVersion, 181 } 182 183 // list of commands that we recognize, but for which btcd has no support because 184 // it lacks support for wallet functionality. For these commands the user 185 // should ask a connected instance of palcwallet. 186 var rpcAskWallet = map[string]struct{}{ 187 "addmultisigaddress": {}, 188 "backupwallet": {}, 189 "createencryptedwallet": {}, 190 "createmultisig": {}, 191 "dumpprivkey": {}, 192 "dumpwallet": {}, 193 "encryptwallet": {}, 194 "getaccount": {}, 195 "getaccountaddress": {}, 196 "getaddressesbyaccount": {}, 197 "getbalance": {}, 198 "getnewaddress": {}, 199 "getrawchangeaddress": {}, 200 "getreceivedbyaccount": {}, 201 "getreceivedbyaddress": {}, 202 "gettransaction": {}, 203 "gettxoutsetinfo": {}, 204 "getunconfirmedbalance": {}, 205 "getwalletinfo": {}, 206 "importprivkey": {}, 207 "importwallet": {}, 208 "keypoolrefill": {}, 209 "listaccounts": {}, 210 "listaddressgroupings": {}, 211 "listlockunspent": {}, 212 "listreceivedbyaccount": {}, 213 "listreceivedbyaddress": {}, 214 "listsinceblock": {}, 215 "listtransactions": {}, 216 "listunspent": {}, 217 "lockunspent": {}, 218 "move": {}, 219 "sendfrom": {}, 220 "sendmany": {}, 221 "sendtoaddress": {}, 222 "setaccount": {}, 223 "settxfee": {}, 224 "signmessage": {}, 225 "signrawtransaction": {}, 226 "walletlock": {}, 227 "walletpassphrase": {}, 228 "walletpassphrasechange": {}, 229 } 230 231 // Commands that are currently unimplemented, but should ultimately be. 232 var rpcUnimplemented = map[string]struct{}{ 233 "estimatepriority": {}, 234 "getchaintips": {}, 235 "getmempoolentry": {}, 236 "getnetworkinfo": {}, 237 "getwork": {}, 238 "invalidateblock": {}, 239 "preciousblock": {}, 240 "reconsiderblock": {}, 241 } 242 243 // Commands that are available to a limited user 244 var rpcLimited = map[string]struct{}{ 245 // Websockets commands 246 "loadtxfilter": {}, 247 "notifyblocks": {}, 248 "notifynewtransactions": {}, 249 "notifyreceived": {}, 250 "notifyspent": {}, 251 "rescan": {}, 252 "rescanblocks": {}, 253 "session": {}, 254 255 // Websockets AND HTTP/S commands 256 "help": {}, 257 258 // HTTP/S-only commands 259 "createrawtransaction": {}, 260 "decoderawtransaction": {}, 261 "decodescript": {}, 262 "estimatefee": {}, 263 "getbestblock": {}, 264 "getbestblockhash": {}, 265 "getblock": {}, 266 "getblockcount": {}, 267 "getblockhash": {}, 268 "getblockheader": {}, 269 "getcfilter": {}, 270 "getcfilterheader": {}, 271 "getcurrentnet": {}, 272 "getdifficulty": {}, 273 "getheaders": {}, 274 "getinfo": {}, 275 "getnettotals": {}, 276 "getnetworkhashps": {}, 277 "getrawmempool": {}, 278 "getrawtransaction": {}, 279 "gettxout": {}, 280 "searchrawtransactions": {}, 281 "sendrawtransaction": {}, 282 "submitblock": {}, 283 "uptime": {}, 284 "validateaddress": {}, 285 "verifymessage": {}, 286 "version": {}, 287 } 288 289 // builderScript is a convenience function which is used for hard-coded scripts 290 // built with the script builder. Any errors are converted to a panic since it 291 // is only, and must only, be used with hard-coded, and therefore, known good, 292 // scripts. 293 func builderScript(builder *txscript.ScriptBuilder) []byte { 294 script, err := builder.Script() 295 if err != nil { 296 panic(err) 297 } 298 return script 299 } 300 301 // internalRPCError is a convenience function to convert an internal error to 302 // an RPC error with the appropriate code set. It also logs the error to the 303 // RPC server subsystem since internal errors really should not occur. The 304 // context parameter is only used in the log message and may be empty if it's 305 // not needed. 306 func internalRPCError(errStr, context string) *btcjson.RPCError { 307 logStr := errStr 308 if context != "" { 309 logStr = context + ": " + errStr 310 } 311 rpcsLog.Error(logStr) 312 return btcjson.NewRPCError(btcjson.ErrRPCInternal.Code, errStr) 313 } 314 315 // rpcDecodeHexError is a convenience function for returning a nicely formatted 316 // RPC error which indicates the provided hex string failed to decode. 317 func rpcDecodeHexError(gotHex string) *btcjson.RPCError { 318 return btcjson.NewRPCError(btcjson.ErrRPCDecodeHexString, 319 fmt.Sprintf("Argument must be hexadecimal string (not %q)", 320 gotHex)) 321 } 322 323 // rpcNoTxInfoError is a convenience function for returning a nicely formatted 324 // RPC error which indicates there is no information available for the provided 325 // transaction hash. 326 func rpcNoTxInfoError(txHash *chainhash.Hash) *btcjson.RPCError { 327 return btcjson.NewRPCError(btcjson.ErrRPCNoTxInfo, 328 fmt.Sprintf("No information available about transaction %v", 329 txHash)) 330 } 331 332 // gbtWorkState houses state that is used in between multiple RPC invocations to 333 // getblocktemplate. 334 type gbtWorkState struct { 335 sync.Mutex 336 lastTxUpdate time.Time 337 lastGenerated time.Time 338 prevHash *chainhash.Hash 339 minTimestamp time.Time 340 template *mining.BlockTemplate 341 notifyMap map[chainhash.Hash]map[int64]chan struct{} 342 timeSource blockchain.MedianTimeSource 343 } 344 345 // newGbtWorkState returns a new instance of a gbtWorkState with all internal 346 // fields initialized and ready to use. 347 func newGbtWorkState(timeSource blockchain.MedianTimeSource) *gbtWorkState { 348 return &gbtWorkState{ 349 notifyMap: make(map[chainhash.Hash]map[int64]chan struct{}), 350 timeSource: timeSource, 351 } 352 } 353 354 // handleUnimplemented is the handler for commands that should ultimately be 355 // supported but are not yet implemented. 356 func handleUnimplemented(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 357 return nil, ErrRPCUnimplemented 358 } 359 360 // handleAskWallet is the handler for commands that are recognized as valid, but 361 // are unable to answer correctly since it involves wallet state. 362 // These commands will be implemented in palcwallet. 363 func handleAskWallet(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 364 return nil, ErrRPCNoWallet 365 } 366 367 // handleAddNode handles addnode commands. 368 func handleAddNode(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 369 c := cmd.(*btcjson.AddNodeCmd) 370 371 addr := normalizeAddress(c.Addr, s.cfg.ChainParams.DefaultPort) 372 var err error 373 switch c.SubCmd { 374 case "add": 375 err = s.cfg.ConnMgr.Connect(addr, true) 376 case "remove": 377 err = s.cfg.ConnMgr.RemoveByAddr(addr) 378 case "onetry": 379 err = s.cfg.ConnMgr.Connect(addr, false) 380 default: 381 return nil, &btcjson.RPCError{ 382 Code: btcjson.ErrRPCInvalidParameter, 383 Message: "invalid subcommand for addnode", 384 } 385 } 386 387 if err != nil { 388 return nil, &btcjson.RPCError{ 389 Code: btcjson.ErrRPCInvalidParameter, 390 Message: err.Error(), 391 } 392 } 393 394 // no data returned unless an error. 395 return nil, nil 396 } 397 398 // handleNode handles node commands. 399 func handleNode(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 400 c := cmd.(*btcjson.NodeCmd) 401 402 var addr string 403 var nodeID uint64 404 var errN, err error 405 params := s.cfg.ChainParams 406 switch c.SubCmd { 407 case "disconnect": 408 // If we have a valid uint disconnect by node id. Otherwise, 409 // attempt to disconnect by address, returning an error if a 410 // valid IP address is not supplied. 411 if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil { 412 err = s.cfg.ConnMgr.DisconnectByID(int32(nodeID)) 413 } else { 414 if _, _, errP := net.SplitHostPort(c.Target); errP == nil || net.ParseIP(c.Target) != nil { 415 addr = normalizeAddress(c.Target, params.DefaultPort) 416 err = s.cfg.ConnMgr.DisconnectByAddr(addr) 417 } else { 418 return nil, &btcjson.RPCError{ 419 Code: btcjson.ErrRPCInvalidParameter, 420 Message: "invalid address or node ID", 421 } 422 } 423 } 424 if err != nil && peerExists(s.cfg.ConnMgr, addr, int32(nodeID)) { 425 426 return nil, &btcjson.RPCError{ 427 Code: btcjson.ErrRPCMisc, 428 Message: "can't disconnect a permanent peer, use remove", 429 } 430 } 431 432 case "remove": 433 // If we have a valid uint disconnect by node id. Otherwise, 434 // attempt to disconnect by address, returning an error if a 435 // valid IP address is not supplied. 436 if nodeID, errN = strconv.ParseUint(c.Target, 10, 32); errN == nil { 437 err = s.cfg.ConnMgr.RemoveByID(int32(nodeID)) 438 } else { 439 if _, _, errP := net.SplitHostPort(c.Target); errP == nil || net.ParseIP(c.Target) != nil { 440 addr = normalizeAddress(c.Target, params.DefaultPort) 441 err = s.cfg.ConnMgr.RemoveByAddr(addr) 442 } else { 443 return nil, &btcjson.RPCError{ 444 Code: btcjson.ErrRPCInvalidParameter, 445 Message: "invalid address or node ID", 446 } 447 } 448 } 449 if err != nil && peerExists(s.cfg.ConnMgr, addr, int32(nodeID)) { 450 return nil, &btcjson.RPCError{ 451 Code: btcjson.ErrRPCMisc, 452 Message: "can't remove a temporary peer, use disconnect", 453 } 454 } 455 456 case "connect": 457 addr = normalizeAddress(c.Target, params.DefaultPort) 458 459 // Default to temporary connections. 460 subCmd := "temp" 461 if c.ConnectSubCmd != nil { 462 subCmd = *c.ConnectSubCmd 463 } 464 465 switch subCmd { 466 case "perm", "temp": 467 err = s.cfg.ConnMgr.Connect(addr, subCmd == "perm") 468 default: 469 return nil, &btcjson.RPCError{ 470 Code: btcjson.ErrRPCInvalidParameter, 471 Message: "invalid subcommand for node connect", 472 } 473 } 474 default: 475 return nil, &btcjson.RPCError{ 476 Code: btcjson.ErrRPCInvalidParameter, 477 Message: "invalid subcommand for node", 478 } 479 } 480 481 if err != nil { 482 return nil, &btcjson.RPCError{ 483 Code: btcjson.ErrRPCInvalidParameter, 484 Message: err.Error(), 485 } 486 } 487 488 // no data returned unless an error. 489 return nil, nil 490 } 491 492 // peerExists determines if a certain peer is currently connected given 493 // information about all currently connected peers. Peer existence is 494 // determined using either a target address or node id. 495 func peerExists(connMgr rpcserverConnManager, addr string, nodeID int32) bool { 496 for _, p := range connMgr.ConnectedPeers() { 497 if p.ToPeer().ID() == nodeID || p.ToPeer().Addr() == addr { 498 return true 499 } 500 } 501 return false 502 } 503 504 // messageToHex serializes a message to the wire protocol encoding using the 505 // latest protocol version and returns a hex-encoded string of the result. 506 func messageToHex(msg wire.Message) (string, error) { 507 var buf bytes.Buffer 508 if err := msg.BtcEncode(&buf, maxProtocolVersion, wire.WitnessEncoding); err != nil { 509 context := fmt.Sprintf("Failed to encode msg of type %T", msg) 510 return "", internalRPCError(err.Error(), context) 511 } 512 513 return hex.EncodeToString(buf.Bytes()), nil 514 } 515 516 // handleCreateRawTransaction handles createrawtransaction commands. 517 func handleCreateRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 518 c := cmd.(*btcjson.CreateRawTransactionCmd) 519 520 // Validate the locktime, if given. 521 if c.LockTime != nil && 522 (*c.LockTime < 0 || *c.LockTime > int64(wire.MaxTxInSequenceNum)) { 523 return nil, &btcjson.RPCError{ 524 Code: btcjson.ErrRPCInvalidParameter, 525 Message: "Locktime out of range", 526 } 527 } 528 529 // Add all transaction inputs to a new transaction after performing 530 // some validity checks. 531 mtx := wire.NewMsgTx(wire.TxVersion) 532 for _, input := range c.Inputs { 533 txHash, err := chainhash.NewHashFromStr(input.Txid) 534 if err != nil { 535 return nil, rpcDecodeHexError(input.Txid) 536 } 537 538 prevOut := wire.NewOutPoint(txHash, input.Vout) 539 txIn := wire.NewTxIn(prevOut, []byte{}, nil) 540 if c.LockTime != nil && *c.LockTime != 0 { 541 txIn.Sequence = wire.MaxTxInSequenceNum - 1 542 } 543 mtx.AddTxIn(txIn) 544 } 545 546 // Add all transaction outputs to the transaction after performing 547 // some validity checks. 548 params := s.cfg.ChainParams 549 for encodedAddr, amount := range c.Amounts { 550 // Ensure amount is in the valid range for monetary amounts. 551 if amount <= 0 || amount*palcutil.SatoshiPerBitcoin > palcutil.MaxSatoshi { 552 return nil, &btcjson.RPCError{ 553 Code: btcjson.ErrRPCType, 554 Message: "Invalid amount", 555 } 556 } 557 558 // Decode the provided address. 559 addr, err := palcutil.DecodeAddress(encodedAddr, params) 560 if err != nil { 561 return nil, &btcjson.RPCError{ 562 Code: btcjson.ErrRPCInvalidAddressOrKey, 563 Message: "Invalid address or key: " + err.Error(), 564 } 565 } 566 567 // Ensure the address is one of the supported types and that 568 // the network encoded with the address matches the network the 569 // server is currently on. 570 switch addr.(type) { 571 case *palcutil.AddressPubKeyHash: 572 case *palcutil.AddressScriptHash: 573 default: 574 return nil, &btcjson.RPCError{ 575 Code: btcjson.ErrRPCInvalidAddressOrKey, 576 Message: "Invalid address or key", 577 } 578 } 579 if !addr.IsForNet(params) { 580 return nil, &btcjson.RPCError{ 581 Code: btcjson.ErrRPCInvalidAddressOrKey, 582 Message: "Invalid address: " + encodedAddr + 583 " is for the wrong network", 584 } 585 } 586 587 // Create a new script which pays to the provided address. 588 pkScript, err := txscript.PayToAddrScript(addr) 589 if err != nil { 590 context := "Failed to generate pay-to-address script" 591 return nil, internalRPCError(err.Error(), context) 592 } 593 594 // Convert the amount to satoshi. 595 satoshi, err := palcutil.NewAmount(amount) 596 if err != nil { 597 context := "Failed to convert amount" 598 return nil, internalRPCError(err.Error(), context) 599 } 600 601 txOut := wire.NewTxOut(int64(satoshi), pkScript) 602 mtx.AddTxOut(txOut) 603 } 604 605 // Set the Locktime, if given. 606 if c.LockTime != nil { 607 mtx.LockTime = uint32(*c.LockTime) 608 } 609 610 // Return the serialized and hex-encoded transaction. Note that this 611 // is intentionally not directly returning because the first return 612 // value is a string and it would result in returning an empty string to 613 // the client instead of nothing (nil) in the case of an error. 614 mtxHex, err := messageToHex(mtx) 615 if err != nil { 616 return nil, err 617 } 618 return mtxHex, nil 619 } 620 621 // handleDebugLevel handles debuglevel commands. 622 func handleDebugLevel(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 623 c := cmd.(*btcjson.DebugLevelCmd) 624 625 // Special show command to list supported subsystems. 626 if c.LevelSpec == "show" { 627 return fmt.Sprintf("Supported subsystems %v", 628 supportedSubsystems()), nil 629 } 630 631 err := parseAndSetDebugLevels(c.LevelSpec) 632 if err != nil { 633 return nil, &btcjson.RPCError{ 634 Code: btcjson.ErrRPCInvalidParams.Code, 635 Message: err.Error(), 636 } 637 } 638 639 return "Done.", nil 640 } 641 642 // witnessToHex formats the passed witness stack as a slice of hex-encoded 643 // strings to be used in a JSON response. 644 func witnessToHex(witness wire.TxWitness) []string { 645 // Ensure nil is returned when there are no entries versus an empty 646 // slice so it can properly be omitted as necessary. 647 if len(witness) == 0 { 648 return nil 649 } 650 651 result := make([]string, 0, len(witness)) 652 for _, wit := range witness { 653 result = append(result, hex.EncodeToString(wit)) 654 } 655 656 return result 657 } 658 659 // createVinList returns a slice of JSON objects for the inputs of the passed 660 // transaction. 661 func createVinList(mtx *wire.MsgTx) []btcjson.Vin { 662 // Coinbase transactions only have a single txin by definition. 663 vinList := make([]btcjson.Vin, len(mtx.TxIn)) 664 if blockchain.IsCoinBaseTx(mtx) { 665 txIn := mtx.TxIn[0] 666 vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript) 667 vinList[0].Sequence = txIn.Sequence 668 vinList[0].Witness = witnessToHex(txIn.Witness) 669 return vinList 670 } 671 672 for i, txIn := range mtx.TxIn { 673 // The disassembled string will contain [error] inline 674 // if the script doesn't fully parse, so ignore the 675 // error here. 676 disbuf, _ := txscript.DisasmString(txIn.SignatureScript) 677 678 vinEntry := &vinList[i] 679 vinEntry.Txid = txIn.PreviousOutPoint.Hash.String() 680 vinEntry.Vout = txIn.PreviousOutPoint.Index 681 vinEntry.Sequence = txIn.Sequence 682 vinEntry.ScriptSig = &btcjson.ScriptSig{ 683 Asm: disbuf, 684 Hex: hex.EncodeToString(txIn.SignatureScript), 685 } 686 687 if mtx.HasWitness() { 688 vinEntry.Witness = witnessToHex(txIn.Witness) 689 } 690 } 691 692 return vinList 693 } 694 695 // createVoutList returns a slice of JSON objects for the outputs of the passed 696 // transaction. 697 func createVoutList(mtx *wire.MsgTx, chainParams *chaincfg.Params, filterAddrMap map[string]struct{}) []btcjson.Vout { 698 voutList := make([]btcjson.Vout, 0, len(mtx.TxOut)) 699 for i, v := range mtx.TxOut { 700 // The disassembled string will contain [error] inline if the 701 // script doesn't fully parse, so ignore the error here. 702 disbuf, _ := txscript.DisasmString(v.PkScript) 703 704 // Ignore the error here since an error means the script 705 // couldn't parse and there is no additional information about 706 // it anyways. 707 scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs( 708 v.PkScript, chainParams) 709 710 // Encode the addresses while checking if the address passes the 711 // filter when needed. 712 passesFilter := len(filterAddrMap) == 0 713 encodedAddrs := make([]string, len(addrs)) 714 for j, addr := range addrs { 715 encodedAddr := addr.EncodeAddress() 716 encodedAddrs[j] = encodedAddr 717 718 // No need to check the map again if the filter already 719 // passes. 720 if passesFilter { 721 continue 722 } 723 if _, exists := filterAddrMap[encodedAddr]; exists { 724 passesFilter = true 725 } 726 } 727 728 if !passesFilter { 729 continue 730 } 731 732 var vout btcjson.Vout 733 vout.N = uint32(i) 734 vout.Value = palcutil.Amount(v.Value).ToBTC() 735 vout.ScriptPubKey.Addresses = encodedAddrs 736 vout.ScriptPubKey.Asm = disbuf 737 vout.ScriptPubKey.Hex = hex.EncodeToString(v.PkScript) 738 vout.ScriptPubKey.Type = scriptClass.String() 739 vout.ScriptPubKey.ReqSigs = int32(reqSigs) 740 741 voutList = append(voutList, vout) 742 } 743 744 return voutList 745 } 746 747 // createTxRawResult converts the passed transaction and associated parameters 748 // to a raw transaction JSON object. 749 func createTxRawResult(chainParams *chaincfg.Params, mtx *wire.MsgTx, 750 txHash string, blkHeader *wire.BlockHeader, blkHash string, 751 blkHeight int32, chainHeight int32) (*btcjson.TxRawResult, error) { 752 753 mtxHex, err := messageToHex(mtx) 754 if err != nil { 755 return nil, err 756 } 757 758 txReply := &btcjson.TxRawResult{ 759 Hex: mtxHex, 760 Txid: txHash, 761 Hash: mtx.WitnessHash().String(), 762 Size: int32(mtx.SerializeSize()), 763 Vsize: int32(mempool.GetTxVirtualSize(palcutil.NewTx(mtx))), 764 Weight: int32(blockchain.GetTransactionWeight(palcutil.NewTx(mtx))), 765 Vin: createVinList(mtx), 766 Vout: createVoutList(mtx, chainParams, nil), 767 Version: uint32(mtx.Version), 768 LockTime: mtx.LockTime, 769 } 770 771 if blkHeader != nil { 772 // This is not a typo, they are identical in bitcoind as well. 773 txReply.Time = blkHeader.Timestamp.Unix() 774 txReply.Blocktime = blkHeader.Timestamp.Unix() 775 txReply.BlockHash = blkHash 776 txReply.Confirmations = uint64(1 + chainHeight - blkHeight) 777 } 778 779 return txReply, nil 780 } 781 782 // handleDecodeRawTransaction handles decoderawtransaction commands. 783 func handleDecodeRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 784 c := cmd.(*btcjson.DecodeRawTransactionCmd) 785 786 // Deserialize the transaction. 787 hexStr := c.HexTx 788 if len(hexStr)%2 != 0 { 789 hexStr = "0" + hexStr 790 } 791 serializedTx, err := hex.DecodeString(hexStr) 792 if err != nil { 793 return nil, rpcDecodeHexError(hexStr) 794 } 795 var mtx wire.MsgTx 796 err = mtx.Deserialize(bytes.NewReader(serializedTx)) 797 if err != nil { 798 return nil, &btcjson.RPCError{ 799 Code: btcjson.ErrRPCDeserialization, 800 Message: "TX decode failed: " + err.Error(), 801 } 802 } 803 804 // Create and return the result. 805 txReply := btcjson.TxRawDecodeResult{ 806 Txid: mtx.TxHash().String(), 807 Version: mtx.Version, 808 Locktime: mtx.LockTime, 809 Vin: createVinList(&mtx), 810 Vout: createVoutList(&mtx, s.cfg.ChainParams, nil), 811 } 812 return txReply, nil 813 } 814 815 // handleDecodeScript handles decodescript commands. 816 func handleDecodeScript(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 817 c := cmd.(*btcjson.DecodeScriptCmd) 818 819 // Convert the hex script to bytes. 820 hexStr := c.HexScript 821 if len(hexStr)%2 != 0 { 822 hexStr = "0" + hexStr 823 } 824 script, err := hex.DecodeString(hexStr) 825 if err != nil { 826 return nil, rpcDecodeHexError(hexStr) 827 } 828 829 // The disassembled string will contain [error] inline if the script 830 // doesn't fully parse, so ignore the error here. 831 disbuf, _ := txscript.DisasmString(script) 832 833 // Get information about the script. 834 // Ignore the error here since an error means the script couldn't parse 835 // and there is no additinal information about it anyways. 836 scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(script, 837 s.cfg.ChainParams) 838 addresses := make([]string, len(addrs)) 839 for i, addr := range addrs { 840 addresses[i] = addr.EncodeAddress() 841 } 842 843 // Convert the script itself to a pay-to-script-hash address. 844 p2sh, err := palcutil.NewAddressScriptHash(script, s.cfg.ChainParams) 845 if err != nil { 846 context := "Failed to convert script to pay-to-script-hash" 847 return nil, internalRPCError(err.Error(), context) 848 } 849 850 // Generate and return the reply. 851 reply := btcjson.DecodeScriptResult{ 852 Asm: disbuf, 853 ReqSigs: int32(reqSigs), 854 Type: scriptClass.String(), 855 Addresses: addresses, 856 } 857 if scriptClass != txscript.ScriptHashTy { 858 reply.P2sh = p2sh.EncodeAddress() 859 } 860 return reply, nil 861 } 862 863 // handleEstimateFee handles estimatefee commands. 864 func handleEstimateFee(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 865 c := cmd.(*btcjson.EstimateFeeCmd) 866 867 if s.cfg.FeeEstimator == nil { 868 return nil, errors.New("Fee estimation disabled") 869 } 870 871 if c.NumBlocks <= 0 { 872 return -1.0, errors.New("Parameter NumBlocks must be positive") 873 } 874 875 feeRate, err := s.cfg.FeeEstimator.EstimateFee(uint32(c.NumBlocks)) 876 877 if err != nil { 878 return -1.0, err 879 } 880 881 // Convert to satoshis per kb. 882 return float64(feeRate), nil 883 } 884 885 // handleGenerate handles generate commands. 886 func handleGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 887 // Respond with an error if there are no addresses to pay the 888 // created blocks to. 889 if len(cfg.miningAddrs) == 0 { 890 return nil, &btcjson.RPCError{ 891 Code: btcjson.ErrRPCInternal.Code, 892 Message: "No payment addresses specified " + 893 "via --miningaddr", 894 } 895 } 896 897 // Respond with an error if there's virtually 0 chance of mining a block 898 // with the CPU. 899 if !s.cfg.ChainParams.GenerateSupported { 900 return nil, &btcjson.RPCError{ 901 Code: btcjson.ErrRPCDifficulty, 902 Message: fmt.Sprintf("No support for `generate` on "+ 903 "the current network, %s, as it's unlikely to "+ 904 "be possible to mine a block with the CPU.", 905 s.cfg.ChainParams.Net), 906 } 907 } 908 909 c := cmd.(*btcjson.GenerateCmd) 910 911 // Respond with an error if the client is requesting 0 blocks to be generated. 912 if c.NumBlocks == 0 { 913 return nil, &btcjson.RPCError{ 914 Code: btcjson.ErrRPCInternal.Code, 915 Message: "Please request a nonzero number of blocks to generate.", 916 } 917 } 918 919 // Create a reply 920 reply := make([]string, c.NumBlocks) 921 922 blockHashes, err := s.cfg.CPUMiner.GenerateNBlocks(c.NumBlocks) 923 if err != nil { 924 return nil, &btcjson.RPCError{ 925 Code: btcjson.ErrRPCInternal.Code, 926 Message: err.Error(), 927 } 928 } 929 930 // Mine the correct number of blocks, assigning the hex representation of the 931 // hash of each one to its place in the reply. 932 for i, hash := range blockHashes { 933 reply[i] = hash.String() 934 } 935 936 return reply, nil 937 } 938 939 // handleGetAddedNodeInfo handles getaddednodeinfo commands. 940 func handleGetAddedNodeInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 941 c := cmd.(*btcjson.GetAddedNodeInfoCmd) 942 943 // Retrieve a list of persistent (added) peers from the server and 944 // filter the list of peers per the specified address (if any). 945 peers := s.cfg.ConnMgr.PersistentPeers() 946 if c.Node != nil { 947 node := *c.Node 948 found := false 949 for i, peer := range peers { 950 if peer.ToPeer().Addr() == node { 951 peers = peers[i : i+1] 952 found = true 953 } 954 } 955 if !found { 956 return nil, &btcjson.RPCError{ 957 Code: btcjson.ErrRPCClientNodeNotAdded, 958 Message: "Node has not been added", 959 } 960 } 961 } 962 963 // Without the dns flag, the result is just a slice of the addresses as 964 // strings. 965 if !c.DNS { 966 results := make([]string, 0, len(peers)) 967 for _, peer := range peers { 968 results = append(results, peer.ToPeer().Addr()) 969 } 970 return results, nil 971 } 972 973 // With the dns flag, the result is an array of JSON objects which 974 // include the result of DNS lookups for each peer. 975 results := make([]*btcjson.GetAddedNodeInfoResult, 0, len(peers)) 976 for _, rpcPeer := range peers { 977 // Set the "address" of the peer which could be an ip address 978 // or a domain name. 979 peer := rpcPeer.ToPeer() 980 var result btcjson.GetAddedNodeInfoResult 981 result.AddedNode = peer.Addr() 982 result.Connected = btcjson.Bool(peer.Connected()) 983 984 // Split the address into host and port portions so we can do 985 // a DNS lookup against the host. When no port is specified in 986 // the address, just use the address as the host. 987 host, _, err := net.SplitHostPort(peer.Addr()) 988 if err != nil { 989 host = peer.Addr() 990 } 991 992 var ipList []string 993 switch { 994 case net.ParseIP(host) != nil, strings.HasSuffix(host, ".onion"): 995 ipList = make([]string, 1) 996 ipList[0] = host 997 default: 998 // Do a DNS lookup for the address. If the lookup fails, just 999 // use the host. 1000 ips, err := btcdLookup(host) 1001 if err != nil { 1002 ipList = make([]string, 1) 1003 ipList[0] = host 1004 break 1005 } 1006 ipList = make([]string, 0, len(ips)) 1007 for _, ip := range ips { 1008 ipList = append(ipList, ip.String()) 1009 } 1010 } 1011 1012 // Add the addresses and connection info to the result. 1013 addrs := make([]btcjson.GetAddedNodeInfoResultAddr, 0, len(ipList)) 1014 for _, ip := range ipList { 1015 var addr btcjson.GetAddedNodeInfoResultAddr 1016 addr.Address = ip 1017 addr.Connected = "false" 1018 if ip == host && peer.Connected() { 1019 addr.Connected = directionString(peer.Inbound()) 1020 } 1021 addrs = append(addrs, addr) 1022 } 1023 result.Addresses = &addrs 1024 results = append(results, &result) 1025 } 1026 return results, nil 1027 } 1028 1029 // handleGetBestBlock implements the getbestblock command. 1030 func handleGetBestBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1031 // All other "get block" commands give either the height, the 1032 // hash, or both but require the block SHA. This gets both for 1033 // the best block. 1034 best := s.cfg.Chain.BestSnapshot() 1035 result := &btcjson.GetBestBlockResult{ 1036 Hash: best.Hash.String(), 1037 Height: best.Height, 1038 } 1039 return result, nil 1040 } 1041 1042 // handleGetBestBlockHash implements the getbestblockhash command. 1043 func handleGetBestBlockHash(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1044 best := s.cfg.Chain.BestSnapshot() 1045 return best.Hash.String(), nil 1046 } 1047 1048 // getDifficultyRatio returns the proof-of-work difficulty as a multiple of the 1049 // minimum difficulty using the passed bits field from the header of a block. 1050 func getDifficultyRatio(bits uint32, params *chaincfg.Params) float64 { 1051 // The minimum difficulty is the max possible proof-of-work limit bits 1052 // converted back to a number. Note this is not the same as the proof of 1053 // work limit directly because the block difficulty is encoded in a block 1054 // with the compact form which loses precision. 1055 max := blockchain.CompactToBig(params.PowLimitBits) 1056 target := blockchain.CompactToBig(bits) 1057 1058 difficulty := new(big.Rat).SetFrac(max, target) 1059 outString := difficulty.FloatString(8) 1060 diff, err := strconv.ParseFloat(outString, 64) 1061 if err != nil { 1062 rpcsLog.Errorf("Cannot get difficulty: %v", err) 1063 return 0 1064 } 1065 return diff 1066 } 1067 1068 // handleGetBlock implements the getblock command. 1069 func handleGetBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1070 c := cmd.(*btcjson.GetBlockCmd) 1071 1072 // Load the raw block bytes from the database. 1073 hash, err := chainhash.NewHashFromStr(c.Hash) 1074 if err != nil { 1075 return nil, rpcDecodeHexError(c.Hash) 1076 } 1077 var blkBytes []byte 1078 err = s.cfg.DB.View(func(dbTx database.Tx) error { 1079 var err error 1080 blkBytes, err = dbTx.FetchBlock(hash) 1081 return err 1082 }) 1083 if err != nil { 1084 return nil, &btcjson.RPCError{ 1085 Code: btcjson.ErrRPCBlockNotFound, 1086 Message: "Block not found", 1087 } 1088 } 1089 // If verbosity is 0, return the serialized block as a hex encoded string. 1090 if c.Verbosity != nil && *c.Verbosity == 0 { 1091 return hex.EncodeToString(blkBytes), nil 1092 } 1093 1094 // Otherwise, generate the JSON object and return it. 1095 1096 // Deserialize the block. 1097 blk, err := palcutil.NewBlockFromBytes(blkBytes) 1098 if err != nil { 1099 context := "Failed to deserialize block" 1100 return nil, internalRPCError(err.Error(), context) 1101 } 1102 1103 // Get the block height from chain. 1104 blockHeight, err := s.cfg.Chain.BlockHeightByHash(hash) 1105 if err != nil { 1106 context := "Failed to obtain block height" 1107 return nil, internalRPCError(err.Error(), context) 1108 } 1109 blk.SetHeight(blockHeight) 1110 best := s.cfg.Chain.BestSnapshot() 1111 1112 // Get next block hash unless there are none. 1113 var nextHashString string 1114 if blockHeight < best.Height { 1115 nextHash, err := s.cfg.Chain.BlockHashByHeight(blockHeight + 1) 1116 if err != nil { 1117 context := "No next block" 1118 return nil, internalRPCError(err.Error(), context) 1119 } 1120 nextHashString = nextHash.String() 1121 } 1122 1123 params := s.cfg.ChainParams 1124 blockHeader := &blk.MsgBlock().Header 1125 blockReply := btcjson.GetBlockVerboseResult{ 1126 Hash: c.Hash, 1127 Version: blockHeader.Version, 1128 VersionHex: fmt.Sprintf("%08x", blockHeader.Version), 1129 MerkleRoot: blockHeader.MerkleRoot.String(), 1130 PreviousHash: blockHeader.PrevBlock.String(), 1131 Nonce: blockHeader.Nonce, 1132 Time: blockHeader.Timestamp.Unix(), 1133 Confirmations: int64(1 + best.Height - blockHeight), 1134 Height: int64(blockHeight), 1135 Size: int32(len(blkBytes)), 1136 StrippedSize: int32(blk.MsgBlock().SerializeSizeStripped()), 1137 Weight: int32(blockchain.GetBlockWeight(blk)), 1138 Bits: strconv.FormatInt(int64(blockHeader.Bits), 16), 1139 Difficulty: getDifficultyRatio(blockHeader.Bits, params), 1140 NextHash: nextHashString, 1141 } 1142 1143 if *c.Verbosity == 1 { 1144 transactions := blk.Transactions() 1145 txNames := make([]string, len(transactions)) 1146 for i, tx := range transactions { 1147 txNames[i] = tx.Hash().String() 1148 } 1149 1150 blockReply.Tx = txNames 1151 } else { 1152 txns := blk.Transactions() 1153 rawTxns := make([]btcjson.TxRawResult, len(txns)) 1154 for i, tx := range txns { 1155 rawTxn, err := createTxRawResult(params, tx.MsgTx(), 1156 tx.Hash().String(), blockHeader, hash.String(), 1157 blockHeight, best.Height) 1158 if err != nil { 1159 return nil, err 1160 } 1161 rawTxns[i] = *rawTxn 1162 } 1163 blockReply.RawTx = rawTxns 1164 } 1165 1166 return blockReply, nil 1167 } 1168 1169 // softForkStatus converts a ThresholdState state into a human readable string 1170 // corresponding to the particular state. 1171 func softForkStatus(state blockchain.ThresholdState) (string, error) { 1172 switch state { 1173 case blockchain.ThresholdDefined: 1174 return "defined", nil 1175 case blockchain.ThresholdStarted: 1176 return "started", nil 1177 case blockchain.ThresholdLockedIn: 1178 return "lockedin", nil 1179 case blockchain.ThresholdActive: 1180 return "active", nil 1181 case blockchain.ThresholdFailed: 1182 return "failed", nil 1183 default: 1184 return "", fmt.Errorf("unknown deployment state: %v", state) 1185 } 1186 } 1187 1188 // handleGetBlockChainInfo implements the getblockchaininfo command. 1189 func handleGetBlockChainInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1190 // Obtain a snapshot of the current best known blockchain state. We'll 1191 // populate the response to this call primarily from this snapshot. 1192 params := s.cfg.ChainParams 1193 chain := s.cfg.Chain 1194 chainSnapshot := chain.BestSnapshot() 1195 1196 chainInfo := &btcjson.GetBlockChainInfoResult{ 1197 Chain: params.Name, 1198 Blocks: chainSnapshot.Height, 1199 Headers: chainSnapshot.Height, 1200 BestBlockHash: chainSnapshot.Hash.String(), 1201 Difficulty: getDifficultyRatio(chainSnapshot.Bits, params), 1202 MedianTime: chainSnapshot.MedianTime.Unix(), 1203 Pruned: false, 1204 SoftForks: &btcjson.SoftForks{ 1205 Bip9SoftForks: make(map[string]*btcjson.Bip9SoftForkDescription), 1206 }, 1207 } 1208 1209 // Next, populate the response with information describing the current 1210 // status of soft-forks deployed via the super-majority block 1211 // signalling mechanism. 1212 height := chainSnapshot.Height 1213 chainInfo.SoftForks.SoftForks = []*btcjson.SoftForkDescription{ 1214 { 1215 ID: "bip34", 1216 Version: 2, 1217 Reject: struct { 1218 Status bool `json:"status"` 1219 }{ 1220 Status: height >= params.BIP0034Height, 1221 }, 1222 }, 1223 { 1224 ID: "bip66", 1225 Version: 3, 1226 Reject: struct { 1227 Status bool `json:"status"` 1228 }{ 1229 Status: height >= params.BIP0066Height, 1230 }, 1231 }, 1232 { 1233 ID: "bip65", 1234 Version: 4, 1235 Reject: struct { 1236 Status bool `json:"status"` 1237 }{ 1238 Status: height >= params.BIP0065Height, 1239 }, 1240 }, 1241 } 1242 1243 // Finally, query the BIP0009 version bits state for all currently 1244 // defined BIP0009 soft-fork deployments. 1245 for deployment, deploymentDetails := range params.Deployments { 1246 // Map the integer deployment ID into a human readable 1247 // fork-name. 1248 var forkName string 1249 switch deployment { 1250 case chaincfg.DeploymentTestDummy: 1251 forkName = "dummy" 1252 1253 case chaincfg.DeploymentCSV: 1254 forkName = "csv" 1255 1256 case chaincfg.DeploymentSegwit: 1257 forkName = "segwit" 1258 1259 case chaincfg.DeploymentTaproot: 1260 forkName = "taproot" 1261 1262 default: 1263 return nil, &btcjson.RPCError{ 1264 Code: btcjson.ErrRPCInternal.Code, 1265 Message: fmt.Sprintf("Unknown deployment %v "+ 1266 "detected", deployment), 1267 } 1268 } 1269 1270 // Query the chain for the current status of the deployment as 1271 // identified by its deployment ID. 1272 deploymentStatus, err := chain.ThresholdState(uint32(deployment)) 1273 if err != nil { 1274 context := "Failed to obtain deployment status" 1275 return nil, internalRPCError(err.Error(), context) 1276 } 1277 1278 // Attempt to convert the current deployment status into a 1279 // human readable string. If the status is unrecognized, then a 1280 // non-nil error is returned. 1281 statusString, err := softForkStatus(deploymentStatus) 1282 if err != nil { 1283 return nil, &btcjson.RPCError{ 1284 Code: btcjson.ErrRPCInternal.Code, 1285 Message: fmt.Sprintf("unknown deployment status: %v", 1286 deploymentStatus), 1287 } 1288 } 1289 1290 // Finally, populate the soft-fork description with all the 1291 // information gathered above. 1292 chainInfo.SoftForks.Bip9SoftForks[forkName] = &btcjson.Bip9SoftForkDescription{ 1293 Status: strings.ToLower(statusString), 1294 Bit: deploymentDetails.BitNumber, 1295 StartTime2: int64(deploymentDetails.StartTime), 1296 Timeout: int64(deploymentDetails.ExpireTime), 1297 } 1298 } 1299 1300 return chainInfo, nil 1301 } 1302 1303 // handleGetBlockCount implements the getblockcount command. 1304 func handleGetBlockCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1305 best := s.cfg.Chain.BestSnapshot() 1306 return int64(best.Height), nil 1307 } 1308 1309 // handleGetBlockHash implements the getblockhash command. 1310 func handleGetBlockHash(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1311 c := cmd.(*btcjson.GetBlockHashCmd) 1312 hash, err := s.cfg.Chain.BlockHashByHeight(int32(c.Index)) 1313 if err != nil { 1314 return nil, &btcjson.RPCError{ 1315 Code: btcjson.ErrRPCOutOfRange, 1316 Message: "Block number out of range", 1317 } 1318 } 1319 1320 return hash.String(), nil 1321 } 1322 1323 // handleGetBlockHeader implements the getblockheader command. 1324 func handleGetBlockHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 1325 c := cmd.(*btcjson.GetBlockHeaderCmd) 1326 1327 // Fetch the header from chain. 1328 hash, err := chainhash.NewHashFromStr(c.Hash) 1329 if err != nil { 1330 return nil, rpcDecodeHexError(c.Hash) 1331 } 1332 blockHeader, err := s.cfg.Chain.HeaderByHash(hash) 1333 if err != nil { 1334 return nil, &btcjson.RPCError{ 1335 Code: btcjson.ErrRPCBlockNotFound, 1336 Message: "Block not found", 1337 } 1338 } 1339 1340 // When the verbose flag isn't set, simply return the serialized block 1341 // header as a hex-encoded string. 1342 if c.Verbose != nil && !*c.Verbose { 1343 var headerBuf bytes.Buffer 1344 err := blockHeader.Serialize(&headerBuf) 1345 if err != nil { 1346 context := "Failed to serialize block header" 1347 return nil, internalRPCError(err.Error(), context) 1348 } 1349 return hex.EncodeToString(headerBuf.Bytes()), nil 1350 } 1351 1352 // The verbose flag is set, so generate the JSON object and return it. 1353 1354 // Get the block height from chain. 1355 blockHeight, err := s.cfg.Chain.BlockHeightByHash(hash) 1356 if err != nil { 1357 context := "Failed to obtain block height" 1358 return nil, internalRPCError(err.Error(), context) 1359 } 1360 best := s.cfg.Chain.BestSnapshot() 1361 1362 // Get next block hash unless there are none. 1363 var nextHashString string 1364 if blockHeight < best.Height { 1365 nextHash, err := s.cfg.Chain.BlockHashByHeight(blockHeight + 1) 1366 if err != nil { 1367 context := "No next block" 1368 return nil, internalRPCError(err.Error(), context) 1369 } 1370 nextHashString = nextHash.String() 1371 } 1372 1373 params := s.cfg.ChainParams 1374 blockHeaderReply := btcjson.GetBlockHeaderVerboseResult{ 1375 Hash: c.Hash, 1376 Confirmations: int64(1 + best.Height - blockHeight), 1377 Height: blockHeight, 1378 Version: blockHeader.Version, 1379 VersionHex: fmt.Sprintf("%08x", blockHeader.Version), 1380 MerkleRoot: blockHeader.MerkleRoot.String(), 1381 NextHash: nextHashString, 1382 PreviousHash: blockHeader.PrevBlock.String(), 1383 Nonce: uint64(blockHeader.Nonce), 1384 Time: blockHeader.Timestamp.Unix(), 1385 Bits: strconv.FormatInt(int64(blockHeader.Bits), 16), 1386 Difficulty: getDifficultyRatio(blockHeader.Bits, params), 1387 } 1388 return blockHeaderReply, nil 1389 } 1390 1391 // encodeTemplateID encodes the passed details into an ID that can be used to 1392 // uniquely identify a block template. 1393 func encodeTemplateID(prevHash *chainhash.Hash, lastGenerated time.Time) string { 1394 return fmt.Sprintf("%s-%d", prevHash.String(), lastGenerated.Unix()) 1395 } 1396 1397 // decodeTemplateID decodes an ID that is used to uniquely identify a block 1398 // template. This is mainly used as a mechanism to track when to update clients 1399 // that are using long polling for block templates. The ID consists of the 1400 // previous block hash for the associated template and the time the associated 1401 // template was generated. 1402 func decodeTemplateID(templateID string) (*chainhash.Hash, int64, error) { 1403 fields := strings.Split(templateID, "-") 1404 if len(fields) != 2 { 1405 return nil, 0, errors.New("invalid longpollid format") 1406 } 1407 1408 prevHash, err := chainhash.NewHashFromStr(fields[0]) 1409 if err != nil { 1410 return nil, 0, errors.New("invalid longpollid format") 1411 } 1412 lastGenerated, err := strconv.ParseInt(fields[1], 10, 64) 1413 if err != nil { 1414 return nil, 0, errors.New("invalid longpollid format") 1415 } 1416 1417 return prevHash, lastGenerated, nil 1418 } 1419 1420 // notifyLongPollers notifies any channels that have been registered to be 1421 // notified when block templates are stale. 1422 // 1423 // This function MUST be called with the state locked. 1424 func (state *gbtWorkState) notifyLongPollers(latestHash *chainhash.Hash, lastGenerated time.Time) { 1425 // Notify anything that is waiting for a block template update from a 1426 // hash which is not the hash of the tip of the best chain since their 1427 // work is now invalid. 1428 for hash, channels := range state.notifyMap { 1429 if !hash.IsEqual(latestHash) { 1430 for _, c := range channels { 1431 close(c) 1432 } 1433 delete(state.notifyMap, hash) 1434 } 1435 } 1436 1437 // Return now if the provided last generated timestamp has not been 1438 // initialized. 1439 if lastGenerated.IsZero() { 1440 return 1441 } 1442 1443 // Return now if there is nothing registered for updates to the current 1444 // best block hash. 1445 channels, ok := state.notifyMap[*latestHash] 1446 if !ok { 1447 return 1448 } 1449 1450 // Notify anything that is waiting for a block template update from a 1451 // block template generated before the most recently generated block 1452 // template. 1453 lastGeneratedUnix := lastGenerated.Unix() 1454 for lastGen, c := range channels { 1455 if lastGen < lastGeneratedUnix { 1456 close(c) 1457 delete(channels, lastGen) 1458 } 1459 } 1460 1461 // Remove the entry altogether if there are no more registered 1462 // channels. 1463 if len(channels) == 0 { 1464 delete(state.notifyMap, *latestHash) 1465 } 1466 } 1467 1468 // NotifyBlockConnected uses the newly-connected block to notify any long poll 1469 // clients with a new block template when their existing block template is 1470 // stale due to the newly connected block. 1471 func (state *gbtWorkState) NotifyBlockConnected(blockHash *chainhash.Hash) { 1472 go func() { 1473 state.Lock() 1474 defer state.Unlock() 1475 1476 state.notifyLongPollers(blockHash, state.lastTxUpdate) 1477 }() 1478 } 1479 1480 // NotifyMempoolTx uses the new last updated time for the transaction memory 1481 // pool to notify any long poll clients with a new block template when their 1482 // existing block template is stale due to enough time passing and the contents 1483 // of the memory pool changing. 1484 func (state *gbtWorkState) NotifyMempoolTx(lastUpdated time.Time) { 1485 go func() { 1486 state.Lock() 1487 defer state.Unlock() 1488 1489 // No need to notify anything if no block templates have been generated 1490 // yet. 1491 if state.prevHash == nil || state.lastGenerated.IsZero() { 1492 return 1493 } 1494 1495 if time.Now().After(state.lastGenerated.Add(time.Second * 1496 gbtRegenerateSeconds)) { 1497 1498 state.notifyLongPollers(state.prevHash, lastUpdated) 1499 } 1500 }() 1501 } 1502 1503 // templateUpdateChan returns a channel that will be closed once the block 1504 // template associated with the passed previous hash and last generated time 1505 // is stale. The function will return existing channels for duplicate 1506 // parameters which allows multiple clients to wait for the same block template 1507 // without requiring a different channel for each client. 1508 // 1509 // This function MUST be called with the state locked. 1510 func (state *gbtWorkState) templateUpdateChan(prevHash *chainhash.Hash, lastGenerated int64) chan struct{} { 1511 // Either get the current list of channels waiting for updates about 1512 // changes to block template for the previous hash or create a new one. 1513 channels, ok := state.notifyMap[*prevHash] 1514 if !ok { 1515 m := make(map[int64]chan struct{}) 1516 state.notifyMap[*prevHash] = m 1517 channels = m 1518 } 1519 1520 // Get the current channel associated with the time the block template 1521 // was last generated or create a new one. 1522 c, ok := channels[lastGenerated] 1523 if !ok { 1524 c = make(chan struct{}) 1525 channels[lastGenerated] = c 1526 } 1527 1528 return c 1529 } 1530 1531 // updateBlockTemplate creates or updates a block template for the work state. 1532 // A new block template will be generated when the current best block has 1533 // changed or the transactions in the memory pool have been updated and it has 1534 // been long enough since the last template was generated. Otherwise, the 1535 // timestamp for the existing block template is updated (and possibly the 1536 // difficulty on testnet per the consesus rules). Finally, if the 1537 // useCoinbaseValue flag is false and the existing block template does not 1538 // already contain a valid payment address, the block template will be updated 1539 // with a randomly selected payment address from the list of configured 1540 // addresses. 1541 // 1542 // This function MUST be called with the state locked. 1543 func (state *gbtWorkState) updateBlockTemplate(s *rpcServer, useCoinbaseValue bool) error { 1544 generator := s.cfg.Generator 1545 lastTxUpdate := generator.TxSource().LastUpdated() 1546 if lastTxUpdate.IsZero() { 1547 lastTxUpdate = time.Now() 1548 } 1549 1550 // Generate a new block template when the current best block has 1551 // changed or the transactions in the memory pool have been updated and 1552 // it has been at least gbtRegenerateSecond since the last template was 1553 // generated. 1554 var msgBlock *wire.MsgBlock 1555 var targetDifficulty string 1556 latestHash := &s.cfg.Chain.BestSnapshot().Hash 1557 template := state.template 1558 if template == nil || state.prevHash == nil || 1559 !state.prevHash.IsEqual(latestHash) || 1560 (state.lastTxUpdate != lastTxUpdate && 1561 time.Now().After(state.lastGenerated.Add(time.Second* 1562 gbtRegenerateSeconds))) { 1563 1564 // Reset the previous best hash the block template was generated 1565 // against so any errors below cause the next invocation to try 1566 // again. 1567 state.prevHash = nil 1568 1569 // Choose a payment address at random if the caller requests a 1570 // full coinbase as opposed to only the pertinent details needed 1571 // to create their own coinbase. 1572 var payAddr palcutil.Address 1573 if !useCoinbaseValue { 1574 payAddr = cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))] 1575 } 1576 1577 // Create a new block template that has a coinbase which anyone 1578 // can redeem. This is only acceptable because the returned 1579 // block template doesn't include the coinbase, so the caller 1580 // will ultimately create their own coinbase which pays to the 1581 // appropriate address(es). 1582 blkTemplate, err := generator.NewBlockTemplate(payAddr) 1583 if err != nil { 1584 return internalRPCError("Failed to create new block "+ 1585 "template: "+err.Error(), "") 1586 } 1587 template = blkTemplate 1588 msgBlock = template.Block 1589 targetDifficulty = fmt.Sprintf("%064x", 1590 blockchain.CompactToBig(msgBlock.Header.Bits)) 1591 1592 // Get the minimum allowed timestamp for the block based on the 1593 // median timestamp of the last several blocks per the chain 1594 // consensus rules. 1595 best := s.cfg.Chain.BestSnapshot() 1596 minTimestamp := mining.MinimumMedianTime(best) 1597 1598 // Update work state to ensure another block template isn't 1599 // generated until needed. 1600 state.template = template 1601 state.lastGenerated = time.Now() 1602 state.lastTxUpdate = lastTxUpdate 1603 state.prevHash = latestHash 1604 state.minTimestamp = minTimestamp 1605 1606 rpcsLog.Debugf("Generated block template (timestamp %v, "+ 1607 "target %s, merkle root %s)", 1608 msgBlock.Header.Timestamp, targetDifficulty, 1609 msgBlock.Header.MerkleRoot) 1610 1611 // Notify any clients that are long polling about the new 1612 // template. 1613 state.notifyLongPollers(latestHash, lastTxUpdate) 1614 } else { 1615 // At this point, there is a saved block template and another 1616 // request for a template was made, but either the available 1617 // transactions haven't change or it hasn't been long enough to 1618 // trigger a new block template to be generated. So, update the 1619 // existing block template. 1620 1621 // When the caller requires a full coinbase as opposed to only 1622 // the pertinent details needed to create their own coinbase, 1623 // add a payment address to the output of the coinbase of the 1624 // template if it doesn't already have one. Since this requires 1625 // mining addresses to be specified via the config, an error is 1626 // returned if none have been specified. 1627 if !useCoinbaseValue && !template.ValidPayAddress { 1628 // Choose a payment address at random. 1629 payToAddr := cfg.miningAddrs[rand.Intn(len(cfg.miningAddrs))] 1630 1631 // Update the block coinbase output of the template to 1632 // pay to the randomly selected payment address. 1633 pkScript, err := txscript.PayToAddrScript(payToAddr) 1634 if err != nil { 1635 context := "Failed to create pay-to-addr script" 1636 return internalRPCError(err.Error(), context) 1637 } 1638 template.Block.Transactions[0].TxOut[0].PkScript = pkScript 1639 template.ValidPayAddress = true 1640 1641 // Update the merkle root. 1642 block := palcutil.NewBlock(template.Block) 1643 merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false) 1644 template.Block.Header.MerkleRoot = *merkles[len(merkles)-1] 1645 } 1646 1647 // Set locals for convenience. 1648 msgBlock = template.Block 1649 targetDifficulty = fmt.Sprintf("%064x", 1650 blockchain.CompactToBig(msgBlock.Header.Bits)) 1651 1652 // Update the time of the block template to the current time 1653 // while accounting for the median time of the past several 1654 // blocks per the chain consensus rules. 1655 generator.UpdateBlockTime(msgBlock) 1656 msgBlock.Header.Nonce = 0 1657 1658 rpcsLog.Debugf("Updated block template (timestamp %v, "+ 1659 "target %s)", msgBlock.Header.Timestamp, 1660 targetDifficulty) 1661 } 1662 1663 return nil 1664 } 1665 1666 // blockTemplateResult returns the current block template associated with the 1667 // state as a btcjson.GetBlockTemplateResult that is ready to be encoded to JSON 1668 // and returned to the caller. 1669 // 1670 // This function MUST be called with the state locked. 1671 func (state *gbtWorkState) blockTemplateResult(useCoinbaseValue bool, submitOld *bool) (*btcjson.GetBlockTemplateResult, error) { 1672 // Ensure the timestamps are still in valid range for the template. 1673 // This should really only ever happen if the local clock is changed 1674 // after the template is generated, but it's important to avoid serving 1675 // invalid block templates. 1676 template := state.template 1677 msgBlock := template.Block 1678 header := &msgBlock.Header 1679 adjustedTime := state.timeSource.AdjustedTime() 1680 maxTime := adjustedTime.Add(time.Second * blockchain.MaxTimeOffsetSeconds) 1681 if header.Timestamp.After(maxTime) { 1682 return nil, &btcjson.RPCError{ 1683 Code: btcjson.ErrRPCOutOfRange, 1684 Message: fmt.Sprintf("The template time is after the "+ 1685 "maximum allowed time for a block - template "+ 1686 "time %v, maximum time %v", adjustedTime, 1687 maxTime), 1688 } 1689 } 1690 1691 // Convert each transaction in the block template to a template result 1692 // transaction. The result does not include the coinbase, so notice 1693 // the adjustments to the various lengths and indices. 1694 numTx := len(msgBlock.Transactions) 1695 transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1) 1696 txIndex := make(map[chainhash.Hash]int64, numTx) 1697 for i, tx := range msgBlock.Transactions { 1698 txID := tx.TxHash() 1699 txIndex[txID] = int64(i) 1700 1701 // Skip the coinbase transaction. 1702 if i == 0 { 1703 continue 1704 } 1705 1706 // Create an array of 1-based indices to transactions that come 1707 // before this one in the transactions list which this one 1708 // depends on. This is necessary since the created block must 1709 // ensure proper ordering of the dependencies. A map is used 1710 // before creating the final array to prevent duplicate entries 1711 // when multiple inputs reference the same transaction. 1712 dependsMap := make(map[int64]struct{}) 1713 for _, txIn := range tx.TxIn { 1714 if idx, ok := txIndex[txIn.PreviousOutPoint.Hash]; ok { 1715 dependsMap[idx] = struct{}{} 1716 } 1717 } 1718 depends := make([]int64, 0, len(dependsMap)) 1719 for idx := range dependsMap { 1720 depends = append(depends, idx) 1721 } 1722 1723 // Serialize the transaction for later conversion to hex. 1724 txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) 1725 if err := tx.Serialize(txBuf); err != nil { 1726 context := "Failed to serialize transaction" 1727 return nil, internalRPCError(err.Error(), context) 1728 } 1729 1730 bTx := palcutil.NewTx(tx) 1731 resultTx := btcjson.GetBlockTemplateResultTx{ 1732 Data: hex.EncodeToString(txBuf.Bytes()), 1733 TxID: txID.String(), 1734 Hash: tx.WitnessHash().String(), 1735 Depends: depends, 1736 Fee: template.Fees[i], 1737 SigOps: template.SigOpCosts[i], 1738 Weight: blockchain.GetTransactionWeight(bTx), 1739 } 1740 transactions = append(transactions, resultTx) 1741 } 1742 1743 // Generate the block template reply. Note that following mutations are 1744 // implied by the included or omission of fields: 1745 // Including MinTime -> time/decrement 1746 // Omitting CoinbaseTxn -> coinbase, generation 1747 targetDifficulty := fmt.Sprintf("%064x", blockchain.CompactToBig(header.Bits)) 1748 templateID := encodeTemplateID(state.prevHash, state.lastGenerated) 1749 reply := btcjson.GetBlockTemplateResult{ 1750 Bits: strconv.FormatInt(int64(header.Bits), 16), 1751 CurTime: header.Timestamp.Unix(), 1752 Height: int64(template.Height), 1753 PreviousHash: header.PrevBlock.String(), 1754 WeightLimit: blockchain.MaxBlockWeight, 1755 SigOpLimit: blockchain.MaxBlockSigOpsCost, 1756 SizeLimit: wire.MaxBlockPayload, 1757 Transactions: transactions, 1758 Version: header.Version, 1759 LongPollID: templateID, 1760 SubmitOld: submitOld, 1761 Target: targetDifficulty, 1762 MinTime: state.minTimestamp.Unix(), 1763 MaxTime: maxTime.Unix(), 1764 Mutable: gbtMutableFields, 1765 NonceRange: gbtNonceRange, 1766 Capabilities: gbtCapabilities, 1767 } 1768 // If the generated block template includes transactions with witness 1769 // data, then include the witness commitment in the GBT result. 1770 if template.WitnessCommitment != nil { 1771 reply.DefaultWitnessCommitment = hex.EncodeToString(template.WitnessCommitment) 1772 } 1773 1774 if useCoinbaseValue { 1775 reply.CoinbaseAux = gbtCoinbaseAux 1776 reply.CoinbaseValue = &msgBlock.Transactions[0].TxOut[0].Value 1777 } else { 1778 // Ensure the template has a valid payment address associated 1779 // with it when a full coinbase is requested. 1780 if !template.ValidPayAddress { 1781 return nil, &btcjson.RPCError{ 1782 Code: btcjson.ErrRPCInternal.Code, 1783 Message: "A coinbase transaction has been " + 1784 "requested, but the server has not " + 1785 "been configured with any payment " + 1786 "addresses via --miningaddr", 1787 } 1788 } 1789 1790 // Serialize the transaction for conversion to hex. 1791 tx := msgBlock.Transactions[0] 1792 txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize())) 1793 if err := tx.Serialize(txBuf); err != nil { 1794 context := "Failed to serialize transaction" 1795 return nil, internalRPCError(err.Error(), context) 1796 } 1797 1798 resultTx := btcjson.GetBlockTemplateResultTx{ 1799 Data: hex.EncodeToString(txBuf.Bytes()), 1800 Hash: tx.TxHash().String(), 1801 Depends: []int64{}, 1802 Fee: template.Fees[0], 1803 SigOps: template.SigOpCosts[0], 1804 } 1805 1806 reply.CoinbaseTxn = &resultTx 1807 } 1808 1809 return &reply, nil 1810 } 1811 1812 // handleGetBlockTemplateLongPoll is a helper for handleGetBlockTemplateRequest 1813 // which deals with handling long polling for block templates. When a caller 1814 // sends a request with a long poll ID that was previously returned, a response 1815 // is not sent until the caller should stop working on the previous block 1816 // template in favor of the new one. In particular, this is the case when the 1817 // old block template is no longer valid due to a solution already being found 1818 // and added to the block chain, or new transactions have shown up and some time 1819 // has passed without finding a solution. 1820 // 1821 // See https://en.bitcoin.it/wiki/BIP_0022 for more details. 1822 func handleGetBlockTemplateLongPoll(s *rpcServer, longPollID string, useCoinbaseValue bool, closeChan <-chan struct{}) (interface{}, error) { 1823 state := s.gbtWorkState 1824 state.Lock() 1825 // The state unlock is intentionally not deferred here since it needs to 1826 // be manually unlocked before waiting for a notification about block 1827 // template changes. 1828 1829 if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil { 1830 state.Unlock() 1831 return nil, err 1832 } 1833 1834 // Just return the current block template if the long poll ID provided by 1835 // the caller is invalid. 1836 prevHash, lastGenerated, err := decodeTemplateID(longPollID) 1837 if err != nil { 1838 result, err := state.blockTemplateResult(useCoinbaseValue, nil) 1839 if err != nil { 1840 state.Unlock() 1841 return nil, err 1842 } 1843 1844 state.Unlock() 1845 return result, nil 1846 } 1847 1848 // Return the block template now if the specific block template 1849 // identified by the long poll ID no longer matches the current block 1850 // template as this means the provided template is stale. 1851 prevTemplateHash := &state.template.Block.Header.PrevBlock 1852 if !prevHash.IsEqual(prevTemplateHash) || 1853 lastGenerated != state.lastGenerated.Unix() { 1854 1855 // Include whether or not it is valid to submit work against the 1856 // old block template depending on whether or not a solution has 1857 // already been found and added to the block chain. 1858 submitOld := prevHash.IsEqual(prevTemplateHash) 1859 result, err := state.blockTemplateResult(useCoinbaseValue, 1860 &submitOld) 1861 if err != nil { 1862 state.Unlock() 1863 return nil, err 1864 } 1865 1866 state.Unlock() 1867 return result, nil 1868 } 1869 1870 // Register the previous hash and last generated time for notifications 1871 // Get a channel that will be notified when the template associated with 1872 // the provided ID is stale and a new block template should be returned to 1873 // the caller. 1874 longPollChan := state.templateUpdateChan(prevHash, lastGenerated) 1875 state.Unlock() 1876 1877 select { 1878 // When the client closes before it's time to send a reply, just return 1879 // now so the goroutine doesn't hang around. 1880 case <-closeChan: 1881 return nil, ErrClientQuit 1882 1883 // Wait until signal received to send the reply. 1884 case <-longPollChan: 1885 // Fallthrough 1886 } 1887 1888 // Get the lastest block template 1889 state.Lock() 1890 defer state.Unlock() 1891 1892 if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil { 1893 return nil, err 1894 } 1895 1896 // Include whether or not it is valid to submit work against the old 1897 // block template depending on whether or not a solution has already 1898 // been found and added to the block chain. 1899 submitOld := prevHash.IsEqual(&state.template.Block.Header.PrevBlock) 1900 result, err := state.blockTemplateResult(useCoinbaseValue, &submitOld) 1901 if err != nil { 1902 return nil, err 1903 } 1904 1905 return result, nil 1906 } 1907 1908 // handleGetBlockTemplateRequest is a helper for handleGetBlockTemplate which 1909 // deals with generating and returning block templates to the caller. It 1910 // handles both long poll requests as specified by BIP 0022 as well as regular 1911 // requests. In addition, it detects the capabilities reported by the caller 1912 // in regards to whether or not it supports creating its own coinbase (the 1913 // coinbasetxn and coinbasevalue capabilities) and modifies the returned block 1914 // template accordingly. 1915 func handleGetBlockTemplateRequest(s *rpcServer, request *btcjson.TemplateRequest, closeChan <-chan struct{}) (interface{}, error) { 1916 // Extract the relevant passed capabilities and restrict the result to 1917 // either a coinbase value or a coinbase transaction object depending on 1918 // the request. Default to only providing a coinbase value. 1919 useCoinbaseValue := true 1920 if request != nil { 1921 var hasCoinbaseValue, hasCoinbaseTxn bool 1922 for _, capability := range request.Capabilities { 1923 switch capability { 1924 case "coinbasetxn": 1925 hasCoinbaseTxn = true 1926 case "coinbasevalue": 1927 hasCoinbaseValue = true 1928 } 1929 } 1930 1931 if hasCoinbaseTxn && !hasCoinbaseValue { 1932 useCoinbaseValue = false 1933 } 1934 } 1935 1936 // When a coinbase transaction has been requested, respond with an error 1937 // if there are no addresses to pay the created block template to. 1938 if !useCoinbaseValue && len(cfg.miningAddrs) == 0 { 1939 return nil, &btcjson.RPCError{ 1940 Code: btcjson.ErrRPCInternal.Code, 1941 Message: "A coinbase transaction has been requested, " + 1942 "but the server has not been configured with " + 1943 "any payment addresses via --miningaddr", 1944 } 1945 } 1946 1947 // Return an error if there are no peers connected since there is no 1948 // way to relay a found block or receive transactions to work on. 1949 // However, allow this state when running in the regression test or 1950 // simulation test mode. 1951 if !(cfg.RegressionTest || cfg.SimNet) && 1952 s.cfg.ConnMgr.ConnectedCount() == 0 { 1953 1954 return nil, &btcjson.RPCError{ 1955 Code: btcjson.ErrRPCClientNotConnected, 1956 Message: "Palcoin is not connected", 1957 } 1958 } 1959 1960 // No point in generating or accepting work before the chain is synced. 1961 currentHeight := s.cfg.Chain.BestSnapshot().Height 1962 if currentHeight != 0 && !s.cfg.SyncMgr.IsCurrent() { 1963 return nil, &btcjson.RPCError{ 1964 Code: btcjson.ErrRPCClientInInitialDownload, 1965 Message: "Palcoin is downloading blocks...", 1966 } 1967 } 1968 1969 // When a long poll ID was provided, this is a long poll request by the 1970 // client to be notified when block template referenced by the ID should 1971 // be replaced with a new one. 1972 if request != nil && request.LongPollID != "" { 1973 return handleGetBlockTemplateLongPoll(s, request.LongPollID, 1974 useCoinbaseValue, closeChan) 1975 } 1976 1977 // Protect concurrent access when updating block templates. 1978 state := s.gbtWorkState 1979 state.Lock() 1980 defer state.Unlock() 1981 1982 // Get and return a block template. A new block template will be 1983 // generated when the current best block has changed or the transactions 1984 // in the memory pool have been updated and it has been at least five 1985 // seconds since the last template was generated. Otherwise, the 1986 // timestamp for the existing block template is updated (and possibly 1987 // the difficulty on testnet per the consesus rules). 1988 if err := state.updateBlockTemplate(s, useCoinbaseValue); err != nil { 1989 return nil, err 1990 } 1991 return state.blockTemplateResult(useCoinbaseValue, nil) 1992 } 1993 1994 // chainErrToGBTErrString converts an error returned from btcchain to a string 1995 // which matches the reasons and format described in BIP0022 for rejection 1996 // reasons. 1997 func chainErrToGBTErrString(err error) string { 1998 // When the passed error is not a RuleError, just return a generic 1999 // rejected string with the error text. 2000 ruleErr, ok := err.(blockchain.RuleError) 2001 if !ok { 2002 return "rejected: " + err.Error() 2003 } 2004 2005 switch ruleErr.ErrorCode { 2006 case blockchain.ErrDuplicateBlock: 2007 return "duplicate" 2008 case blockchain.ErrBlockTooBig: 2009 return "bad-blk-length" 2010 case blockchain.ErrBlockWeightTooHigh: 2011 return "bad-blk-weight" 2012 case blockchain.ErrBlockVersionTooOld: 2013 return "bad-version" 2014 case blockchain.ErrInvalidTime: 2015 return "bad-time" 2016 case blockchain.ErrTimeTooOld: 2017 return "time-too-old" 2018 case blockchain.ErrTimeTooNew: 2019 return "time-too-new" 2020 case blockchain.ErrDifficultyTooLow: 2021 return "bad-diffbits" 2022 case blockchain.ErrUnexpectedDifficulty: 2023 return "bad-diffbits" 2024 case blockchain.ErrHighHash: 2025 return "high-hash" 2026 case blockchain.ErrBadMerkleRoot: 2027 return "bad-txnmrklroot" 2028 case blockchain.ErrBadCheckpoint: 2029 return "bad-checkpoint" 2030 case blockchain.ErrForkTooOld: 2031 return "fork-too-old" 2032 case blockchain.ErrCheckpointTimeTooOld: 2033 return "checkpoint-time-too-old" 2034 case blockchain.ErrNoTransactions: 2035 return "bad-txns-none" 2036 case blockchain.ErrNoTxInputs: 2037 return "bad-txns-noinputs" 2038 case blockchain.ErrNoTxOutputs: 2039 return "bad-txns-nooutputs" 2040 case blockchain.ErrTxTooBig: 2041 return "bad-txns-size" 2042 case blockchain.ErrBadTxOutValue: 2043 return "bad-txns-outputvalue" 2044 case blockchain.ErrDuplicateTxInputs: 2045 return "bad-txns-dupinputs" 2046 case blockchain.ErrBadTxInput: 2047 return "bad-txns-badinput" 2048 case blockchain.ErrMissingTxOut: 2049 return "bad-txns-missinginput" 2050 case blockchain.ErrUnfinalizedTx: 2051 return "bad-txns-unfinalizedtx" 2052 case blockchain.ErrDuplicateTx: 2053 return "bad-txns-duplicate" 2054 case blockchain.ErrOverwriteTx: 2055 return "bad-txns-overwrite" 2056 case blockchain.ErrImmatureSpend: 2057 return "bad-txns-maturity" 2058 case blockchain.ErrSpendTooHigh: 2059 return "bad-txns-highspend" 2060 case blockchain.ErrBadFees: 2061 return "bad-txns-fees" 2062 case blockchain.ErrTooManySigOps: 2063 return "high-sigops" 2064 case blockchain.ErrFirstTxNotCoinbase: 2065 return "bad-txns-nocoinbase" 2066 case blockchain.ErrMultipleCoinbases: 2067 return "bad-txns-multicoinbase" 2068 case blockchain.ErrBadCoinbaseScriptLen: 2069 return "bad-cb-length" 2070 case blockchain.ErrBadCoinbaseValue: 2071 return "bad-cb-value" 2072 case blockchain.ErrMissingCoinbaseHeight: 2073 return "bad-cb-height" 2074 case blockchain.ErrBadCoinbaseHeight: 2075 return "bad-cb-height" 2076 case blockchain.ErrScriptMalformed: 2077 return "bad-script-malformed" 2078 case blockchain.ErrScriptValidation: 2079 return "bad-script-validate" 2080 case blockchain.ErrUnexpectedWitness: 2081 return "unexpected-witness" 2082 case blockchain.ErrInvalidWitnessCommitment: 2083 return "bad-witness-nonce-size" 2084 case blockchain.ErrWitnessCommitmentMismatch: 2085 return "bad-witness-merkle-match" 2086 case blockchain.ErrPreviousBlockUnknown: 2087 return "prev-blk-not-found" 2088 case blockchain.ErrInvalidAncestorBlock: 2089 return "bad-prevblk" 2090 case blockchain.ErrPrevBlockNotBest: 2091 return "inconclusive-not-best-prvblk" 2092 } 2093 2094 return "rejected: " + err.Error() 2095 } 2096 2097 // handleGetBlockTemplateProposal is a helper for handleGetBlockTemplate which 2098 // deals with block proposals. 2099 // 2100 // See https://en.bitcoin.it/wiki/BIP_0023 for more details. 2101 func handleGetBlockTemplateProposal(s *rpcServer, request *btcjson.TemplateRequest) (interface{}, error) { 2102 hexData := request.Data 2103 if hexData == "" { 2104 return false, &btcjson.RPCError{ 2105 Code: btcjson.ErrRPCType, 2106 Message: fmt.Sprintf("Data must contain the " + 2107 "hex-encoded serialized block that is being " + 2108 "proposed"), 2109 } 2110 } 2111 2112 // Ensure the provided data is sane and deserialize the proposed block. 2113 if len(hexData)%2 != 0 { 2114 hexData = "0" + hexData 2115 } 2116 dataBytes, err := hex.DecodeString(hexData) 2117 if err != nil { 2118 return false, &btcjson.RPCError{ 2119 Code: btcjson.ErrRPCDeserialization, 2120 Message: fmt.Sprintf("Data must be "+ 2121 "hexadecimal string (not %q)", hexData), 2122 } 2123 } 2124 var msgBlock wire.MsgBlock 2125 if err := msgBlock.Deserialize(bytes.NewReader(dataBytes)); err != nil { 2126 return nil, &btcjson.RPCError{ 2127 Code: btcjson.ErrRPCDeserialization, 2128 Message: "Block decode failed: " + err.Error(), 2129 } 2130 } 2131 block := palcutil.NewBlock(&msgBlock) 2132 2133 // Ensure the block is building from the expected previous block. 2134 expectedPrevHash := s.cfg.Chain.BestSnapshot().Hash 2135 prevHash := &block.MsgBlock().Header.PrevBlock 2136 if !expectedPrevHash.IsEqual(prevHash) { 2137 return "bad-prevblk", nil 2138 } 2139 2140 if err := s.cfg.Chain.CheckConnectBlockTemplate(block); err != nil { 2141 if _, ok := err.(blockchain.RuleError); !ok { 2142 errStr := fmt.Sprintf("Failed to process block proposal: %v", err) 2143 rpcsLog.Error(errStr) 2144 return nil, &btcjson.RPCError{ 2145 Code: btcjson.ErrRPCVerify, 2146 Message: errStr, 2147 } 2148 } 2149 2150 rpcsLog.Infof("Rejected block proposal: %v", err) 2151 return chainErrToGBTErrString(err), nil 2152 } 2153 2154 return nil, nil 2155 } 2156 2157 // handleGetBlockTemplate implements the getblocktemplate command. 2158 // 2159 // See https://en.bitcoin.it/wiki/BIP_0022 and 2160 // https://en.bitcoin.it/wiki/BIP_0023 for more details. 2161 func handleGetBlockTemplate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2162 c := cmd.(*btcjson.GetBlockTemplateCmd) 2163 request := c.Request 2164 2165 // Set the default mode and override it if supplied. 2166 mode := "template" 2167 if request != nil && request.Mode != "" { 2168 mode = request.Mode 2169 } 2170 2171 switch mode { 2172 case "template": 2173 return handleGetBlockTemplateRequest(s, request, closeChan) 2174 case "proposal": 2175 return handleGetBlockTemplateProposal(s, request) 2176 } 2177 2178 return nil, &btcjson.RPCError{ 2179 Code: btcjson.ErrRPCInvalidParameter, 2180 Message: "Invalid mode", 2181 } 2182 } 2183 2184 // handleGetCFilter implements the getcfilter command. 2185 func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2186 if s.cfg.CfIndex == nil { 2187 return nil, &btcjson.RPCError{ 2188 Code: btcjson.ErrRPCNoCFIndex, 2189 Message: "The CF index must be enabled for this command", 2190 } 2191 } 2192 2193 c := cmd.(*btcjson.GetCFilterCmd) 2194 hash, err := chainhash.NewHashFromStr(c.Hash) 2195 if err != nil { 2196 return nil, rpcDecodeHexError(c.Hash) 2197 } 2198 2199 filterBytes, err := s.cfg.CfIndex.FilterByBlockHash(hash, c.FilterType) 2200 if err != nil { 2201 rpcsLog.Debugf("Could not find committed filter for %v: %v", 2202 hash, err) 2203 return nil, &btcjson.RPCError{ 2204 Code: btcjson.ErrRPCBlockNotFound, 2205 Message: "Block not found", 2206 } 2207 } 2208 2209 rpcsLog.Debugf("Found committed filter for %v", hash) 2210 return hex.EncodeToString(filterBytes), nil 2211 } 2212 2213 // handleGetCFilterHeader implements the getcfilterheader command. 2214 func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2215 if s.cfg.CfIndex == nil { 2216 return nil, &btcjson.RPCError{ 2217 Code: btcjson.ErrRPCNoCFIndex, 2218 Message: "The CF index must be enabled for this command", 2219 } 2220 } 2221 2222 c := cmd.(*btcjson.GetCFilterHeaderCmd) 2223 hash, err := chainhash.NewHashFromStr(c.Hash) 2224 if err != nil { 2225 return nil, rpcDecodeHexError(c.Hash) 2226 } 2227 2228 headerBytes, err := s.cfg.CfIndex.FilterHeaderByBlockHash(hash, c.FilterType) 2229 if len(headerBytes) > 0 { 2230 rpcsLog.Debugf("Found header of committed filter for %v", hash) 2231 } else { 2232 rpcsLog.Debugf("Could not find header of committed filter for %v: %v", 2233 hash, err) 2234 return nil, &btcjson.RPCError{ 2235 Code: btcjson.ErrRPCBlockNotFound, 2236 Message: "Block not found", 2237 } 2238 } 2239 2240 hash.SetBytes(headerBytes) 2241 return hash.String(), nil 2242 } 2243 2244 // handleGetConnectionCount implements the getconnectioncount command. 2245 func handleGetConnectionCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2246 return s.cfg.ConnMgr.ConnectedCount(), nil 2247 } 2248 2249 // handleGetCurrentNet implements the getcurrentnet command. 2250 func handleGetCurrentNet(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2251 return s.cfg.ChainParams.Net, nil 2252 } 2253 2254 // handleGetDifficulty implements the getdifficulty command. 2255 func handleGetDifficulty(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2256 best := s.cfg.Chain.BestSnapshot() 2257 return getDifficultyRatio(best.Bits, s.cfg.ChainParams), nil 2258 } 2259 2260 // handleGetGenerate implements the getgenerate command. 2261 func handleGetGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2262 return s.cfg.CPUMiner.IsMining(), nil 2263 } 2264 2265 // handleGetHashesPerSec implements the gethashespersec command. 2266 func handleGetHashesPerSec(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2267 return int64(s.cfg.CPUMiner.HashesPerSecond()), nil 2268 } 2269 2270 // handleGetHeaders implements the getheaders command. 2271 // 2272 // NOTE: This is a btcsuite extension originally ported from 2273 // github.com/decred/dcrd. 2274 func handleGetHeaders(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2275 c := cmd.(*btcjson.GetHeadersCmd) 2276 2277 // Fetch the requested headers from chain while respecting the provided 2278 // block locators and stop hash. 2279 blockLocators := make([]*chainhash.Hash, len(c.BlockLocators)) 2280 for i := range c.BlockLocators { 2281 blockLocator, err := chainhash.NewHashFromStr(c.BlockLocators[i]) 2282 if err != nil { 2283 return nil, rpcDecodeHexError(c.BlockLocators[i]) 2284 } 2285 blockLocators[i] = blockLocator 2286 } 2287 var hashStop chainhash.Hash 2288 if c.HashStop != "" { 2289 err := chainhash.Decode(&hashStop, c.HashStop) 2290 if err != nil { 2291 return nil, rpcDecodeHexError(c.HashStop) 2292 } 2293 } 2294 headers := s.cfg.SyncMgr.LocateHeaders(blockLocators, &hashStop) 2295 2296 // Return the serialized block headers as hex-encoded strings. 2297 hexBlockHeaders := make([]string, len(headers)) 2298 var buf bytes.Buffer 2299 for i, h := range headers { 2300 err := h.Serialize(&buf) 2301 if err != nil { 2302 return nil, internalRPCError(err.Error(), 2303 "Failed to serialize block header") 2304 } 2305 hexBlockHeaders[i] = hex.EncodeToString(buf.Bytes()) 2306 buf.Reset() 2307 } 2308 return hexBlockHeaders, nil 2309 } 2310 2311 // handleGetInfo implements the getinfo command. We only return the fields 2312 // that are not related to wallet functionality. 2313 func handleGetInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2314 best := s.cfg.Chain.BestSnapshot() 2315 ret := &btcjson.InfoChainResult{ 2316 Version: int32(1000000*appMajor + 10000*appMinor + 100*appPatch), 2317 ProtocolVersion: int32(maxProtocolVersion), 2318 Blocks: best.Height, 2319 TimeOffset: int64(s.cfg.TimeSource.Offset().Seconds()), 2320 Connections: s.cfg.ConnMgr.ConnectedCount(), 2321 Proxy: cfg.Proxy, 2322 Difficulty: getDifficultyRatio(best.Bits, s.cfg.ChainParams), 2323 TestNet: cfg.TestNet3, 2324 RelayFee: cfg.minRelayTxFee.ToBTC(), 2325 } 2326 2327 return ret, nil 2328 } 2329 2330 // handleGetMempoolInfo implements the getmempoolinfo command. 2331 func handleGetMempoolInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2332 mempoolTxns := s.cfg.TxMemPool.TxDescs() 2333 2334 var numBytes int64 2335 for _, txD := range mempoolTxns { 2336 numBytes += int64(txD.Tx.MsgTx().SerializeSize()) 2337 } 2338 2339 ret := &btcjson.GetMempoolInfoResult{ 2340 Size: int64(len(mempoolTxns)), 2341 Bytes: numBytes, 2342 } 2343 2344 return ret, nil 2345 } 2346 2347 // handleGetMiningInfo implements the getmininginfo command. We only return the 2348 // fields that are not related to wallet functionality. 2349 func handleGetMiningInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2350 // Create a default getnetworkhashps command to use defaults and make 2351 // use of the existing getnetworkhashps handler. 2352 gnhpsCmd := btcjson.NewGetNetworkHashPSCmd(nil, nil) 2353 networkHashesPerSecIface, err := handleGetNetworkHashPS(s, gnhpsCmd, 2354 closeChan) 2355 if err != nil { 2356 return nil, err 2357 } 2358 networkHashesPerSec, ok := networkHashesPerSecIface.(int64) 2359 if !ok { 2360 return nil, &btcjson.RPCError{ 2361 Code: btcjson.ErrRPCInternal.Code, 2362 Message: "networkHashesPerSec is not an int64", 2363 } 2364 } 2365 2366 best := s.cfg.Chain.BestSnapshot() 2367 result := btcjson.GetMiningInfoResult{ 2368 Blocks: int64(best.Height), 2369 CurrentBlockSize: best.BlockSize, 2370 CurrentBlockWeight: best.BlockWeight, 2371 CurrentBlockTx: best.NumTxns, 2372 Difficulty: getDifficultyRatio(best.Bits, s.cfg.ChainParams), 2373 Generate: s.cfg.CPUMiner.IsMining(), 2374 GenProcLimit: s.cfg.CPUMiner.NumWorkers(), 2375 HashesPerSec: s.cfg.CPUMiner.HashesPerSecond(), 2376 NetworkHashPS: float64(networkHashesPerSec), 2377 PooledTx: uint64(s.cfg.TxMemPool.Count()), 2378 TestNet: cfg.TestNet3, 2379 } 2380 return &result, nil 2381 } 2382 2383 // handleGetNetTotals implements the getnettotals command. 2384 func handleGetNetTotals(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2385 totalBytesRecv, totalBytesSent := s.cfg.ConnMgr.NetTotals() 2386 reply := &btcjson.GetNetTotalsResult{ 2387 TotalBytesRecv: totalBytesRecv, 2388 TotalBytesSent: totalBytesSent, 2389 TimeMillis: time.Now().UTC().UnixNano() / int64(time.Millisecond), 2390 } 2391 return reply, nil 2392 } 2393 2394 // handleGetNetworkHashPS implements the getnetworkhashps command. 2395 func handleGetNetworkHashPS(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2396 // Note: All valid error return paths should return an int64. 2397 // Literal zeros are inferred as int, and won't coerce to int64 2398 // because the return value is an interface{}. 2399 2400 c := cmd.(*btcjson.GetNetworkHashPSCmd) 2401 2402 // When the passed height is too high or zero, just return 0 now 2403 // since we can't reasonably calculate the number of network hashes 2404 // per second from invalid values. When it's negative, use the current 2405 // best block height. 2406 best := s.cfg.Chain.BestSnapshot() 2407 endHeight := int32(-1) 2408 if c.Height != nil { 2409 endHeight = int32(*c.Height) 2410 } 2411 if endHeight > best.Height || endHeight == 0 { 2412 return int64(0), nil 2413 } 2414 if endHeight < 0 { 2415 endHeight = best.Height 2416 } 2417 2418 // Calculate the number of blocks per retarget interval based on the 2419 // chain parameters. 2420 blocksPerRetarget := int32(s.cfg.ChainParams.TargetTimespan / 2421 s.cfg.ChainParams.TargetTimePerBlock) 2422 2423 // Calculate the starting block height based on the passed number of 2424 // blocks. When the passed value is negative, use the last block the 2425 // difficulty changed as the starting height. Also make sure the 2426 // starting height is not before the beginning of the chain. 2427 numBlocks := int32(120) 2428 if c.Blocks != nil { 2429 numBlocks = int32(*c.Blocks) 2430 } 2431 var startHeight int32 2432 if numBlocks <= 0 { 2433 startHeight = endHeight - ((endHeight % blocksPerRetarget) + 1) 2434 } else { 2435 startHeight = endHeight - numBlocks 2436 } 2437 if startHeight < 0 { 2438 startHeight = 0 2439 } 2440 rpcsLog.Debugf("Calculating network hashes per second from %d to %d", 2441 startHeight, endHeight) 2442 2443 // Find the min and max block timestamps as well as calculate the total 2444 // amount of work that happened between the start and end blocks. 2445 var minTimestamp, maxTimestamp time.Time 2446 totalWork := big.NewInt(0) 2447 for curHeight := startHeight; curHeight <= endHeight; curHeight++ { 2448 hash, err := s.cfg.Chain.BlockHashByHeight(curHeight) 2449 if err != nil { 2450 context := "Failed to fetch block hash" 2451 return nil, internalRPCError(err.Error(), context) 2452 } 2453 2454 // Fetch the header from chain. 2455 header, err := s.cfg.Chain.HeaderByHash(hash) 2456 if err != nil { 2457 context := "Failed to fetch block header" 2458 return nil, internalRPCError(err.Error(), context) 2459 } 2460 2461 if curHeight == startHeight { 2462 minTimestamp = header.Timestamp 2463 maxTimestamp = minTimestamp 2464 } else { 2465 totalWork.Add(totalWork, blockchain.CalcWork(header.Bits)) 2466 2467 if minTimestamp.After(header.Timestamp) { 2468 minTimestamp = header.Timestamp 2469 } 2470 if maxTimestamp.Before(header.Timestamp) { 2471 maxTimestamp = header.Timestamp 2472 } 2473 } 2474 } 2475 2476 // Calculate the difference in seconds between the min and max block 2477 // timestamps and avoid division by zero in the case where there is no 2478 // time difference. 2479 timeDiff := int64(maxTimestamp.Sub(minTimestamp) / time.Second) 2480 if timeDiff == 0 { 2481 return int64(0), nil 2482 } 2483 2484 hashesPerSec := new(big.Int).Div(totalWork, big.NewInt(timeDiff)) 2485 return hashesPerSec.Int64(), nil 2486 } 2487 2488 // handleGetNodeAddresses implements the getnodeaddresses command. 2489 func handleGetNodeAddresses(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2490 c := cmd.(*btcjson.GetNodeAddressesCmd) 2491 2492 count := int32(1) 2493 if c.Count != nil { 2494 count = *c.Count 2495 if count <= 0 { 2496 return nil, &btcjson.RPCError{ 2497 Code: btcjson.ErrRPCInvalidParameter, 2498 Message: "Address count out of range", 2499 } 2500 } 2501 } 2502 2503 nodes := s.cfg.ConnMgr.NodeAddresses() 2504 if n := int32(len(nodes)); n < count { 2505 count = n 2506 } 2507 2508 addresses := make([]*btcjson.GetNodeAddressesResult, 0, count) 2509 for _, node := range nodes[:count] { 2510 address := &btcjson.GetNodeAddressesResult{ 2511 Time: node.Timestamp.Unix(), 2512 Services: uint64(node.Services), 2513 Address: node.IP.String(), 2514 Port: node.Port, 2515 } 2516 addresses = append(addresses, address) 2517 } 2518 2519 return addresses, nil 2520 } 2521 2522 // handleGetPeerInfo implements the getpeerinfo command. 2523 func handleGetPeerInfo(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2524 peers := s.cfg.ConnMgr.ConnectedPeers() 2525 syncPeerID := s.cfg.SyncMgr.SyncPeerID() 2526 infos := make([]*btcjson.GetPeerInfoResult, 0, len(peers)) 2527 for _, p := range peers { 2528 statsSnap := p.ToPeer().StatsSnapshot() 2529 info := &btcjson.GetPeerInfoResult{ 2530 ID: statsSnap.ID, 2531 Addr: statsSnap.Addr, 2532 AddrLocal: p.ToPeer().LocalAddr().String(), 2533 Services: fmt.Sprintf("%08d", uint64(statsSnap.Services)), 2534 RelayTxes: !p.IsTxRelayDisabled(), 2535 LastSend: statsSnap.LastSend.Unix(), 2536 LastRecv: statsSnap.LastRecv.Unix(), 2537 BytesSent: statsSnap.BytesSent, 2538 BytesRecv: statsSnap.BytesRecv, 2539 ConnTime: statsSnap.ConnTime.Unix(), 2540 PingTime: float64(statsSnap.LastPingMicros), 2541 TimeOffset: statsSnap.TimeOffset, 2542 Version: statsSnap.Version, 2543 SubVer: statsSnap.UserAgent, 2544 Inbound: statsSnap.Inbound, 2545 StartingHeight: statsSnap.StartingHeight, 2546 CurrentHeight: statsSnap.LastBlock, 2547 BanScore: int32(p.BanScore()), 2548 FeeFilter: p.FeeFilter(), 2549 SyncNode: statsSnap.ID == syncPeerID, 2550 } 2551 if p.ToPeer().LastPingNonce() != 0 { 2552 wait := float64(time.Since(statsSnap.LastPingTime).Nanoseconds()) 2553 // We actually want microseconds. 2554 info.PingWait = wait / 1000 2555 } 2556 infos = append(infos, info) 2557 } 2558 return infos, nil 2559 } 2560 2561 // handleGetRawMempool implements the getrawmempool command. 2562 func handleGetRawMempool(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2563 c := cmd.(*btcjson.GetRawMempoolCmd) 2564 mp := s.cfg.TxMemPool 2565 2566 if c.Verbose != nil && *c.Verbose { 2567 return mp.RawMempoolVerbose(), nil 2568 } 2569 2570 // The response is simply an array of the transaction hashes if the 2571 // verbose flag is not set. 2572 descs := mp.TxDescs() 2573 hashStrings := make([]string, len(descs)) 2574 for i := range hashStrings { 2575 hashStrings[i] = descs[i].Tx.Hash().String() 2576 } 2577 2578 return hashStrings, nil 2579 } 2580 2581 // handleGetRawTransaction implements the getrawtransaction command. 2582 func handleGetRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2583 c := cmd.(*btcjson.GetRawTransactionCmd) 2584 2585 // Convert the provided transaction hash hex to a Hash. 2586 txHash, err := chainhash.NewHashFromStr(c.Txid) 2587 if err != nil { 2588 return nil, rpcDecodeHexError(c.Txid) 2589 } 2590 2591 verbose := false 2592 if c.Verbose != nil { 2593 verbose = *c.Verbose != 0 2594 } 2595 2596 // Try to fetch the transaction from the memory pool and if that fails, 2597 // try the block database. 2598 var mtx *wire.MsgTx 2599 var blkHash *chainhash.Hash 2600 var blkHeight int32 2601 tx, err := s.cfg.TxMemPool.FetchTransaction(txHash) 2602 if err != nil { 2603 if s.cfg.TxIndex == nil { 2604 return nil, &btcjson.RPCError{ 2605 Code: btcjson.ErrRPCNoTxInfo, 2606 Message: "The transaction index must be " + 2607 "enabled to query the blockchain " + 2608 "(specify --txindex)", 2609 } 2610 } 2611 2612 // Look up the location of the transaction. 2613 blockRegion, err := s.cfg.TxIndex.TxBlockRegion(txHash) 2614 if err != nil { 2615 context := "Failed to retrieve transaction location" 2616 return nil, internalRPCError(err.Error(), context) 2617 } 2618 if blockRegion == nil { 2619 return nil, rpcNoTxInfoError(txHash) 2620 } 2621 2622 // Load the raw transaction bytes from the database. 2623 var txBytes []byte 2624 err = s.cfg.DB.View(func(dbTx database.Tx) error { 2625 var err error 2626 txBytes, err = dbTx.FetchBlockRegion(blockRegion) 2627 return err 2628 }) 2629 if err != nil { 2630 return nil, rpcNoTxInfoError(txHash) 2631 } 2632 2633 // When the verbose flag isn't set, simply return the serialized 2634 // transaction as a hex-encoded string. This is done here to 2635 // avoid deserializing it only to reserialize it again later. 2636 if !verbose { 2637 return hex.EncodeToString(txBytes), nil 2638 } 2639 2640 // Grab the block height. 2641 blkHash = blockRegion.Hash 2642 blkHeight, err = s.cfg.Chain.BlockHeightByHash(blkHash) 2643 if err != nil { 2644 context := "Failed to retrieve block height" 2645 return nil, internalRPCError(err.Error(), context) 2646 } 2647 2648 // Deserialize the transaction 2649 var msgTx wire.MsgTx 2650 err = msgTx.Deserialize(bytes.NewReader(txBytes)) 2651 if err != nil { 2652 context := "Failed to deserialize transaction" 2653 return nil, internalRPCError(err.Error(), context) 2654 } 2655 mtx = &msgTx 2656 } else { 2657 // When the verbose flag isn't set, simply return the 2658 // network-serialized transaction as a hex-encoded string. 2659 if !verbose { 2660 // Note that this is intentionally not directly 2661 // returning because the first return value is a 2662 // string and it would result in returning an empty 2663 // string to the client instead of nothing (nil) in the 2664 // case of an error. 2665 mtxHex, err := messageToHex(tx.MsgTx()) 2666 if err != nil { 2667 return nil, err 2668 } 2669 return mtxHex, nil 2670 } 2671 2672 mtx = tx.MsgTx() 2673 } 2674 2675 // The verbose flag is set, so generate the JSON object and return it. 2676 var blkHeader *wire.BlockHeader 2677 var blkHashStr string 2678 var chainHeight int32 2679 if blkHash != nil { 2680 // Fetch the header from chain. 2681 header, err := s.cfg.Chain.HeaderByHash(blkHash) 2682 if err != nil { 2683 context := "Failed to fetch block header" 2684 return nil, internalRPCError(err.Error(), context) 2685 } 2686 2687 blkHeader = &header 2688 blkHashStr = blkHash.String() 2689 chainHeight = s.cfg.Chain.BestSnapshot().Height 2690 } 2691 2692 rawTxn, err := createTxRawResult(s.cfg.ChainParams, mtx, txHash.String(), 2693 blkHeader, blkHashStr, blkHeight, chainHeight) 2694 if err != nil { 2695 return nil, err 2696 } 2697 return *rawTxn, nil 2698 } 2699 2700 // handleGetTxOut handles gettxout commands. 2701 func handleGetTxOut(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2702 c := cmd.(*btcjson.GetTxOutCmd) 2703 2704 // Convert the provided transaction hash hex to a Hash. 2705 txHash, err := chainhash.NewHashFromStr(c.Txid) 2706 if err != nil { 2707 return nil, rpcDecodeHexError(c.Txid) 2708 } 2709 2710 // If requested and the tx is available in the mempool try to fetch it 2711 // from there, otherwise attempt to fetch from the block database. 2712 var bestBlockHash string 2713 var confirmations int32 2714 var value int64 2715 var pkScript []byte 2716 var isCoinbase bool 2717 includeMempool := true 2718 if c.IncludeMempool != nil { 2719 includeMempool = *c.IncludeMempool 2720 } 2721 // TODO: This is racy. It should attempt to fetch it directly and check 2722 // the error. 2723 if includeMempool && s.cfg.TxMemPool.HaveTransaction(txHash) { 2724 tx, err := s.cfg.TxMemPool.FetchTransaction(txHash) 2725 if err != nil { 2726 return nil, rpcNoTxInfoError(txHash) 2727 } 2728 2729 mtx := tx.MsgTx() 2730 if c.Vout > uint32(len(mtx.TxOut)-1) { 2731 return nil, &btcjson.RPCError{ 2732 Code: btcjson.ErrRPCInvalidTxVout, 2733 Message: "Output index number (vout) does not " + 2734 "exist for transaction.", 2735 } 2736 } 2737 2738 txOut := mtx.TxOut[c.Vout] 2739 if txOut == nil { 2740 errStr := fmt.Sprintf("Output index: %d for txid: %s "+ 2741 "does not exist", c.Vout, txHash) 2742 return nil, internalRPCError(errStr, "") 2743 } 2744 2745 best := s.cfg.Chain.BestSnapshot() 2746 bestBlockHash = best.Hash.String() 2747 confirmations = 0 2748 value = txOut.Value 2749 pkScript = txOut.PkScript 2750 isCoinbase = blockchain.IsCoinBaseTx(mtx) 2751 } else { 2752 out := wire.OutPoint{Hash: *txHash, Index: c.Vout} 2753 entry, err := s.cfg.Chain.FetchUtxoEntry(out) 2754 if err != nil { 2755 return nil, rpcNoTxInfoError(txHash) 2756 } 2757 2758 // To match the behavior of the reference client, return nil 2759 // (JSON null) if the transaction output is spent by another 2760 // transaction already in the main chain. Mined transactions 2761 // that are spent by a mempool transaction are not affected by 2762 // this. 2763 if entry == nil || entry.IsSpent() { 2764 return nil, nil 2765 } 2766 2767 best := s.cfg.Chain.BestSnapshot() 2768 bestBlockHash = best.Hash.String() 2769 confirmations = 1 + best.Height - entry.BlockHeight() 2770 value = entry.Amount() 2771 pkScript = entry.PkScript() 2772 isCoinbase = entry.IsCoinBase() 2773 } 2774 2775 // Disassemble script into single line printable format. 2776 // The disassembled string will contain [error] inline if the script 2777 // doesn't fully parse, so ignore the error here. 2778 disbuf, _ := txscript.DisasmString(pkScript) 2779 2780 // Get further info about the script. 2781 // Ignore the error here since an error means the script couldn't parse 2782 // and there is no additional information about it anyways. 2783 scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(pkScript, 2784 s.cfg.ChainParams) 2785 addresses := make([]string, len(addrs)) 2786 for i, addr := range addrs { 2787 addresses[i] = addr.EncodeAddress() 2788 } 2789 2790 txOutReply := &btcjson.GetTxOutResult{ 2791 BestBlock: bestBlockHash, 2792 Confirmations: int64(confirmations), 2793 Value: palcutil.Amount(value).ToBTC(), 2794 ScriptPubKey: btcjson.ScriptPubKeyResult{ 2795 Asm: disbuf, 2796 Hex: hex.EncodeToString(pkScript), 2797 ReqSigs: int32(reqSigs), 2798 Type: scriptClass.String(), 2799 Addresses: addresses, 2800 }, 2801 Coinbase: isCoinbase, 2802 } 2803 return txOutReply, nil 2804 } 2805 2806 // handleHelp implements the help command. 2807 func handleHelp(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2808 c := cmd.(*btcjson.HelpCmd) 2809 2810 // Provide a usage overview of all commands when no specific command 2811 // was specified. 2812 var command string 2813 if c.Command != nil { 2814 command = *c.Command 2815 } 2816 if command == "" { 2817 usage, err := s.helpCacher.rpcUsage(false) 2818 if err != nil { 2819 context := "Failed to generate RPC usage" 2820 return nil, internalRPCError(err.Error(), context) 2821 } 2822 return usage, nil 2823 } 2824 2825 // Check that the command asked for is supported and implemented. Only 2826 // search the main list of handlers since help should not be provided 2827 // for commands that are unimplemented or related to wallet 2828 // functionality. 2829 if _, ok := rpcHandlers[command]; !ok { 2830 return nil, &btcjson.RPCError{ 2831 Code: btcjson.ErrRPCInvalidParameter, 2832 Message: "Unknown command: " + command, 2833 } 2834 } 2835 2836 // Get the help for the command. 2837 help, err := s.helpCacher.rpcMethodHelp(command) 2838 if err != nil { 2839 context := "Failed to generate help" 2840 return nil, internalRPCError(err.Error(), context) 2841 } 2842 return help, nil 2843 } 2844 2845 // handlePing implements the ping command. 2846 func handlePing(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 2847 // Ask server to ping \o_ 2848 nonce, err := wire.RandomUint64() 2849 if err != nil { 2850 return nil, internalRPCError("Not sending ping - failed to "+ 2851 "generate nonce: "+err.Error(), "") 2852 } 2853 s.cfg.ConnMgr.BroadcastMessage(wire.NewMsgPing(nonce)) 2854 2855 return nil, nil 2856 } 2857 2858 // retrievedTx represents a transaction that was either loaded from the 2859 // transaction memory pool or from the database. When a transaction is loaded 2860 // from the database, it is loaded with the raw serialized bytes while the 2861 // mempool has the fully deserialized structure. This structure therefore will 2862 // have one of the two fields set depending on where is was retrieved from. 2863 // This is mainly done for efficiency to avoid extra serialization steps when 2864 // possible. 2865 type retrievedTx struct { 2866 txBytes []byte 2867 blkHash *chainhash.Hash // Only set when transaction is in a block. 2868 tx *palcutil.Tx 2869 } 2870 2871 // fetchInputTxos fetches the outpoints from all transactions referenced by the 2872 // inputs to the passed transaction by checking the transaction mempool first 2873 // then the transaction index for those already mined into blocks. 2874 func fetchInputTxos(s *rpcServer, tx *wire.MsgTx) (map[wire.OutPoint]wire.TxOut, error) { 2875 mp := s.cfg.TxMemPool 2876 originOutputs := make(map[wire.OutPoint]wire.TxOut) 2877 for txInIndex, txIn := range tx.TxIn { 2878 // Attempt to fetch and use the referenced transaction from the 2879 // memory pool. 2880 origin := &txIn.PreviousOutPoint 2881 originTx, err := mp.FetchTransaction(&origin.Hash) 2882 if err == nil { 2883 txOuts := originTx.MsgTx().TxOut 2884 if origin.Index >= uint32(len(txOuts)) { 2885 errStr := fmt.Sprintf("unable to find output "+ 2886 "%v referenced from transaction %s:%d", 2887 origin, tx.TxHash(), txInIndex) 2888 return nil, internalRPCError(errStr, "") 2889 } 2890 2891 originOutputs[*origin] = *txOuts[origin.Index] 2892 continue 2893 } 2894 2895 // Look up the location of the transaction. 2896 blockRegion, err := s.cfg.TxIndex.TxBlockRegion(&origin.Hash) 2897 if err != nil { 2898 context := "Failed to retrieve transaction location" 2899 return nil, internalRPCError(err.Error(), context) 2900 } 2901 if blockRegion == nil { 2902 return nil, rpcNoTxInfoError(&origin.Hash) 2903 } 2904 2905 // Load the raw transaction bytes from the database. 2906 var txBytes []byte 2907 err = s.cfg.DB.View(func(dbTx database.Tx) error { 2908 var err error 2909 txBytes, err = dbTx.FetchBlockRegion(blockRegion) 2910 return err 2911 }) 2912 if err != nil { 2913 return nil, rpcNoTxInfoError(&origin.Hash) 2914 } 2915 2916 // Deserialize the transaction 2917 var msgTx wire.MsgTx 2918 err = msgTx.Deserialize(bytes.NewReader(txBytes)) 2919 if err != nil { 2920 context := "Failed to deserialize transaction" 2921 return nil, internalRPCError(err.Error(), context) 2922 } 2923 2924 // Add the referenced output to the map. 2925 if origin.Index >= uint32(len(msgTx.TxOut)) { 2926 errStr := fmt.Sprintf("unable to find output %v "+ 2927 "referenced from transaction %s:%d", origin, 2928 tx.TxHash(), txInIndex) 2929 return nil, internalRPCError(errStr, "") 2930 } 2931 originOutputs[*origin] = *msgTx.TxOut[origin.Index] 2932 } 2933 2934 return originOutputs, nil 2935 } 2936 2937 // createVinListPrevOut returns a slice of JSON objects for the inputs of the 2938 // passed transaction. 2939 func createVinListPrevOut(s *rpcServer, mtx *wire.MsgTx, chainParams *chaincfg.Params, vinExtra bool, filterAddrMap map[string]struct{}) ([]btcjson.VinPrevOut, error) { 2940 // Coinbase transactions only have a single txin by definition. 2941 if blockchain.IsCoinBaseTx(mtx) { 2942 // Only include the transaction if the filter map is empty 2943 // because a coinbase input has no addresses and so would never 2944 // match a non-empty filter. 2945 if len(filterAddrMap) != 0 { 2946 return nil, nil 2947 } 2948 2949 txIn := mtx.TxIn[0] 2950 vinList := make([]btcjson.VinPrevOut, 1) 2951 vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript) 2952 vinList[0].Sequence = txIn.Sequence 2953 return vinList, nil 2954 } 2955 2956 // Use a dynamically sized list to accommodate the address filter. 2957 vinList := make([]btcjson.VinPrevOut, 0, len(mtx.TxIn)) 2958 2959 // Lookup all of the referenced transaction outputs needed to populate 2960 // the previous output information if requested. 2961 var originOutputs map[wire.OutPoint]wire.TxOut 2962 if vinExtra || len(filterAddrMap) > 0 { 2963 var err error 2964 originOutputs, err = fetchInputTxos(s, mtx) 2965 if err != nil { 2966 return nil, err 2967 } 2968 } 2969 2970 for _, txIn := range mtx.TxIn { 2971 // The disassembled string will contain [error] inline 2972 // if the script doesn't fully parse, so ignore the 2973 // error here. 2974 disbuf, _ := txscript.DisasmString(txIn.SignatureScript) 2975 2976 // Create the basic input entry without the additional optional 2977 // previous output details which will be added later if 2978 // requested and available. 2979 prevOut := &txIn.PreviousOutPoint 2980 vinEntry := btcjson.VinPrevOut{ 2981 Txid: prevOut.Hash.String(), 2982 Vout: prevOut.Index, 2983 Sequence: txIn.Sequence, 2984 ScriptSig: &btcjson.ScriptSig{ 2985 Asm: disbuf, 2986 Hex: hex.EncodeToString(txIn.SignatureScript), 2987 }, 2988 } 2989 2990 if len(txIn.Witness) != 0 { 2991 vinEntry.Witness = witnessToHex(txIn.Witness) 2992 } 2993 2994 // Add the entry to the list now if it already passed the filter 2995 // since the previous output might not be available. 2996 passesFilter := len(filterAddrMap) == 0 2997 if passesFilter { 2998 vinList = append(vinList, vinEntry) 2999 } 3000 3001 // Only populate previous output information if requested and 3002 // available. 3003 if len(originOutputs) == 0 { 3004 continue 3005 } 3006 originTxOut, ok := originOutputs[*prevOut] 3007 if !ok { 3008 continue 3009 } 3010 3011 // Ignore the error here since an error means the script 3012 // couldn't parse and there is no additional information about 3013 // it anyways. 3014 _, addrs, _, _ := txscript.ExtractPkScriptAddrs( 3015 originTxOut.PkScript, chainParams) 3016 3017 // Encode the addresses while checking if the address passes the 3018 // filter when needed. 3019 encodedAddrs := make([]string, len(addrs)) 3020 for j, addr := range addrs { 3021 encodedAddr := addr.EncodeAddress() 3022 encodedAddrs[j] = encodedAddr 3023 3024 // No need to check the map again if the filter already 3025 // passes. 3026 if passesFilter { 3027 continue 3028 } 3029 if _, exists := filterAddrMap[encodedAddr]; exists { 3030 passesFilter = true 3031 } 3032 } 3033 3034 // Ignore the entry if it doesn't pass the filter. 3035 if !passesFilter { 3036 continue 3037 } 3038 3039 // Add entry to the list if it wasn't already done above. 3040 if len(filterAddrMap) != 0 { 3041 vinList = append(vinList, vinEntry) 3042 } 3043 3044 // Update the entry with previous output information if 3045 // requested. 3046 if vinExtra { 3047 vinListEntry := &vinList[len(vinList)-1] 3048 vinListEntry.PrevOut = &btcjson.PrevOut{ 3049 Addresses: encodedAddrs, 3050 Value: palcutil.Amount(originTxOut.Value).ToBTC(), 3051 } 3052 } 3053 } 3054 3055 return vinList, nil 3056 } 3057 3058 // fetchMempoolTxnsForAddress queries the address index for all unconfirmed 3059 // transactions that involve the provided address. The results will be limited 3060 // by the number to skip and the number requested. 3061 func fetchMempoolTxnsForAddress(s *rpcServer, addr palcutil.Address, numToSkip, numRequested uint32) ([]*palcutil.Tx, uint32) { 3062 // There are no entries to return when there are less available than the 3063 // number being skipped. 3064 mpTxns := s.cfg.AddrIndex.UnconfirmedTxnsForAddress(addr) 3065 numAvailable := uint32(len(mpTxns)) 3066 if numToSkip > numAvailable { 3067 return nil, numAvailable 3068 } 3069 3070 // Filter the available entries based on the number to skip and number 3071 // requested. 3072 rangeEnd := numToSkip + numRequested 3073 if rangeEnd > numAvailable { 3074 rangeEnd = numAvailable 3075 } 3076 return mpTxns[numToSkip:rangeEnd], numToSkip 3077 } 3078 3079 // handleSearchRawTransactions implements the searchrawtransactions command. 3080 func handleSearchRawTransactions(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3081 // Respond with an error if the address index is not enabled. 3082 addrIndex := s.cfg.AddrIndex 3083 if addrIndex == nil { 3084 return nil, &btcjson.RPCError{ 3085 Code: btcjson.ErrRPCMisc, 3086 Message: "Address index must be enabled (--addrindex)", 3087 } 3088 } 3089 3090 // Override the flag for including extra previous output information in 3091 // each input if needed. 3092 c := cmd.(*btcjson.SearchRawTransactionsCmd) 3093 vinExtra := false 3094 if c.VinExtra != nil { 3095 vinExtra = *c.VinExtra != 0 3096 } 3097 3098 // Including the extra previous output information requires the 3099 // transaction index. Currently the address index relies on the 3100 // transaction index, so this check is redundant, but it's better to be 3101 // safe in case the address index is ever changed to not rely on it. 3102 if vinExtra && s.cfg.TxIndex == nil { 3103 return nil, &btcjson.RPCError{ 3104 Code: btcjson.ErrRPCMisc, 3105 Message: "Transaction index must be enabled (--txindex)", 3106 } 3107 } 3108 3109 // Attempt to decode the supplied address. 3110 params := s.cfg.ChainParams 3111 addr, err := palcutil.DecodeAddress(c.Address, params) 3112 if err != nil { 3113 return nil, &btcjson.RPCError{ 3114 Code: btcjson.ErrRPCInvalidAddressOrKey, 3115 Message: "Invalid address or key: " + err.Error(), 3116 } 3117 } 3118 3119 // Override the default number of requested entries if needed. Also, 3120 // just return now if the number of requested entries is zero to avoid 3121 // extra work. 3122 numRequested := 100 3123 if c.Count != nil { 3124 numRequested = *c.Count 3125 if numRequested < 0 { 3126 numRequested = 1 3127 } 3128 } 3129 if numRequested == 0 { 3130 return nil, nil 3131 } 3132 3133 // Override the default number of entries to skip if needed. 3134 var numToSkip int 3135 if c.Skip != nil { 3136 numToSkip = *c.Skip 3137 if numToSkip < 0 { 3138 numToSkip = 0 3139 } 3140 } 3141 3142 // Override the reverse flag if needed. 3143 var reverse bool 3144 if c.Reverse != nil { 3145 reverse = *c.Reverse 3146 } 3147 3148 // Add transactions from mempool first if client asked for reverse 3149 // order. Otherwise, they will be added last (as needed depending on 3150 // the requested counts). 3151 // 3152 // NOTE: This code doesn't sort by dependency. This might be something 3153 // to do in the future for the client's convenience, or leave it to the 3154 // client. 3155 numSkipped := uint32(0) 3156 addressTxns := make([]retrievedTx, 0, numRequested) 3157 if reverse { 3158 // Transactions in the mempool are not in a block header yet, 3159 // so the block header field in the retieved transaction struct 3160 // is left nil. 3161 mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr, 3162 uint32(numToSkip), uint32(numRequested)) 3163 numSkipped += mpSkipped 3164 for _, tx := range mpTxns { 3165 addressTxns = append(addressTxns, retrievedTx{tx: tx}) 3166 } 3167 } 3168 3169 // Fetch transactions from the database in the desired order if more are 3170 // needed. 3171 if len(addressTxns) < numRequested { 3172 err = s.cfg.DB.View(func(dbTx database.Tx) error { 3173 regions, dbSkipped, err := addrIndex.TxRegionsForAddress( 3174 dbTx, addr, uint32(numToSkip)-numSkipped, 3175 uint32(numRequested-len(addressTxns)), reverse) 3176 if err != nil { 3177 return err 3178 } 3179 3180 // Load the raw transaction bytes from the database. 3181 serializedTxns, err := dbTx.FetchBlockRegions(regions) 3182 if err != nil { 3183 return err 3184 } 3185 3186 // Add the transaction and the hash of the block it is 3187 // contained in to the list. Note that the transaction 3188 // is left serialized here since the caller might have 3189 // requested non-verbose output and hence there would be 3190 // no point in deserializing it just to reserialize it 3191 // later. 3192 for i, serializedTx := range serializedTxns { 3193 addressTxns = append(addressTxns, retrievedTx{ 3194 txBytes: serializedTx, 3195 blkHash: regions[i].Hash, 3196 }) 3197 } 3198 numSkipped += dbSkipped 3199 3200 return nil 3201 }) 3202 if err != nil { 3203 context := "Failed to load address index entries" 3204 return nil, internalRPCError(err.Error(), context) 3205 } 3206 3207 } 3208 3209 // Add transactions from mempool last if client did not request reverse 3210 // order and the number of results is still under the number requested. 3211 if !reverse && len(addressTxns) < numRequested { 3212 // Transactions in the mempool are not in a block header yet, 3213 // so the block header field in the retieved transaction struct 3214 // is left nil. 3215 mpTxns, mpSkipped := fetchMempoolTxnsForAddress(s, addr, 3216 uint32(numToSkip)-numSkipped, uint32(numRequested- 3217 len(addressTxns))) 3218 numSkipped += mpSkipped 3219 for _, tx := range mpTxns { 3220 addressTxns = append(addressTxns, retrievedTx{tx: tx}) 3221 } 3222 } 3223 3224 // Address has never been used if neither source yielded any results. 3225 if len(addressTxns) == 0 { 3226 return nil, &btcjson.RPCError{ 3227 Code: btcjson.ErrRPCNoTxInfo, 3228 Message: "No information available about address", 3229 } 3230 } 3231 3232 // Serialize all of the transactions to hex. 3233 hexTxns := make([]string, len(addressTxns)) 3234 for i := range addressTxns { 3235 // Simply encode the raw bytes to hex when the retrieved 3236 // transaction is already in serialized form. 3237 rtx := &addressTxns[i] 3238 if rtx.txBytes != nil { 3239 hexTxns[i] = hex.EncodeToString(rtx.txBytes) 3240 continue 3241 } 3242 3243 // Serialize the transaction first and convert to hex when the 3244 // retrieved transaction is the deserialized structure. 3245 hexTxns[i], err = messageToHex(rtx.tx.MsgTx()) 3246 if err != nil { 3247 return nil, err 3248 } 3249 } 3250 3251 // When not in verbose mode, simply return a list of serialized txns. 3252 if c.Verbose != nil && *c.Verbose == 0 { 3253 return hexTxns, nil 3254 } 3255 3256 // Normalize the provided filter addresses (if any) to ensure there are 3257 // no duplicates. 3258 filterAddrMap := make(map[string]struct{}) 3259 if c.FilterAddrs != nil && len(*c.FilterAddrs) > 0 { 3260 for _, addr := range *c.FilterAddrs { 3261 filterAddrMap[addr] = struct{}{} 3262 } 3263 } 3264 3265 // The verbose flag is set, so generate the JSON object and return it. 3266 best := s.cfg.Chain.BestSnapshot() 3267 srtList := make([]btcjson.SearchRawTransactionsResult, len(addressTxns)) 3268 for i := range addressTxns { 3269 // The deserialized transaction is needed, so deserialize the 3270 // retrieved transaction if it's in serialized form (which will 3271 // be the case when it was lookup up from the database). 3272 // Otherwise, use the existing deserialized transaction. 3273 rtx := &addressTxns[i] 3274 var mtx *wire.MsgTx 3275 if rtx.tx == nil { 3276 // Deserialize the transaction. 3277 mtx = new(wire.MsgTx) 3278 err := mtx.Deserialize(bytes.NewReader(rtx.txBytes)) 3279 if err != nil { 3280 context := "Failed to deserialize transaction" 3281 return nil, internalRPCError(err.Error(), 3282 context) 3283 } 3284 } else { 3285 mtx = rtx.tx.MsgTx() 3286 } 3287 3288 result := &srtList[i] 3289 result.Hex = hexTxns[i] 3290 result.Txid = mtx.TxHash().String() 3291 result.Vin, err = createVinListPrevOut(s, mtx, params, vinExtra, 3292 filterAddrMap) 3293 if err != nil { 3294 return nil, err 3295 } 3296 result.Vout = createVoutList(mtx, params, filterAddrMap) 3297 result.Version = mtx.Version 3298 result.LockTime = mtx.LockTime 3299 3300 // Transactions grabbed from the mempool aren't yet in a block, 3301 // so conditionally fetch block details here. This will be 3302 // reflected in the final JSON output (mempool won't have 3303 // confirmations or block information). 3304 var blkHeader *wire.BlockHeader 3305 var blkHashStr string 3306 var blkHeight int32 3307 if blkHash := rtx.blkHash; blkHash != nil { 3308 // Fetch the header from chain. 3309 header, err := s.cfg.Chain.HeaderByHash(blkHash) 3310 if err != nil { 3311 return nil, &btcjson.RPCError{ 3312 Code: btcjson.ErrRPCBlockNotFound, 3313 Message: "Block not found", 3314 } 3315 } 3316 3317 // Get the block height from chain. 3318 height, err := s.cfg.Chain.BlockHeightByHash(blkHash) 3319 if err != nil { 3320 context := "Failed to obtain block height" 3321 return nil, internalRPCError(err.Error(), context) 3322 } 3323 3324 blkHeader = &header 3325 blkHashStr = blkHash.String() 3326 blkHeight = height 3327 } 3328 3329 // Add the block information to the result if there is any. 3330 if blkHeader != nil { 3331 // This is not a typo, they are identical in Bitcoin 3332 // Core as well. 3333 result.Time = blkHeader.Timestamp.Unix() 3334 result.Blocktime = blkHeader.Timestamp.Unix() 3335 result.BlockHash = blkHashStr 3336 result.Confirmations = uint64(1 + best.Height - blkHeight) 3337 } 3338 } 3339 3340 return srtList, nil 3341 } 3342 3343 // handleSendRawTransaction implements the sendrawtransaction command. 3344 func handleSendRawTransaction(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3345 c := cmd.(*btcjson.SendRawTransactionCmd) 3346 // Deserialize and send off to tx relay 3347 hexStr := c.HexTx 3348 if len(hexStr)%2 != 0 { 3349 hexStr = "0" + hexStr 3350 } 3351 serializedTx, err := hex.DecodeString(hexStr) 3352 if err != nil { 3353 return nil, rpcDecodeHexError(hexStr) 3354 } 3355 var msgTx wire.MsgTx 3356 err = msgTx.Deserialize(bytes.NewReader(serializedTx)) 3357 if err != nil { 3358 return nil, &btcjson.RPCError{ 3359 Code: btcjson.ErrRPCDeserialization, 3360 Message: "TX decode failed: " + err.Error(), 3361 } 3362 } 3363 3364 // Use 0 for the tag to represent local node. 3365 tx := palcutil.NewTx(&msgTx) 3366 acceptedTxs, err := s.cfg.TxMemPool.ProcessTransaction(tx, false, false, 0) 3367 if err != nil { 3368 // When the error is a rule error, it means the transaction was 3369 // simply rejected as opposed to something actually going wrong, 3370 // so log it as such. Otherwise, something really did go wrong, 3371 // so log it as an actual error and return. 3372 ruleErr, ok := err.(mempool.RuleError) 3373 if !ok { 3374 rpcsLog.Errorf("Failed to process transaction %v: %v", 3375 tx.Hash(), err) 3376 3377 return nil, &btcjson.RPCError{ 3378 Code: btcjson.ErrRPCTxError, 3379 Message: "TX rejected: " + err.Error(), 3380 } 3381 } 3382 3383 rpcsLog.Debugf("Rejected transaction %v: %v", tx.Hash(), err) 3384 3385 // We'll then map the rule error to the appropriate RPC error, 3386 // matching bitcoind's behavior. 3387 code := btcjson.ErrRPCTxError 3388 if txRuleErr, ok := ruleErr.Err.(mempool.TxRuleError); ok { 3389 errDesc := txRuleErr.Description 3390 switch { 3391 case strings.Contains( 3392 strings.ToLower(errDesc), "orphan transaction", 3393 ): 3394 code = btcjson.ErrRPCTxError 3395 3396 case strings.Contains( 3397 strings.ToLower(errDesc), "transaction already exists", 3398 ): 3399 code = btcjson.ErrRPCTxAlreadyInChain 3400 3401 default: 3402 code = btcjson.ErrRPCTxRejected 3403 } 3404 } 3405 3406 return nil, &btcjson.RPCError{ 3407 Code: code, 3408 Message: "TX rejected: " + err.Error(), 3409 } 3410 } 3411 3412 // When the transaction was accepted it should be the first item in the 3413 // returned array of accepted transactions. The only way this will not 3414 // be true is if the API for ProcessTransaction changes and this code is 3415 // not properly updated, but ensure the condition holds as a safeguard. 3416 // 3417 // Also, since an error is being returned to the caller, ensure the 3418 // transaction is removed from the memory pool. 3419 if len(acceptedTxs) == 0 || !acceptedTxs[0].Tx.Hash().IsEqual(tx.Hash()) { 3420 s.cfg.TxMemPool.RemoveTransaction(tx, true) 3421 3422 errStr := fmt.Sprintf("transaction %v is not in accepted list", 3423 tx.Hash()) 3424 return nil, internalRPCError(errStr, "") 3425 } 3426 3427 // Generate and relay inventory vectors for all newly accepted 3428 // transactions into the memory pool due to the original being 3429 // accepted. 3430 s.cfg.ConnMgr.RelayTransactions(acceptedTxs) 3431 3432 // Notify both websocket and getblocktemplate long poll clients of all 3433 // newly accepted transactions. 3434 s.NotifyNewTransactions(acceptedTxs) 3435 3436 // Keep track of all the sendrawtransaction request txns so that they 3437 // can be rebroadcast if they don't make their way into a block. 3438 txD := acceptedTxs[0] 3439 iv := wire.NewInvVect(wire.InvTypeTx, txD.Tx.Hash()) 3440 s.cfg.ConnMgr.AddRebroadcastInventory(iv, txD) 3441 3442 return tx.Hash().String(), nil 3443 } 3444 3445 // handleSetGenerate implements the setgenerate command. 3446 func handleSetGenerate(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3447 c := cmd.(*btcjson.SetGenerateCmd) 3448 3449 // Disable generation regardless of the provided generate flag if the 3450 // maximum number of threads (goroutines for our purposes) is 0. 3451 // Otherwise enable or disable it depending on the provided flag. 3452 generate := c.Generate 3453 genProcLimit := -1 3454 if c.GenProcLimit != nil { 3455 genProcLimit = *c.GenProcLimit 3456 } 3457 if genProcLimit == 0 { 3458 generate = false 3459 } 3460 3461 if !generate { 3462 s.cfg.CPUMiner.Stop() 3463 } else { 3464 // Respond with an error if there are no addresses to pay the 3465 // created blocks to. 3466 if len(cfg.miningAddrs) == 0 { 3467 return nil, &btcjson.RPCError{ 3468 Code: btcjson.ErrRPCInternal.Code, 3469 Message: "No payment addresses specified " + 3470 "via --miningaddr", 3471 } 3472 } 3473 3474 // It's safe to call start even if it's already started. 3475 s.cfg.CPUMiner.SetNumWorkers(int32(genProcLimit)) 3476 s.cfg.CPUMiner.Start() 3477 } 3478 return nil, nil 3479 } 3480 3481 // Text used to signify that a signed message follows and to prevent 3482 // inadvertently signing a transaction. 3483 const messageSignatureHeader = "Palcoin Signed Message:\n" 3484 3485 // handleSignMessageWithPrivKey implements the signmessagewithprivkey command. 3486 func handleSignMessageWithPrivKey(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3487 c := cmd.(*btcjson.SignMessageWithPrivKeyCmd) 3488 3489 wif, err := palcutil.DecodeWIF(c.PrivKey) 3490 if err != nil { 3491 message := "Invalid private key" 3492 switch err { 3493 case palcutil.ErrMalformedPrivateKey: 3494 message = "Malformed private key" 3495 case palcutil.ErrChecksumMismatch: 3496 message = "Private key checksum mismatch" 3497 } 3498 return nil, &btcjson.RPCError{ 3499 Code: btcjson.ErrRPCInvalidAddressOrKey, 3500 Message: message, 3501 } 3502 } 3503 if !wif.IsForNet(s.cfg.ChainParams) { 3504 return nil, &btcjson.RPCError{ 3505 Code: btcjson.ErrRPCInvalidAddressOrKey, 3506 Message: "Private key for wrong network", 3507 } 3508 } 3509 3510 var buf bytes.Buffer 3511 wire.WriteVarString(&buf, 0, messageSignatureHeader) 3512 wire.WriteVarString(&buf, 0, c.Message) 3513 messageHash := chainhash.DoubleHashB(buf.Bytes()) 3514 3515 sig, err := btcec.SignCompact(btcec.S256(), wif.PrivKey, 3516 messageHash, wif.CompressPubKey) 3517 if err != nil { 3518 return nil, &btcjson.RPCError{ 3519 Code: btcjson.ErrRPCInvalidAddressOrKey, 3520 Message: "Sign failed", 3521 } 3522 } 3523 3524 return base64.StdEncoding.EncodeToString(sig), nil 3525 } 3526 3527 // handleStop implements the stop command. 3528 func handleStop(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3529 select { 3530 case s.requestProcessShutdown <- struct{}{}: 3531 default: 3532 } 3533 return "btcd stopping.", nil 3534 } 3535 3536 // handleSubmitBlock implements the submitblock command. 3537 func handleSubmitBlock(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3538 c := cmd.(*btcjson.SubmitBlockCmd) 3539 3540 // Deserialize the submitted block. 3541 hexStr := c.HexBlock 3542 if len(hexStr)%2 != 0 { 3543 hexStr = "0" + c.HexBlock 3544 } 3545 serializedBlock, err := hex.DecodeString(hexStr) 3546 if err != nil { 3547 return nil, rpcDecodeHexError(hexStr) 3548 } 3549 3550 block, err := palcutil.NewBlockFromBytes(serializedBlock) 3551 if err != nil { 3552 return nil, &btcjson.RPCError{ 3553 Code: btcjson.ErrRPCDeserialization, 3554 Message: "Block decode failed: " + err.Error(), 3555 } 3556 } 3557 3558 // Process this block using the same rules as blocks coming from other 3559 // nodes. This will in turn relay it to the network like normal. 3560 _, err = s.cfg.SyncMgr.SubmitBlock(block, blockchain.BFNone) 3561 if err != nil { 3562 return fmt.Sprintf("rejected: %s", err.Error()), nil 3563 } 3564 3565 rpcsLog.Infof("Accepted block %s via submitblock", block.Hash()) 3566 return nil, nil 3567 } 3568 3569 // handleUptime implements the uptime command. 3570 func handleUptime(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3571 return time.Now().Unix() - s.cfg.StartupTime, nil 3572 } 3573 3574 // handleValidateAddress implements the validateaddress command. 3575 func handleValidateAddress(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3576 c := cmd.(*btcjson.ValidateAddressCmd) 3577 3578 result := btcjson.ValidateAddressChainResult{} 3579 addr, err := palcutil.DecodeAddress(c.Address, s.cfg.ChainParams) 3580 if err != nil { 3581 // Return the default value (false) for IsValid. 3582 return result, nil 3583 } 3584 3585 switch addr := addr.(type) { 3586 case *palcutil.AddressPubKeyHash: 3587 result.IsScript = btcjson.Bool(false) 3588 result.IsWitness = btcjson.Bool(false) 3589 3590 case *palcutil.AddressScriptHash: 3591 result.IsScript = btcjson.Bool(true) 3592 result.IsWitness = btcjson.Bool(false) 3593 3594 case *palcutil.AddressPubKey: 3595 result.IsScript = btcjson.Bool(false) 3596 result.IsWitness = btcjson.Bool(false) 3597 3598 case *palcutil.AddressWitnessPubKeyHash: 3599 result.IsScript = btcjson.Bool(false) 3600 result.IsWitness = btcjson.Bool(true) 3601 result.WitnessVersion = btcjson.Int32(int32(addr.WitnessVersion())) 3602 result.WitnessProgram = btcjson.String(hex.EncodeToString(addr.WitnessProgram())) 3603 3604 case *palcutil.AddressWitnessScriptHash: 3605 result.IsScript = btcjson.Bool(true) 3606 result.IsWitness = btcjson.Bool(true) 3607 result.WitnessVersion = btcjson.Int32(int32(addr.WitnessVersion())) 3608 result.WitnessProgram = btcjson.String(hex.EncodeToString(addr.WitnessProgram())) 3609 3610 default: 3611 // Handle the case when a new Address is supported by palcutil, but none 3612 // of the cases were matched in the switch block. The current behaviour 3613 // is to do nothing, and only populate the Address and IsValid fields. 3614 } 3615 3616 result.Address = addr.EncodeAddress() 3617 result.IsValid = true 3618 3619 return result, nil 3620 } 3621 3622 func verifyChain(s *rpcServer, level, depth int32) error { 3623 best := s.cfg.Chain.BestSnapshot() 3624 finishHeight := best.Height - depth 3625 if finishHeight < 0 { 3626 finishHeight = 0 3627 } 3628 rpcsLog.Infof("Verifying chain for %d blocks at level %d", 3629 best.Height-finishHeight, level) 3630 3631 for height := best.Height; height > finishHeight; height-- { 3632 // Level 0 just looks up the block. 3633 block, err := s.cfg.Chain.BlockByHeight(height) 3634 if err != nil { 3635 rpcsLog.Errorf("Verify is unable to fetch block at "+ 3636 "height %d: %v", height, err) 3637 return err 3638 } 3639 3640 // Level 1 does basic chain sanity checks. 3641 if level > 0 { 3642 err := blockchain.CheckBlockSanity(block, 3643 s.cfg.ChainParams.PowLimit, s.cfg.TimeSource) 3644 if err != nil { 3645 rpcsLog.Errorf("Verify is unable to validate "+ 3646 "block at hash %v height %d: %v", 3647 block.Hash(), height, err) 3648 return err 3649 } 3650 } 3651 } 3652 rpcsLog.Infof("Chain verify completed successfully") 3653 3654 return nil 3655 } 3656 3657 // handleVerifyChain implements the verifychain command. 3658 func handleVerifyChain(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3659 c := cmd.(*btcjson.VerifyChainCmd) 3660 3661 var checkLevel, checkDepth int32 3662 if c.CheckLevel != nil { 3663 checkLevel = *c.CheckLevel 3664 } 3665 if c.CheckDepth != nil { 3666 checkDepth = *c.CheckDepth 3667 } 3668 3669 err := verifyChain(s, checkLevel, checkDepth) 3670 return err == nil, nil 3671 } 3672 3673 // handleVerifyMessage implements the verifymessage command. 3674 func handleVerifyMessage(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3675 c := cmd.(*btcjson.VerifyMessageCmd) 3676 3677 // Decode the provided address. 3678 params := s.cfg.ChainParams 3679 addr, err := palcutil.DecodeAddress(c.Address, params) 3680 if err != nil { 3681 return nil, &btcjson.RPCError{ 3682 Code: btcjson.ErrRPCInvalidAddressOrKey, 3683 Message: "Invalid address or key: " + err.Error(), 3684 } 3685 } 3686 3687 // Only P2PKH addresses are valid for signing. 3688 if _, ok := addr.(*palcutil.AddressPubKeyHash); !ok { 3689 return nil, &btcjson.RPCError{ 3690 Code: btcjson.ErrRPCType, 3691 Message: "Address is not a pay-to-pubkey-hash address", 3692 } 3693 } 3694 3695 // Decode base64 signature. 3696 sig, err := base64.StdEncoding.DecodeString(c.Signature) 3697 if err != nil { 3698 return nil, &btcjson.RPCError{ 3699 Code: btcjson.ErrRPCParse.Code, 3700 Message: "Malformed base64 encoding: " + err.Error(), 3701 } 3702 } 3703 3704 // Validate the signature - this just shows that it was valid at all. 3705 // we will compare it with the key next. 3706 var buf bytes.Buffer 3707 wire.WriteVarString(&buf, 0, messageSignatureHeader) 3708 wire.WriteVarString(&buf, 0, c.Message) 3709 expectedMessageHash := chainhash.DoubleHashB(buf.Bytes()) 3710 pk, wasCompressed, err := btcec.RecoverCompact(btcec.S256(), sig, 3711 expectedMessageHash) 3712 if err != nil { 3713 // Mirror Bitcoin Core behavior, which treats error in 3714 // RecoverCompact as invalid signature. 3715 return false, nil 3716 } 3717 3718 // Reconstruct the pubkey hash. 3719 var serializedPK []byte 3720 if wasCompressed { 3721 serializedPK = pk.SerializeCompressed() 3722 } else { 3723 serializedPK = pk.SerializeUncompressed() 3724 } 3725 address, err := palcutil.NewAddressPubKey(serializedPK, params) 3726 if err != nil { 3727 // Again mirror Bitcoin Core behavior, which treats error in public key 3728 // reconstruction as invalid signature. 3729 return false, nil 3730 } 3731 3732 // Return boolean if addresses match. 3733 return address.EncodeAddress() == c.Address, nil 3734 } 3735 3736 // handleVersion implements the version command. 3737 // 3738 // NOTE: This is a btcsuite extension ported from github.com/decred/dcrd. 3739 func handleVersion(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { 3740 result := map[string]btcjson.VersionResult{ 3741 "btcdjsonrpcapi": { 3742 VersionString: jsonrpcSemverString, 3743 Major: jsonrpcSemverMajor, 3744 Minor: jsonrpcSemverMinor, 3745 Patch: jsonrpcSemverPatch, 3746 }, 3747 } 3748 return result, nil 3749 } 3750 3751 // rpcServer provides a concurrent safe RPC server to a chain server. 3752 type rpcServer struct { 3753 started int32 3754 shutdown int32 3755 cfg rpcserverConfig 3756 authsha [sha256.Size]byte 3757 limitauthsha [sha256.Size]byte 3758 ntfnMgr *wsNotificationManager 3759 numClients int32 3760 statusLines map[int]string 3761 statusLock sync.RWMutex 3762 wg sync.WaitGroup 3763 gbtWorkState *gbtWorkState 3764 helpCacher *helpCacher 3765 requestProcessShutdown chan struct{} 3766 quit chan int 3767 } 3768 3769 // httpStatusLine returns a response Status-Line (RFC 2616 Section 6.1) 3770 // for the given request and response status code. This function was lifted and 3771 // adapted from the standard library HTTP server code since it's not exported. 3772 func (s *rpcServer) httpStatusLine(req *http.Request, code int) string { 3773 // Fast path: 3774 key := code 3775 proto11 := req.ProtoAtLeast(1, 1) 3776 if !proto11 { 3777 key = -key 3778 } 3779 s.statusLock.RLock() 3780 line, ok := s.statusLines[key] 3781 s.statusLock.RUnlock() 3782 if ok { 3783 return line 3784 } 3785 3786 // Slow path: 3787 proto := "HTTP/1.0" 3788 if proto11 { 3789 proto = "HTTP/1.1" 3790 } 3791 codeStr := strconv.Itoa(code) 3792 text := http.StatusText(code) 3793 if text != "" { 3794 line = proto + " " + codeStr + " " + text + "\r\n" 3795 s.statusLock.Lock() 3796 s.statusLines[key] = line 3797 s.statusLock.Unlock() 3798 } else { 3799 text = "status code " + codeStr 3800 line = proto + " " + codeStr + " " + text + "\r\n" 3801 } 3802 3803 return line 3804 } 3805 3806 // writeHTTPResponseHeaders writes the necessary response headers prior to 3807 // writing an HTTP body given a request to use for protocol negotiation, headers 3808 // to write, a status code, and a writer. 3809 func (s *rpcServer) writeHTTPResponseHeaders(req *http.Request, headers http.Header, code int, w io.Writer) error { 3810 _, err := io.WriteString(w, s.httpStatusLine(req, code)) 3811 if err != nil { 3812 return err 3813 } 3814 3815 err = headers.Write(w) 3816 if err != nil { 3817 return err 3818 } 3819 3820 _, err = io.WriteString(w, "\r\n") 3821 return err 3822 } 3823 3824 // Stop is used by server.go to stop the rpc listener. 3825 func (s *rpcServer) Stop() error { 3826 if atomic.AddInt32(&s.shutdown, 1) != 1 { 3827 rpcsLog.Infof("RPC server is already in the process of shutting down") 3828 return nil 3829 } 3830 rpcsLog.Warnf("RPC server shutting down") 3831 for _, listener := range s.cfg.Listeners { 3832 err := listener.Close() 3833 if err != nil { 3834 rpcsLog.Errorf("Problem shutting down rpc: %v", err) 3835 return err 3836 } 3837 } 3838 s.ntfnMgr.Shutdown() 3839 s.ntfnMgr.WaitForShutdown() 3840 close(s.quit) 3841 s.wg.Wait() 3842 rpcsLog.Infof("RPC server shutdown complete") 3843 return nil 3844 } 3845 3846 // RequestedProcessShutdown returns a channel that is sent to when an authorized 3847 // RPC client requests the process to shutdown. If the request can not be read 3848 // immediately, it is dropped. 3849 func (s *rpcServer) RequestedProcessShutdown() <-chan struct{} { 3850 return s.requestProcessShutdown 3851 } 3852 3853 // NotifyNewTransactions notifies both websocket and getblocktemplate long 3854 // poll clients of the passed transactions. This function should be called 3855 // whenever new transactions are added to the mempool. 3856 func (s *rpcServer) NotifyNewTransactions(txns []*mempool.TxDesc) { 3857 for _, txD := range txns { 3858 // Notify websocket clients about mempool transactions. 3859 s.ntfnMgr.NotifyMempoolTx(txD.Tx, true) 3860 3861 // Potentially notify any getblocktemplate long poll clients 3862 // about stale block templates due to the new transaction. 3863 s.gbtWorkState.NotifyMempoolTx(s.cfg.TxMemPool.LastUpdated()) 3864 } 3865 } 3866 3867 // limitConnections responds with a 503 service unavailable and returns true if 3868 // adding another client would exceed the maximum allow RPC clients. 3869 // 3870 // This function is safe for concurrent access. 3871 func (s *rpcServer) limitConnections(w http.ResponseWriter, remoteAddr string) bool { 3872 if int(atomic.LoadInt32(&s.numClients)+1) > cfg.RPCMaxClients { 3873 rpcsLog.Infof("Max RPC clients exceeded [%d] - "+ 3874 "disconnecting client %s", cfg.RPCMaxClients, 3875 remoteAddr) 3876 http.Error(w, "503 Too busy. Try again later.", 3877 http.StatusServiceUnavailable) 3878 return true 3879 } 3880 return false 3881 } 3882 3883 // incrementClients adds one to the number of connected RPC clients. Note 3884 // this only applies to standard clients. Websocket clients have their own 3885 // limits and are tracked separately. 3886 // 3887 // This function is safe for concurrent access. 3888 func (s *rpcServer) incrementClients() { 3889 atomic.AddInt32(&s.numClients, 1) 3890 } 3891 3892 // decrementClients subtracts one from the number of connected RPC clients. 3893 // Note this only applies to standard clients. Websocket clients have their own 3894 // limits and are tracked separately. 3895 // 3896 // This function is safe for concurrent access. 3897 func (s *rpcServer) decrementClients() { 3898 atomic.AddInt32(&s.numClients, -1) 3899 } 3900 3901 // checkAuth checks the HTTP Basic authentication supplied by a wallet 3902 // or RPC client in the HTTP request r. If the supplied authentication 3903 // does not match the username and password expected, a non-nil error is 3904 // returned. 3905 // 3906 // This check is time-constant. 3907 // 3908 // The first bool return value signifies auth success (true if successful) and 3909 // the second bool return value specifies whether the user can change the state 3910 // of the server (true) or whether the user is limited (false). The second is 3911 // always false if the first is. 3912 func (s *rpcServer) checkAuth(r *http.Request, require bool) (bool, bool, error) { 3913 authhdr := r.Header["Authorization"] 3914 if len(authhdr) <= 0 { 3915 if require { 3916 rpcsLog.Warnf("RPC authentication failure from %s", 3917 r.RemoteAddr) 3918 return false, false, errors.New("auth failure") 3919 } 3920 3921 return false, false, nil 3922 } 3923 3924 authsha := sha256.Sum256([]byte(authhdr[0])) 3925 3926 // Check for limited auth first as in environments with limited users, those 3927 // are probably expected to have a higher volume of calls 3928 limitcmp := subtle.ConstantTimeCompare(authsha[:], s.limitauthsha[:]) 3929 if limitcmp == 1 { 3930 return true, false, nil 3931 } 3932 3933 // Check for admin-level auth 3934 cmp := subtle.ConstantTimeCompare(authsha[:], s.authsha[:]) 3935 if cmp == 1 { 3936 return true, true, nil 3937 } 3938 3939 // Request's auth doesn't match either user 3940 rpcsLog.Warnf("RPC authentication failure from %s", r.RemoteAddr) 3941 return false, false, errors.New("auth failure") 3942 } 3943 3944 // parsedRPCCmd represents a JSON-RPC request object that has been parsed into 3945 // a known concrete command along with any error that might have happened while 3946 // parsing it. 3947 type parsedRPCCmd struct { 3948 jsonrpc btcjson.RPCVersion 3949 id interface{} 3950 method string 3951 cmd interface{} 3952 err *btcjson.RPCError 3953 } 3954 3955 // standardCmdResult checks that a parsed command is a standard Bitcoin JSON-RPC 3956 // command and runs the appropriate handler to reply to the command. Any 3957 // commands which are not recognized or not implemented will return an error 3958 // suitable for use in replies. 3959 func (s *rpcServer) standardCmdResult(cmd *parsedRPCCmd, closeChan <-chan struct{}) (interface{}, error) { 3960 handler, ok := rpcHandlers[cmd.method] 3961 if ok { 3962 goto handled 3963 } 3964 _, ok = rpcAskWallet[cmd.method] 3965 if ok { 3966 handler = handleAskWallet 3967 goto handled 3968 } 3969 _, ok = rpcUnimplemented[cmd.method] 3970 if ok { 3971 handler = handleUnimplemented 3972 goto handled 3973 } 3974 return nil, btcjson.ErrRPCMethodNotFound 3975 handled: 3976 3977 return handler(s, cmd.cmd, closeChan) 3978 } 3979 3980 // parseCmd parses a JSON-RPC request object into known concrete command. The 3981 // err field of the returned parsedRPCCmd struct will contain an RPC error that 3982 // is suitable for use in replies if the command is invalid in some way such as 3983 // an unregistered command or invalid parameters. 3984 func parseCmd(request *btcjson.Request) *parsedRPCCmd { 3985 parsedCmd := parsedRPCCmd{ 3986 jsonrpc: request.Jsonrpc, 3987 id: request.ID, 3988 method: request.Method, 3989 } 3990 3991 cmd, err := btcjson.UnmarshalCmd(request) 3992 if err != nil { 3993 // When the error is because the method is not registered, 3994 // produce a method not found RPC error. 3995 if jerr, ok := err.(btcjson.Error); ok && 3996 jerr.ErrorCode == btcjson.ErrUnregisteredMethod { 3997 3998 parsedCmd.err = btcjson.ErrRPCMethodNotFound 3999 return &parsedCmd 4000 } 4001 4002 // Otherwise, some type of invalid parameters is the 4003 // cause, so produce the equivalent RPC error. 4004 parsedCmd.err = btcjson.NewRPCError( 4005 btcjson.ErrRPCInvalidParams.Code, err.Error()) 4006 return &parsedCmd 4007 } 4008 4009 parsedCmd.cmd = cmd 4010 return &parsedCmd 4011 } 4012 4013 // createMarshalledReply returns a new marshalled JSON-RPC response given the 4014 // passed parameters. It will automatically convert errors that are not of 4015 // the type *btcjson.RPCError to the appropriate type as needed. 4016 func createMarshalledReply(rpcVersion btcjson.RPCVersion, id interface{}, result interface{}, replyErr error) ([]byte, error) { 4017 var jsonErr *btcjson.RPCError 4018 if replyErr != nil { 4019 if jErr, ok := replyErr.(*btcjson.RPCError); ok { 4020 jsonErr = jErr 4021 } else { 4022 jsonErr = internalRPCError(replyErr.Error(), "") 4023 } 4024 } 4025 4026 return btcjson.MarshalResponse(rpcVersion, id, result, jsonErr) 4027 } 4028 4029 // processRequest determines the incoming request type (single or batched), 4030 // parses it and returns a marshalled response. 4031 func (s *rpcServer) processRequest(request *btcjson.Request, isAdmin bool, closeChan <-chan struct{}) []byte { 4032 var result interface{} 4033 var err error 4034 var jsonErr *btcjson.RPCError 4035 4036 if !isAdmin { 4037 if _, ok := rpcLimited[request.Method]; !ok { 4038 jsonErr = internalRPCError("limited user not "+ 4039 "authorized for this method", "") 4040 } 4041 } 4042 4043 if jsonErr == nil { 4044 if request.Method == "" || request.Params == nil { 4045 jsonErr = &btcjson.RPCError{ 4046 Code: btcjson.ErrRPCInvalidRequest.Code, 4047 Message: "Invalid request: malformed", 4048 } 4049 msg, err := createMarshalledReply(request.Jsonrpc, request.ID, result, jsonErr) 4050 if err != nil { 4051 rpcsLog.Errorf("Failed to marshal reply: %v", err) 4052 return nil 4053 } 4054 return msg 4055 } 4056 4057 // Valid requests with no ID (notifications) must not have a response 4058 // per the JSON-RPC spec. 4059 if request.ID == nil { 4060 return nil 4061 } 4062 4063 // Attempt to parse the JSON-RPC request into a known 4064 // concrete command. 4065 parsedCmd := parseCmd(request) 4066 if parsedCmd.err != nil { 4067 jsonErr = parsedCmd.err 4068 } else { 4069 result, err = s.standardCmdResult(parsedCmd, 4070 closeChan) 4071 if err != nil { 4072 if rpcErr, ok := err.(*btcjson.RPCError); ok { 4073 jsonErr = rpcErr 4074 } else { 4075 jsonErr = &btcjson.RPCError{ 4076 Code: btcjson.ErrRPCInvalidRequest.Code, 4077 Message: "Invalid request: malformed", 4078 } 4079 } 4080 } 4081 } 4082 } 4083 4084 // Marshal the response. 4085 msg, err := createMarshalledReply(request.Jsonrpc, request.ID, result, jsonErr) 4086 if err != nil { 4087 rpcsLog.Errorf("Failed to marshal reply: %v", err) 4088 return nil 4089 } 4090 return msg 4091 } 4092 4093 // jsonRPCRead handles reading and responding to RPC messages. 4094 func (s *rpcServer) jsonRPCRead(w http.ResponseWriter, r *http.Request, isAdmin bool) { 4095 if atomic.LoadInt32(&s.shutdown) != 0 { 4096 return 4097 } 4098 4099 // Read and close the JSON-RPC request body from the caller. 4100 body, err := ioutil.ReadAll(r.Body) 4101 r.Body.Close() 4102 if err != nil { 4103 errCode := http.StatusBadRequest 4104 http.Error(w, fmt.Sprintf("%d error reading JSON message: %v", 4105 errCode, err), errCode) 4106 return 4107 } 4108 4109 // Unfortunately, the http server doesn't provide the ability to 4110 // change the read deadline for the new connection and having one breaks 4111 // long polling. However, not having a read deadline on the initial 4112 // connection would mean clients can connect and idle forever. Thus, 4113 // hijack the connecton from the HTTP server, clear the read deadline, 4114 // and handle writing the response manually. 4115 hj, ok := w.(http.Hijacker) 4116 if !ok { 4117 errMsg := "webserver doesn't support hijacking" 4118 rpcsLog.Warnf(errMsg) 4119 errCode := http.StatusInternalServerError 4120 http.Error(w, strconv.Itoa(errCode)+" "+errMsg, errCode) 4121 return 4122 } 4123 conn, buf, err := hj.Hijack() 4124 if err != nil { 4125 rpcsLog.Warnf("Failed to hijack HTTP connection: %v", err) 4126 errCode := http.StatusInternalServerError 4127 http.Error(w, strconv.Itoa(errCode)+" "+err.Error(), errCode) 4128 return 4129 } 4130 defer conn.Close() 4131 defer buf.Flush() 4132 conn.SetReadDeadline(timeZeroVal) 4133 4134 // Attempt to parse the raw body into a JSON-RPC request. 4135 // Setup a close notifier. Since the connection is hijacked, 4136 // the CloseNotifer on the ResponseWriter is not available. 4137 closeChan := make(chan struct{}, 1) 4138 go func() { 4139 _, err = conn.Read(make([]byte, 1)) 4140 if err != nil { 4141 close(closeChan) 4142 } 4143 }() 4144 4145 var results []json.RawMessage 4146 var batchSize int 4147 var batchedRequest bool 4148 4149 // Determine request type 4150 if bytes.HasPrefix(body, batchedRequestPrefix) { 4151 batchedRequest = true 4152 } 4153 4154 // Process a single request 4155 if !batchedRequest { 4156 var req btcjson.Request 4157 var resp json.RawMessage 4158 err = json.Unmarshal(body, &req) 4159 if err != nil { 4160 jsonErr := &btcjson.RPCError{ 4161 Code: btcjson.ErrRPCParse.Code, 4162 Message: fmt.Sprintf("Failed to parse request: %v", 4163 err), 4164 } 4165 resp, err = btcjson.MarshalResponse(btcjson.RpcVersion1, nil, nil, jsonErr) 4166 if err != nil { 4167 rpcsLog.Errorf("Failed to create reply: %v", err) 4168 } 4169 } 4170 4171 if err == nil { 4172 // The JSON-RPC 1.0 spec defines that notifications must have their "id" 4173 // set to null and states that notifications do not have a response. 4174 // 4175 // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and 4176 // without an "id" member. The specification states that notifications 4177 // must not be responded to. JSON-RPC 2.0 permits the null value as a 4178 // valid request id, therefore such requests are not notifications. 4179 // 4180 // Bitcoin Core serves requests with "id":null or even an absent "id", 4181 // and responds to such requests with "id":null in the response. 4182 // 4183 // Palcd does not respond to any request without and "id" or "id":null, 4184 // regardless the indicated JSON-RPC protocol version unless RPC quirks 4185 // are enabled. With RPC quirks enabled, such requests will be responded 4186 // to if the reqeust does not indicate JSON-RPC version. 4187 // 4188 // RPC quirks can be enabled by the user to avoid compatibility issues 4189 // with software relying on Core's behavior. 4190 if req.ID == nil && !(cfg.RPCQuirks && req.Jsonrpc == "") { 4191 return 4192 } 4193 resp = s.processRequest(&req, isAdmin, closeChan) 4194 } 4195 4196 if resp != nil { 4197 results = append(results, resp) 4198 } 4199 } 4200 4201 // Process a batched request 4202 if batchedRequest { 4203 var batchedRequests []interface{} 4204 var resp json.RawMessage 4205 err = json.Unmarshal(body, &batchedRequests) 4206 if err != nil { 4207 jsonErr := &btcjson.RPCError{ 4208 Code: btcjson.ErrRPCParse.Code, 4209 Message: fmt.Sprintf("Failed to parse request: %v", 4210 err), 4211 } 4212 resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) 4213 if err != nil { 4214 rpcsLog.Errorf("Failed to create reply: %v", err) 4215 } 4216 4217 if resp != nil { 4218 results = append(results, resp) 4219 } 4220 } 4221 4222 if err == nil { 4223 // Response with an empty batch error if the batch size is zero 4224 if len(batchedRequests) == 0 { 4225 jsonErr := &btcjson.RPCError{ 4226 Code: btcjson.ErrRPCInvalidRequest.Code, 4227 Message: "Invalid request: empty batch", 4228 } 4229 resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) 4230 if err != nil { 4231 rpcsLog.Errorf("Failed to marshal reply: %v", err) 4232 } 4233 4234 if resp != nil { 4235 results = append(results, resp) 4236 } 4237 } 4238 4239 // Process each batch entry individually 4240 if len(batchedRequests) > 0 { 4241 batchSize = len(batchedRequests) 4242 4243 for _, entry := range batchedRequests { 4244 var reqBytes []byte 4245 reqBytes, err = json.Marshal(entry) 4246 if err != nil { 4247 jsonErr := &btcjson.RPCError{ 4248 Code: btcjson.ErrRPCInvalidRequest.Code, 4249 Message: fmt.Sprintf("Invalid request: %v", 4250 err), 4251 } 4252 resp, err = btcjson.MarshalResponse(btcjson.RpcVersion2, nil, nil, jsonErr) 4253 if err != nil { 4254 rpcsLog.Errorf("Failed to create reply: %v", err) 4255 } 4256 4257 if resp != nil { 4258 results = append(results, resp) 4259 } 4260 continue 4261 } 4262 4263 var req btcjson.Request 4264 err := json.Unmarshal(reqBytes, &req) 4265 if err != nil { 4266 jsonErr := &btcjson.RPCError{ 4267 Code: btcjson.ErrRPCInvalidRequest.Code, 4268 Message: fmt.Sprintf("Invalid request: %v", 4269 err), 4270 } 4271 resp, err = btcjson.MarshalResponse("", nil, nil, jsonErr) 4272 if err != nil { 4273 rpcsLog.Errorf("Failed to create reply: %v", err) 4274 } 4275 4276 if resp != nil { 4277 results = append(results, resp) 4278 } 4279 continue 4280 } 4281 4282 resp = s.processRequest(&req, isAdmin, closeChan) 4283 if resp != nil { 4284 results = append(results, resp) 4285 } 4286 } 4287 } 4288 } 4289 } 4290 4291 var msg = []byte{} 4292 if batchedRequest && batchSize > 0 { 4293 if len(results) > 0 { 4294 // Form the batched response json 4295 var buffer bytes.Buffer 4296 buffer.WriteByte('[') 4297 for idx, reply := range results { 4298 if idx == len(results)-1 { 4299 buffer.Write(reply) 4300 buffer.WriteByte(']') 4301 break 4302 } 4303 buffer.Write(reply) 4304 buffer.WriteByte(',') 4305 } 4306 msg = buffer.Bytes() 4307 } 4308 } 4309 4310 if !batchedRequest || batchSize == 0 { 4311 // Respond with the first results entry for single requests 4312 if len(results) > 0 { 4313 msg = results[0] 4314 } 4315 } 4316 4317 // Write the response. 4318 err = s.writeHTTPResponseHeaders(r, w.Header(), http.StatusOK, buf) 4319 if err != nil { 4320 rpcsLog.Error(err) 4321 return 4322 } 4323 if _, err := buf.Write(msg); err != nil { 4324 rpcsLog.Errorf("Failed to write marshalled reply: %v", err) 4325 } 4326 4327 // Terminate with newline to maintain compatibility with Bitcoin Core. 4328 if err := buf.WriteByte('\n'); err != nil { 4329 rpcsLog.Errorf("Failed to append terminating newline to reply: %v", err) 4330 } 4331 } 4332 4333 // jsonAuthFail sends a message back to the client if the http auth is rejected. 4334 func jsonAuthFail(w http.ResponseWriter) { 4335 w.Header().Add("WWW-Authenticate", `Basic realm="btcd RPC"`) 4336 http.Error(w, "401 Unauthorized.", http.StatusUnauthorized) 4337 } 4338 4339 // Start is used by server.go to start the rpc listener. 4340 func (s *rpcServer) Start() { 4341 if atomic.AddInt32(&s.started, 1) != 1 { 4342 return 4343 } 4344 4345 rpcsLog.Trace("Starting RPC server") 4346 rpcServeMux := http.NewServeMux() 4347 httpServer := &http.Server{ 4348 Handler: rpcServeMux, 4349 4350 // Timeout connections which don't complete the initial 4351 // handshake within the allowed timeframe. 4352 ReadTimeout: time.Second * rpcAuthTimeoutSeconds, 4353 } 4354 rpcServeMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 4355 w.Header().Set("Connection", "close") 4356 w.Header().Set("Content-Type", "application/json") 4357 r.Close = true 4358 4359 // Limit the number of connections to max allowed. 4360 if s.limitConnections(w, r.RemoteAddr) { 4361 return 4362 } 4363 4364 // Keep track of the number of connected clients. 4365 s.incrementClients() 4366 defer s.decrementClients() 4367 _, isAdmin, err := s.checkAuth(r, true) 4368 if err != nil { 4369 jsonAuthFail(w) 4370 return 4371 } 4372 4373 // Read and respond to the request. 4374 s.jsonRPCRead(w, r, isAdmin) 4375 }) 4376 4377 // Websocket endpoint. 4378 rpcServeMux.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) { 4379 authenticated, isAdmin, err := s.checkAuth(r, false) 4380 if err != nil { 4381 jsonAuthFail(w) 4382 return 4383 } 4384 4385 // Attempt to upgrade the connection to a websocket connection 4386 // using the default size for read/write buffers. 4387 ws, err := websocket.Upgrade(w, r, nil, 0, 0) 4388 if err != nil { 4389 if _, ok := err.(websocket.HandshakeError); !ok { 4390 rpcsLog.Errorf("Unexpected websocket error: %v", 4391 err) 4392 } 4393 http.Error(w, "400 Bad Request.", http.StatusBadRequest) 4394 return 4395 } 4396 s.WebsocketHandler(ws, r.RemoteAddr, authenticated, isAdmin) 4397 }) 4398 4399 for _, listener := range s.cfg.Listeners { 4400 s.wg.Add(1) 4401 go func(listener net.Listener) { 4402 rpcsLog.Infof("RPC server listening on %s", listener.Addr()) 4403 httpServer.Serve(listener) 4404 rpcsLog.Tracef("RPC listener done for %s", listener.Addr()) 4405 s.wg.Done() 4406 }(listener) 4407 } 4408 4409 s.ntfnMgr.Start() 4410 } 4411 4412 // genCertPair generates a key/cert pair to the paths provided. 4413 func genCertPair(certFile, keyFile string) error { 4414 rpcsLog.Infof("Generating TLS certificates...") 4415 4416 org := "btcd autogenerated cert" 4417 validUntil := time.Now().Add(10 * 365 * 24 * time.Hour) 4418 cert, key, err := palcutil.NewTLSCertPair(org, validUntil, nil) 4419 if err != nil { 4420 return err 4421 } 4422 4423 // Write cert and key files. 4424 if err = ioutil.WriteFile(certFile, cert, 0666); err != nil { 4425 return err 4426 } 4427 if err = ioutil.WriteFile(keyFile, key, 0600); err != nil { 4428 os.Remove(certFile) 4429 return err 4430 } 4431 4432 rpcsLog.Infof("Done generating TLS certificates") 4433 return nil 4434 } 4435 4436 // rpcserverPeer represents a peer for use with the RPC server. 4437 // 4438 // The interface contract requires that all of these methods are safe for 4439 // concurrent access. 4440 type rpcserverPeer interface { 4441 // ToPeer returns the underlying peer instance. 4442 ToPeer() *peer.Peer 4443 4444 // IsTxRelayDisabled returns whether or not the peer has disabled 4445 // transaction relay. 4446 IsTxRelayDisabled() bool 4447 4448 // BanScore returns the current integer value that represents how close 4449 // the peer is to being banned. 4450 BanScore() uint32 4451 4452 // FeeFilter returns the requested current minimum fee rate for which 4453 // transactions should be announced. 4454 FeeFilter() int64 4455 } 4456 4457 // rpcserverConnManager represents a connection manager for use with the RPC 4458 // server. 4459 // 4460 // The interface contract requires that all of these methods are safe for 4461 // concurrent access. 4462 type rpcserverConnManager interface { 4463 // Connect adds the provided address as a new outbound peer. The 4464 // permanent flag indicates whether or not to make the peer persistent 4465 // and reconnect if the connection is lost. Attempting to connect to an 4466 // already existing peer will return an error. 4467 Connect(addr string, permanent bool) error 4468 4469 // RemoveByID removes the peer associated with the provided id from the 4470 // list of persistent peers. Attempting to remove an id that does not 4471 // exist will return an error. 4472 RemoveByID(id int32) error 4473 4474 // RemoveByAddr removes the peer associated with the provided address 4475 // from the list of persistent peers. Attempting to remove an address 4476 // that does not exist will return an error. 4477 RemoveByAddr(addr string) error 4478 4479 // DisconnectByID disconnects the peer associated with the provided id. 4480 // This applies to both inbound and outbound peers. Attempting to 4481 // remove an id that does not exist will return an error. 4482 DisconnectByID(id int32) error 4483 4484 // DisconnectByAddr disconnects the peer associated with the provided 4485 // address. This applies to both inbound and outbound peers. 4486 // Attempting to remove an address that does not exist will return an 4487 // error. 4488 DisconnectByAddr(addr string) error 4489 4490 // ConnectedCount returns the number of currently connected peers. 4491 ConnectedCount() int32 4492 4493 // NetTotals returns the sum of all bytes received and sent across the 4494 // network for all peers. 4495 NetTotals() (uint64, uint64) 4496 4497 // ConnectedPeers returns an array consisting of all connected peers. 4498 ConnectedPeers() []rpcserverPeer 4499 4500 // PersistentPeers returns an array consisting of all the persistent 4501 // peers. 4502 PersistentPeers() []rpcserverPeer 4503 4504 // BroadcastMessage sends the provided message to all currently 4505 // connected peers. 4506 BroadcastMessage(msg wire.Message) 4507 4508 // AddRebroadcastInventory adds the provided inventory to the list of 4509 // inventories to be rebroadcast at random intervals until they show up 4510 // in a block. 4511 AddRebroadcastInventory(iv *wire.InvVect, data interface{}) 4512 4513 // RelayTransactions generates and relays inventory vectors for all of 4514 // the passed transactions to all connected peers. 4515 RelayTransactions(txns []*mempool.TxDesc) 4516 4517 // NodeAddresses returns an array consisting node addresses which can 4518 // potentially be used to find new nodes in the network. 4519 NodeAddresses() []*wire.NetAddress 4520 } 4521 4522 // rpcserverSyncManager represents a sync manager for use with the RPC server. 4523 // 4524 // The interface contract requires that all of these methods are safe for 4525 // concurrent access. 4526 type rpcserverSyncManager interface { 4527 // IsCurrent returns whether or not the sync manager believes the chain 4528 // is current as compared to the rest of the network. 4529 IsCurrent() bool 4530 4531 // SubmitBlock submits the provided block to the network after 4532 // processing it locally. 4533 SubmitBlock(block *palcutil.Block, flags blockchain.BehaviorFlags) (bool, error) 4534 4535 // Pause pauses the sync manager until the returned channel is closed. 4536 Pause() chan<- struct{} 4537 4538 // SyncPeerID returns the ID of the peer that is currently the peer being 4539 // used to sync from or 0 if there is none. 4540 SyncPeerID() int32 4541 4542 // LocateHeaders returns the headers of the blocks after the first known 4543 // block in the provided locators until the provided stop hash or the 4544 // current tip is reached, up to a max of wire.MaxBlockHeadersPerMsg 4545 // hashes. 4546 LocateHeaders(locators []*chainhash.Hash, hashStop *chainhash.Hash) []wire.BlockHeader 4547 } 4548 4549 // rpcserverConfig is a descriptor containing the RPC server configuration. 4550 type rpcserverConfig struct { 4551 // Listeners defines a slice of listeners for which the RPC server will 4552 // take ownership of and accept connections. Since the RPC server takes 4553 // ownership of these listeners, they will be closed when the RPC server 4554 // is stopped. 4555 Listeners []net.Listener 4556 4557 // StartupTime is the unix timestamp for when the server that is hosting 4558 // the RPC server started. 4559 StartupTime int64 4560 4561 // ConnMgr defines the connection manager for the RPC server to use. It 4562 // provides the RPC server with a means to do things such as add, 4563 // remove, connect, disconnect, and query peers as well as other 4564 // connection-related data and tasks. 4565 ConnMgr rpcserverConnManager 4566 4567 // SyncMgr defines the sync manager for the RPC server to use. 4568 SyncMgr rpcserverSyncManager 4569 4570 // These fields allow the RPC server to interface with the local block 4571 // chain data and state. 4572 TimeSource blockchain.MedianTimeSource 4573 Chain *blockchain.BlockChain 4574 ChainParams *chaincfg.Params 4575 DB database.DB 4576 4577 // TxMemPool defines the transaction memory pool to interact with. 4578 TxMemPool *mempool.TxPool 4579 4580 // These fields allow the RPC server to interface with mining. 4581 // 4582 // Generator produces block templates and the CPUMiner solves them using 4583 // the CPU. CPU mining is typically only useful for test purposes when 4584 // doing regression or simulation testing. 4585 Generator *mining.BlkTmplGenerator 4586 CPUMiner *cpuminer.CPUMiner 4587 4588 // These fields define any optional indexes the RPC server can make use 4589 // of to provide additional data when queried. 4590 TxIndex *indexers.TxIndex 4591 AddrIndex *indexers.AddrIndex 4592 CfIndex *indexers.CfIndex 4593 4594 // The fee estimator keeps track of how long transactions are left in 4595 // the mempool before they are mined into blocks. 4596 FeeEstimator *mempool.FeeEstimator 4597 } 4598 4599 // newRPCServer returns a new instance of the rpcServer struct. 4600 func newRPCServer(config *rpcserverConfig) (*rpcServer, error) { 4601 rpc := rpcServer{ 4602 cfg: *config, 4603 statusLines: make(map[int]string), 4604 gbtWorkState: newGbtWorkState(config.TimeSource), 4605 helpCacher: newHelpCacher(), 4606 requestProcessShutdown: make(chan struct{}), 4607 quit: make(chan int), 4608 } 4609 if cfg.RPCUser != "" && cfg.RPCPass != "" { 4610 login := cfg.RPCUser + ":" + cfg.RPCPass 4611 auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) 4612 rpc.authsha = sha256.Sum256([]byte(auth)) 4613 } 4614 if cfg.RPCLimitUser != "" && cfg.RPCLimitPass != "" { 4615 login := cfg.RPCLimitUser + ":" + cfg.RPCLimitPass 4616 auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login)) 4617 rpc.limitauthsha = sha256.Sum256([]byte(auth)) 4618 } 4619 rpc.ntfnMgr = newWsNotificationManager(&rpc) 4620 rpc.cfg.Chain.Subscribe(rpc.handleBlockchainNotification) 4621 4622 return &rpc, nil 4623 } 4624 4625 // Callback for notifications from blockchain. It notifies clients that are 4626 // long polling for changes or subscribed to websockets notifications. 4627 func (s *rpcServer) handleBlockchainNotification(notification *blockchain.Notification) { 4628 switch notification.Type { 4629 case blockchain.NTBlockAccepted: 4630 block, ok := notification.Data.(*palcutil.Block) 4631 if !ok { 4632 rpcsLog.Warnf("Chain accepted notification is not a block.") 4633 break 4634 } 4635 4636 // Allow any clients performing long polling via the 4637 // getblocktemplate RPC to be notified when the new block causes 4638 // their old block template to become stale. 4639 s.gbtWorkState.NotifyBlockConnected(block.Hash()) 4640 4641 case blockchain.NTBlockConnected: 4642 block, ok := notification.Data.(*palcutil.Block) 4643 if !ok { 4644 rpcsLog.Warnf("Chain connected notification is not a block.") 4645 break 4646 } 4647 4648 // Notify registered websocket clients of incoming block. 4649 s.ntfnMgr.NotifyBlockConnected(block) 4650 4651 case blockchain.NTBlockDisconnected: 4652 block, ok := notification.Data.(*palcutil.Block) 4653 if !ok { 4654 rpcsLog.Warnf("Chain disconnected notification is not a block.") 4655 break 4656 } 4657 4658 // Notify registered websocket clients. 4659 s.ntfnMgr.NotifyBlockDisconnected(block) 4660 } 4661 } 4662 4663 func init() { 4664 rpcHandlers = rpcHandlersBeforeInit 4665 rand.Seed(time.Now().UnixNano()) 4666 }