From 5ce0ed600997eafaed25ad4936c1d84ec6ad2b5a Mon Sep 17 00:00:00 2001 From: Alex Date: Fri, 16 Dec 2016 16:59:31 -0700 Subject: [PATCH] Port `getheaders` JSON-RPC command from dcrd --- extensions.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/extensions.go b/extensions.go index c0c0c8e8..e5315b9a 100644 --- a/extensions.go +++ b/extensions.go @@ -1,12 +1,14 @@ -// Copyright (c) 2014-2016 The btcsuite developers -// Copyright (c) 2015-2016 The Decred developers +// 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 btcrpcclient import ( + "bytes" "encoding/base64" + "encoding/hex" "encoding/json" "fmt" @@ -233,6 +235,76 @@ 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 +} + +// 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(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) FutureGetHeadersResult { + locators := make([]string, len(blockLocators)) + for i := range blockLocators { + locators[i] = blockLocators[i].String() + } + hash := "" + if hashStop != nil { + hash = hashStop.String() + } + cmd := btcjson.NewGetHeadersCmd(locators, hash) + 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 hashStop. +// +// NOTE: This is a btcsuite extension ported from +// github.com/decred/dcrrpcclient. +func (c *Client) GetHeaders(blockLocators []chainhash.Hash, hashStop *chainhash.Hash) ([]wire.BlockHeader, error) { + return c.GetHeadersAsync(blockLocators, hashStop).Receive() +} + // FutureExportWatchingWalletResult is a future promise to deliver the result of // an ExportWatchingWalletAsync RPC invocation (or an applicable error). type FutureExportWatchingWalletResult chan *response