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