Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpcclient: Add getblockfilter JSON-RPC client command #1579

Merged
merged 1 commit into from
Aug 31, 2020

Conversation

lindlof
Copy link
Contributor

@lindlof lindlof commented May 16, 2020

Adds getblockfilter call to JSON-RPC client.

@lindlof lindlof changed the title Add getblockfilter JSON-RPC client command rpcclient: Add getblockfilter JSON-RPC client command May 16, 2020
Comment on lines +172 to +182
// NewGetBlockFilterCmd returns a new instance which can be used to issue a
// getblockfilter JSON-RPC command.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We generally add the following comment whenever there are optional arguments.

Suggested change
// NewGetBlockFilterCmd returns a new instance which can be used to issue a
// getblockfilter JSON-RPC command.
// 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.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right on. Added these.

Comment on lines 213 to 214
Filter string `json:"filter"`
Header string `json:"header"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Whenever possible, adding extra comments always helps, since it shows up beautifully on pkg.go.dev.

Suggested change
Filter string `json:"filter"`
Header string `json:"header"`
Filter string `json:"filter"` // the hex-encoded filter data
Header string `json:"header"` // the hex-encoded filter header

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good shout makes the result easier to consume. Didn't consider pkg.go.dev

Also added comments to GetBlockFilterCmd fields though they're not as visible through rpcclient.

Copy link
Contributor

@onyb onyb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. 👍 Just added some minor remarks about comments.

Copy link
Contributor Author

@lindlof lindlof left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appended the changes to the original commit. Now I realised perhaps it would be easier for reviewers if I would have introduced fixes in a new commit and in the end you'd squash merge.

@@ -163,6 +163,24 @@ func NewGetBlockCountCmd() *GetBlockCountCmd {
return &GetBlockCountCmd{}
}

// GetBlockFilterCmd defines the getblockfilter JSON-RPC command.
type GetBlockFilterCmd struct {
BlockHash string // The hash of the block
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest using the chainhash.Hash type here.

Copy link
Contributor Author

@lindlof lindlof May 25, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These btcjson.*Cmd structs are generally using basic types assigned through NewCmd constructors. btcjson.assignField function makes a conversion from command-line input to the basic type that NewCmd takes.

While it's possible to implement JSON Unmarshaler to use a more specific type as you suggest I think the idea is to keep these types as stupid as possible.

In the JSON-RPC request the type will be string that the server has to unmarshal. Just taking the string from command-line and converting it to a JSON-RPC request without any semantic validation offloads the validation to server. Doing validation client-side would result in double validation which would be more fragile and more complex to consume.

As I see it GetBlockFilterCmd defines the JSON-RPC command which shouldn't be aware of non-JSON types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rpcclient.GetBlockFilter now takes chainhash.Hash. rpcclient is where to take the Golang call and transform it to JSON.

// GetBlockFilterCmd defines the getblockfilter JSON-RPC command.
type GetBlockFilterCmd struct {
BlockHash string // The hash of the block
FilterType *string // The type name of the filter, default=basic
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at the Bitcoin Core codebase, "basic" is the only known filter type there. Are there any other known types out in the wild? Might make sense to create a custom type for this instead of passing in a string.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haven't seen others than types basic. Not sure how standard the filter names are but first see
my previous response about doing validation only server-side.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can see that for instance in btcjson.AddNodeCmd there is a custom type AddNodeSubCmd being used but in that case the options are in the spec.

In case of getblockfilter the spec only mentions basic which is the default anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BIP 157 describes that initial filter types are defined in BIP 158 which defines only the Basic filter.

Bitcoin Core CLI seems to allow describing any getblockfilter in a CLI command and will send the request server which will reject any unknown filter type name. I'd have the similar behavior in btcctl and just handle this as a string.

In rpcclient the second parameter of rpcclient.GetBlockFilter could have a more specific type, for instance we can call it FilterTypeName. For the server-side implementation of getblockfilter to resolve the filter for the name we can map the basic FilterTypeName to wire.GCSFilterRegular.

I'll look at how to best implement FilterTypeName. It seems a good idea for rpcclient.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good points about validation, as well as that in this specific scenario it might not be possible to construct a good type.

Just so you understand my reasoning: custom types are (at least for me) very beneficial when coding with btcd packages as a library, because they limit the scope of possibilities and place you on a narrower path of "valid actions". Does this make sense?

Copy link
Contributor Author

@lindlof lindlof May 26, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed definitely should have types for the rpcclient API. Sorry about the fuss - with the way you suggested the CLI mechanism works just as well when defining FilterTypeName as a type of string (facepalm)

Please see the new commit 9d7bd87

rpcclient/chain.go Outdated Show resolved Hide resolved
Copy link
Contributor

@torkelrogstad torkelrogstad left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 🥇

Comment on lines +81 to +85
func NewFilterTypeName(v FilterTypeName) *FilterTypeName {
p := new(FilterTypeName)
*p = v
return p
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was about to comment that it might make sense to make the const FilterTypeBasic a var so it would be possible to do &FilterTypeBasic, but seems like you already anticipated this and added a nice solution:-)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wasn't super happy about adding helper for this but it allows using const instead of var and is pretty consistent with how rpcclient API is used

Add type for second getblockfilter param
@lindlof
Copy link
Contributor Author

lindlof commented May 27, 2020

@onyb @torkelrogstad Squashed ready to merge

Copy link
Contributor

@Rjected Rjected left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The rpcclient implementation looks good, but since our existing getcfilter does the exact same thing, I think we can just alias getblockfilter to the existing code for GetCFilterCmd, and skip rewriting filter types.

@lindlof
Copy link
Contributor Author

lindlof commented Jul 15, 2020

The rpcclient implementation looks good, but since our existing getcfilter does the exact same thing, I think we can just alias getblockfilter to the existing code for GetCFilterCmd, and skip rewriting filter types.

@Rjected GetCFilterCmd takes byte filtertype and GetBlockFilterCmd takes string filtertype. Not sure if there is any sensible way to reuse GetCFilterCmd. The response type is different too. Do miss something?

Copy link
Contributor

@Rjected Rjected left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lindlof sorry for the late response. Yeah I get what you're saying now, unless we want to deviate from core we need these new types. If we ever decide to support this on the server side, we could potentially reuse implementation but yeah I don't see how the client implementation could really benefit from the type reuse.

Copy link
Member

@jcvernaleo jcvernaleo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@jcvernaleo jcvernaleo merged commit b68c50e into btcsuite:master Aug 31, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants