diff --git a/btcjson/chainsvrcmds.go b/btcjson/chainsvrcmds.go index 9461ff8b..f3993975 100644 --- a/btcjson/chainsvrcmds.go +++ b/btcjson/chainsvrcmds.go @@ -293,6 +293,21 @@ func NewGetCFilterCmd(hash string, extended bool) *GetCFilterCmd { } } +// GetCFilterHeaderCmd defines the getcfilterheader JSON-RPC command. +type GetCFilterHeaderCmd struct { + Hash string + Extended bool +} + +// NewGetCFilterHeaderCmd returns a new instance which can be used to issue a +// getcfilterheader JSON-RPC command. +func NewGetCFilterHeaderCmd(hash string, extended bool) *GetCFilterHeaderCmd { + return &GetCFilterHeaderCmd{ + Hash: hash, + Extended: extended, + } +} + // GetChainTipsCmd defines the getchaintips JSON-RPC command. type GetChainTipsCmd struct{} @@ -771,6 +786,7 @@ func init() { MustRegisterCmd("getblockheader", (*GetBlockHeaderCmd)(nil), flags) MustRegisterCmd("getblocktemplate", (*GetBlockTemplateCmd)(nil), flags) MustRegisterCmd("getcfilter", (*GetCFilterCmd)(nil), flags) + MustRegisterCmd("getcfilterheader", (*GetCFilterHeaderCmd)(nil), flags) MustRegisterCmd("getchaintips", (*GetChainTipsCmd)(nil), flags) MustRegisterCmd("getconnectioncount", (*GetConnectionCountCmd)(nil), flags) MustRegisterCmd("getdifficulty", (*GetDifficultyCmd)(nil), flags) diff --git a/btcjson/chainsvrcmds_test.go b/btcjson/chainsvrcmds_test.go index a5b43b2d..1b2c33e7 100644 --- a/btcjson/chainsvrcmds_test.go +++ b/btcjson/chainsvrcmds_test.go @@ -330,6 +330,19 @@ func TestChainSvrCmds(t *testing.T) { Hash: "123", }, }, + { + name: "getcfilterheader", + newCmd: func() (interface{}, error) { + return btcjson.NewCmd("getcfilterheader", "123", false) + }, + staticCmd: func() interface{} { + return btcjson.NewGetCFilterHeaderCmd("123", false) + }, + marshalled: `{"jsonrpc":"1.0","method":"getcfilterheader","params":["123",false],"id":1}`, + unmarshalled: &btcjson.GetCFilterHeaderCmd{ + Hash: "123", + }, + }, { name: "getchaintips", newCmd: func() (interface{}, error) { diff --git a/rpcserver.go b/rpcserver.go index 6654cd61..a7ebf3a9 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -143,6 +143,7 @@ var rpcHandlersBeforeInit = map[string]commandHandler{ "getblockheader": handleGetBlockHeader, "getblocktemplate": handleGetBlockTemplate, "getcfilter": handleGetCFilter, + "getcfilterheader": handleGetCFilterHeader, "getconnectioncount": handleGetConnectionCount, "getcurrentnet": handleGetCurrentNet, "getdifficulty": handleGetDifficulty, @@ -260,6 +261,7 @@ var rpcLimited = map[string]struct{}{ "getblockhash": {}, "getblockheader": {}, "getcfilter": {}, + "getcfilterheader": {}, "getcurrentnet": {}, "getdifficulty": {}, "getheaders": {}, @@ -2169,6 +2171,29 @@ func handleGetCFilter(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) return hex.EncodeToString(filterBytes), nil } +// handleGetCFilterHeader implements the getcfilterheader command. +func handleGetCFilterHeader(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { + c := cmd.(*btcjson.GetCFilterHeaderCmd) + hash, err := chainhash.NewHashFromStr(c.Hash) + if err != nil { + return nil, rpcDecodeHexError(c.Hash) + } + + headerBytes, err := s.server.cfIndex.FilterHeaderByBlockHash(hash, c.Extended) + if len(headerBytes) > 0 { + rpcsLog.Debugf("Found header of committed filter for %v", hash) + } else { + rpcsLog.Debugf("Could not find header of committed filter for %v: %v", + hash, err) + return nil, &btcjson.RPCError{ + Code: btcjson.ErrRPCBlockNotFound, + Message: "Block not found", + } + } + + return hex.EncodeToString(headerBytes), nil +} + // handleGetConnectionCount implements the getconnectioncount command. func handleGetConnectionCount(s *rpcServer, cmd interface{}, closeChan <-chan struct{}) (interface{}, error) { return s.cfg.ConnMgr.ConnectedCount(), nil