Skip to content

Conversation

@tvpeter
Copy link
Collaborator

@tvpeter tvpeter commented Nov 18, 2025

Description

This PR adds the following methods:

  • getblock
  • getblockverbose
  • getblockcount
  • getblockhash
  • getblockfilter
  • getblockheader
  • getrawmempool
  • getrawtransaction

Fixes #4

Depends on #3

Checklists

All Submissions:

  • I've signed all my commits
  • I followed the contribution guidelines
  • I ran cargo fmt and cargo clippy before committing

New Features:

  • I've added tests for the new feature
  • I've added docs for the new feature
  • [] I've updated CHANGELOG.md

@oleonardolima oleonardolima self-requested a review November 19, 2025 17:38
@oleonardolima oleonardolima added the enhancement New feature or request label Nov 19, 2025
- getblockcount
- getblockhash
- getblockfilter
- getblockheader
- getrawmempool
- getrawtransaction
@tvpeter tvpeter force-pushed the feat/blockchain-rpc-methods branch from d73bb7a to 6543635 Compare November 25, 2025 05:21
- add integration tests for blockchain methods
@tvpeter tvpeter force-pushed the feat/blockchain-rpc-methods branch from 6543635 to 3a16fa4 Compare November 25, 2025 05:22
Copy link
Collaborator

@ValuedMammal ValuedMammal left a comment

Choose a reason for hiding this comment

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

So far I agree with the way you've defined the client methods. I mainly focused on reviewing the implementation of the client code, and haven't spent as much time looking at the test code yet.

By convention, the commits should appear as type(module): Summary, for example

3a16fa4 test: Add integration tests
6f95a7f feat(client): Add blockchain methods

Other notes:

  • Going forward try to have more descriptive API docs
  • We should look into testing the client using corepc_node to minimize the amount of manual testing needed and so we can run the integration tests in CI.

Comment on lines +118 to +123
let bytes: Vec<u8> = Vec::<u8>::from_hex(&hex_string).map_err(Error::HexToBytes)?;

let block: Block = deserialize(&bytes)
.map_err(|e| Error::InvalidResponse(format!("failed to deserialize block: {e}")))?;

Ok(block)
Copy link
Collaborator

Choose a reason for hiding this comment

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

For things that can be consensus decoded directly from a hex string, like Block, Header, and Transaction, I think it will be easier to use deserialize_hex and have a new Error::DecodeHex error that wraps the FromHexError.

Suggested change
let bytes: Vec<u8> = Vec::<u8>::from_hex(&hex_string).map_err(Error::HexToBytes)?;
let block: Block = deserialize(&bytes)
.map_err(|e| Error::InvalidResponse(format!("failed to deserialize block: {e}")))?;
Ok(block)
bitcoin::consensus::encode::deserialize_hex(&hex_string).map_err(Error::DecodeHex)

Comment on lines +127 to +130
pub fn get_block_verbose(&self, block_hash: &BlockHash) -> Result<GetBlockVerboseOne, Error> {
let res: GetBlockVerboseOne = self.call("getblock", &[json!(block_hash), json!(1)])?;
Ok(res)
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I assume we first want to deserialize the response as a type from corepc_types (e.g. v29::GetBlockVerboseOne), and then call into_model on it. Also we'll need a test for it.

Comment on lines +146 to +162
let raw: serde_json::Value = self.call("getblockhash", &[json!(height)])?;

let hash_str = match raw {
serde_json::Value::String(s) => s,
serde_json::Value::Object(obj) => obj
.get("hash")
.and_then(|v| v.as_str())
.ok_or_else(|| Error::InvalidResponse("getblockhash: missing 'hash' field".into()))?
.to_string(),
_ => {
return Err(Error::InvalidResponse(
"getblockhash: unexpected response type".into(),
));
}
};

BlockHash::from_str(&hash_str).map_err(Error::HexToArray)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This seems complicated. Don't we always expect the value to be String?

Suggested change
let raw: serde_json::Value = self.call("getblockhash", &[json!(height)])?;
let hash_str = match raw {
serde_json::Value::String(s) => s,
serde_json::Value::Object(obj) => obj
.get("hash")
.and_then(|v| v.as_str())
.ok_or_else(|| Error::InvalidResponse("getblockhash: missing 'hash' field".into()))?
.to_string(),
_ => {
return Err(Error::InvalidResponse(
"getblockhash: unexpected response type".into(),
));
}
};
BlockHash::from_str(&hash_str).map_err(Error::HexToArray)
let hex: String = self.call("getblockhash", &[json!(height)])?;
Ok(hex.parse()?)

}

/// Get block filter
pub fn get_block_filter(&self, block_hash: BlockHash) -> Result<GetBlockFilter, Error> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

For consistency we should decide whether the API can take a block hash by value or by reference.

Suggested change
pub fn get_block_filter(&self, block_hash: BlockHash) -> Result<GetBlockFilter, Error> {
pub fn get_block_filter(&self, block_hash: &BlockHash) -> Result<GetBlockFilter, Error> {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Add RPC Blockchain methods for Core v30

3 participants