Skip to content

Add verbosity support to getblockheader RPC#1006

Merged
Davidson-Souza merged 3 commits into
getfloresta:masterfrom
moisesPompilio:refactor-get-header
May 15, 2026
Merged

Add verbosity support to getblockheader RPC#1006
Davidson-Souza merged 3 commits into
getfloresta:masterfrom
moisesPompilio:refactor-get-header

Conversation

@moisesPompilio
Copy link
Copy Markdown
Collaborator

Description and Notes

Add support for the verbosity parameter to the getblockheader RPC, bringing it in line with Bitcoin Core behavior.

Previously, getblockheader only supported the raw mode, returning the block header as a hexadecimal string. With this change, it now also supports verbose mode, returning a structured JSON object with the full block header details.

The verbose response follows the same RPC shape and default verbosity behavior as Bitcoin Core. In addition, the verbose output reuses the same header formatting logic as getblock, since both methods expose the same header fields. To avoid duplication, the shared header data is now produced by a helper function that returns a fully populated object ready for use by both RPCs.

Closes: #606

How to verify the changes you have done?

  • Run the integration tests for getblockheader and confirm they pass.
  • Verify that the integration test compares Floresta's getblockheader output against Bitcoin Core correctly.
  • Check that the RPC documentation for getblockheader has been updated properly.
  • Confirm that getblockheader is exposed with the verbosity parameter in the CLI.
  • Test both verbosity modes and ensure the returned fields match the expected raw and verbose formats.

