kaspad/rpcclient/extensions.go
Ori Newman d2daf334a5 [NOD-241] Implement lower resolution peer rendezvous point discovery (#353)
* [NOD-241] Implement lower resolution peer rendezvous point discovery

* [NOD-241] Implement lower resolution peer rendezvous point discovery

* [NOD-241] Find exact rendezvous point

* [NOD-241] Find exact rendezvous point

* [NOD-241] Fix tests

* [NOD-241] Remove hash stop from MsgBlockLocator and add tests to MsgBlockLocator and MsgGetBlockLocator

* [NOD-241] Change everywhere startHash to hashStart and change comments

* [NOD-241] Fix locateBlockNodes to stop at hashStop

* [NOD-241] Formatted locatorSummary.

* [NOD-241] Fix node reversal

* [NOD-241] Fix hash start and hash stop order, and don't include startNode in dag.blockLocator

* [NOD-241] rename locateBlockNodes -> getBlueBlocksBetween and add a comment to it

* [NOD-241] change hash start to start hash and hash stop to stop hash

* [NOD-241] Move block locator stuff to a different file

* [NOD-241] Rename msggetblocks.go to msggetblockinvs.go

* [NOD-241] Format project

* [NOD-241] Rename rpcserverSyncManager.LocateHeaders to GetBlueBlocksHeadersBetween

* [NOD-241] Move the logic of finding the highest shared block to OnBlockLocator

* [NOD-241] Rename chainHeight -> nextChainHeight

* [NOD-241] Fix typo in comment
2019-08-19 15:35:13 +03:00

339 lines
10 KiB
Go

// Copyright (c) 2014-2017 The btcsuite developers
// Copyright (c) 2015-2017 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package rpcclient
import (
"bytes"
"encoding/hex"
"encoding/json"
"github.com/daglabs/btcd/btcjson"
"github.com/daglabs/btcd/util/daghash"
"github.com/daglabs/btcd/wire"
)
// FutureDebugLevelResult is a future promise to deliver the result of a
// DebugLevelAsync RPC invocation (or an applicable error).
type FutureDebugLevelResult chan *response
// Receive waits for the response promised by the future and returns the result
// of setting the debug logging level to the passed level specification or the
// list of of the available subsystems for the special keyword 'show'.
func (r FutureDebugLevelResult) Receive() (string, error) {
res, err := receiveFuture(r)
if err != nil {
return "", err
}
// Unmashal the result as a string.
var result string
err = json.Unmarshal(res, &result)
if err != nil {
return "", err
}
return result, nil
}
// DebugLevelAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on
// the returned instance.
//
// See DebugLevel for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) DebugLevelAsync(levelSpec string) FutureDebugLevelResult {
cmd := btcjson.NewDebugLevelCmd(levelSpec)
return c.sendCmd(cmd)
}
// DebugLevel dynamically sets the debug logging level to the passed level
// specification.
//
// The levelspec can be either a debug level or of the form:
// <subsystem>=<level>,<subsystem2>=<level2>,...
//
// Additionally, the special keyword 'show' can be used to get a list of the
// available subsystems.
//
// NOTE: This is a btcd extension.
func (c *Client) DebugLevel(levelSpec string) (string, error) {
return c.DebugLevelAsync(levelSpec).Receive()
}
// FutureGetBestBlockResult is a future promise to deliver the result of a
// GetBestBlockAsync RPC invocation (or an applicable error).
type FutureGetBestBlockResult chan *response
// Receive waits for the response promised by the future and returns the hash
// and height of the block in the longest (best) chain.
func (r FutureGetBestBlockResult) Receive() (*daghash.Hash, uint64, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, 0, err
}
// Unmarshal result as a getbestblock result object.
var bestBlock btcjson.GetBestBlockResult
err = json.Unmarshal(res, &bestBlock)
if err != nil {
return nil, 0, err
}
// Convert to hash from string.
hash, err := daghash.NewHashFromStr(bestBlock.Hash)
if err != nil {
return nil, 0, err
}
return hash, bestBlock.Height, nil
}
// GetBestBlockAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See GetBestBlock for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) GetBestBlockAsync() FutureGetBestBlockResult {
cmd := btcjson.NewGetBestBlockCmd()
return c.sendCmd(cmd)
}
// GetBestBlock returns the hash and height of the block in the longest (best)
// chain.
//
// NOTE: This is a btcd extension.
func (c *Client) GetBestBlock() (*daghash.Hash, uint64, error) {
return c.GetBestBlockAsync().Receive()
}
// FutureGetCurrentNetResult is a future promise to deliver the result of a
// GetCurrentNetAsync RPC invocation (or an applicable error).
type FutureGetCurrentNetResult chan *response
// Receive waits for the response promised by the future and returns the network
// the server is running on.
func (r FutureGetCurrentNetResult) Receive() (wire.BitcoinNet, error) {
res, err := receiveFuture(r)
if err != nil {
return 0, err
}
// Unmarshal result as an int64.
var net int64
err = json.Unmarshal(res, &net)
if err != nil {
return 0, err
}
return wire.BitcoinNet(net), nil
}
// GetCurrentNetAsync returns an instance of a type that can be used to get the
// result of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See GetCurrentNet for the blocking version and more details.
//
// NOTE: This is a btcd extension.
func (c *Client) GetCurrentNetAsync() FutureGetCurrentNetResult {
cmd := btcjson.NewGetCurrentNetCmd()
return c.sendCmd(cmd)
}
// GetCurrentNet returns the network the server is running on.
//
// NOTE: This is a btcd extension.
func (c *Client) GetCurrentNet() (wire.BitcoinNet, error) {
return c.GetCurrentNetAsync().Receive()
}
// FutureGetHeadersResult is a future promise to deliver the result of a
// getheaders RPC invocation (or an applicable error).
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
type FutureGetHeadersResult chan *response
// Receive waits for the response promised by the future and returns the
// getheaders result.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (r FutureGetHeadersResult) Receive() ([]wire.BlockHeader, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a slice of strings.
var result []string
err = json.Unmarshal(res, &result)
if err != nil {
return nil, err
}
// Deserialize the []string into []wire.BlockHeader.
headers := make([]wire.BlockHeader, len(result))
for i, headerHex := range result {
serialized, err := hex.DecodeString(headerHex)
if err != nil {
return nil, err
}
err = headers[i].Deserialize(bytes.NewReader(serialized))
if err != nil {
return nil, err
}
}
return headers, nil
}
// GetTopHeadersAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the returned instance.
//
// See GetTopHeaders for the blocking version and more details.
func (c *Client) GetTopHeadersAsync(startHash *daghash.Hash) FutureGetHeadersResult {
var hash *string
if startHash != nil {
hash = btcjson.String(startHash.String())
}
cmd := btcjson.NewGetTopHeadersCmd(hash)
return c.sendCmd(cmd)
}
// GetTopHeaders sends a getTopHeaders rpc command to the server.
func (c *Client) GetTopHeaders(startHash *daghash.Hash) ([]wire.BlockHeader, error) {
return c.GetTopHeadersAsync(startHash).Receive()
}
// GetHeadersAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the returned instance.
//
// See GetHeaders for the blocking version and more details.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) GetHeadersAsync(startHash, stopHash *daghash.Hash) FutureGetHeadersResult {
startHashStr := ""
if startHash != nil {
startHashStr = startHash.String()
}
stopHashStr := ""
if stopHash != nil {
stopHashStr = stopHash.String()
}
cmd := btcjson.NewGetHeadersCmd(startHashStr, stopHashStr)
return c.sendCmd(cmd)
}
// GetHeaders mimics the wire protocol getheaders and headers messages by
// returning all headers on the main chain after the first known block in the
// locators, up until a block hash matches stopHash.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) GetHeaders(startHash, stopHash *daghash.Hash) ([]wire.BlockHeader, error) {
return c.GetHeadersAsync(startHash, stopHash).Receive()
}
// FutureSessionResult is a future promise to deliver the result of a
// SessionAsync RPC invocation (or an applicable error).
type FutureSessionResult chan *response
// Receive waits for the response promised by the future and returns the
// session result.
func (r FutureSessionResult) Receive() (*btcjson.SessionResult, error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a session result object.
var session btcjson.SessionResult
err = json.Unmarshal(res, &session)
if err != nil {
return nil, err
}
return &session, nil
}
// SessionAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See Session for the blocking version and more details.
//
// NOTE: This is a btcsuite extension.
func (c *Client) SessionAsync() FutureSessionResult {
// Not supported in HTTP POST mode.
if c.config.HTTPPostMode {
return newFutureError(ErrWebsocketsRequired)
}
cmd := btcjson.NewSessionCmd()
return c.sendCmd(cmd)
}
// Session returns details regarding a websocket client's current connection.
//
// This RPC requires the client to be running in websocket mode.
//
// NOTE: This is a btcsuite extension.
func (c *Client) Session() (*btcjson.SessionResult, error) {
return c.SessionAsync().Receive()
}
// FutureVersionResult is a future promise to deliver the result of a version
// RPC invocation (or an applicable error).
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
type FutureVersionResult chan *response
// Receive waits for the response promised by the future and returns the version
// result.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (r FutureVersionResult) Receive() (map[string]btcjson.VersionResult,
error) {
res, err := receiveFuture(r)
if err != nil {
return nil, err
}
// Unmarshal result as a version result object.
var vr map[string]btcjson.VersionResult
err = json.Unmarshal(res, &vr)
if err != nil {
return nil, err
}
return vr, nil
}
// VersionAsync returns an instance of a type that can be used to get the result
// of the RPC at some future time by invoking the Receive function on the
// returned instance.
//
// See Version for the blocking version and more details.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) VersionAsync() FutureVersionResult {
cmd := btcjson.NewVersionCmd()
return c.sendCmd(cmd)
}
// Version returns information about the server's JSON-RPC API versions.
//
// NOTE: This is a btcsuite extension ported from
// github.com/decred/dcrrpcclient.
func (c *Client) Version() (map[string]btcjson.VersionResult, error) {
return c.VersionAsync().Receive()
}