The getblockheader RPC
returns a block header, given its hash. The header data is returned as
a JSON object (verbose=true, default) or in raw hex form (verbose=false).
The REST interface
provides another way to query a bitcoind node. It’s not enabled by default; specify the
bitcoind -rest command-line option or rest=1 in the config file to enable this service.
The REST interface also provides a
blockheader
endpoint to fetch block headers; on mainnet, try:
This returns five block headers beginning with the specified block hash. You can specify
the number of headers by appending ?count=nnn to the URL.
The maximum number of results is 2000.
This PR proposes to allow the getblockheader RPC to return more than one header by adding an
optional count argument, bringing it in line with the functionality offered in the REST interface.
The new count argument is placed after the verbose argument. Why?
Suppose you do not want to specify the verbose argument (that is, you prefer the default),
but you do want to specify count. Is there a way to do that?
Why is the type of the count argument an
RPCArg::Type::AMOUNT
rather than a RPCArg::Type::NUM as would seem more natural?
The default number of headers to return is 1, yet there is a difference
between specifying count=1 and not specifying a count. What is this difference?
Why do these behave differently, and should they?
Why is the count limited to 2000? Do you agree with this limit?
What are the tradeoffs?
What does
this call
to
EnsureAnyChainman
do? Why are the Ensure* family of functions often used in RPC handlers?
Why does the PR modify
client.cpp?
What are the meanings of the values in the vRPCConvertParams table?
Does the getblockheader RPC work on a pruned node? Why or why not?
How does this compare with the getblock RPC?
Why is getblockheader’s block specification argument a hash instead of a height?
Related: How does the RPC determine the next header in the series (if more
than a single header is being returned)?
(Hint: how is
this loop
advanced?)
What happens if you specify a block hash that isn’t part of the
active (“best”) chain?
Bonus question: The PR
callsCChain::Next()
without cs_main being held. Is this safe?
<stickies-v> backwards compatibility! people not aware of the update would be passing what they think is their verbose argument into the count parameter, which could fail silently or explicitly
<LarryRuane> Any time we add an argument to an RPC, it should always come at the end, and it should have a default -- yes exactly, so that if there are scripts or whatever, they continue to work (assuming the default is the old behavior)
<LarryRuane> Q3 - Suppose you do not want to specify the verbose argument (that is, you prefer the default), but you do want to specify count. Is there a way to do that?
<stickies-v> I don't agree that new parameters need to have a default - it can be preferable to not have a default and make the RPC call fail explicitly, e.g. to avoid unsafe behaviour
<stickies-v> it depends on the parameter/change, really. but yes generally if it is safe we should strive to not have new parameters break existing infrastructure too much
<stickies-v> if we introduce a non-backwards compatible rpc change (e.g. deprecating a method, or some parameter(s)), users can temporarily revert to the old behaviour by starting bitcoind with `-deprecatedrpc=<method_name>` to use the previous version of that rpc, until it is usually completely removed in the next major release
<LarryRuane> so back to Q3 - Suppose you do not want to specify the verbose argument (that is, you prefer the default), but you do want to specify count. Is there a way to do that?
<LarryRuane> note that `bitcoin-cli` arguments that start with a dash are for `bitcoin-cli` itself ... without the dash, they're just passed on (with any remaining arguments) to `bitcoind`
<LarryRuane> ok let's go to the next question (but again, feel free to keep discussing previous things): 4 - Why is the type of the count argument an RPCArg::Type::AMOUNT rather than a RPCArg::Type::NUM as would seem more natural?
<enel> This was a while ago, but I think from the PR discussion you can see the reviews called for "null". And I used AMOUNT to take in both "null" string and int values. This may not be the correct RPCArg::Type.
<stickies-v> "-named` works with any RPCs" that's mostly but not entirely true, there are a few exceptions to this, e.g. "bitcoin-cli -netinfo -named level=1" does not work, you need to use positional "cli -netinfo"
<LarryRuane> I think the reason it's an AMOUNT is that an AMOUNT can be a string or a number ... and the reason we want it to be able to be a string is ... hint see the JSON spec https://www.json.org/json-en.html
<willcl_ark> So because we want legacy behaviour to use `null` rather than `0` (internally, but unlikely to come from the user) then we need to use an AMOUNT?
<stickies-v> I'm not sure about that. When using the CLI, we would already automatically convert 2 into a NUM type. When using the RPC programatically, I think there's no reason to not specify the field as an integer?
<LarryRuane> If you read the discussion in the PR, initially the default was going to be zero, but that would be strange because it would return one entry
<theStack> stickies-v: -netinfo is not a real RPC though, it's afair a pure bitcoin-cli helper that calls RPCs internally (like getnetworkinfo) and displays it in a user-friendly way
<stickies-v> `bitcoin-cli method_name` null - if method_name isn't expecting a string then I'm pretty sure null would get parsed into an actual null object and passed to the RPC like that?
<LarryRuane> I don't think that generates a null object ...it's just the JSON token "null" (which is listed in the JSON spec) ... well this is getting pretty detailed, perhaps we can continue
<LarryRuane> Q5 - The default number of headers to return is 1, yet there is a difference between specifying count=1 and not specifying a count. What is this difference? Why do these behave differently, and should they?
<stickies-v> LarryRuane: it seems to work fine with NUM. Code change here (https://github.com/bitcoin/bitcoin/pull/25261/files#r1024323103) and then cli works fine like this: `bitcoin-cli -signet getblockheader 00000086d6b2636cb2a392d45edc4ec544a10024d30141c9adf4bfd9de533b53 true null`
<LarryRuane> Great, see, review club rocks! I just tried specifying a count of 1 to REST and it returns an array (with one entry) ... zero isn't allowed
<stickies-v> LarryRuane: "Doesn't REST return 5 entries by default?" historically speaking, a big raison-d'etre for the REST interface was to make it faster to do a specific set of large requests, by e.g. reducing the amount of serialization needed, and by batching things.
<stickies-v> brunoerg: but UniValues are already nullable, so wouldn't it be more explicit to just use null? not a fan of magic values when we can avoid them, personally
<willcl_ark> I guess the limit will naturally help minimise DoS risks for the server in being asked to return huge amounts of data, but shouldn't be a concern really on the CLI, more for the REST
<stickies-v> willcl_ark: hmmm, I think safe is a misnomer. People can still use it to DDOS your node etc. It's safe in that it doesn't touch any of your wallet stuff etc, but it's very much not designed to be a public webservice
<stickies-v> adam2k: not sure which calendar you're using, but some (e.g. google calendar) actually support the UTC timezone so you don't need to change it on every DST change
<LarryRuane> As I understand it, the `Ensure*` functions ensure that the needed object is instantiated, and if not, throws an exception ... you don't want an RPC client to crash the node, so we don't want it to be an assert
<LarryRuane> sure, if anyone's still interesting, I like Q9 - Does the getblockheader RPC work on a pruned node? Why or why not? How does this compare with the getblock RPC?