diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 1292e46c..63834585 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -200,6 +200,33 @@ func NewGetBlockCountCmd() *GetBlockCountCmd { return &GetBlockCountCmd{} } +// FilterTypeName defines the type used in the getblockfilter JSON-RPC command for the +// filter type field. +type FilterTypeName string + +const ( + // FilterTypeBasic is the basic filter type defined in BIP0158. + FilterTypeBasic FilterTypeName = "basic" +) + +// GetBlockFilterCmd defines the getblockfilter JSON-RPC command. +type GetBlockFilterCmd struct { + BlockHash string // The hash of the block + FilterType *FilterTypeName // The type name of the filter, default=basic +} + +// NewGetBlockFilterCmd returns a new instance which can be used to issue a +// getblockfilter JSON-RPC command. +// +// The parameters which are pointers indicate they are optional. Passing nil +// for optional parameters will use the default value. +func NewGetBlockFilterCmd(blockHash string, filterType *FilterTypeName) *GetBlockFilterCmd { + return &GetBlockFilterCmd{ + BlockHash: blockHash, + FilterType: filterType, + } +} + // GetBlockHashCmd defines the getblockhash JSON-RPC command. type GetBlockHashCmd struct { Index int64 @@ -909,6 +936,7 @@ func init() { MustRegisterCmd("getblock", (*GetBlockCmd)(nil), flags) MustRegisterCmd("getblockchaininfo", (*GetBlockChainInfoCmd)(nil), flags) MustRegisterCmd("getblockcount", (*GetBlockCountCmd)(nil), flags) + MustRegisterCmd("getblockfilter", (*GetBlockFilterCmd)(nil), flags) MustRegisterCmd("getblockhash", (*GetBlockHashCmd)(nil), flags) MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblockstats", (*GetBlockStatsCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index 9aeac49e..9087135d 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -334,6 +334,28 @@ func TestChainSvrCmds(t *testing.T) { marshalled: `{"jsonrpc":"1.0","method":"getblockcount","params":[],"id":1}`, unmarshalled: &btcjson.GetBlockCountCmd{}, }, + { + name: "getblockfilter", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockfilter", "0000afaf") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockFilterCmd("0000afaf", nil) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockfilter","params":["0000afaf"],"id":1}`, + unmarshalled: &btcjson.GetBlockFilterCmd{"0000afaf", nil}, + }, + { + name: "getblockfilter optional filtertype", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getblockfilter", "0000afaf", "basic") + }, + staticCmd: func() interface{} { + return btcjson.NewGetBlockFilterCmd("0000afaf", btcjson.NewFilterTypeName(btcjson.FilterTypeBasic)) + }, + marshalled: `{"jsonrpc":"1.0","method":"getblockfilter","params":["0000afaf","basic"],"id":1}`, + unmarshalled: &btcjson.GetBlockFilterCmd{"0000afaf", btcjson.NewFilterTypeName(btcjson.FilterTypeBasic)}, + }, { name: "getblockhash", newCmd: func() (interface{}, error) { diff --git a/btcjson/chainsvrresults.go b/btcjson/chainsvrresults.go index 63225802..5699c53c 100644 --- a/btcjson/chainsvrresults.go +++ b/btcjson/chainsvrresults.go @@ -226,6 +226,13 @@ type GetBlockChainInfoResult struct { *UnifiedSoftForks } +// GetBlockFilterResult models the data returned from the getblockfilter +// command. +type GetBlockFilterResult struct { + Filter string `json:"filter"` // the hex-encoded filter data + Header string `json:"header"` // the hex-encoded filter header +} + // GetBlockTemplateResultTx models the transactions field of the // getblocktemplate command. type GetBlockTemplateResultTx struct { diff --git a/btcjson/helpers.go b/btcjson/helpers.go index d9b452e7..eda26cb8 100644 --- a/btcjson/helpers.go +++ b/btcjson/helpers.go @@ -75,3 +75,11 @@ func String(v string) *string { *p = v return p } + +// NewFilterTypeName is a helper routine that allocates a new FilterTypeName value to store v and +// returns a pointer to it. This is useful when assigning optional parameters. +func NewFilterTypeName(v FilterTypeName) *FilterTypeName { + p := new(FilterTypeName) + *p = v + return p +} diff --git a/rpcclient/chain.go b/rpcclient/chain.go index c0c6a159..4d7c455d 100644 --- a/rpcclient/chain.go +++ b/rpcclient/chain.go @@ -508,6 +508,44 @@ func (c *Client) GetBlockChainInfo() (*btcjson.GetBlockChainInfoResult, error) { return c.GetBlockChainInfoAsync().Receive() } +// FutureGetBlockFilterResult is a future promise to deliver the result of a +// GetBlockFilterAsync RPC invocation (or an applicable error). +type FutureGetBlockFilterResult chan *response + +// Receive waits for the response promised by the future and returns block filter +// result provided by the server. +func (r FutureGetBlockFilterResult) Receive() (*btcjson.GetBlockFilterResult, error) { + res, err := receiveFuture(r) + if err != nil { + return nil, err + } + + var blockFilter btcjson.GetBlockFilterResult + err = json.Unmarshal(res, &blockFilter) + if err != nil { + return nil, err + } + + return &blockFilter, nil +} + +// GetBlockFilterAsync 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 GetBlockFilter for the blocking version and more details. +func (c *Client) GetBlockFilterAsync(blockHash chainhash.Hash, filterType *btcjson.FilterTypeName) FutureGetBlockFilterResult { + hash := blockHash.String() + + cmd := btcjson.NewGetBlockFilterCmd(hash, filterType) + return c.sendCmd(cmd) +} + +// GetBlockFilter retrieves a BIP0157 content filter for a particular block. +func (c *Client) GetBlockFilter(blockHash chainhash.Hash, filterType *btcjson.FilterTypeName) (*btcjson.GetBlockFilterResult, error) { + return c.GetBlockFilterAsync(blockHash, filterType).Receive() +} + // FutureGetBlockHashResult is a future promise to deliver the result of a // GetBlockHashAsync RPC invocation (or an applicable error). type FutureGetBlockHashResult chan *response