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

Treestate RPCs #90

Merged
merged 5 commits into from
Nov 13, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 77 additions & 26 deletions zaino-serve/src/rpc/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -965,6 +965,8 @@ impl CompactTxStreamer for GrpcClient {
/// See section 3.7 of the Zcash protocol specification. It returns several other useful
/// values also (even though they can be obtained using GetBlock).
/// The block can be specified by either height or hash.
///
/// TODO: This is slow. Chain, along with other blockchain info should be saved on startup and used here [blockcache?].
fn get_tree_state<'life0, 'async_trait>(
&'life0 self,
request: tonic::Request<BlockId>,
Expand All @@ -982,43 +984,63 @@ impl CompactTxStreamer for GrpcClient {
{
println!("[TEST] Received call of get_tree_state.");
Box::pin(async {
let block_id = request.into_inner();
let hash_or_height = if block_id.height != 0 {
block_id.height.to_string()
} else {
hex::encode(block_id.hash)
};

let zebrad_client = JsonRpcConnector::new(
self.zebrad_uri.clone(),
Some("xxxxxx".to_string()),
Some("xxxxxx".to_string()),
)
.await?;

// TODO: This is slow. Chain, along with other blockchain info should be saved on startup and used here [blockcache?].
let chain = zebrad_client
let chain_info = zebrad_client
.get_blockchain_info()
.await
.map_err(|e| e.to_grpc_status())?
.chain;
let treestate = zebrad_client
.get_treestate(hash_or_height)
.await
.map_err(|e| e.to_grpc_status())?;
Ok(tonic::Response::new(TreeState {
network: chain,
height: treestate.height as u64,
hash: treestate.hash.to_string(),
time: treestate.time,
sapling_tree: treestate.sapling.inner().inner().clone(),
orchard_tree: treestate.orchard.inner().inner().clone(),
}))
let block_id = request.into_inner();
let hash_or_height = if block_id.height != 0 {
match u32::try_from(block_id.height) {
Ok(height) => {
if height >= chain_info.blocks.0 {
return Err(tonic::Status::out_of_range(
format!(
"Error: Height out of range [{}]. Height requested is greater than the best chain tip [{}].",
height, chain_info.blocks.0,
)
));
} else {
height.to_string()
}
}
Err(_) => {
return Err(tonic::Status::invalid_argument(
"Error: Height out of range. Failed to convert to u32.",
));
}
}
} else {
hex::encode(block_id.hash)
};
match zebrad_client.get_treestate(hash_or_height).await {
Ok(state) => Ok(tonic::Response::new(TreeState {
network: chain_info.chain,
height: state.height as u64,
hash: state.hash.to_string(),
time: state.time,
sapling_tree: state.sapling.inner().inner().clone(),
orchard_tree: state.orchard.inner().inner().clone(),
})),
Err(e) => {
// TODO: Hide server error from clients before release. Currently useful for dev purposes.
return Err(tonic::Status::unknown(format!(
"Error: Failed to retrieve treestate from node. Server Error: {}",
e.to_string(),
)));
}
}
})
}

/// This RPC has not been implemented as it is not currently used by zingolib.
/// If you require this RPC please open an issue or PR at the Zingo-Indexer github (https://github.com/zingolabs/zingo-indexer).
/// GetLatestTreeState returns the note commitment tree state corresponding to the chain tip.
///
/// TODO: This is slow. Chain, along with other blockchain info should be saved on startup and used here [blockcache?].
fn get_latest_tree_state<'life0, 'async_trait>(
&'life0 self,
_request: tonic::Request<Empty>,
Expand All @@ -1036,7 +1058,36 @@ impl CompactTxStreamer for GrpcClient {
{
println!("[TEST] Received call of get_latest_tree_state.");
Box::pin(async {
Err(tonic::Status::unimplemented("get_latest_tree_state not yet implemented. If you require this RPC please open an issue or PR at the Zingo-Indexer github (https://github.com/zingolabs/zingo-indexer)."))
let zebrad_client = JsonRpcConnector::new(
self.zebrad_uri.clone(),
Some("xxxxxx".to_string()),
Some("xxxxxx".to_string()),
)
.await?;
let chain_info = zebrad_client
.get_blockchain_info()
.await
.map_err(|e| e.to_grpc_status())?;
match zebrad_client
.get_treestate(chain_info.blocks.0.to_string())
.await
{
Ok(state) => Ok(tonic::Response::new(TreeState {
network: chain_info.chain,
height: state.height as u64,
hash: state.hash.to_string(),
time: state.time,
sapling_tree: state.sapling.inner().inner().clone(),
orchard_tree: state.orchard.inner().inner().clone(),
})),
Err(e) => {
// TODO: Hide server error from clients before release. Currently useful for dev purposes.
return Err(tonic::Status::unknown(format!(
"Error: Failed to retrieve treestate from node. Server Error: {}",
e.to_string(),
)));
}
}
})
}

Expand Down
Loading