1 package chainrpc
2 3 import (
4 "bytes"
5 "crypto/sha256"
6 "crypto/subtle"
7 "encoding/base64"
8 "encoding/hex"
9 js "encoding/json"
10 "errors"
11 "fmt"
12 "io"
13 "io/ioutil"
14 "math/big"
15 "math/rand"
16 "net"
17 "net/http"
18 "os"
19 "strconv"
20 "strings"
21 "sync"
22 "sync/atomic"
23 "time"
24 25 "github.com/p9c/p9/pkg/qu"
26 27 "github.com/btcsuite/websocket"
28 uberatomic "go.uber.org/atomic"
29 30 "github.com/p9c/p9/pkg/amt"
31 "github.com/p9c/p9/pkg/bits"
32 "github.com/p9c/p9/pkg/block"
33 "github.com/p9c/p9/pkg/btcaddr"
34 "github.com/p9c/p9/pkg/chaincfg"
35 "github.com/p9c/p9/pkg/fork"
36 "github.com/p9c/p9/pod/config"
37 38 "github.com/p9c/p9/cmd/node/active"
39 "github.com/p9c/p9/pkg/blockchain"
40 "github.com/p9c/p9/pkg/btcjson"
41 "github.com/p9c/p9/pkg/chainhash"
42 "github.com/p9c/p9/pkg/database"
43 "github.com/p9c/p9/pkg/indexers"
44 "github.com/p9c/p9/pkg/mempool"
45 "github.com/p9c/p9/pkg/mining"
46 p "github.com/p9c/p9/pkg/peer"
47 "github.com/p9c/p9/pkg/txscript"
48 "github.com/p9c/p9/pkg/util"
49 "github.com/p9c/p9/pkg/wire"
50 )
51 52 const (
53 deserialfail = "Failed to deserialize transaction"
54 blockheightfail = "Failed to obtain block height"
55 )
56 57 type CommandHandler struct {
58 Fn func(*Server, interface{}, qu.C) (interface{}, error)
59 Call chan API
60 Result func() API
61 }
62 63 // GBTWorkState houses state that is used in between multiple RPC invocations to getblocktemplate.
64 type GBTWorkState struct {
65 sync.Mutex
66 LastTxUpdate time.Time
67 LastGenerated time.Time
68 prevHash *chainhash.Hash
69 MinTimestamp time.Time
70 Template *mining.BlockTemplate
71 NotifyMap map[chainhash.Hash]map[int64]qu.C
72 TimeSource blockchain.MedianTimeSource
73 Algo string
74 StateCfg *active.Config
75 Config *config.Config
76 }
77 78 // ParsedRPCCmd represents a JSON-RPC request object that has been parsed into a known concrete command along with any
79 // error that might have happened while parsing it.
80 type ParsedRPCCmd struct {
81 ID interface{}
82 Method string
83 Cmd interface{}
84 Err *btcjson.RPCError
85 }
86 87 // RetrievedTx represents a transaction that was either loaded from the transaction memory pool or from the database.
88 //
89 // When a transaction is loaded from the database, it is loaded with the raw serialized bytes while the mempool has the
90 // fully deserialized structure.
91 //
92 // This structure therefore will have one of the two fields set depending on where is was retrieved from.
93 //
94 // This is mainly done for efficiency to avoid extra serialization steps when possible.
95 type RetrievedTx struct {
96 TxBytes []byte
97 BlkHash *chainhash.Hash // Only set when transaction is in a block.
98 Tx *util.Tx
99 }
100 101 // Server provides a concurrent safe RPC Server to a chain Server.
102 type Server struct {
103 Cfg ServerConfig
104 StateCfg *active.Config
105 Config *config.Config
106 NtfnMgr *WSNtfnMgr
107 StatusLines map[int]string
108 StatusLock sync.RWMutex
109 WG sync.WaitGroup
110 GBTWorkState *GBTWorkState
111 HelpCacher *HelpCacher
112 RequestProcessShutdown qu.C
113 Quit qu.C
114 Started int32
115 Shutdown int32
116 NumClients int32
117 AuthSHA [sha256.Size]byte
118 LimitAuthSHA [sha256.Size]byte
119 StartController, StopController qu.C
120 }
121 122 // ServerConfig is a descriptor containing the RPC Server configuration.
123 type ServerConfig struct {
124 // Cx passes through the context variable for setting up a Server
125 Cfg *config.Config
126 // Listeners defines a slice of listeners for which the RPC Server will take ownership of and accept connections.
127 //
128 // Since the RPC Server takes ownership of these listeners, they will be closed when the RPC Server is stopped.
129 Listeners []net.Listener
130 // StartupTime is the unix timestamp for when the Server that is hosting the RPC Server started.
131 StartupTime int64
132 // ConnMgr defines the connection manager for the RPC Server to use.
133 //
134 // It provides the RPC Server with a means to do things such as add, remove, connect, disconnect, and query peers as
135 // well as other connection-related data and tasks.
136 ConnMgr ServerConnManager
137 // SyncMgr defines the sync manager for the RPC Server to use.
138 SyncMgr ServerSyncManager
139 // These fields allow the RPC Server to interface with the local block chain data and state.
140 TimeSource blockchain.MedianTimeSource
141 Chain *blockchain.BlockChain
142 ChainParams *chaincfg.Params
143 DB database.DB
144 // TxMemPool defines the transaction memory pool to interact with.
145 TxMemPool *mempool.TxPool
146 // These fields allow the RPC Server to interface with mining.
147 //
148 // Generator produces block templates and the CPUMiner solves them using the CPU.
149 //
150 // CPU mining is typically only useful for test purposes when doing regression or simulation testing.
151 // until there was divhash
152 Generator *mining.BlkTmplGenerator
153 // CPUMiner *cpuminer.CPUMiner
154 //
155 // These fields define any optional indexes the RPC Server can make use of to provide additional data when queried.
156 TxIndex *indexers.TxIndex
157 AddrIndex *indexers.AddrIndex
158 CfIndex *indexers.CFIndex
159 // The fee estimator keeps track of how long transactions are left in the mempool before they are mined into blocks.
160 FeeEstimator *mempool.FeeEstimator
161 // Algo sets the algorithm expected from the RPC endpoint. This allows multiple ports to serve multiple types of
162 // miners with one main node per algorithm. Currently 514 for Scrypt and anything else passes for SHA256d.
163 Algo string
164 // CPUMiner *exec.Cmd
165 Hashrate uberatomic.Uint64
166 Quit qu.C
167 StartController, StopController qu.C
168 }
169 170 // ServerConnManager represents a connection manager for use with the RPC Server. The interface contract requires that
171 // all of these methods are safe for concurrent access.
172 type ServerConnManager interface {
173 // Connect adds the provided address as a new outbound peer. The permanent flag indicates whether or not to make the
174 // peer persistent and reconnect if the connection is lost. Attempting to connect to an already existing peer will
175 // return an error.
176 Connect(addr string, permanent bool) error
177 // RemoveByID removes the peer associated with the provided id from the list of persistent peers.
178 //
179 // Attempting to remove an id that does not exist will return an error.
180 RemoveByID(id int32) error
181 // RemoveByAddr removes the peer associated with the provided address from the list of persistent peers.
182 //
183 // Attempting to remove an address that does not exist will return an error.
184 RemoveByAddr(addr string) error
185 // DisconnectByID disconnects the peer associated with the provided id. This applies to both inbound and outbound
186 // peers.
187 //
188 // Attempting to remove an id that does not exist will return an error.
189 DisconnectByID(id int32) error
190 // DisconnectByAddr disconnects the peer associated with the provided address. This applies to both inbound and
191 // outbound peers.
192 //
193 // Attempting to remove an address that does not exist will return an error.
194 DisconnectByAddr(addr string) error
195 // ConnectedCount returns the number of currently connected peers.
196 ConnectedCount() int32
197 // NetTotals returns the sum of all bytes received and sent across the network for all peers.
198 NetTotals() (uint64, uint64)
199 // ConnectedPeers returns an array consisting of all connected peers.
200 ConnectedPeers() []ServerPeer
201 // PersistentPeers returns an array consisting of all the persistent peers.
202 PersistentPeers() []ServerPeer
203 // BroadcastMessage sends the provided message to all currently connected
204 // peers.
205 BroadcastMessage(msg wire.Message)
206 // AddRebroadcastInventory adds the provided inventory to the list of inventories to be rebroadcast at random
207 // intervals until they show up in a block.
208 AddRebroadcastInventory(iv *wire.InvVect, data interface{})
209 // RelayTransactions generates and relays inventory vectors for all of the passed transactions to all connected
210 // peers.
211 RelayTransactions(txns []*mempool.TxDesc)
212 }
213 214 // ServerPeer represents a peer for use with the RPC Server.
215 //
216 // The interface contract requires that all of these methods are safe for concurrent access.
217 type ServerPeer interface {
218 // ToPeer returns the underlying peer instance.
219 ToPeer() *p.Peer
220 // IsTxRelayDisabled returns whether or not the peer has disabled transaction relay.
221 IsTxRelayDisabled() bool
222 // GetBanScore returns the current integer value that represents how close the peer is to being banned.
223 GetBanScore() uint32
224 // GetFeeFilter returns the requested current minimum fee rate for which transactions should be announced.
225 GetFeeFilter() int64
226 }
227 228 // ServerSyncManager represents a sync manager for use with the RPC Server.
229 //
230 // The interface contract requires that all of these methods are safe for concurrent access.
231 type ServerSyncManager interface {
232 // IsCurrent returns whether or not the sync manager believes the chain is current as compared to the rest of the
233 // network.
234 IsCurrent() bool
235 // SubmitBlock submits the provided block to the network after processing it locally.
236 SubmitBlock(block *block.Block, flags blockchain.BehaviorFlags) (
237 bool, error,
238 )
239 // Pause pauses the sync manager until the returned channel is closed.
240 Pause() chan<- struct{}
241 // SyncPeerID returns the ID of the peer that is currently the peer being used to sync from or 0 if there is none.
242 SyncPeerID() int32
243 // LocateHeaders returns the headers of the blocks after the first known block in the provided locators until the
244 // provided stop hash or the current tip is reached, up to a max of wire.MaxBlockHeadersPerMsg hashes.
245 LocateHeaders(
246 locators []*chainhash.Hash, hashStop *chainhash.Hash,
247 ) []wire.BlockHeader
248 }
249 250 // API version constants
251 const (
252 JSONRPCSemverString = "1.3.0"
253 JSONRPCSemverMajor = 1
254 JSONRPCSemverMinor = 3
255 JSONRPCSemverPatch = 0
256 // RPCAuthTimeoutSeconds is the number of seconds a connection to the RPC Server is allowed to stay open without
257 // authenticating before it is closed.
258 RPCAuthTimeoutSeconds = 10
259 // GBTNonceRange is two 32-bit big-endian hexadecimal integers which represent the valid ranges of nonces returned
260 // by the getblocktemplate RPC.
261 GBTNonceRange = "00000000ffffffff"
262 // GBTRegenerateSeconds is the number of seconds that must pass before a new template is generated when the previous
263 // block hash has not changed and there have been changes to the available transactions in the memory pool.
264 GBTRegenerateSeconds = 60
265 // MaxProtocolVersion is the max protocol version the Server supports.
266 MaxProtocolVersion = 70002
267 )
268 269 func getIfc() chan interface{} {
270 return make(chan interface{})
271 }
272 273 var (
274 // ErrRPCNoWallet is an error returned to RPC clients when the provided command is recognized as a wallet command.
275 ErrRPCNoWallet = &btcjson.RPCError{
276 Code: btcjson.ErrRPCNoWallet,
277 Message: "This implementation does not implement wallet commands",
278 }
279 // ErrRPCUnimplemented is an error returned to RPC clients when the provided command is recognized, but not
280 // implemented.
281 ErrRPCUnimplemented = &btcjson.RPCError{
282 Code: btcjson.ErrRPCUnimplemented,
283 Message: "Command unimplemented",
284 }
285 // GBTCapabilities describes additional capabilities returned with a block template generated by the
286 // getblocktemplate RPC.
287 //
288 // It is declared here to avoid the overhead of creating the slice on every invocation for constant data.
289 GBTCapabilities = []string{"proposal"}
290 // GBTCoinbaseAux describes additional data that miners should include in the coinbase signature script.
291 //
292 // It is declared here to avoid the overhead of creating a new object on every invocation for constant data.
293 GBTCoinbaseAux = &btcjson.GetBlockTemplateResultAux{
294 Flags: hex.EncodeToString(
295 BuilderScript(
296 txscript.
297 NewScriptBuilder().
298 AddData([]byte(mining.CoinbaseFlags)),
299 ),
300 ),
301 }
302 // GBTMutableFields are the manipulations the Server allows to be made to block templates generated by the
303 // getblocktemplate RPC.
304 //
305 // It is declared here to avoid the overhead of creating the slice on every invocation for constant data.
306 GBTMutableFields = []string{
307 "time", "transactions/add", "prevblock", "coinbase/append",
308 }
309 310 // RPCAskWallet is list of commands that we recognize, but for which pod has no support because it lacks support for
311 // wallet functionality. For these commands the user should ask a connected instance of the wallet.
312 RPCAskWallet = map[string]CommandHandler{
313 "addmultisigaddress": {},
314 "backupwallet": {},
315 "createencryptedwallet": {},
316 "createmultisig": {},
317 "dumpprivkey": {},
318 "dumpwallet": {},
319 "dropwallethistory": {},
320 "encryptwallet": {},
321 "getaccount": {},
322 "getaccountaddress": {},
323 "getaddressesbyaccount": {},
324 "getbalance": {},
325 "getnewaddress": {},
326 "getrawchangeaddress": {},
327 "getreceivedbyaccount": {},
328 "getreceivedbyaddress": {},
329 "gettransaction": {},
330 "gettxoutsetinfo": {},
331 "getunconfirmedbalance": {},
332 "getwalletinfo": {},
333 "importprivkey": {},
334 "importwallet": {},
335 "keypoolrefill": {},
336 "listaccounts": {},
337 "listaddressgroupings": {},
338 "listlockunspent": {},
339 "listreceivedbyaccount": {},
340 "listreceivedbyaddress": {},
341 "listsinceblock": {},
342 "listtransactions": {},
343 "listunspent": {},
344 "lockunspent": {},
345 "move": {},
346 "sendfrom": {},
347 "sendmany": {},
348 "sendtoaddress": {},
349 "setaccount": {},
350 "settxfee": {},
351 "signmessage": {},
352 "signrawtransaction": {},
353 "walletlock": {},
354 "walletpassphrase": {},
355 "walletpassphrasechange": {},
356 }
357 358 // RPCHandlers maps RPC command strings to appropriate handler functions.
359 //
360 // This is set by init because help references RPCHandlers and thus causes a dependency loop.
361 RPCHandlers map[string]CommandHandler
362 363 // RPCLimited RPCHandlersBeforeInit is
364 //
365 // RPCHandlersBeforeInit = map[string]CommandHandler{
366 // "addnode": {
367 // HandleAddNode, make(chan API), func() API {
368 // return API{
369 // btcjson.AddNodeCmd{},
370 // make(chan AddNodeRes),
371 // }
372 // },
373 // },
374 // "createrawtransaction": {
375 // HandleCreateRawTransaction, make(chan API),
376 // func() API {
377 // return API{btcjson.CreateRawTransactionCmd{},
378 // make(chan CreateRawTransactionRes)}
379 // },
380 // },
381 // // "debuglevel": handleDebugLevel,
382 // "decoderawtransaction": {
383 // HandleDecodeRawTransaction, make(chan API),
384 // func() API {
385 // return API{btcjson.DecodeRawTransactionCmd{},
386 // make(chan DecodeRawTransactionRes)}
387 // },
388 // },
389 // "decodescript": {
390 // HandleDecodeScript, make(chan API),
391 // func() API {
392 // return API{btcjson.DecodeScriptCmd{},
393 // make(chan DecodeScriptRes)}
394 // },
395 // },
396 // "estimatefee": {
397 // HandleEstimateFee, make(chan API),
398 // func() API {
399 // return API{btcjson.EstimateFeeCmd{},
400 // make(chan EstimateFeeRes)}
401 // },
402 // },
403 // "generate": {
404 // HandleGenerate, make(chan API),
405 // func() API { return API{nil, make(chan GenerateRes)} },
406 // },
407 // "getaddednodeinfo": {
408 // HandleGetAddedNodeInfo, make(chan API),
409 // func() API {
410 // return API{btcjson.GetAddedNodeInfoCmd{},
411 // make(chan GetAddedNodeInfoRes)}
412 // },
413 // },
414 // "getbestblock": {
415 // HandleGetBestBlock, make(chan API),
416 // func() API { return API{nil, make(chan GetBestBlockRes)} },
417 // },
418 // "getbestblockhash": {
419 // HandleGetBestBlockHash, make(chan API),
420 // func() API { return API{nil, make(chan GetBestBlockHashRes)} },
421 // },
422 // "getblock": {
423 // HandleGetBlock, make(chan API),
424 // func() API {
425 // return API{btcjson.GetBlockCmd{},
426 // make(chan GetBlockRes)}
427 // },
428 // },
429 // "getblockchaininfo": {
430 // HandleGetBlockChainInfo, make(chan API),
431 // func() API { return API{nil, make(chan GetBlockChainInfoRes)} },
432 // },
433 // "getblockcount": {
434 // HandleGetBlockCount, make(chan API),
435 // func() API { return API{nil, make(chan GetBlockCountRes)} },
436 // },
437 // "getblockhash": {
438 // HandleGetBlockHash, make(chan API),
439 // func() API {
440 // return API{btcjson.GetBlockHashCmd{},
441 // make(chan GetBlockHashRes)}
442 // },
443 // },
444 // "getblockheader": {
445 // HandleGetBlockHeader, make(chan API),
446 // func() API {
447 // return API{btcjson.GetBlockHeaderCmd{},
448 // make(chan GetBlockHeaderRes)}
449 // },
450 // },
451 // "getblocktemplate": {
452 // HandleGetBlockTemplate, make(chan API),
453 // func() API {
454 // return API{btcjson.GetBlockTemplateCmd{},
455 // make(chan GetBlockTemplateRes)}
456 // },
457 // },
458 // "getcfilter": {
459 // HandleGetCFilter, make(chan API),
460 // func() API {
461 // return API{btcjson.GetCFilterCmd{},
462 // make(chan GetCFilterRes)}
463 // },
464 // },
465 // "getcfilterheader": {
466 // HandleGetCFilterHeader, make(chan API),
467 // func() API {
468 // return API{btcjson.GetCFilterHeaderCmd{},
469 // make(chan GetCFilterHeaderRes)}
470 // },
471 // },
472 // "getconnectioncount": {
473 // HandleGetConnectionCount, make(chan API),
474 // func() API { return API{nil, make(chan GetConnectionCountRes)} },
475 // },
476 // "getcurrentnet": {
477 // HandleGetCurrentNet, make(chan API),
478 // func() API { return API{nil, make(chan GetCurrentNetRes)} },
479 // },
480 // "getdifficulty": {
481 // HandleGetDifficulty, make(chan API),
482 // func() API {
483 // return API{btcjson.GetDifficultyCmd{},
484 // make(chan GetDifficultyRes)}
485 // },
486 // },
487 // "getgenerate": {
488 // HandleGetGenerate, make(chan API),
489 // func() API {
490 // return API{btcjson.GetHeadersCmd{},
491 // make(chan GetGenerateRes)}
492 // },
493 // },
494 // "gethashespersec": {
495 // HandleGetHashesPerSec, make(chan API),
496 // func() API { return API{nil, make(chan GetHashesPerSecRes)} },
497 // },
498 // "getheaders": {
499 // HandleGetHeaders, make(chan API),
500 // func() API {
501 // return API{btcjson.GetHeadersCmd{},
502 // make(chan GetHeadersRes)}
503 // },
504 // },
505 // "getinfo": {
506 // HandleGetInfo, make(chan API),
507 // func() API { return API{nil, make(chan GetInfoRes)} },
508 // },
509 // "getmempoolinfo": {
510 // HandleGetMempoolInfo, make(chan API),
511 // func() API { return API{nil, make(chan GetMempoolInfoRes)} },
512 // },
513 // "getmininginfo": {
514 // HandleGetMiningInfo, make(chan API),
515 // func() API { return API{nil, make(chan GetMiningInfoRes)} },
516 // },
517 // "getnettotals": {
518 // HandleGetNetTotals, make(chan API),
519 // func() API { return API{nil, make(chan GetNetTotalsRes)} },
520 // },
521 // "getnetworkhashps": {
522 // HandleGetNetworkHashPS, make(chan API),
523 // func() API {
524 // return API{btcjson.GetNetworkHashPSCmd{},
525 // make(chan GetNetworkHashPSRes)}
526 // },
527 // },
528 // "getpeerinfo": {
529 // HandleGetPeerInfo, make(chan API),
530 // func() API { return API{nil, make(chan GetPeerInfoRes)} },
531 // },
532 // "getrawmempool": {
533 // HandleGetRawMempool, make(chan API),
534 // func() API {
535 // return API{btcjson.GetRawMempoolCmd{},
536 // make(chan GetRawMempoolRes)}
537 // },
538 // },
539 // "getrawtransaction": {
540 // HandleGetRawTransaction, make(chan API),
541 // func() API {
542 // return API{btcjson.GetRawTransactionCmd{},
543 // make(chan GetRawTransactionRes)}
544 // },
545 // },
546 // "gettxout": {
547 // HandleGetTxOut, make(chan API),
548 // func() API {
549 // return API{btcjson.GetTxOutCmd{},
550 // make(chan GetTxOutRes)}
551 // },
552 // },
553 // // "getwork": HandleGetWork,
554 // "help": {
555 // HandleHelp, make(chan API),
556 // func() API {
557 // return API{btcjson.HelpCmd{},
558 // make(chan HelpRes)}
559 // },
560 // },
561 // "node": {
562 // HandleNode, make(chan API),
563 // func() API {
564 // return API{btcjson.NodeCmd{},
565 // make(chan NodeRes)}
566 // },
567 // },
568 // "ping": {
569 // HandlePing, make(chan API),
570 // func() API { return API{nil, make(chan PingRes)} },
571 // },
572 // "searchrawtransactions": {
573 // HandleSearchRawTransactions, make(chan API),
574 // func() API {
575 // return API{btcjson.SearchRawTransactionsCmd{},
576 // make(chan SearchRawTransactionsRes)}
577 // },
578 // },
579 // "sendrawtransaction": {
580 // HandleSendRawTransaction, make(chan API),
581 // func() API {
582 // return API{btcjson.SendRawTransactionCmd{},
583 // make(chan SendRawTransactionRes)}
584 // },
585 // },
586 // "setgenerate": {
587 // HandleSetGenerate, make(chan API),
588 // func() API {
589 // return API{btcjson.SetGenerateCmd{},
590 // make(chan SetGenerateRes)}
591 // },
592 // },
593 // "stop": {
594 // HandleStop, make(chan API),
595 // func() API { return API{nil, make(chan StopRes)} },
596 // },
597 // "restart": {
598 // HandleRestart, make(chan API),
599 // func() API { return API{nil, make(chan RestartRes)} },
600 // },
601 // "resetchain": {
602 // HandleResetChain, make(chan API),
603 // func() API { return API{nil, make(chan ResetChainRes)} },
604 // },
605 // // "dropwallethistory": HandleDropWalletHistory,
606 // "submitblock": {
607 // HandleSubmitBlock, make(chan API),
608 // func() API {
609 // return API{btcjson.SubmitBlockCmd{},
610 // make(chan SubmitBlockRes)}
611 // },
612 // },
613 // "uptime": {
614 // HandleUptime, make(chan API),
615 // func() API { return API{nil, make(chan UptimeRes)} },
616 // },
617 // "validateaddress": {
618 // HandleValidateAddress, make(chan API),
619 // func() API {
620 // return API{btcjson.ValidateAddressCmd{},
621 // make(chan ValidateAddressRes)}
622 // },
623 // },
624 // "verifychain": {
625 // HandleVerifyChain, make(chan API),
626 // func() API {
627 // return API{btcjson.VerifyChainCmd{},
628 // make(chan VerifyChainRes)}
629 // },
630 // },
631 // "verifymessage": {
632 // HandleVerifyMessage, make(chan API),
633 // func() API {
634 // return API{btcjson.VerifyMessageCmd{},
635 // make(chan VerifyMessageRes)}
636 // },
637 // },
638 // "version": {
639 // HandleVersion, make(chan API),
640 // func() API {
641 // return API{btcjson.VersionCmd{},
642 // make(chan VersionRes)}
643 // },
644 // },
645 // }
646 647 // RPCLimited isCommands that are available to a limited user
648 RPCLimited = map[string]CommandHandler{
649 // Websockets commands
650 "loadtxfilter": {},
651 "notifyblocks": {},
652 "notifynewtransactions": {},
653 "notifyreceived": {},
654 "notifyspent": {},
655 "rescan": {},
656 "rescanblocks": {},
657 "session": {},
658 // Websockets AND HTTP/S commands
659 "help": {},
660 // HTTP/S-only commands
661 "createrawtransaction": {},
662 "decoderawtransaction": {},
663 "decodescript": {},
664 "estimatefee": {},
665 "getbestblock": {},
666 "getbestblockhash": {},
667 "getblock": {},
668 "getblockcount": {},
669 "getblockhash": {},
670 "getblockheader": {},
671 "getcfilter": {},
672 "getcfilterheader": {},
673 "getcurrentnet": {},
674 "getdifficulty": {},
675 "getheaders": {},
676 "getinfo": {},
677 "getnettotals": {},
678 "getnetworkhashps": {},
679 "getrawmempool": {},
680 "getrawtransaction": {},
681 "gettxout": {},
682 "searchrawtransactions": {},
683 "sendrawtransaction": {},
684 "submitblock": {},
685 "uptime": {},
686 "validateaddress": {},
687 "verifymessage": {},
688 "version": {},
689 }
690 // RPCUnimplemented is commands that are currently unimplemented, but should ultimately be.
691 RPCUnimplemented = map[string]struct{}{
692 "estimatepriority": {},
693 "getchaintips": {},
694 "getmempoolentry": {},
695 "getnetworkinfo": {},
696 "getwork": {},
697 "invalidateblock": {},
698 "preciousblock": {},
699 "reconsiderblock": {},
700 }
701 )
702 703 // NotifyBlockConnected uses the newly-connected block to notify any long poll clients with a new block template when
704 // their existing block template is stale due to the newly connected block.
705 func (state *GBTWorkState) NotifyBlockConnected(blockHash *chainhash.Hash) {
706 go func() {
707 state.Lock()
708 statelasttxupdate := state.LastTxUpdate
709 state.Unlock()
710 state.NotifyLongPollers(blockHash, statelasttxupdate)
711 }()
712 }
713 714 // NotifyMempoolTx uses the new last updated time for the transaction memory pool to notify any long poll clients with a
715 // new block template when their existing block template is stale due to enough time passing and the contents of the
716 // memory pool changing.
717 func (state *GBTWorkState) NotifyMempoolTx(lastUpdated time.Time) {
718 go func() {
719 state.Lock()
720 defer state.Unlock()
721 // No need to notify anything if no block templates have been generated yet.
722 if state.prevHash == nil || state.LastGenerated.IsZero() {
723 return
724 }
725 if time.Now().After(state.LastGenerated.Add(time.Second * GBTRegenerateSeconds)) {
726 state.NotifyLongPollers(state.prevHash, lastUpdated)
727 }
728 }()
729 }
730 731 // BlockTemplateResult returns the current block template associated with the state as a json.GetBlockTemplateResult
732 // that is ready to be encoded to JSON and returned to the caller.
733 //
734 // This function MUST be called with the state locked.
735 func (state *GBTWorkState) BlockTemplateResult(
736 useCoinbaseValue bool, submitOld *bool,
737 ) (
738 *btcjson.GetBlockTemplateResult,
739 error,
740 ) {
741 // Ensure the timestamps are still in valid range for the template.
742 //
743 // This should really only ever happen if the local clock is changed after the template is generated, but it's
744 // important to avoid serving invalid block templates.
745 template := state.Template
746 msgBlock := template.Block
747 header := &msgBlock.Header
748 adjustedTime := state.TimeSource.AdjustedTime()
749 maxTime := adjustedTime.Add(time.Second * blockchain.MaxTimeOffsetSeconds)
750 if header.Timestamp.After(maxTime) {
751 return nil, &btcjson.RPCError{
752 Code: btcjson.ErrRPCOutOfRange,
753 Message: fmt.Sprintf(
754 "The template time is after the "+
755 "maximum allowed time for a block - template "+
756 "time %v, maximum time %v", adjustedTime,
757 maxTime,
758 ),
759 }
760 }
761 // Convert each transaction in the block template to a template result transaction. The result does not include the
762 // coinbase, so notice the adjustments to the various lengths and indices.
763 numTx := len(msgBlock.Transactions)
764 transactions := make([]btcjson.GetBlockTemplateResultTx, 0, numTx-1)
765 txIndex := make(map[chainhash.Hash]int64, numTx)
766 for i, tx := range msgBlock.Transactions {
767 txHash := tx.TxHash()
768 txIndex[txHash] = int64(i)
769 // Skip the coinbase transaction.
770 if i == 0 {
771 continue
772 }
773 // Create an array of 1-based indices to transactions that come before this one in the transactions list which
774 // this one depends on.
775 //
776 // This is necessary since the created block must ensure proper ordering of the dependencies.
777 //
778 // A map is used before creating the final array to prevent duplicate entries when multiple inputs reference the
779 // same transaction.
780 dependsMap := make(map[int64]struct{})
781 for _, txIn := range tx.TxIn {
782 if idx, ok := txIndex[txIn.PreviousOutPoint.Hash]; ok {
783 dependsMap[idx] = struct{}{}
784 }
785 }
786 depends := make([]int64, 0, len(dependsMap))
787 for idx := range dependsMap {
788 depends = append(depends, idx)
789 }
790 // Serialize the transaction for later conversion to hex.
791 txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
792 if e := tx.Serialize(txBuf); E.Chk(e) {
793 context := "Failed to serialize transaction"
794 return nil, InternalRPCError(e.Error(), context)
795 }
796 bTx := util.NewTx(tx)
797 resultTx := btcjson.GetBlockTemplateResultTx{
798 Data: hex.EncodeToString(txBuf.Bytes()),
799 Hash: txHash.String(),
800 Depends: depends,
801 Fee: template.Fees[i],
802 SigOps: template.SigOpCosts[i],
803 Weight: blockchain.GetTransactionWeight(bTx),
804 }
805 transactions = append(transactions, resultTx)
806 }
807 // Generate the block template reply.
808 //
809 // Note that following mutations are implied by the included or omission of fields:
810 //
811 // Including MinTime -> time/ decrement
812 //
813 // Omitting CoinbaseTxn -> coinbase, generation
814 targetDifficulty := fmt.Sprintf("%064x", bits.CompactToBig(header.Bits))
815 templateID := EncodeTemplateID(state.prevHash, state.LastGenerated)
816 reply := btcjson.GetBlockTemplateResult{
817 Bits: strconv.FormatInt(int64(header.Bits), 16),
818 CurTime: header.Timestamp.Unix(),
819 Height: int64(template.Height),
820 PreviousHash: header.PrevBlock.String(),
821 WeightLimit: blockchain.MaxBlockWeight,
822 SigOpLimit: blockchain.MaxBlockSigOpsCost,
823 SizeLimit: wire.MaxBlockPayload,
824 Transactions: transactions,
825 Version: header.Version,
826 LongPollID: templateID,
827 SubmitOld: submitOld,
828 Target: targetDifficulty,
829 MinTime: state.MinTimestamp.Unix(),
830 MaxTime: maxTime.Unix(),
831 Mutable: GBTMutableFields,
832 NonceRange: GBTNonceRange,
833 Capabilities: GBTCapabilities,
834 }
835 // // If the generated block template includes transactions with witness data, then
836 // // include the witness commitment in the GBT result.
837 // if template.WitnessCommitment != nil {
838 // reply.DefaultWitnessCommitment = hex.EncodeToString(template.WitnessCommitment)
839 // }
840 if useCoinbaseValue {
841 reply.CoinbaseAux = GBTCoinbaseAux
842 reply.CoinbaseValue = &msgBlock.Transactions[0].TxOut[0].Value
843 } else {
844 // Ensure the template has a valid payment address associated with it when a full coinbase is requested.
845 if !template.ValidPayAddress {
846 return nil, &btcjson.RPCError{
847 Code: btcjson.ErrRPCInternal.Code,
848 Message: "A coinbase transaction has been " +
849 "requested, but the Server has not " +
850 "been configured with any payment " +
851 "addresses via --miningaddr",
852 }
853 }
854 // Serialize the transaction for conversion to hex.
855 tx := msgBlock.Transactions[0]
856 txBuf := bytes.NewBuffer(make([]byte, 0, tx.SerializeSize()))
857 if e := tx.Serialize(txBuf); E.Chk(e) {
858 context := "Failed to serialize transaction"
859 return nil, InternalRPCError(e.Error(), context)
860 }
861 resultTx := btcjson.GetBlockTemplateResultTx{
862 Data: hex.EncodeToString(txBuf.Bytes()),
863 Hash: tx.TxHash().String(),
864 Depends: []int64{},
865 Fee: template.Fees[0],
866 SigOps: template.SigOpCosts[0],
867 }
868 reply.CoinbaseTxn = &resultTx
869 }
870 return &reply, nil
871 }
872 873 // NotifyLongPollers notifies any channels that have been registered to be notified when block templates are stale.
874 //
875 // This function MUST be called with the state locked.
876 func (state *GBTWorkState) NotifyLongPollers(
877 latestHash *chainhash.Hash,
878 lastGenerated time.Time,
879 ) {
880 // Notify anything that is waiting for a block template update from a hash which is not the hash of the tip of the
881 // best chain since their work is now invalid.
882 for hash, channels := range state.NotifyMap {
883 if !hash.IsEqual(latestHash) {
884 for _, c := range channels {
885 c.Q()
886 }
887 delete(state.NotifyMap, hash)
888 }
889 }
890 // Return now if the provided last generated timestamp has not been initialized.
891 if lastGenerated.IsZero() {
892 return
893 }
894 // Return now if there is nothing registered for updates to the current best block hash.
895 channels, ok := state.NotifyMap[*latestHash]
896 if !ok {
897 return
898 }
899 // Notify anything that is waiting for a block template update from a block template generated before the most
900 // recently generated block template.
901 lastGeneratedUnix := lastGenerated.Unix()
902 for lastGen, c := range channels {
903 if lastGen < lastGeneratedUnix {
904 c.Q()
905 delete(channels, lastGen)
906 }
907 }
908 // Remove the entry altogether if there are no more registered channels.
909 if len(channels) == 0 {
910 delete(state.NotifyMap, *latestHash)
911 }
912 }
913 914 // TemplateUpdateChan returns a channel that will be closed once the block template associated with the passed previous
915 // hash and last generated time is stale.
916 //
917 // The function will return existing channels for duplicate parameters which allows to wait for the same block template
918 // without requiring a different channel for each client.
919 //
920 // This function MUST be called with the state locked.
921 func (state *GBTWorkState) TemplateUpdateChan(
922 prevHash *chainhash.Hash, lastGenerated int64,
923 ) qu.C {
924 // Either get the current list of channels waiting for updates about changes to block template for the previous hash
925 // or create a new one.
926 channels, ok := state.NotifyMap[*prevHash]
927 if !ok {
928 m := make(map[int64]qu.C)
929 state.NotifyMap[*prevHash] = m
930 channels = m
931 }
932 // Get the current channel associated with the time the block template was last generated or create a new one.
933 c, ok := channels[lastGenerated]
934 if !ok {
935 c = qu.T()
936 channels[lastGenerated] = c
937 }
938 return c
939 }
940 941 // UpdateBlockTemplate creates or updates a block template for the work state.
942 //
943 // A new block template will be generated when the current best block has changed or the transactions in the memory pool
944 // have been updated and it has been long enough since the last template was generated.
945 //
946 // Otherwise, the timestamp for the existing block template is updated (and possibly the difficulty on testnet per the
947 // consensus rules).
948 //
949 // Finally, if the useCoinbaseValue flag is false and the existing block template does not already contain a valid
950 // payment address, the block template will be updated with a randomly selected payment address from the list of
951 // configured addresses.
952 //
953 // This function MUST be called with the state locked.
954 func (state *GBTWorkState) UpdateBlockTemplate(
955 s *Server,
956 useCoinbaseValue bool,
957 ) (e error) {
958 generator := s.Cfg.Generator
959 lastTxUpdate := generator.GetTxSource().LastUpdated()
960 if lastTxUpdate.IsZero() {
961 lastTxUpdate = time.Now()
962 }
963 // Generate a new block template when the current best block has changed or the transactions in the memory pool have
964 // been updated and it has been at least gbtRegenerateSecond since the last template was generated.
965 var msgBlock *wire.Block
966 var targetDifficulty string
967 latestHash := &s.Cfg.Chain.BestSnapshot().Hash
968 template := state.Template
969 if template == nil || state.prevHash == nil ||
970 !state.prevHash.IsEqual(latestHash) ||
971 (state.LastTxUpdate != lastTxUpdate &&
972 time.Now().After(
973 state.LastGenerated.Add(
974 time.Second*
975 GBTRegenerateSeconds,
976 ),
977 )) {
978 // Reset the previous best hash the block template was generated against so any errors below cause the next
979 // invocation to try again.
980 state.prevHash = nil
981 // Choose a payment address at random if the caller requests a full coinbase as opposed to only the pertinent
982 // details needed to create their own coinbase.
983 var payAddr btcaddr.Address
984 if !useCoinbaseValue {
985 payAddr = s.StateCfg.ActiveMiningAddrs[rand.Intn(
986 len(
987 s.StateCfg.
988 ActiveMiningAddrs,
989 ),
990 )]
991 }
992 // Create a new block template that has a coinbase which anyone can redeem.
993 //
994 // This is only acceptable because the returned block template doesn't include the coinbase, so the caller will
995 // ultimately create their own coinbase which pays to the appropriate address(es).
996 blkTemplate, e := generator.NewBlockTemplate(payAddr, state.Algo)
997 if e != nil {
998 return InternalRPCError(
999 "(rpcserver.go) Failed to create new block "+
1000 "template: "+e.Error(), "",
1001 )
1002 }
1003 template = blkTemplate
1004 msgBlock = template.Block
1005 targetDifficulty = fmt.Sprintf(
1006 "%064x",
1007 bits.CompactToBig(msgBlock.Header.Bits),
1008 )
1009 // Get the minimum allowed timestamp for the block based on the median timestamp of the last several blocks per
1010 // the chain consensus rules.
1011 best := s.Cfg.Chain.BestSnapshot()
1012 minTimestamp := mining.MinimumMedianTime(best)
1013 // Update work state to ensure another block template isn't generated until needed.
1014 state.Template = template
1015 state.LastGenerated = time.Now()
1016 state.LastTxUpdate = lastTxUpdate
1017 state.prevHash = latestHash
1018 state.MinTimestamp = minTimestamp
1019 D.F(
1020 "generated block template (timestamp %v, target %s, merkle root %s)",
1021 msgBlock.Header.Timestamp,
1022 targetDifficulty,
1023 msgBlock.Header.MerkleRoot,
1024 )
1025 1026 // Notify any clients that are long polling about the new template.
1027 state.NotifyLongPollers(latestHash, lastTxUpdate)
1028 } else {
1029 // At this point, there is a saved block template and another request for a template was made, but either the
1030 // available transactions haven't change or it hasn't been long enough to trigger a new block template to be
1031 // generated.
1032 //
1033 // So, update the existing block template.
1034 //
1035 // When the caller requires a full coinbase as opposed to only the pertinent details needed to create their own
1036 // coinbase, add a payment address to the output of the coinbase of the template if it doesn't already have one.
1037 //
1038 // Since this requires mining addresses to be specified via the config, an error is returned if none have been
1039 // specified.
1040 if !useCoinbaseValue && !template.ValidPayAddress {
1041 // Choose a payment address at random.
1042 payToAddr := s.StateCfg.ActiveMiningAddrs[rand.Intn(
1043 len(
1044 s.
1045 StateCfg.ActiveMiningAddrs,
1046 ),
1047 )]
1048 // Update the block coinbase output of the template to pay to the randomly selected payment address.
1049 pkScript, e := txscript.PayToAddrScript(payToAddr)
1050 if e != nil {
1051 context := "Failed to create pay-to-addr script"
1052 return InternalRPCError(e.Error(), context)
1053 }
1054 template.Block.Transactions[0].TxOut[0].PkScript = pkScript
1055 template.ValidPayAddress = true
1056 // Update the merkle root.
1057 block := block.NewBlock(template.Block)
1058 merkles := blockchain.BuildMerkleTreeStore(block.Transactions(), false)
1059 template.Block.Header.MerkleRoot = *merkles.GetRoot()
1060 }
1061 // Set locals for convenience.
1062 msgBlock = template.Block
1063 targetDifficulty = fmt.Sprintf(
1064 "%064x",
1065 bits.CompactToBig(msgBlock.Header.Bits),
1066 )
1067 // Update the time of the block template to the current time while accounting for the median time of the past
1068 // several blocks per the chain consensus rules.
1069 e := generator.UpdateBlockTime(0, msgBlock)
1070 if e != nil {
1071 D.Ln(e)
1072 1073 }
1074 msgBlock.Header.Nonce = 0
1075 D.F(
1076 "updated block template (timestamp %v, target %s)",
1077 msgBlock.Header.Timestamp,
1078 targetDifficulty,
1079 )
1080 1081 }
1082 return nil
1083 }
1084 1085 // NotifyNewTransactions notifies both websocket and getblocktemplate long poll clients of the passed transactions.
1086 //
1087 // This function should be called whenever new transactions are added to the mempool.
1088 func (s *Server) NotifyNewTransactions(txns []*mempool.TxDesc) {
1089 for _, txD := range txns {
1090 // Notify websocket clients about mempool transactions.
1091 s.NtfnMgr.SendNotifyMempoolTx(txD.Tx, true)
1092 // Potentially notify any getblocktemplate long poll clients about stale block templates due to the new
1093 // transaction.
1094 s.GBTWorkState.NotifyMempoolTx(s.Cfg.TxMemPool.LastUpdated())
1095 }
1096 }
1097 1098 // RequestedProcessShutdown returns a channel that is sent to when an authorized RPC client requests the process to
1099 // shutdown. If the request can not be read immediately, it is dropped.
1100 func (s *Server) RequestedProcessShutdown() qu.C {
1101 return s.RequestProcessShutdown
1102 }
1103 1104 // Start is used by Server to start the rpc listener.
1105 func (s *Server) Start() {
1106 if atomic.AddInt32(&s.Started, 1) != 1 {
1107 return
1108 }
1109 rpcServeMux := http.NewServeMux()
1110 httpServer := &http.Server{
1111 Handler: rpcServeMux,
1112 // Timeout connections which don't complete the initial handshake within the allowed timeframe.
1113 ReadTimeout: time.Second * RPCAuthTimeoutSeconds,
1114 }
1115 rpcServeMux.HandleFunc(
1116 "/", func(w http.ResponseWriter, r *http.Request) {
1117 I.Ln("handling new connection from", r.RemoteAddr)
1118 w.Header().Set("Connection", "close")
1119 w.Header().Set("Content-Type", "application/json")
1120 r.Close = true
1121 // Limit the number of connections to max allowed.
1122 if s.LimitConnections(w, r.RemoteAddr) {
1123 return
1124 }
1125 // Keep track of the number of connected clients.
1126 s.IncrementClients()
1127 defer s.DecrementClients()
1128 _, isAdmin, e := s.CheckAuth(r, true)
1129 if e != nil {
1130 JSONAuthFail(w)
1131 return
1132 }
1133 // Read and respond to the request.
1134 s.JSONRPCRead(w, r, isAdmin)
1135 },
1136 )
1137 // Websocket endpoint.
1138 rpcServeMux.HandleFunc(
1139 "/ws", func(w http.ResponseWriter, r *http.Request) {
1140 I.Ln("handling new connection from", r.RemoteAddr)
1141 authenticated, isAdmin, e := s.CheckAuth(r, false)
1142 if e != nil {
1143 JSONAuthFail(w)
1144 return
1145 }
1146 // Attempt to upgrade the connection to a websocket connection using the default size for read/write buffers.
1147 ws, e := websocket.Upgrade(w, r, nil, 0, 0)
1148 if e != nil {
1149 if _, ok := e.(websocket.HandshakeError); !ok {
1150 E.Ln("unexpected websocket error:", e)
1151 1152 }
1153 http.Error(w, "400 Bad Request.", http.StatusBadRequest)
1154 return
1155 }
1156 s.WebsocketHandler(ws, r.RemoteAddr, authenticated, isAdmin)
1157 },
1158 )
1159 for _, listener := range s.Cfg.Listeners {
1160 s.WG.Add(1)
1161 go func(listener net.Listener) {
1162 I.Ln("chain RPC Server listening on ", listener.Addr())
1163 e := httpServer.Serve(listener)
1164 if e != nil {
1165 D.Ln(e)
1166 }
1167 D.Ln("chain RPC listener done for", listener.Addr())
1168 if e := listener.Close(); E.Chk(e) {
1169 }
1170 s.WG.Done()
1171 }(listener)
1172 }
1173 s.NtfnMgr.WG.Add(2)
1174 s.NtfnMgr.Start()
1175 }
1176 1177 // Stop is used by Server.go_ to stop the rpc listener.
1178 func (s *Server) Stop() (e error) {
1179 if atomic.AddInt32(&s.Shutdown, 1) != 1 {
1180 W.Ln("RPC Server is already in the process of shutting down")
1181 return nil
1182 }
1183 I.Ln("RPC Server shutting down")
1184 s.Quit.Q()
1185 for _, listener := range s.Cfg.Listeners {
1186 e := listener.Close()
1187 if e != nil {
1188 E.Ln("problem shutting down RPC:", e)
1189 return e
1190 }
1191 }
1192 s.NtfnMgr.Shutdown()
1193 s.NtfnMgr.WaitForShutdown()
1194 s.WG.Wait()
1195 D.Ln("RPC Server shutdown complete")
1196 return nil
1197 }
1198 1199 // CheckAuth checks the HTTP Basic authentication supplied by a wallet or RPC client in the HTTP request r.
1200 //
1201 // If the supplied authentication does not match the username and password expected, a non-nil error is returned. This
1202 // check is time-constant.
1203 //
1204 // The first bool return value signifies auth success ( true if successful) and the second bool return value specifies
1205 // whether the user can change the state of the Server (true) or whether the user is limited (false).
1206 //
1207 // The second is always false if the first is.
1208 func (s *Server) CheckAuth(r *http.Request, require bool) (bool, bool, error) {
1209 authhdr := r.Header["Authorization"]
1210 if len(authhdr) == 0 {
1211 if require {
1212 W.Ln("RPC authentication failure from", r.RemoteAddr)
1213 1214 return false, false, errors.New("auth failure")
1215 }
1216 return false, false, nil
1217 }
1218 authsha := sha256.Sum256([]byte(authhdr[0]))
1219 // Chk for limited auth first as in environments with limited users, those are probably expected to have a higher
1220 // volume of calls
1221 limitcmp := subtle.ConstantTimeCompare(authsha[:], s.LimitAuthSHA[:])
1222 if limitcmp == 1 {
1223 return true, false, nil
1224 }
1225 // Chk for admin-level auth
1226 cmp := subtle.ConstantTimeCompare(authsha[:], s.AuthSHA[:])
1227 if cmp == 1 {
1228 return true, true, nil
1229 }
1230 // Request's auth doesn't match either user
1231 W.Ln("RPC authentication failure from", r.RemoteAddr)
1232 1233 return false, false, errors.New("auth failure")
1234 }
1235 1236 // DecrementClients subtracts one from the number of connected RPC clients. Note this only applies to standard clients.
1237 //
1238 // Websocket clients have their own limits and are tracked separately. This function is safe for concurrent access.
1239 func (s *Server) DecrementClients() {
1240 atomic.AddInt32(&s.NumClients, -1)
1241 }
1242 1243 // HandleBlockchainNotification handles callbacks for notifications from blockchain. It notifies clients that are long
1244 // polling for changes or subscribed to websockets notifications.
1245 func (s *Server) HandleBlockchainNotification(notification *blockchain.Notification) {
1246 if s.Cfg.Chain.IsCurrent() {
1247 switch notification.Type {
1248 case blockchain.NTBlockAccepted:
1249 block, ok := notification.Data.(*block.Block)
1250 if !ok {
1251 W.Ln("chain accepted notification is not a block")
1252 break
1253 }
1254 // Allow any clients performing long polling via the getblocktemplate RPC to be notified when the new block
1255 // causes their old block template to become stale.
1256 s.GBTWorkState.NotifyBlockConnected(block.Hash())
1257 case blockchain.NTBlockConnected:
1258 block, ok := notification.Data.(*block.Block)
1259 if !ok {
1260 W.Ln("chain connected notification is not a block")
1261 break
1262 }
1263 // Notify registered websocket clients of incoming block.
1264 s.NtfnMgr.SendNotifyBlockConnected(block)
1265 case blockchain.NTBlockDisconnected:
1266 block, ok := notification.Data.(*block.Block)
1267 if !ok {
1268 W.Ln("chain disconnected notification is not a block.")
1269 break
1270 }
1271 // Notify registered websocket clients.
1272 s.NtfnMgr.SendNotifyBlockDisconnected(block)
1273 }
1274 }
1275 }
1276 1277 // HTTPStatusLine returns a response Status-Line (RFC 2616 Section 6.1) for the given request and response status code.
1278 //
1279 // This function was lifted and adapted from the standard library HTTP Server code since it's not exported.
1280 func (s *Server) HTTPStatusLine(req *http.Request, code int) string {
1281 // Fast path:
1282 key := code
1283 proto11 := req.ProtoAtLeast(1, 1)
1284 if !proto11 {
1285 key = -key
1286 }
1287 s.StatusLock.RLock()
1288 line, ok := s.StatusLines[key]
1289 s.StatusLock.RUnlock()
1290 if ok {
1291 return line
1292 }
1293 // Slow path:
1294 proto := "HTTP/1.0"
1295 if proto11 {
1296 proto = "HTTP/1.1"
1297 }
1298 codeStr := strconv.Itoa(code)
1299 text := http.StatusText(code)
1300 if text != "" {
1301 line = proto + " " + codeStr + " " + text + "\r\n"
1302 s.StatusLock.Lock()
1303 s.StatusLines[key] = line
1304 s.StatusLock.Unlock()
1305 } else {
1306 text = "status code " + codeStr
1307 line = proto + " " + codeStr + " " + text + "\r\n"
1308 }
1309 return line
1310 }
1311 1312 // IncrementClients adds one to the number of connected RPC clients. Note this only applies to standard clients.
1313 //
1314 // Websocket clients have their own limits and are tracked separately.
1315 //
1316 // This function is safe for concurrent access.
1317 func (s *Server) IncrementClients() {
1318 atomic.AddInt32(&s.NumClients, 1)
1319 }
1320 1321 // JSONRPCRead handles reading and responding to RPC messages.
1322 func (s *Server) JSONRPCRead(
1323 w http.ResponseWriter, r *http.Request, isAdmin bool,
1324 ) {
1325 if atomic.LoadInt32(&s.Shutdown) != 0 {
1326 return
1327 }
1328 // Read and close the JSON-RPC request body from the caller.
1329 var e error
1330 var body []byte
1331 if body, e = ioutil.ReadAll(r.Body); E.Chk(e) {
1332 }
1333 I.Ln("read JSONRPC request", string(body))
1334 if e = r.Body.Close(); E.Chk(e) {
1335 }
1336 if e != nil {
1337 errCode := http.StatusBadRequest
1338 http.Error(
1339 w, fmt.Sprintf(
1340 "%d error reading JSON message: %v",
1341 errCode, e,
1342 ), errCode,
1343 )
1344 return
1345 }
1346 // Unfortunately, the http Server doesn't provide the ability to change the read deadline for the new connection and
1347 // having one breaks long polling.
1348 //
1349 // However, not having a read deadline on the initial connection would mean clients can connect and idle forever.
1350 //
1351 // Thus, hijack the connection from the HTTP Server, clear the read deadline, and handle writing the response
1352 // manually.
1353 hj, ok := w.(http.Hijacker)
1354 if !ok {
1355 errMsg := "webserver doesn't support hijacking"
1356 W.F(errMsg)
1357 errCode := http.StatusInternalServerError
1358 http.Error(w, strconv.Itoa(errCode)+" "+errMsg, errCode)
1359 return
1360 }
1361 conn, buf, e := hj.Hijack()
1362 if e != nil {
1363 W.Ln("failed to hijack HTTP connection:", e)
1364 errCode := http.StatusInternalServerError
1365 http.Error(w, strconv.Itoa(errCode)+" "+e.Error(), errCode)
1366 return
1367 }
1368 defer func() {
1369 if e = buf.Flush(); E.Chk(e) {
1370 }
1371 if e = conn.Close(); E.Chk(e) {
1372 }
1373 }()
1374 e = conn.SetReadDeadline(TimeZeroVal)
1375 if e != nil {
1376 D.Ln(e)
1377 }
1378 // Attempt to parse the raw body into a JSON-RPC request.
1379 var responseID interface{}
1380 var jsonErr error
1381 var result interface{}
1382 var request btcjson.Request
1383 if e = js.Unmarshal(body, &request); E.Chk(e) {
1384 jsonErr = &btcjson.RPCError{
1385 Code: btcjson.ErrRPCParse.Code,
1386 Message: "Failed to parse request: " + e.Error(),
1387 }
1388 }
1389 I.S(request)
1390 if jsonErr == nil {
1391 // The JSON-RPC 1.0 spec defines that notifications must have their "id"
1392 // set to null and states that notifications do not have a response.
1393 //
1394 // A JSON-RPC 2.0 notification is a request with "json-rpc":"2.0", and without an "id" member.
1395 //
1396 // The specification states that notifications must not be responded to. JSON-RPC 2.0 permits the null value as
1397 // a valid request id, therefore such requests are not notifications.
1398 //
1399 // Bitcoin Core serves requests with "id":null or even an absent "id", and responds to such requests with
1400 // "id":null in the response. Save does not respond to any request without and "id" or "id":null, regardless the
1401 // indicated JSON-RPC protocol version unless RPC quirks are enabled.
1402 //
1403 // With RPC quirks enabled, such requests will be responded to if the request does not indicate JSON-RPC
1404 // version. RPC quirks can be enabled by the user to avoid compatibility issues with software relying on Core's
1405 // behavior.
1406 if request.ID == nil && !(s.Config.RPCQuirks.True() && request.Jsonrpc == "") {
1407 return
1408 }
1409 // The parse was at least successful enough to have an ID so set it for the response.
1410 responseID = request.ID
1411 // Setup a close notifier. Since the connection is hijacked, the CloseNotifer on the ResponseWriter is not
1412 // available.
1413 closeChan := qu.Ts(1)
1414 go func() {
1415 _, e = conn.Read(make([]byte, 1))
1416 if e != nil {
1417 closeChan.Q()
1418 }
1419 }()
1420 // Chk if the user is limited and set error if method unauthorized
1421 if !isAdmin {
1422 if _, ok := RPCLimited[request.Method]; !ok {
1423 jsonErr = &btcjson.RPCError{
1424 Code: btcjson.ErrRPCInvalidParams.Code,
1425 Message: "limited user not authorized for this method",
1426 }
1427 }
1428 }
1429 if jsonErr == nil {
1430 // Attempt to parse the JSON-RPC request into a known concrete command.
1431 parsedCmd := ParseCmd(&request)
1432 if parsedCmd.Err != nil {
1433 jsonErr = parsedCmd.Err
1434 } else {
1435 I.Ln("calling method:", parsedCmd.Method)
1436 result, jsonErr = s.StandardCmdResult(parsedCmd, closeChan)
1437 }
1438 }
1439 }
1440 // Marshal the response.
1441 var msg []byte
1442 msg, e = CreateMarshalledReply(responseID, result, jsonErr)
1443 if e != nil {
1444 E.Ln("failed to marshal reply:", e)
1445 return
1446 }
1447 I.Ln("\n" + string(msg))
1448 // Write the response.
1449 e = s.WriteHTTPResponseHeaders(r, w.Header(), http.StatusOK, buf)
1450 if e != nil {
1451 E.Ln(e)
1452 return
1453 }
1454 if _, e = buf.Write(msg); E.Chk(e) {
1455 E.Ln("failed to write marshalled reply:", e)
1456 }
1457 // Terminate with newline to maintain compatibility with Bitcoin Core.
1458 if e := buf.WriteByte('\n'); E.Chk(e) {
1459 E.Ln("failed to append terminating newline to reply:", e)
1460 1461 }
1462 }
1463 1464 // LimitConnections responds with a 503 service unavailable and returns true if adding another client would exceed the
1465 // maximum allow RPC clients.
1466 //
1467 // This function is safe for concurrent access.
1468 func (s *Server) LimitConnections(
1469 w http.ResponseWriter, remoteAddr string,
1470 ) bool {
1471 if int(atomic.LoadInt32(&s.NumClients)+1) > s.Config.RPCMaxClients.V() {
1472 I.F(
1473 "max RPC clients exceeded [%d] - disconnecting client %s",
1474 s.Config.RPCMaxClients, remoteAddr,
1475 )
1476 1477 http.Error(
1478 w, "503 Too busy. Try again later.",
1479 http.StatusServiceUnavailable,
1480 )
1481 return true
1482 }
1483 return false
1484 }
1485 1486 // StandardCmdResult checks that a parsed command is a standard Bitcoin JSON-RPC command and runs the appropriate
1487 // handler to reply to the command.
1488 //
1489 // Any commands which are not recognized or not implemented will return an error suitable for use in replies.
1490 func (s *Server) StandardCmdResult(
1491 cmd *ParsedRPCCmd,
1492 closeChan qu.C,
1493 ) (interface{}, error) {
1494 handler, ok := RPCHandlers[cmd.Method]
1495 if ok {
1496 goto handled
1497 }
1498 _, ok = RPCAskWallet[cmd.Method]
1499 if ok {
1500 handler.Fn = HandleAskWallet
1501 goto handled
1502 }
1503 _, ok = RPCUnimplemented[cmd.Method]
1504 if ok {
1505 handler.Fn = HandleUnimplemented
1506 goto handled
1507 }
1508 return nil, btcjson.ErrRPCMethodNotFound
1509 handled:
1510 return handler.Fn(s, cmd.Cmd, closeChan)
1511 }
1512 1513 // WriteHTTPResponseHeaders writes the necessary response headers prior to writing an HTTP body given a request to use
1514 // for protocol negotiation, headers to write, a status code, and a writer.
1515 func (s *Server) WriteHTTPResponseHeaders(
1516 req *http.Request,
1517 headers http.Header, code int, w io.Writer,
1518 ) (e error) {
1519 _, e = io.WriteString(w, s.HTTPStatusLine(req, code))
1520 if e != nil {
1521 return e
1522 }
1523 e = headers.Write(w)
1524 if e != nil {
1525 return e
1526 }
1527 _, e = io.WriteString(w, "\r\n")
1528 return e
1529 }
1530 1531 // BuilderScript is a convenience function which is used for hard-coded scripts built with the script builder. Any
1532 // errors are converted to a panic since it is only, and must only, be used with hard-coded, and therefore, known good,
1533 // scripts.
1534 func BuilderScript(builder *txscript.ScriptBuilder) []byte {
1535 script, e := builder.Script()
1536 if e != nil {
1537 panic(e)
1538 }
1539 return script
1540 }
1541 1542 // ChainErrToGBTErrString converts an error returned from btcchain to a string which matches the reasons and format
1543 // described in BIP0022 for rejection reasons.
1544 func ChainErrToGBTErrString(e error) string {
1545 // When the passed error is not a RuleError, just return a generic rejected string with the error text.
1546 ruleErr, ok := e.(blockchain.RuleError)
1547 if !ok {
1548 return "rejected: " + e.Error()
1549 }
1550 switch ruleErr.ErrorCode {
1551 case blockchain.ErrDuplicateBlock:
1552 return "duplicate"
1553 case blockchain.ErrBlockTooBig:
1554 return "bad-blk-length"
1555 case blockchain.ErrBlockWeightTooHigh:
1556 return "bad-blk-weight"
1557 case blockchain.ErrBlockVersionTooOld:
1558 return "bad-version"
1559 case blockchain.ErrInvalidTime:
1560 return "bad-time"
1561 case blockchain.ErrTimeTooOld:
1562 return "time-too-old"
1563 case blockchain.ErrTimeTooNew:
1564 return "time-too-new"
1565 case blockchain.ErrDifficultyTooLow:
1566 return "bad-diffbits"
1567 case blockchain.ErrUnexpectedDifficulty:
1568 return "bad-diffbits"
1569 case blockchain.ErrHighHash:
1570 return "high-hash"
1571 case blockchain.ErrBadMerkleRoot:
1572 return "bad-txnmrklroot"
1573 case blockchain.ErrBadCheckpoint:
1574 return "bad-checkpoint"
1575 case blockchain.ErrForkTooOld:
1576 return "fork-too-old"
1577 case blockchain.ErrCheckpointTimeTooOld:
1578 return "checkpoint-time-too-old"
1579 case blockchain.ErrNoTransactions:
1580 return "bad-txns-none"
1581 case blockchain.ErrNoTxInputs:
1582 return "bad-txns-noinputs"
1583 case blockchain.ErrNoTxOutputs:
1584 return "bad-txns-nooutputs"
1585 case blockchain.ErrTxTooBig:
1586 return "bad-txns-size"
1587 case blockchain.ErrBadTxOutValue:
1588 return "bad-txns-outputvalue"
1589 case blockchain.ErrDuplicateTxInputs:
1590 return "bad-txns-dupinputs"
1591 case blockchain.ErrBadTxInput:
1592 return "bad-txns-badinput"
1593 case blockchain.ErrMissingTxOut:
1594 return "bad-txns-missinginput"
1595 case blockchain.ErrUnfinalizedTx:
1596 return "bad-txns-unfinalizedtx"
1597 case blockchain.ErrDuplicateTx:
1598 return "bad-txns-duplicate"
1599 case blockchain.ErrOverwriteTx:
1600 return "bad-txns-overwrite"
1601 case blockchain.ErrImmatureSpend:
1602 return "bad-txns-maturity"
1603 case blockchain.ErrSpendTooHigh:
1604 return "bad-txns-highspend"
1605 case blockchain.ErrBadFees:
1606 return "bad-txns-fees"
1607 case blockchain.ErrTooManySigOps:
1608 return "high-sigops"
1609 case blockchain.ErrFirstTxNotCoinbase:
1610 return "bad-txns-nocoinbase"
1611 case blockchain.ErrMultipleCoinbases:
1612 return "bad-txns-multicoinbase"
1613 case blockchain.ErrBadCoinbaseScriptLen:
1614 return "bad-cb-length"
1615 case blockchain.ErrBadCoinbaseValue:
1616 return "bad-cb-value"
1617 case blockchain.ErrMissingCoinbaseHeight:
1618 return "bad-cb-height"
1619 case blockchain.ErrBadCoinbaseHeight:
1620 return "bad-cb-height"
1621 case blockchain.ErrScriptMalformed:
1622 return "bad-script-malformed"
1623 case blockchain.ErrScriptValidation:
1624 return "bad-script-validate"
1625 // case blockchain.ErrUnexpectedWitness:
1626 // return "unexpected-witness"
1627 // case blockchain.ErrInvalidWitnessCommitment:
1628 // return "bad-witness-nonce-size"
1629 // case blockchain.ErrWitnessCommitmentMismatch:
1630 // return "bad-witness-merkle-match"
1631 case blockchain.ErrPreviousBlockUnknown:
1632 return "prev-blk-not-found"
1633 case blockchain.ErrInvalidAncestorBlock:
1634 return "bad-prevblk"
1635 case blockchain.ErrPrevBlockNotBest:
1636 return "inconclusive-not-best-prvblk"
1637 }
1638 return "rejected: " + e.Error()
1639 }
1640 1641 // CreateMarshalledReply returns a new marshalled JSON-RPC response given the passed parameters. It will automatically
1642 // convert errors that are not of the type *json.RPCError to the appropriate type as needed.
1643 func CreateMarshalledReply(id, result interface{}, replyErr error) (
1644 []byte, error,
1645 ) {
1646 var jsonErr *btcjson.RPCError
1647 if replyErr != nil {
1648 if jErr, ok := replyErr.(*btcjson.RPCError); ok {
1649 jsonErr = jErr
1650 } else {
1651 jsonErr = InternalRPCError(replyErr.Error(), "")
1652 }
1653 }
1654 return btcjson.MarshalResponse(id, result, jsonErr)
1655 }
1656 1657 // CreateTxRawResult converts the passed transaction and associated parameters to a raw transaction JSON object.
1658 func CreateTxRawResult(
1659 chainParams *chaincfg.Params, mtx *wire.MsgTx,
1660 txHash string, blkHeader *wire.BlockHeader, blkHash string, blkHeight int32,
1661 chainHeight int32,
1662 ) (*btcjson.TxRawResult, error) {
1663 mtxHex, e := MessageToHex(mtx)
1664 if e != nil {
1665 return nil, e
1666 }
1667 txReply := &btcjson.TxRawResult{
1668 Hex: mtxHex,
1669 Txid: txHash,
1670 Hash: mtx.TxHash().String(), // WitnessHash().String(),
1671 Size: int32(mtx.SerializeSize()),
1672 Vsize: int32(mempool.GetTxVirtualSize(util.NewTx(mtx))),
1673 Vin: CreateVinList(mtx),
1674 Vout: CreateVoutList(mtx, chainParams, nil),
1675 Version: mtx.Version,
1676 LockTime: mtx.LockTime,
1677 }
1678 if blkHeader != nil {
1679 // This is not a typo, they are identical in bitcoind as well.
1680 txReply.Time = blkHeader.Timestamp.Unix()
1681 txReply.Blocktime = blkHeader.Timestamp.Unix()
1682 txReply.BlockHash = blkHash
1683 txReply.Confirmations = uint64(1 + chainHeight - blkHeight)
1684 }
1685 return txReply, nil
1686 }
1687 1688 // CreateVinList returns a slice of JSON objects for the inputs of the passed transaction.
1689 func CreateVinList(mtx *wire.MsgTx) []btcjson.Vin {
1690 // Coinbase transactions only have a single txin by definition.
1691 vinList := make([]btcjson.Vin, len(mtx.TxIn))
1692 if blockchain.IsCoinBaseTx(mtx) {
1693 txIn := mtx.TxIn[0]
1694 vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript)
1695 vinList[0].Sequence = txIn.Sequence
1696 // vinList[0].Witness = WitnessToHex(txIn.Witness)
1697 return vinList
1698 }
1699 for i, txIn := range mtx.TxIn {
1700 // The disassembled string will contain [error] inline if the script doesn't
1701 // fully parse, so ignore the error here.
1702 disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
1703 vinEntry := &vinList[i]
1704 vinEntry.Txid = txIn.PreviousOutPoint.Hash.String()
1705 vinEntry.Vout = txIn.PreviousOutPoint.Index
1706 vinEntry.Sequence = txIn.Sequence
1707 vinEntry.ScriptSig = &btcjson.ScriptSig{
1708 Asm: disbuf,
1709 Hex: hex.EncodeToString(txIn.SignatureScript),
1710 }
1711 // if mtx.HasWitness() {
1712 // vinEntry.Witness = WitnessToHex(txIn.Witness)
1713 // }
1714 }
1715 return vinList
1716 }
1717 1718 // CreateVinListPrevOut returns a slice of JSON objects for the inputs of the
1719 // passed transaction.
1720 func CreateVinListPrevOut(
1721 s *Server, mtx *wire.MsgTx,
1722 chainParams *chaincfg.Params, vinExtra bool,
1723 filterAddrMap map[string]struct{},
1724 ) ([]btcjson.VinPrevOut, error) {
1725 // Coinbase transactions only have a single txin by definition.
1726 if blockchain.IsCoinBaseTx(mtx) {
1727 // Only include the transaction if the filter map is empty because a coinbase
1728 // input has no addresses and so would never match a non-empty filter.
1729 if len(filterAddrMap) != 0 {
1730 return nil, nil
1731 }
1732 txIn := mtx.TxIn[0]
1733 vinList := make([]btcjson.VinPrevOut, 1)
1734 vinList[0].Coinbase = hex.EncodeToString(txIn.SignatureScript)
1735 vinList[0].Sequence = txIn.Sequence
1736 return vinList, nil
1737 }
1738 // Use a dynamically sized list to accommodate the address filter.
1739 vinList := make([]btcjson.VinPrevOut, 0, len(mtx.TxIn))
1740 // Lookup all of the referenced transaction outputs needed to populate the previous output information if requested.
1741 var originOutputs map[wire.OutPoint]wire.TxOut
1742 if vinExtra || len(filterAddrMap) > 0 {
1743 var e error
1744 originOutputs, e = FetchInputTxos(s, mtx)
1745 if e != nil {
1746 return nil, e
1747 }
1748 }
1749 for _, txIn := range mtx.TxIn {
1750 // The disassembled string will contain [error] inline if the script doesn't
1751 // fully parse, so ignore the error here.
1752 disbuf, _ := txscript.DisasmString(txIn.SignatureScript)
1753 // Create the basic input entry without the additional optional previous output
1754 // details which will be added later if requested and available.
1755 prevOut := &txIn.PreviousOutPoint
1756 vinEntry := btcjson.VinPrevOut{
1757 Txid: prevOut.Hash.String(),
1758 Vout: prevOut.Index,
1759 Sequence: txIn.Sequence,
1760 ScriptSig: &btcjson.ScriptSig{
1761 Asm: disbuf,
1762 Hex: hex.EncodeToString(txIn.SignatureScript),
1763 },
1764 }
1765 // if len(txIn.Witness) != 0 {
1766 // vinEntry.Witness = WitnessToHex(txIn.Witness)
1767 // }
1768 // Add the entry to the list now if it already passed the filter since the
1769 // previous output might not be available.
1770 passesFilter := len(filterAddrMap) == 0
1771 if passesFilter {
1772 vinList = append(vinList, vinEntry)
1773 }
1774 // Only populate previous output information if requested and available.
1775 if len(originOutputs) == 0 {
1776 continue
1777 }
1778 originTxOut, ok := originOutputs[*prevOut]
1779 if !ok {
1780 continue
1781 }
1782 // Ignore the error here since an error means the script couldn't parse and there is no additional information
1783 // about it anyways.
1784 _, addrs, _, _ := txscript.ExtractPkScriptAddrs(originTxOut.PkScript, chainParams)
1785 // Encode the addresses while checking if the address passes the filter when needed.
1786 encodedAddrs := make([]string, len(addrs))
1787 for j, addr := range addrs {
1788 encodedAddr := addr.EncodeAddress()
1789 encodedAddrs[j] = encodedAddr
1790 // No need to check the map again if the filter already passes.
1791 if passesFilter {
1792 continue
1793 }
1794 if _, exists := filterAddrMap[encodedAddr]; exists {
1795 passesFilter = true
1796 }
1797 }
1798 // Ignore the entry if it doesn't pass the filter.
1799 if !passesFilter {
1800 continue
1801 }
1802 // Add entry to the list if it wasn't already done above.
1803 if len(filterAddrMap) != 0 {
1804 vinList = append(vinList, vinEntry)
1805 }
1806 // Update the entry with previous output information if requested.
1807 if vinExtra {
1808 vinListEntry := &vinList[len(vinList)-1]
1809 vinListEntry.PrevOut = &btcjson.PrevOut{
1810 Addresses: encodedAddrs,
1811 Value: amt.Amount(originTxOut.Value).ToDUO(),
1812 }
1813 }
1814 }
1815 return vinList, nil
1816 }
1817 1818 // CreateVoutList returns a slice of JSON objects for the outputs of the passed transaction.
1819 func CreateVoutList(
1820 mtx *wire.MsgTx, chainParams *chaincfg.Params,
1821 filterAddrMap map[string]struct{},
1822 ) []btcjson.Vout {
1823 voutList := make([]btcjson.Vout, 0, len(mtx.TxOut))
1824 for i, v := range mtx.TxOut {
1825 // The disassembled string will contain [error] inline if the script doesn't fully parse, so ignore the error
1826 // here.
1827 disbuf, _ := txscript.DisasmString(v.PkScript)
1828 // Ignore the error here since an error means the script couldn't parse and there is no additional information
1829 // about it anyways.
1830 scriptClass, addrs, reqSigs, _ := txscript.ExtractPkScriptAddrs(v.PkScript, chainParams)
1831 // Encode the addresses while checking if the address passes the filter when needed.
1832 passesFilter := len(filterAddrMap) == 0
1833 encodedAddrs := make([]string, len(addrs))
1834 for j, addr := range addrs {
1835 encodedAddr := addr.EncodeAddress()
1836 encodedAddrs[j] = encodedAddr
1837 // No need to check the map again if the filter already passes.
1838 if passesFilter {
1839 continue
1840 }
1841 if _, exists := filterAddrMap[encodedAddr]; exists {
1842 passesFilter = true
1843 }
1844 }
1845 if !passesFilter {
1846 continue
1847 }
1848 var vout btcjson.Vout
1849 vout.N = uint32(i)
1850 vout.Value = amt.Amount(v.Value).ToDUO()
1851 vout.ScriptPubKey.Addresses = encodedAddrs
1852 vout.ScriptPubKey.Asm = disbuf
1853 vout.ScriptPubKey.Hex = hex.EncodeToString(v.PkScript)
1854 vout.ScriptPubKey.Type = scriptClass.String()
1855 vout.ScriptPubKey.ReqSigs = int32(reqSigs)
1856 voutList = append(voutList, vout)
1857 }
1858 return voutList
1859 }
1860 1861 // DecodeTemplateID decodes an ID that is used to uniquely identify a block template. This is mainly used as a mechanism
1862 // to track when to update clients that are using long polling for block templates. The ID consists of the previous
1863 // block hash for the associated template and the time the associated template was generated.
1864 func DecodeTemplateID(templateID string) (*chainhash.Hash, int64, error) {
1865 fields := strings.Split(templateID, "-")
1866 if len(fields) != 2 {
1867 return nil, 0, errors.New("invalid longpollid format")
1868 }
1869 prevHash, e := chainhash.NewHashFromStr(fields[0])
1870 if e != nil {
1871 return nil, 0, errors.New("invalid longpollid format")
1872 }
1873 lastGenerated, e := strconv.ParseInt(fields[1], 10, 64)
1874 if e != nil {
1875 return nil, 0, errors.New("invalid longpollid format")
1876 }
1877 return prevHash, lastGenerated, nil
1878 }
1879 1880 // EncodeTemplateID encodes the passed details into an ID that can be used to uniquely identify a block template.
1881 func EncodeTemplateID(
1882 prevHash *chainhash.Hash, lastGenerated time.Time,
1883 ) string {
1884 return fmt.Sprintf("%s-%d", prevHash.String(), lastGenerated.Unix())
1885 }
1886 1887 // FetchInputTxos fetches the outpoints from all transactions referenced by the inputs to the passed transaction by
1888 // checking the transaction mempool first then the transaction index for those already mined into blocks.
1889 func FetchInputTxos(s *Server, tx *wire.MsgTx) (
1890 map[wire.OutPoint]wire.TxOut, error,
1891 ) {
1892 mp := s.Cfg.TxMemPool
1893 originOutputs := make(map[wire.OutPoint]wire.TxOut)
1894 for txInIndex, txIn := range tx.TxIn {
1895 // Attempt to fetch and use the referenced transaction from the memory pool.
1896 origin := &txIn.PreviousOutPoint
1897 originTx, e := mp.FetchTransaction(&origin.Hash)
1898 if e == nil {
1899 txOuts := originTx.MsgTx().TxOut
1900 if origin.Index >= uint32(len(txOuts)) {
1901 errStr := fmt.Sprintf(
1902 "unable to find output %v referenced from transaction %s:%d", origin, tx.TxHash(), txInIndex,
1903 )
1904 return nil, InternalRPCError(errStr, "")
1905 }
1906 originOutputs[*origin] = *txOuts[origin.Index]
1907 continue
1908 }
1909 // Look up the location of the transaction.
1910 blockRegion, e := s.Cfg.TxIndex.TxBlockRegion(&origin.Hash)
1911 if e != nil {
1912 context := "Failed to retrieve transaction location"
1913 return nil, InternalRPCError(e.Error(), context)
1914 }
1915 if blockRegion == nil {
1916 return nil, NoTxInfoError(&origin.Hash)
1917 }
1918 // Load the raw transaction bytes from the database.
1919 var txBytes []byte
1920 e = s.Cfg.DB.View(
1921 func(dbTx database.Tx) (e error) {
1922 txBytes, e = dbTx.FetchBlockRegion(blockRegion)
1923 return e
1924 },
1925 )
1926 if e != nil {
1927 return nil, NoTxInfoError(&origin.Hash)
1928 }
1929 // Deserialize the transaction
1930 var msgTx wire.MsgTx
1931 e = msgTx.Deserialize(bytes.NewReader(txBytes))
1932 if e != nil {
1933 context := deserialfail
1934 return nil, InternalRPCError(e.Error(), context)
1935 }
1936 // Add the referenced output to the map.
1937 if origin.Index >= uint32(len(msgTx.TxOut)) {
1938 errStr := fmt.Sprintf(
1939 "unable to find output %v "+
1940 "referenced from transaction %s:%d", origin,
1941 tx.TxHash(), txInIndex,
1942 )
1943 return nil, InternalRPCError(errStr, "")
1944 }
1945 originOutputs[*origin] = *msgTx.TxOut[origin.Index]
1946 }
1947 return originOutputs, nil
1948 }
1949 1950 // FetchMempoolTxnsForAddress queries the address index for all unconfirmed transactions that involve the provided
1951 // address. The results will be limited by the number to skip and the number requested.
1952 func FetchMempoolTxnsForAddress(
1953 s *Server, addr btcaddr.Address, numToSkip,
1954 numRequested uint32,
1955 ) ([]*util.Tx, uint32) {
1956 // There are no entries to return when there are less available than the
1957 // number being skipped.
1958 mpTxns := s.Cfg.AddrIndex.UnconfirmedTxnsForAddress(addr)
1959 numAvailable := uint32(len(mpTxns))
1960 if numToSkip > numAvailable {
1961 return nil, numAvailable
1962 }
1963 // Filter the available entries based on the number to skip and number requested.
1964 rangeEnd := numToSkip + numRequested
1965 if rangeEnd > numAvailable {
1966 rangeEnd = numAvailable
1967 }
1968 return mpTxns[numToSkip:rangeEnd], numToSkip
1969 }
1970 1971 // GenCertPair generates a key/cert pair to the paths provided.
1972 func GenCertPair(certFile, keyFile string) (e error) {
1973 I.Ln("generating TLS certificates...")
1974 org := "pod autogenerated cert"
1975 validUntil := time.Now().Add(10 * 365 * 24 * time.Hour)
1976 cert, key, e := util.NewTLSCertPair(org, validUntil, nil)
1977 if e != nil {
1978 return e
1979 }
1980 // Write cert and key files.
1981 if e = ioutil.WriteFile(certFile, cert, 0666); E.Chk(e) {
1982 return e
1983 }
1984 if e = ioutil.WriteFile(keyFile, key, 0600); E.Chk(e) {
1985 if e = os.Remove(certFile); E.Chk(e) {
1986 }
1987 return e
1988 }
1989 I.Ln("Done generating TLS certificates")
1990 return nil
1991 }
1992 1993 // GetDifficultyRatio returns the proof-of-work difficulty as a multiple of the
1994 // minimum difficulty using the passed bits field from the header of a block.
1995 func GetDifficultyRatio(
1996 b uint32, params *chaincfg.Params,
1997 algo int32,
1998 ) float64 {
1999 // The minimum difficulty is the max possible proof-of-work limit bits converted
2000 // back to a number. Note this is not the same as the proof of work limit
2001 // directly because the block difficulty is encoded in a block with the compact
2002 // form which loses precision.
2003 max := bits.CompactToBig(0x1d00ffff)
2004 target := bits.CompactToBig(b)
2005 difficulty := new(big.Rat).SetFrac(max, target)
2006 outString := difficulty.FloatString(8)
2007 diff, e := strconv.ParseFloat(outString, 64)
2008 if e != nil {
2009 E.Ln("cannot get difficulty:", e)
2010 2011 return 0
2012 }
2013 return diff
2014 }
2015 2016 // NormalizeAddress returns addr with the passed default port appended if there
2017 // is not already a port specified.
2018 func NormalizeAddress(addr, defaultPort string) string {
2019 var e error
2020 _, _, e = net.SplitHostPort(addr)
2021 if e != nil {
2022 return net.JoinHostPort(addr, defaultPort)
2023 }
2024 return addr
2025 }
2026 2027 func init() {
2028 2029 RPCHandlers = RPCHandlersBeforeInit
2030 rand.Seed(time.Now().UnixNano())
2031 }
2032 2033 // InternalRPCError is a convenience function to convert an internal error to an
2034 // RPC error with the appropriate code set. It also logs the error to the RPC
2035 // Server subsystem since internal errors really should not occur.
2036 //
2037 // The context parameter is only used in the l mayo be empty if it's not needed.
2038 func InternalRPCError(errStr, context string) *btcjson.RPCError {
2039 logStr := errStr
2040 if context != "" {
2041 logStr = context + ": " + errStr
2042 }
2043 E.Ln(logStr)
2044 2045 return btcjson.NewRPCError(btcjson.ErrRPCInternal.Code, errStr)
2046 }
2047 2048 // JSONAuthFail sends a message back to the client if the http auth is rejected.
2049 func JSONAuthFail(w http.ResponseWriter) {
2050 w.Header().Add("WWW-Authenticate", `Basic realm="pod RPC"`)
2051 http.Error(w, "401 Unauthorized.", http.StatusUnauthorized)
2052 }
2053 2054 // MessageToHex serializes a message to the wire protocol encoding using the
2055 // latest protocol version and returns a hex-encoded string of the result.
2056 func MessageToHex(msg wire.Message) (string, error) {
2057 var buf bytes.Buffer
2058 if e := msg.BtcEncode(
2059 &buf, MaxProtocolVersion,
2060 wire.BaseEncoding,
2061 ); E.Chk(e) {
2062 context := fmt.Sprintf("Failed to encode msg of type %Ter", msg)
2063 return "", InternalRPCError(e.Error(), context)
2064 }
2065 return hex.EncodeToString(buf.Bytes()), nil
2066 }
2067 2068 // NewGbtWorkState returns a new instance of a GBTWorkState with all internal
2069 // fields initialized and ready to use.
2070 func NewGbtWorkState(
2071 timeSource blockchain.MedianTimeSource,
2072 algoName string,
2073 ) *GBTWorkState {
2074 return &GBTWorkState{
2075 NotifyMap: make(map[chainhash.Hash]map[int64]qu.C),
2076 TimeSource: timeSource,
2077 Algo: algoName,
2078 }
2079 }
2080 2081 // NewRPCServer returns a new instance of the RPCServer struct.
2082 func NewRPCServer(
2083 config *ServerConfig, statecfg *active.Config,
2084 podcfg *config.Config,
2085 ) (*Server, error) {
2086 rpc := Server{
2087 Cfg: *config,
2088 Config: podcfg,
2089 StateCfg: statecfg,
2090 StatusLines: make(map[int]string),
2091 GBTWorkState: NewGbtWorkState(config.TimeSource, config.Algo),
2092 HelpCacher: NewHelpCacher(),
2093 RequestProcessShutdown: qu.T(),
2094 Quit: qu.T(),
2095 }
2096 if podcfg.Username.V() != "" && podcfg.Password.V() != "" {
2097 login := podcfg.Username.V() + ":" + podcfg.Password.V()
2098 // I.Ln("login:", login)
2099 auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
2100 rpc.AuthSHA = sha256.Sum256([]byte(auth))
2101 }
2102 if podcfg.LimitUser.V() != "" && podcfg.LimitPass.V() != "" {
2103 login := podcfg.LimitUser.V() + ":" + podcfg.LimitPass.V()
2104 // I.Ln("login:", login)
2105 auth := "Basic " + base64.StdEncoding.EncodeToString([]byte(login))
2106 rpc.LimitAuthSHA = sha256.Sum256([]byte(auth))
2107 }
2108 rpc.NtfnMgr = NewWSNotificationManager(&rpc)
2109 rpc.Cfg.Chain.Subscribe(rpc.HandleBlockchainNotification)
2110 return &rpc, nil
2111 }
2112 2113 // ParseCmd parses a JSON-RPC request object into known concrete command. The
2114 // err field of the returned ParsedRPCCmd struct will contain an RPC error that
2115 // is suitable for use in replies if the command is invalid in some way such as
2116 // an unregistered command or invalid parameters.
2117 func ParseCmd(request *btcjson.Request) *ParsedRPCCmd {
2118 var parsedCmd ParsedRPCCmd
2119 parsedCmd.ID = request.ID
2120 parsedCmd.Method = request.Method
2121 cmd, e := btcjson.UnmarshalCmd(request)
2122 if e != nil {
2123 // When the error is because the method is not registered, produce a method not found RPC error.
2124 if jerr, ok := e.(btcjson.GeneralError); ok &&
2125 jerr.ErrorCode == btcjson.ErrUnregisteredMethod {
2126 parsedCmd.Err = btcjson.ErrRPCMethodNotFound
2127 return &parsedCmd
2128 }
2129 // Otherwise, some type of invalid parameters is the cause, so produce the equivalent RPC error.
2130 parsedCmd.Err = btcjson.NewRPCError(
2131 btcjson.ErrRPCInvalidParams.Code, e.Error(),
2132 )
2133 return &parsedCmd
2134 }
2135 parsedCmd.Cmd = cmd
2136 return &parsedCmd
2137 }
2138 2139 // PeerExists determines if a certain peer is currently connected given
2140 // information about all currently connected peers.
2141 //
2142 // Peer existence is determined using either a target address or node id.
2143 func PeerExists(connMgr ServerConnManager, addr string, nodeID int32) bool {
2144 for _, pp := range connMgr.ConnectedPeers() {
2145 if pp.ToPeer().ID() == nodeID || pp.ToPeer().Addr() == addr {
2146 return true
2147 }
2148 }
2149 return false
2150 }
2151 2152 // DecodeHexError is a convenience function for returning a nicely formatted RPC
2153 // error which indicates the provided hex string failed to decode.
2154 func DecodeHexError(gotHex string) *btcjson.RPCError {
2155 return btcjson.NewRPCError(
2156 btcjson.ErrRPCDecodeHexString,
2157 fmt.Sprintf(
2158 "Argument must be hexadecimal string (not %q)",
2159 gotHex,
2160 ),
2161 )
2162 }
2163 2164 // NoTxInfoError is a convenience function for returning a nicely formatted RPC
2165 // error which indicates there is no information available for the provided
2166 // transaction hash.
2167 func NoTxInfoError(txHash *chainhash.Hash) *btcjson.RPCError {
2168 return btcjson.NewRPCError(
2169 btcjson.ErrRPCNoTxInfo,
2170 fmt.Sprintf(
2171 "No information available about transaction %v",
2172 txHash,
2173 ),
2174 )
2175 }
2176 2177 // SoftForkStatus converts a ThresholdState state into a human readable string
2178 // corresponding to the particular state.
2179 func SoftForkStatus(state blockchain.ThresholdState) (string, error) {
2180 switch state {
2181 case blockchain.ThresholdDefined:
2182 return "defined", nil
2183 case blockchain.ThresholdStarted:
2184 return "started", nil
2185 case blockchain.ThresholdLockedIn:
2186 return "lockedin", nil
2187 case blockchain.ThresholdActive:
2188 return "active", nil
2189 case blockchain.ThresholdFailed:
2190 return "failed", nil
2191 default:
2192 return "", fmt.Errorf("unknown deployment state: %v", state)
2193 }
2194 }
2195 2196 // VerifyChain does?
2197 func VerifyChain(s *Server, level, depth int32) (e error) {
2198 best := s.Cfg.Chain.BestSnapshot()
2199 finishHeight := best.Height - depth
2200 if finishHeight < 0 {
2201 finishHeight = 0
2202 }
2203 I.F(
2204 "verifying chain for %d blocks at level %d",
2205 best.Height-finishHeight,
2206 level,
2207 )
2208 2209 var blk *block.Block
2210 for height := best.Height; height > finishHeight; height-- {
2211 // Level 0 just looks up the block.
2212 blk, e = s.Cfg.Chain.BlockByHeight(height)
2213 if e != nil {
2214 E.F("verify is unable to fetch block at height %d: %v", height, e)
2215 return e
2216 }
2217 powLimit := fork.GetMinDiff(
2218 fork.GetAlgoName(
2219 blk.WireBlock().Header.
2220 Version, height,
2221 ), height,
2222 )
2223 var pb *block.Block
2224 if pb, e = s.Cfg.Chain.BlockByHash(&blk.WireBlock().Header.PrevBlock); E.Chk(e) {
2225 return
2226 }
2227 // Level 1 does basic chain sanity checks.
2228 if level > 0 {
2229 e = blockchain.CheckBlockSanity(
2230 blk,
2231 powLimit,
2232 s.Cfg.TimeSource,
2233 true,
2234 blk.Height(),
2235 pb.WireBlock().Header.Timestamp,
2236 )
2237 if e != nil {
2238 E.F(
2239 "verify is unable to validate block at hash %v height %d: %v %s",
2240 blk.Hash(), height, e,
2241 )
2242 return e
2243 }
2244 }
2245 }
2246 I.Ln("chain verify completed successfully")
2247 return nil
2248 }
2249 2250 /*
2251 // handleDebugLevel handles debuglevel commands.
2252 func handleDebugLevel( s *RPCServer, cmd interface{}, closeChan <-qu.C) (interface{}, error) {
2253 c := cmd.(*json.DebugLevelCmd)
2254 // Special show command to list supported subsystems.
2255 if c.LevelSpec == "show" {
2256 return fmt.Sprintf("Supported subsystems %v",
2257 supportedSubsystems()), nil
2258 }
2259 e := parseAndSetDebugLevels(c.LevelSpec)
2260 if e != nil {
2261 return nil, &json.RPCError{
2262 Code: json.ErrRPCInvalidParams.Code,
2263 Message: err.ScriptError(),
2264 }
2265 }
2266 return "Done.", nil
2267 }
2268 */
2269 2270 // // WitnessToHex formats the passed witness stack as a slice of hex-encoded
2271 // // strings to be used in a JSON response.
2272 // func WitnessToHex(witness wire.TxWitness) []string {
2273 // // Ensure nil is returned when there are no entries versus an empty slice so it
2274 // // can properly be omitted as necessary.
2275 // if len(witness) == 0 {
2276 // return nil
2277 // }
2278 // result := make([]string, 0, len(witness))
2279 // for _, wit := range witness {
2280 // result = append(result, hex.EncodeToString(wit))
2281 // }
2282 // return result
2283 // }
2284