@moisesPompilio moisesPompilio self-assigned this Apr 27, 2026
@moisesPompilio moisesPompilio added the ecosystem support Enable interoperability, compatibility and practical integration with the broader Bitcoin ecosystem label Apr 27, 2026
@github-project-automation github-project-automation Bot moved this to Backlog in Floresta Apr 27, 2026
@moisesPompilio moisesPompilio added this to the Q2/2026 milestone Apr 27, 2026
@moisesPompilio moisesPompilio moved this from Backlog to In progress in Floresta Apr 27, 2026
@moisesPompilio moisesPompilio moved this from In progress to Needs review in Floresta Apr 27, 2026
/// Formats block header data for JSON-RPC responses.
/// Computes all necessary header fields (height, confirmations, chain work, difficulty, etc.)
/// in the correct format ready for `getblockheader` and `getblock` RPC methods.
fn handle_get_block_header_verbose(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice work @moisesPompilio ..
little nit: handle_get_block_header_verbose reads like a request handler, bt here it just formats...i'd suggest format_block_header_verbose or block_header_verbose_fields .

@Davidson-Souza
Copy link
Copy Markdown
Member

Needs rebase.

@moisesPompilio moisesPompilio force-pushed the refactor-get-header branch from 34c2fe2 to 1cf7b61 Compare May 1, 2026 14:14
confirmations,
difficulty,
hash: header.block_hash().to_string(),
height: height as i64,
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I dunno what is the project's default approach for using as, since it can be unsafe (as is same as try_into().unwrap()).

Since all the casts here goes from u32 to i64 this is safe, but it can silently introduce a panic if the source type changes to something bigger.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good catch. I replaced the as casts with into, so it warns me if the conversion is safe. However, some of them were not safe, so I used try_into instead and added automatic error conversion to report the overflow that happened

@lorenzolfm
Copy link
Copy Markdown
Contributor

LGTM

@moisesPompilio moisesPompilio force-pushed the refactor-get-header branch 2 times, most recently from 849cc5d to 257d59c Compare May 1, 2026 15:55
@moisesPompilio
Copy link
Copy Markdown
Collaborator Author

257d59c I did the rebase and converted the test change I made to the pytest style. I also started replacing as with into and try_into to make the code safer.


/// Formats block header data for JSON-RPC responses.
/// Computes all necessary header fields (height, confirmations, chain work, difficulty, etc.)
/// in the correct format ready for `getblockheader` and `getblock` RPC methods.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
/// in the correct format ready for `getblockheader` and `getblock` RPC methods.
/// Same as `get_block_header_inner` but verbose.

I prefer something more straight to the point, cutting implicit info, partially mentioning aditional fields is unecessary since one can check this looking at the returned struct but the latter is good too

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

Comment on lines +330 to +342
let height = header.get_height(&self.chain)?;
let median_time = header.calculate_median_time_past(&self.chain)?;
let chain_work = header.calculate_chain_work(&self.chain)?.to_string_hex();
let confirmations = header.get_confirmations(&self.chain)?;
let version_hex = header.get_version_hex();

let next_block_hash = header
.get_next_block_hash(&self.chain)?
.map(|h| h.to_string());

let bits = header.get_bits_hex();
let difficulty = header.get_difficulty();
let target = header.get_target_hex();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The extensions are shining

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, getblock and getblockheader differ in that one includes the transactions and the other doesn’t, basically. The rest of the fields would be the same.


#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum GetBlockHeaderRes {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

docstrings for this one ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done


#[derive(Debug, Deserialize, Serialize)]
#[serde(untagged)]
pub enum GetBlockHeaderRes {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Docstrings for this one too ?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

Comment thread doc/rpc/getblockheader.md Outdated
- `previousblockhash` - (string, optional) The hash of the previous block.
- `nextblockhash` - (string, optional) The hash of the next block.

### Error Enum `CommandError`
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
### Error Enum `CommandError`
### Error Enum

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

Comment thread tests/floresta-cli/getblockheader.py Outdated
Comment on lines +43 to +44
# This causes the median time of recent blocks to be different from earlier blocks, which is
# necessary for proper testing.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
# This causes the median time of recent blocks to be different from earlier blocks, which is
# necessary for proper testing.
# We need different timestamps to cause the median time of recent blocks to be different from earlier blocks, which is
# necessary for proper testing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

MempoolAccept(MempoolError),

/// A numeric conversion overflows, e.g., u64 to u32
ConversionOverflow(String),
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Wait, it feels really off to have this kind of error here, surely theres an existing alternative for this

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I don’t think there are alternatives, because there are some situations where we’re working with usize, whose size varies. So sometimes we need to convert usize to u32 or i64, and there’s a risk of overflow depending on the computer’s architecture.

@luisschwab
Copy link
Copy Markdown
Member

Needs rebase

Methods::GetBlockHeader { hash } => {
serde_json::to_string_pretty(&client.get_block_header(hash)?)?
Methods::GetBlockHeader { hash, verbosity } => {
serde_json::to_string_pretty(&client.get_block_header(hash, verbosity)?)?
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

65acc75 and 481e59c
can be squashed, they pretty much jut add verbosity support for getblockheader

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

node_manager: Any = None

@pytest.mark.rpc
def test_get_blockheader(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This test is very very nice. Can you extend it with failures cases too?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

@moisesPompilio moisesPompilio force-pushed the refactor-get-header branch 3 times, most recently from 739a8c5 to d04f180 Compare May 14, 2026 18:23
@moisesPompilio
Copy link
Copy Markdown
Collaborator Author

d04f180 I rebased and made the changes requested in @jaoleal review comments.

@moisesPompilio moisesPompilio requested a review from jaoleal May 14, 2026 18:27
Copy link
Copy Markdown
Member

@jaoleal jaoleal left a comment

Choose a reason for hiding this comment

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

ACK d04f180

Comment on lines +143 to +146
Raw(String),
/// A verbose block header, as returned by `getblockheader` with verbosity true
Verbose(Box<GetBlockHeaderVerbose>),
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
Raw(String),
/// A verbose block header, as returned by `getblockheader` with verbosity true
Verbose(Box<GetBlockHeaderVerbose>),
}
Raw(String),
/// A verbose block header, as returned by `getblockheader` with verbosity true
Verbose(Box<GetBlockHeaderVerbose>),
}

nit

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I had a pending review with this, forgot to publish.

Agree 👍

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done

@Micah-Shallom
Copy link
Copy Markdown
Contributor

ACK d04f180

Implement verbosity parameter for `getblockheader` RPC with both raw and verbose modes.
Extract `get_block_header_inner()` helper method to retrieve headers by hash, consolidating previously
duplicated logic. Introduce `get_block_header_verbose_inner()` for consistent header
formatting across RPC methods. Expose the verbosity optional parameter in the FlorestaRPC
trait's `get_block_header` method, allowing clients to choose between raw (hex string) and
verbose (JSON object) response formats.

Both `getblockheader` and `getblock` now reuse the same header formatting logic, reducing
code duplication and improving maintainability.

Closes: getfloresta#606
Improve the getblockheader integration test to validate responses across multiple
block scenarios: genesis block, a random block from the chain, and the tip block.
Test both verbosity modes (false and true) to ensure correct formatting in all cases.
Rename helper method to validate_headers_match for better clarity.
@moisesPompilio
Copy link
Copy Markdown
Collaborator Author

44fffb5 I fixed the nit identified by @jaoleal .

@jaoleal

This comment was marked as duplicate.

Copy link
Copy Markdown
Member

@jaoleal jaoleal left a comment

Choose a reason for hiding this comment

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

ACK 44fffb5

Copy link
Copy Markdown
Member

@Davidson-Souza Davidson-Souza left a comment

Choose a reason for hiding this comment

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

ACK 44fffb5

@Davidson-Souza Davidson-Souza merged commit d1ea3e9 into getfloresta:master May 15, 2026
11 checks passed
@github-project-automation github-project-automation Bot moved this from Needs review to Done in Floresta May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ecosystem support Enable interoperability, compatibility and practical integration with the broader Bitcoin ecosystem

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Missing fields in getblockheader rpc

6 participants