From c27f268d676b424b5de44ab2d471a05e4649872a Mon Sep 17 00:00:00 2001 From: al amoda Date: Wed, 13 Aug 2025 18:28:50 -0400 Subject: [PATCH 01/33] begin impl getblockheader, rough in backends --- zaino-state/src/backends/fetch.rs | 18 ++++++++++++++++-- zaino-state/src/backends/state.rs | 14 +++++++++++--- zaino-state/src/indexer.rs | 15 ++++++++++++++- 3 files changed, 41 insertions(+), 6 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index bd183f897..ba145da15 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -13,8 +13,8 @@ use zebra_rpc::{ client::{GetSubtreesByIndexResponse, GetTreestateResponse, ValidateAddressResponse}, methods::{ AddressBalance, AddressStrings, GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, - GetBlockHashResponse, GetBlockchainInfoResponse, GetInfo, GetRawTransaction, - SentTransactionHash, + GetBlockHashResponse, GetBlockHeaderResponse, GetBlockchainInfoResponse, GetInfo, + GetRawTransaction, SentTransactionHash, }, }; @@ -202,6 +202,20 @@ impl ZcashIndexer for FetchServiceSubscriber { Ok(self.fetcher.get_info().await?.into()) } + // TODO add original implementation + /// getblockheader "hash" ( verbose ) + /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. + /// If verbose is true, returns an Object with information about blockheader . + /// + /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// method: post + /// tags: blockchain + /// + // TODO compare with getinfo + async fn get_block_header(&self) -> Result { + panic!("demo only"); + } + /// Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct. /// /// zcashd reference: [`getblockchaininfo`](https://zcash.github.io/rpc/getblockchaininfo.html) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 2ae4b2f33..c19205899 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -51,9 +51,9 @@ use zebra_rpc::{ methods::{ chain_tip_difficulty, AddressBalance, AddressStrings, ConsensusBranchIdHex, GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, GetBlockHash, GetBlockHeader, - GetBlockHeaderObject, GetBlockTransaction, GetBlockTrees, GetBlockchainInfoResponse, - GetInfo, GetRawTransaction, NetworkUpgradeInfo, NetworkUpgradeStatus, SentTransactionHash, - TipConsensusBranch, + GetBlockHeaderObject, GetBlockHeaderResponse, GetBlockTransaction, GetBlockTrees, + GetBlockchainInfoResponse, GetInfo, GetRawTransaction, NetworkUpgradeInfo, + NetworkUpgradeStatus, SentTransactionHash, TipConsensusBranch, }, server::error::LegacyCode, sync::init_read_state_with_syncer, @@ -410,6 +410,7 @@ impl StateServiceSubscriber { }; let response = if !verbose { + // TODO --> +Response GetBlockHeader::Raw(HexData(header.zcash_serialize_to_vec()?)) } else { let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state @@ -489,6 +490,7 @@ impl StateServiceSubscriber { next_block_hash, ); + // TODO --> +Response GetBlockHeader::Object(Box::new(block_header)) }; @@ -727,9 +729,11 @@ impl StateServiceSubscriber { ); let header_obj = match header? { + // TODO --> +Response GetBlockHeader::Raw(_hex_data) => unreachable!( "`true` was passed to get_block_header, an object should be returned" ), + // TODO --> +Response GetBlockHeader::Object(get_block_header_object) => get_block_header_object, }; @@ -852,6 +856,10 @@ impl ZcashIndexer for StateServiceSubscriber { .map_err(|e| StateServiceError::Custom(e.to_string())) } + async fn get_block_header(&self) -> Result { + panic!("ouch"); + } + async fn get_difficulty(&self) -> Result { chain_tip_difficulty( self.config.network.clone(), diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index a75d03c80..1c30455fc 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -19,7 +19,8 @@ use zebra_rpc::{ client::{GetSubtreesByIndexResponse, GetTreestateResponse, ValidateAddressResponse}, methods::{ AddressBalance, AddressStrings, GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, - GetBlockHash, GetBlockchainInfoResponse, GetInfo, GetRawTransaction, SentTransactionHash, + GetBlockHash, GetBlockHeaderResponse, GetBlockchainInfoResponse, GetInfo, + GetRawTransaction, SentTransactionHash, }, }; @@ -165,6 +166,18 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// [required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89) async fn get_blockchain_info(&self) -> Result; + // TODO add original implementation + /// getblockheader "hash" ( verbose ) + /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. + /// If verbose is true, returns an Object with information about blockheader . + /// + /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// method: post + /// tags: blockchain + /// + // TODO compare with getinfo + async fn get_block_header(&self) -> Result; + /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. /// /// zcashd reference: [`getdifficulty`](https://zcash.github.io/rpc/getdifficulty.html) From 18371852cb32b378d1272ab3b56b734aa1fae740 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 14 Aug 2025 10:58:08 -0400 Subject: [PATCH 02/33] change deprecated GetBlockHeader to equivalent GetBlockHeaderResponse in state.rs --- zaino-state/src/backends/state.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index c19205899..9cf2ca33b 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -50,10 +50,10 @@ use zebra_rpc::{ }, methods::{ chain_tip_difficulty, AddressBalance, AddressStrings, ConsensusBranchIdHex, - GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, GetBlockHash, GetBlockHeader, - GetBlockHeaderObject, GetBlockHeaderResponse, GetBlockTransaction, GetBlockTrees, - GetBlockchainInfoResponse, GetInfo, GetRawTransaction, NetworkUpgradeInfo, - NetworkUpgradeStatus, SentTransactionHash, TipConsensusBranch, + GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, GetBlockHash, GetBlockHeaderObject, + GetBlockHeaderResponse, GetBlockTransaction, GetBlockTrees, GetBlockchainInfoResponse, + GetInfo, GetRawTransaction, NetworkUpgradeInfo, NetworkUpgradeStatus, SentTransactionHash, + TipConsensusBranch, }, server::error::LegacyCode, sync::init_read_state_with_syncer, @@ -410,8 +410,7 @@ impl StateServiceSubscriber { }; let response = if !verbose { - // TODO --> +Response - GetBlockHeader::Raw(HexData(header.zcash_serialize_to_vec()?)) + GetBlockHeaderResponse::Raw(HexData(header.zcash_serialize_to_vec()?)) } else { let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state .ready() @@ -490,8 +489,7 @@ impl StateServiceSubscriber { next_block_hash, ); - // TODO --> +Response - GetBlockHeader::Object(Box::new(block_header)) + GetBlockHeaderResponse::Object(Box::new(block_header)) }; Ok(response) @@ -729,12 +727,12 @@ impl StateServiceSubscriber { ); let header_obj = match header? { - // TODO --> +Response - GetBlockHeader::Raw(_hex_data) => unreachable!( + GetBlockHeaderResponse::Raw(_hex_data) => unreachable!( "`true` was passed to get_block_header, an object should be returned" ), - // TODO --> +Response - GetBlockHeader::Object(get_block_header_object) => get_block_header_object, + GetBlockHeaderResponse::Object(get_block_header_object) => { + get_block_header_object + } }; let (transactions_response, size, block_info): (Vec, _, _) = From 68a978bcca90de702ed93752ac62826f705e4fb5 Mon Sep 17 00:00:00 2001 From: al amoda Date: Thu, 14 Aug 2025 12:10:12 -0400 Subject: [PATCH 03/33] complete change to GetBlockHeaderResponse, change panics to unreachable --- zaino-state/src/backends/fetch.rs | 2 +- zaino-state/src/backends/state.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index ba145da15..d2b719169 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -213,7 +213,7 @@ impl ZcashIndexer for FetchServiceSubscriber { /// // TODO compare with getinfo async fn get_block_header(&self) -> Result { - panic!("demo only"); + unreachable!("work in progress"); } /// Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct. diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 9cf2ca33b..767864108 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -379,7 +379,7 @@ impl StateServiceSubscriber { network: &Network, hash_or_height: HashOrHeight, verbose: Option, - ) -> Result { + ) -> Result { let mut state = state.clone(); let verbose = verbose.unwrap_or(true); let network = network.clone(); @@ -855,7 +855,7 @@ impl ZcashIndexer for StateServiceSubscriber { } async fn get_block_header(&self) -> Result { - panic!("ouch"); + unreachable!("work in progress"); } async fn get_difficulty(&self) -> Result { From 387c891c35c82b920624607164b3917d7ee4dfdb Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 15 Aug 2025 17:35:03 -0400 Subject: [PATCH 04/33] WIP demo GetBlockHeaderResponse --- zaino-state/src/backends/state.rs | 45 ++++++++++++++++++++++++++++++- zaino-state/src/indexer.rs | 9 ++++--- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 767864108..96b7b57b5 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -42,6 +42,7 @@ use zebra_chain::{ primitives, serialization::ZcashSerialize, subtree::NoteCommitmentSubtreeIndex, + work::equihash::Solution, }; use zebra_rpc::{ client::{ @@ -67,7 +68,7 @@ use chrono::{DateTime, Utc}; use futures::{TryFutureExt as _, TryStreamExt as _}; use hex::{FromHex as _, ToHex}; use indexmap::IndexMap; -use std::{collections::HashSet, future::poll_fn, str::FromStr, sync::Arc}; +use std::{collections::HashSet, future::poll_fn, rc::Rc, str::FromStr, sync::Arc}; use tokio::{ sync::mpsc, time::{self, timeout}, @@ -854,7 +855,49 @@ impl ZcashIndexer for StateServiceSubscriber { .map_err(|e| StateServiceError::Custom(e.to_string())) } + /// Returns a string that is serialized, hex-encoded data for blockheader 'hash', or + /// if verbose, returns an Object with information about blockheader . + /// Request parameters: + /// 1. "hash" (string, required) The block hash + /// 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data + /// The Zcash source is considered canonical: + /// ... async fn get_block_header(&self) -> Result { + let state = self.read_state_service.clone(); + + // zebra-rpc/src/methods.rs 3645 + Ok(GetBlockHeaderResponse::Object({ + Box::new(GetBlockHeaderObject { + //type: Hash + hash: "string_of_hash".to_string(), + confirmations: 0, + // type: Height + height: 11, + version: 1, + // type: Root + merkle_root: "string_of_merkleroot".to_string(), + final_sapling_root: "string_of_finalsaplingroot".to_string, + // unix epoch, u64 + time: 1755284848, + // [u8; 32] + nonce: [0; 32], + // type: CompactDifficulty + bits: "string_of_bits, 1d00ffff".to_string(), + // f64 + difficulty: 1.123, + // type: Hash + previous_block_hash: "string_of_previousblockhash".to_string(), + // type: Option + next_block_hash: "string_of_nextblockhash".to_string(), + // undocumented u64 + sapling_tree_size: 87, + // undocumented [u8; 32] + block_commitments: [0; 32], + // undocumented Solution type + // The Equihash solution in the requested block header. + solution: Solution::Common(Box::new([0; 32])), + }) + })); unreachable!("work in progress"); } diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 1c30455fc..71f710c78 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -166,16 +166,19 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// [required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89) async fn get_blockchain_info(&self) -> Result; - // TODO add original implementation /// getblockheader "hash" ( verbose ) /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader . /// - /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// zcashd web reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post /// tags: blockchain /// - // TODO compare with getinfo + /// # Notes + /// + /// zebra includes several fields not in the zcashd web reference. + // TODO Check both zebra and zcashd source + // TODO add links to original implementation async fn get_block_header(&self) -> Result; /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. From 9fe93d995a265a43cf2dae24fdef797dccd102fd Mon Sep 17 00:00:00 2001 From: al amoda Date: Fri, 15 Aug 2025 22:14:52 -0400 Subject: [PATCH 05/33] WIP add use zebra_chain::block::Hash --- zaino-state/src/backends/state.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 96b7b57b5..88228b499 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -36,7 +36,7 @@ use zaino_proto::proto::{ }; use zebra_chain::{ - block::{Header, Height, SerializedBlock}, + block::{Hash, Header, Height, SerializedBlock}, chain_tip::NetworkChainTipHeightEstimator, parameters::{ConsensusBranchId, Network, NetworkKind, NetworkUpgrade}, primitives, @@ -68,7 +68,7 @@ use chrono::{DateTime, Utc}; use futures::{TryFutureExt as _, TryStreamExt as _}; use hex::{FromHex as _, ToHex}; use indexmap::IndexMap; -use std::{collections::HashSet, future::poll_fn, rc::Rc, str::FromStr, sync::Arc}; +use std::{collections::HashSet, future::poll_fn, str::FromStr, sync::Arc}; use tokio::{ sync::mpsc, time::{self, timeout}, @@ -334,9 +334,7 @@ pub struct ChainTipSubscriber(zebra_state::ChainTipChange); impl ChainTipSubscriber { /// Waits until the tip hash has changed (relative to the last time this method /// was called), then returns the best tip's block hash. - pub async fn next_tip_hash( - &mut self, - ) -> Result { + pub async fn next_tip_hash(&mut self) -> Result { self.0 .wait_for_tip_change() .await @@ -582,7 +580,7 @@ impl StateServiceSubscriber { }; let Ok(hash_or_height) = <[u8; 32]>::try_from(child_block.prev_hash.as_slice()) - .map(zebra_chain::block::Hash) + .map(Hash) .map(HashOrHeight::from) else { break; @@ -865,6 +863,9 @@ impl ZcashIndexer for StateServiceSubscriber { async fn get_block_header(&self) -> Result { let state = self.read_state_service.clone(); + // ReadStateService exposes a db in finalized state, but I am not sure how to + // access the block header response, see Zebra code and trace from that end to see how they get to it? + // // zebra-rpc/src/methods.rs 3645 Ok(GetBlockHeaderResponse::Object({ Box::new(GetBlockHeaderObject { @@ -895,7 +896,7 @@ impl ZcashIndexer for StateServiceSubscriber { block_commitments: [0; 32], // undocumented Solution type // The Equihash solution in the requested block header. - solution: Solution::Common(Box::new([0; 32])), + solution: Solution::Common([0; 1334]), }) })); unreachable!("work in progress"); @@ -1414,7 +1415,7 @@ impl ZcashIndexer for StateServiceSubscriber { Some(tx.confirmations), &self.config.network, Some(tx.block_time), - Some(zebra_chain::block::Hash::from_bytes( + Some(Hash::from_bytes( self.block_cache .get_compact_block( HashOrHeight::Height(tx.height).to_string(), From cf96e056a8060d9263a295bbaed787cc7caeb7af Mon Sep 17 00:00:00 2001 From: al amoda Date: Sat, 16 Aug 2025 00:24:15 -0400 Subject: [PATCH 06/33] returning Ok(GetBlockHeaderResponse::Object) with sequential args --- zaino-state/src/backends/state.rs | 71 +++++++++++++++++++------------ 1 file changed, 44 insertions(+), 27 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 88228b499..95765cb16 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -36,13 +36,13 @@ use zaino_proto::proto::{ }; use zebra_chain::{ - block::{Hash, Header, Height, SerializedBlock}, + block::{merkle::Root, Hash, Header, Height, SerializedBlock}, chain_tip::NetworkChainTipHeightEstimator, parameters::{ConsensusBranchId, Network, NetworkKind, NetworkUpgrade}, primitives, serialization::ZcashSerialize, subtree::NoteCommitmentSubtreeIndex, - work::equihash::Solution, + work::{difficulty::CompactDifficulty, equihash::Solution}, }; use zebra_rpc::{ client::{ @@ -861,45 +861,62 @@ impl ZcashIndexer for StateServiceSubscriber { /// The Zcash source is considered canonical: /// ... async fn get_block_header(&self) -> Result { - let state = self.read_state_service.clone(); - + // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to // access the block header response, see Zebra code and trace from that end to see how they get to it? // // zebra-rpc/src/methods.rs 3645 Ok(GetBlockHeaderResponse::Object({ - Box::new(GetBlockHeaderObject { + Box::new(GetBlockHeaderObject::new( //type: Hash - hash: "string_of_hash".to_string(), - confirmations: 0, + //hash: + Hash::from([0; 32]), + //"string_of_hash".to_string(), + //confirmations: + 0, // type: Height - height: 11, - version: 1, + //height: + Height(13), + //version: + 1, // type: Root - merkle_root: "string_of_merkleroot".to_string(), - final_sapling_root: "string_of_finalsaplingroot".to_string, + //merkle_root: + Root::from([0; 32]), + // undocumented [u8; 32] + //block_commitments: + [0; 32], + //final_sapling_root: + [1; 32], + // undocumented u64 + //sapling_tree_size: + 87, // unix epoch, u64 - time: 1755284848, + //time: + 1755284848, // [u8; 32] - nonce: [0; 32], + //nonce: + [0; 32], + // undocumented Solution type + // The Equihash solution in the requested block header. + //solution: + Solution::Common([0; 1344]), // type: CompactDifficulty - bits: "string_of_bits, 1d00ffff".to_string(), + //bits: + CompactDifficulty::from_bytes_in_display_order(&[1; 4]).unwrap(), + //from_hex() also possible + //example = "1d00ffff" // f64 - difficulty: 1.123, + //difficulty: + 1.123, // type: Hash - previous_block_hash: "string_of_previousblockhash".to_string(), + //previous_block_hash: + Hash::from([1; 32]), // type: Option - next_block_hash: "string_of_nextblockhash".to_string(), - // undocumented u64 - sapling_tree_size: 87, - // undocumented [u8; 32] - block_commitments: [0; 32], - // undocumented Solution type - // The Equihash solution in the requested block header. - solution: Solution::Common([0; 1334]), - }) - })); - unreachable!("work in progress"); + //next_block_hash: + Some(Hash::from([2; 32])), + )) + })) + //unreachable!("work in progress"); } async fn get_difficulty(&self) -> Result { From 5cbe73fb881b8a8c68fc56c662c4097140d997a8 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sat, 16 Aug 2025 00:32:38 -0400 Subject: [PATCH 07/33] tidy --- zaino-state/src/backends/state.rs | 47 +++++++++++++++---------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 95765cb16..b6537072d 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -868,55 +868,52 @@ impl ZcashIndexer for StateServiceSubscriber { // zebra-rpc/src/methods.rs 3645 Ok(GetBlockHeaderResponse::Object({ Box::new(GetBlockHeaderObject::new( - //type: Hash - //hash: + // type: Hash + // hash: Hash::from([0; 32]), - //"string_of_hash".to_string(), - //confirmations: + // confirmations: 0, // type: Height - //height: + // height: Height(13), - //version: + // version: 1, // type: Root - //merkle_root: + // merkle_root: Root::from([0; 32]), - // undocumented [u8; 32] - //block_commitments: + // undocumented. type: [u8; 32] + // block_commitments: [0; 32], - //final_sapling_root: + // final_sapling_root: [1; 32], - // undocumented u64 - //sapling_tree_size: + // undocumented. type: u64 + // sapling_tree_size: 87, // unix epoch, u64 - //time: + // time: 1755284848, // [u8; 32] - //nonce: + // nonce: [0; 32], - // undocumented Solution type + // undocumented. type: Solution // The Equihash solution in the requested block header. - //solution: + // solution: Solution::Common([0; 1344]), // type: CompactDifficulty - //bits: + // from_hex() also possible , for example = "1d00ffff" + // bits: CompactDifficulty::from_bytes_in_display_order(&[1; 4]).unwrap(), - //from_hex() also possible - //example = "1d00ffff" - // f64 - //difficulty: + // type: f64 + // difficulty: 1.123, // type: Hash - //previous_block_hash: + // previous_block_hash: Hash::from([1; 32]), - // type: Option - //next_block_hash: + // type: Option + // next_block_hash: Some(Hash::from([2; 32])), )) })) - //unreachable!("work in progress"); } async fn get_difficulty(&self) -> Result { From 1d3c723087c6c00c5374c80d39a206f1936b98f8 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sun, 17 Aug 2025 13:35:13 -0400 Subject: [PATCH 08/33] add documentation links to zcashd code, lint docs --- zaino-state/src/backends/fetch.rs | 1 - zaino-state/src/backends/state.rs | 25 +++++++++++++++++++++++-- zaino-state/src/indexer.rs | 2 +- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index d2b719169..68c922071 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -210,7 +210,6 @@ impl ZcashIndexer for FetchServiceSubscriber { /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post /// tags: blockchain - /// // TODO compare with getinfo async fn get_block_header(&self) -> Result { unreachable!("work in progress"); diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index b6537072d..e715e79b6 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -351,7 +351,7 @@ impl StateServiceSubscriber { pub fn chaintip_update_subscriber(&self) -> ChainTipSubscriber { ChainTipSubscriber(self.chain_tip_change.clone()) } - /// Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string. + /// Returns the requested block header by hash or height, as a [`GetBlockHeaderResponse`] JSON string. /// If the block is not in Zebra's state, /// returns [error code `-8`.](https://github.com/zcash/zcash/issues/5758) /// if a height was passed or -5 if a hash was passed. @@ -859,7 +859,28 @@ impl ZcashIndexer for StateServiceSubscriber { /// 1. "hash" (string, required) The block hash /// 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data /// The Zcash source is considered canonical: - /// ... + /// + /// The function does not modify the state of the object it is called on (const), + /// with a return type defined as CBlockHeader in chain.h file: + /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.h#L449 + /// + /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L121) + /// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, + /// including a field of the same data used as argument: + /// { + /// CBlockHeader block; + /// block.nVersion = nVersion; + /// block.hashPrevBlock = hashPrevBlock; + /// block.hashMerkleRoot = hashMerkleRoot; + /// block.hashBlockCommitments = hashBlockCommitments; + /// block.nTime = nTime; + /// block.nBits = nBits; + /// block.nNonce = nNonce; + /// block.nSolution = nSolution; + /// return block; + /// } + /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) + /// async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 71f710c78..52629584f 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -166,7 +166,7 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// [required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89) async fn get_blockchain_info(&self) -> Result; - /// getblockheader "hash" ( verbose ) + /// getblockheader 'hash' ( verbose ) /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader . /// From 15ddab64fe9ffefa85ee540b11815ebc6c089b40 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sun, 17 Aug 2025 14:14:47 -0400 Subject: [PATCH 09/33] add explicit online docs, link to zebra code, lint --- zaino-state/src/backends/fetch.rs | 2 +- zaino-state/src/backends/state.rs | 26 +++++++++++++++++++++++++- zaino-state/src/indexer.rs | 2 +- 3 files changed, 27 insertions(+), 3 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index 68c922071..702f40adb 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -203,7 +203,7 @@ impl ZcashIndexer for FetchServiceSubscriber { } // TODO add original implementation - /// getblockheader "hash" ( verbose ) + /// getblockheader "hash" { verbose } /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader . /// diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index e715e79b6..cd2cc67e9 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -853,11 +853,29 @@ impl ZcashIndexer for StateServiceSubscriber { .map_err(|e| StateServiceError::Custom(e.to_string())) } + /// zcash online RPC docs: /// Returns a string that is serialized, hex-encoded data for blockheader 'hash', or /// if verbose, returns an Object with information about blockheader . /// Request parameters: /// 1. "hash" (string, required) The block hash /// 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data + /// + ///Result (for verbose = true): + /// { + /// "hash" : "hash", (string) the block hash (same as provided) + /// "confirmations" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain + /// "height" : n, (numeric) The block height or index + /// "version" : n, (numeric) The block version + /// "merkleroot" : "xxxx", (string) The merkle root + /// "finalsaplingroot" : "xxxx", (string) The root of the Sapling commitment tree after applying this block + /// "time" : ttt, (numeric) The block time in seconds since epoch (Jan 1 1970 GMT) + /// "nonce" : n, (numeric) The nonce + /// "bits" : "1d00ffff", (string) The bits + /// "difficulty" : x.xxx, (numeric) The difficulty + /// "previousblockhash" : "hash", (string) The hash of the previous block + /// "nextblockhash" : "hash" (string) The hash of the next block + /// } + /// /// The Zcash source is considered canonical: /// /// The function does not modify the state of the object it is called on (const), @@ -868,6 +886,8 @@ impl ZcashIndexer for StateServiceSubscriber { /// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, /// including a field of the same data used as argument: /// { + // TODO: this is different than the online docs. + // maybe setting some default fields when creating the block I don't see here? /// CBlockHeader block; /// block.nVersion = nVersion; /// block.hashPrevBlock = hashPrevBlock; @@ -879,14 +899,18 @@ impl ZcashIndexer for StateServiceSubscriber { /// block.nSolution = nSolution; /// return block; /// } + /// [another handy link] /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) /// + /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, + /// which is backed by BlockHeaderObjects (in verbose form). + /// From Zebra Release 2.4.1 + /// (https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to // access the block header response, see Zebra code and trace from that end to see how they get to it? // - // zebra-rpc/src/methods.rs 3645 Ok(GetBlockHeaderResponse::Object({ Box::new(GetBlockHeaderObject::new( // type: Hash diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 52629584f..5f57159fc 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -166,7 +166,7 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// [required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89) async fn get_blockchain_info(&self) -> Result; - /// getblockheader 'hash' ( verbose ) + /// getblockheader 'hash' { verbose } /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader . /// From b3fa8163823caefb7d1bae35553a0cb3eb187d88 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sun, 17 Aug 2025 14:41:52 -0400 Subject: [PATCH 10/33] lint doc comments --- zaino-state/src/backends/fetch.rs | 2 +- zaino-state/src/backends/state.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index 702f40adb..e73c90644 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -205,7 +205,7 @@ impl ZcashIndexer for FetchServiceSubscriber { // TODO add original implementation /// getblockheader "hash" { verbose } /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. - /// If verbose is true, returns an Object with information about blockheader . + /// If verbose is true, returns an Object with information about blockheader 'hash'. /// /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index cd2cc67e9..88b3e6f3e 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -855,7 +855,7 @@ impl ZcashIndexer for StateServiceSubscriber { /// zcash online RPC docs: /// Returns a string that is serialized, hex-encoded data for blockheader 'hash', or - /// if verbose, returns an Object with information about blockheader . + /// if verbose, returns an Object with information about blockheader 'hash'. /// Request parameters: /// 1. "hash" (string, required) The block hash /// 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data @@ -899,12 +899,12 @@ impl ZcashIndexer for StateServiceSubscriber { /// block.nSolution = nSolution; /// return block; /// } - /// [another handy link] + /// [chain.cpp link] /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) /// /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, /// which is backed by BlockHeaderObjects (in verbose form). - /// From Zebra Release 2.4.1 + /// [From Zebra Release 2.4.1:] /// (https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); From 3b8ae55d3f93df80f9018c619fa57d49f769bed8 Mon Sep 17 00:00:00 2001 From: al amoda Date: Sun, 17 Aug 2025 14:57:22 -0400 Subject: [PATCH 11/33] lint doc comments --- zaino-state/src/backends/state.rs | 3 +-- zaino-state/src/indexer.rs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 88b3e6f3e..e54215f0d 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -904,8 +904,7 @@ impl ZcashIndexer for StateServiceSubscriber { /// /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, /// which is backed by BlockHeaderObjects (in verbose form). - /// [From Zebra Release 2.4.1:] - /// (https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) + /// [From Zebra Release 2.4.1:](https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 5f57159fc..b1baf4b98 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -168,7 +168,7 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// getblockheader 'hash' { verbose } /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. - /// If verbose is true, returns an Object with information about blockheader . + /// If verbose is true, returns an Object with information about blockheader 'hash'. /// /// zcashd web reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post From 451770efddceb67fd66ef8ade83833cca2016e03 Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 13:08:27 -0400 Subject: [PATCH 12/33] lint doc comments --- zaino-state/src/backends/state.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index e54215f0d..bdbc61324 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -878,12 +878,12 @@ impl ZcashIndexer for StateServiceSubscriber { /// /// The Zcash source is considered canonical: /// - /// The function does not modify the state of the object it is called on (const), + /// The function does not modify the state of the object it is called on `const`, /// with a return type defined as CBlockHeader in chain.h file: /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.h#L449 /// /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L121) - /// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, + /// GetBlochHeader() seems to take arg of CBlockHeader -hash of block- and has a return with these fields, /// including a field of the same data used as argument: /// { // TODO: this is different than the online docs. @@ -903,7 +903,7 @@ impl ZcashIndexer for StateServiceSubscriber { /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) /// /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, - /// which is backed by BlockHeaderObjects (in verbose form). + /// which is backed by BlockHeaderObjects in verbose form. /// [From Zebra Release 2.4.1:](https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); From 3a9f64d4e018b3a40a58c2e01cd99929a005e454 Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 13:27:57 -0400 Subject: [PATCH 13/33] doc comment adjustment --- zaino-state/src/backends/state.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index bdbc61324..eff173cb0 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -860,7 +860,7 @@ impl ZcashIndexer for StateServiceSubscriber { /// 1. "hash" (string, required) The block hash /// 2. verbose (boolean, optional, default=true) true for a json object, false for the hex encoded data /// - ///Result (for verbose = true): + /// Result (for verbose = true): /// { /// "hash" : "hash", (string) the block hash (same as provided) /// "confirmations" : n, (numeric) The number of confirmations, or -1 if the block is not on the main chain @@ -882,11 +882,11 @@ impl ZcashIndexer for StateServiceSubscriber { /// with a return type defined as CBlockHeader in chain.h file: /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.h#L449 /// - /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L121) + /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L121 /// GetBlochHeader() seems to take arg of CBlockHeader -hash of block- and has a return with these fields, /// including a field of the same data used as argument: /// { - // TODO: this is different than the online docs. + // TODO: this is different than the online docs, we should drill into zcashd // maybe setting some default fields when creating the block I don't see here? /// CBlockHeader block; /// block.nVersion = nVersion; @@ -899,17 +899,19 @@ impl ZcashIndexer for StateServiceSubscriber { /// block.nSolution = nSolution; /// return block; /// } - /// [chain.cpp link] - /// (https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) + /// chain.cpp link + /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82 /// /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, /// which is backed by BlockHeaderObjects in verbose form. - /// [From Zebra Release 2.4.1:](https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645) + /// From Zebra Release 2.4.1: + /// https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645 async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to // access the block header response, see Zebra code and trace from that end to see how they get to it? // + // TODO this is only a response for VERBOSE - arguments / parameters? compare with other RPCs that take arguments Ok(GetBlockHeaderResponse::Object({ Box::new(GetBlockHeaderObject::new( // type: Hash From 020985efb071a97b7ab620d8fa1707ead6f9aac5 Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 14:11:14 -0400 Subject: [PATCH 14/33] doc comment adjust --- zaino-state/src/backends/state.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index eff173cb0..6ee843102 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -880,9 +880,10 @@ impl ZcashIndexer for StateServiceSubscriber { /// /// The function does not modify the state of the object it is called on `const`, /// with a return type defined as CBlockHeader in chain.h file: - /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.h#L449 + /// /// - /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L121 + /// see also + /// /// GetBlochHeader() seems to take arg of CBlockHeader -hash of block- and has a return with these fields, /// including a field of the same data used as argument: /// { @@ -899,13 +900,12 @@ impl ZcashIndexer for StateServiceSubscriber { /// block.nSolution = nSolution; /// return block; /// } - /// chain.cpp link - /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82 + /// [chain.cpp link](https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) /// /// The successful return Result of our function is GetBlockHeaderResponse, a type defined in zebra, /// which is backed by BlockHeaderObjects in verbose form. /// From Zebra Release 2.4.1: - /// https://github.com/ZcashFoundation/zebra/blob/0893e1a7f499cadad1d9480216b3057dfd7900c7/zebra-rpc/src/methods.rs#L3645 + /// async fn get_block_header(&self) -> Result { // let state = self.read_state_service.clone(); // ReadStateService exposes a db in finalized state, but I am not sure how to From 6d4dcf435a923c5521478be787cd5cb9212837c2 Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 14:32:46 -0400 Subject: [PATCH 15/33] doc comment adjust --- zaino-state/src/backends/state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 6ee843102..aa915055c 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -878,13 +878,13 @@ impl ZcashIndexer for StateServiceSubscriber { /// /// The Zcash source is considered canonical: /// - /// The function does not modify the state of the object it is called on `const`, + /// The function does not modify the state of the object: it is called on `const`, /// with a return type defined as CBlockHeader in chain.h file: /// /// /// see also /// - /// GetBlochHeader() seems to take arg of CBlockHeader -hash of block- and has a return with these fields, + /// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, /// including a field of the same data used as argument: /// { // TODO: this is different than the online docs, we should drill into zcashd From 79dbd6c54be842e091a287577577d9f9c5e9b72c Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 14:36:47 -0400 Subject: [PATCH 16/33] doc comment adjust --- zaino-state/src/backends/fetch.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index e73c90644..be1f01742 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -203,7 +203,7 @@ impl ZcashIndexer for FetchServiceSubscriber { } // TODO add original implementation - /// getblockheader "hash" { verbose } + /// getblockheader 'hash' ( verbose ) /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader 'hash'. /// From 012e3791ebd8db34bac7b7fc6cbaaa14fe74273c Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 14:46:53 -0400 Subject: [PATCH 17/33] doc comment adjust --- zaino-state/src/indexer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index b1baf4b98..1df20111b 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -166,7 +166,7 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// [required for lightwalletd support.](https://github.com/zcash/lightwalletd/blob/v0.4.9/common/common.go#L72-L89) async fn get_blockchain_info(&self) -> Result; - /// getblockheader 'hash' { verbose } + /// getblockheader 'hash' ( verbose ) /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader 'hash'. /// From 8a793cdb719a3e04ebf138fac759d12c598c9848 Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 15:12:44 -0400 Subject: [PATCH 18/33] add method to connector.rs --- zaino-fetch/src/jsonrpsee/connector.rs | 14 +++++++++++++- zaino-state/src/backends/fetch.rs | 4 +--- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/zaino-fetch/src/jsonrpsee/connector.rs b/zaino-fetch/src/jsonrpsee/connector.rs index c0054d5a5..9eba3b512 100644 --- a/zaino-fetch/src/jsonrpsee/connector.rs +++ b/zaino-fetch/src/jsonrpsee/connector.rs @@ -20,7 +20,7 @@ use std::{ time::Duration, }; use tracing::error; -use zebra_rpc::client::ValidateAddressResponse; +use zebra_rpc::{client::ValidateAddressResponse, methods::GetBlockHeaderResponse}; use crate::jsonrpsee::{ error::{JsonRpcError, TransportError}, @@ -419,6 +419,18 @@ impl JsonRpSeeConnector { .await } + /// from online zcashd RPC reference docs: + /// getblockheader 'hash' ( verbose ) + /// + /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. + /// If verbose is true, returns an Object with information about blockheader . + pub async fn get_block_header( + &self, + ) -> Result> { + // do something + unreachable!("so far"); + } + /// Returns details on the active state of the TX memory pool. /// /// online zcash rpc reference: [`getmempoolinfo`](https://zcash.github.io/rpc/getmempoolinfo.html) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index be1f01742..3cfdd3266 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -202,7 +202,6 @@ impl ZcashIndexer for FetchServiceSubscriber { Ok(self.fetcher.get_info().await?.into()) } - // TODO add original implementation /// getblockheader 'hash' ( verbose ) /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. /// If verbose is true, returns an Object with information about blockheader 'hash'. @@ -210,9 +209,8 @@ impl ZcashIndexer for FetchServiceSubscriber { /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post /// tags: blockchain - // TODO compare with getinfo async fn get_block_header(&self) -> Result { - unreachable!("work in progress"); + Ok(self.fetcher.get_block_header().await?) } /// Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct. From 491f2ccd9972036eaabd74aed41111b96dd8a47f Mon Sep 17 00:00:00 2001 From: al amoda Date: Mon, 18 Aug 2025 16:06:37 -0400 Subject: [PATCH 19/33] add zaino-fetch response type --- zaino-fetch/src/jsonrpsee/connector.rs | 10 +++---- zaino-fetch/src/jsonrpsee/response.rs | 41 ++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/zaino-fetch/src/jsonrpsee/connector.rs b/zaino-fetch/src/jsonrpsee/connector.rs index 9eba3b512..827fb495d 100644 --- a/zaino-fetch/src/jsonrpsee/connector.rs +++ b/zaino-fetch/src/jsonrpsee/connector.rs @@ -20,16 +20,16 @@ use std::{ time::Duration, }; use tracing::error; -use zebra_rpc::{client::ValidateAddressResponse, methods::GetBlockHeaderResponse}; +use zebra_rpc::client::ValidateAddressResponse; use crate::jsonrpsee::{ error::{JsonRpcError, TransportError}, response::{ GetBalanceError, GetBalanceResponse, GetBlockCountResponse, GetBlockError, GetBlockHash, - GetBlockResponse, GetBlockchainInfoResponse, GetInfoResponse, GetMempoolInfoResponse, - GetSubtreesError, GetSubtreesResponse, GetTransactionResponse, GetTreestateError, - GetTreestateResponse, GetUtxosError, GetUtxosResponse, SendTransactionError, - SendTransactionResponse, TxidsError, TxidsResponse, + GetBlockHeaderResponse, GetBlockResponse, GetBlockchainInfoResponse, GetInfoResponse, + GetMempoolInfoResponse, GetSubtreesError, GetSubtreesResponse, GetTransactionResponse, + GetTreestateError, GetTreestateResponse, GetUtxosError, GetUtxosResponse, + SendTransactionError, SendTransactionResponse, TxidsError, TxidsResponse, }, }; diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index a8c4dbff5..aa41757dc 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1563,3 +1563,44 @@ pub struct GetMempoolInfoResponse { impl ResponseToError for GetMempoolInfoResponse { type RpcError = Infallible; } + +/// The Zcash source code is considered canonical: +/// The function does not modify the state of the object: it is called on `const`, +/// with a return type defined as CBlockHeader in chain.h file: +/// +/// +/// see also +/// +/// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, +/// including a field of the same data used as argument: +/// { +// TODO: this is different than the online docs, we should drill into zcashd +// maybe setting some default fields when creating the block I don't see here? +/// CBlockHeader block; +/// block.nVersion = nVersion; +/// block.hashPrevBlock = hashPrevBlock; +/// block.hashMerkleRoot = hashMerkleRoot; +/// block.hashBlockCommitments = hashBlockCommitments; +/// block.nTime = nTime; +/// block.nBits = nBits; +/// block.nNonce = nNonce; +/// block.nSolution = nSolution; +/// return block; +/// } +/// [chain.cpp link](https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) +#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] +pub struct GetBlockHeaderResponse { + // fields taken from zcashd source code pasted above + version: (), + hash_previous_block: (), + hash_merkle_root: (), + hash_block_commitments: (), + time: (), + bits: (), + nonce: (), + solution: (), +} + +impl ResponseToError for GetBlockHeaderResponse { + type RpcError = Infallible; +} From 5923bcf80029e7dfa8284579c725392abb8fc19c Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 19 Aug 2025 20:16:58 -0400 Subject: [PATCH 20/33] WIP mv fn to instance method, static method shim --- zaino-state/src/backends/fetch.rs | 30 +- zaino-state/src/backends/state.rs | 445 ++++++++++++++++++++---------- zaino-state/src/indexer.rs | 24 +- 3 files changed, 350 insertions(+), 149 deletions(-) diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index 3cfdd3266..857c922e7 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -13,8 +13,8 @@ use zebra_rpc::{ client::{GetSubtreesByIndexResponse, GetTreestateResponse, ValidateAddressResponse}, methods::{ AddressBalance, AddressStrings, GetAddressTxIdsRequest, GetAddressUtxos, GetBlock, - GetBlockHashResponse, GetBlockHeaderResponse, GetBlockchainInfoResponse, GetInfo, - GetRawTransaction, SentTransactionHash, + GetBlockHashResponse, GetBlockchainInfoResponse, GetInfo, GetRawTransaction, + SentTransactionHash, }, }; @@ -22,7 +22,7 @@ use zaino_fetch::{ chain::{transaction::FullTransaction, utils::ParseFromSlice}, jsonrpsee::{ connector::{JsonRpSeeConnector, RpcError}, - response::GetMempoolInfoResponse, + response::{GetBlockHeaderResponse, GetMempoolInfoResponse}, }, }; @@ -209,7 +209,29 @@ impl ZcashIndexer for FetchServiceSubscriber { /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post /// tags: blockchain - async fn get_block_header(&self) -> Result { + // TODO params are only demos + async fn get_block_header( + &self, + _hash_or_height_demo: HashOrHeight, + _verbose: Option, + ) -> Result { + Ok(self.fetcher.get_block_header().await?) + } + + /// getblockheader 'hash' ( verbose ) + /// If verbose is false, returns a string that is serialized, hex-encoded data for blockheader 'hash'. + /// If verbose is true, returns an Object with information about blockheader 'hash'. + /// + /// online zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// method: post + /// tags: blockchain + // TODO params are only demos + async fn get_block_header_static( + _, + _, + _hash_or_height_demo: HashOrHeight, + _verbose: Option, + ) -> Result { Ok(self.fetcher.get_block_header().await?) } diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index aa915055c..4cca41e89 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -306,6 +306,7 @@ impl Drop for StateService { } } +// TODO - why is this called a fetch service subscriber?! it's in state. /// A fetch service subscriber. /// /// Subscribers should be @@ -351,148 +352,6 @@ impl StateServiceSubscriber { pub fn chaintip_update_subscriber(&self) -> ChainTipSubscriber { ChainTipSubscriber(self.chain_tip_change.clone()) } - /// Returns the requested block header by hash or height, as a [`GetBlockHeaderResponse`] JSON string. - /// If the block is not in Zebra's state, - /// returns [error code `-8`.](https://github.com/zcash/zcash/issues/5758) - /// if a height was passed or -5 if a hash was passed. - /// - /// zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) - /// method: post - /// tags: blockchain - /// - /// # Parameters - /// - /// - `hash_or_height`: (string, required, example="1") The hash or height - /// for the block to be returned. - /// - `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, - /// true for a json object - /// - /// # Notes - /// - /// The undocumented `chainwork` field is not returned. - /// - /// This rpc is used by get_block(verbose), there is currently no - /// plan to offer this RPC publicly. - async fn get_block_header( - state: &ReadStateService, - network: &Network, - hash_or_height: HashOrHeight, - verbose: Option, - ) -> Result { - let mut state = state.clone(); - let verbose = verbose.unwrap_or(true); - let network = network.clone(); - - let zebra_state::ReadResponse::BlockHeader { - header, - hash, - height, - next_block_hash, - } = state - .ready() - .and_then(|service| service.call(zebra_state::ReadRequest::BlockHeader(hash_or_height))) - .await - .map_err(|_| { - StateServiceError::RpcError(RpcError { - // Compatibility with zcashd. Note that since this function - // is reused by getblock(), we return the errors expected - // by it (they differ whether a hash or a height was passed) - code: LegacyCode::InvalidParameter as i64, - message: "block height not in best chain".to_string(), - data: None, - }) - })? - else { - return Err(StateServiceError::Custom( - "Unexpected response to BlockHeader request".to_string(), - )); - }; - - let response = if !verbose { - GetBlockHeaderResponse::Raw(HexData(header.zcash_serialize_to_vec()?)) - } else { - let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state - .ready() - .and_then(|service| { - service.call(zebra_state::ReadRequest::SaplingTree(hash_or_height)) - }) - .await? - else { - return Err(StateServiceError::Custom( - "Unexpected response to SaplingTree request".to_string(), - )); - }; - // This could be `None` if there's a chain reorg between state queries. - let sapling_tree = sapling_tree.ok_or_else(|| { - StateServiceError::RpcError(zaino_fetch::jsonrpsee::connector::RpcError { - code: LegacyCode::InvalidParameter as i64, - message: "missing sapling tree for block".to_string(), - data: None, - }) - })?; - - let zebra_state::ReadResponse::Depth(depth) = state - .ready() - .and_then(|service| service.call(zebra_state::ReadRequest::Depth(hash))) - .await? - else { - return Err(StateServiceError::Custom( - "Unexpected response to Depth request".to_string(), - )); - }; - - // From - // TODO: Deduplicate const definition, consider - // refactoring this to avoid duplicate logic - const NOT_IN_BEST_CHAIN_CONFIRMATIONS: i64 = -1; - - // Confirmations are one more than the depth. - // Depth is limited by height, so it will never overflow an i64. - let confirmations = depth - .map(|depth| i64::from(depth) + 1) - .unwrap_or(NOT_IN_BEST_CHAIN_CONFIRMATIONS); - - let mut nonce = *header.nonce; - nonce.reverse(); - - let sapling_activation = NetworkUpgrade::Sapling.activation_height(&network); - let sapling_tree_size = sapling_tree.count(); - let final_sapling_root: [u8; 32] = - if sapling_activation.is_some() && height >= sapling_activation.unwrap() { - let mut root: [u8; 32] = sapling_tree.root().into(); - root.reverse(); - root - } else { - [0; 32] - }; - - let difficulty = header.difficulty_threshold.relative_to_network(&network); - let block_commitments = - header_to_block_commitments(&header, &network, height, final_sapling_root)?; - - let block_header = GetBlockHeaderObject::new( - hash, - confirmations, - height, - header.version, - header.merkle_root, - block_commitments, - final_sapling_root, - sapling_tree_size, - header.time.timestamp(), - nonce, - header.solution, - header.difficulty_threshold, - difficulty, - header.previous_block_hash, - next_block_hash, - ); - - GetBlockHeaderResponse::Object(Box::new(block_header)) - }; - - Ok(response) - } /// Return a list of consecutive compact blocks. #[allow(dead_code)] @@ -716,7 +575,7 @@ impl StateServiceSubscriber { let (fullblock, orchard_tree_response, header, block_info) = futures::join!( blockandsize_future, orchard_future, - StateServiceSubscriber::get_block_header( + StateServiceSubscriber::get_block_header_static( &state_3, network, hash_or_height, @@ -725,6 +584,7 @@ impl StateServiceSubscriber { block_info_future ); + // TODO matching against a fetch -type here, this could be wrong or untangled let header_obj = match header? { GetBlockHeaderResponse::Raw(_hex_data) => unreachable!( "`true` was passed to get_block_header, an object should be returned" @@ -853,6 +713,302 @@ impl ZcashIndexer for StateServiceSubscriber { .map_err(|e| StateServiceError::Custom(e.to_string())) } + /// Returns the requested block header by hash or height, as a [`GetBlockHeaderResponse`] JSON string. + /// If the block is not in Zebra's state, + /// returns [error code `-8`.](https://github.com/zcash/zcash/issues/5758) + /// if a height was passed or -5 if a hash was passed. + /// + /// zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// method: post + /// tags: blockchain + /// + /// # Parameters + /// + /// - `hash_or_height`: (string, required, example="1") The hash or height + /// for the block to be returned. + /// - `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, + /// true for a json object + /// + /// # Notes + /// + /// The undocumented `chainwork` field is not returned. + /// + /// This rpc is used by get_block(verbose), there is currently no + /// plan to offer this RPC publicly. + async fn get_block_header_static( + state: &ReadStateService, + network: &Network, + //network: self.config.network.clone(), + hash_or_height: HashOrHeight, + verbose: Option, + ) -> Result { + let mut state = state.clone(); + let verbose = verbose.unwrap_or(true); + let network = network.clone(); + + let zebra_state::ReadResponse::BlockHeader { + header, + hash, + height, + next_block_hash, + } = state + .ready() + .and_then(|service| service.call(zebra_state::ReadRequest::BlockHeader(hash_or_height))) + .await + .map_err(|_| { + StateServiceError::RpcError(RpcError { + // Compatibility with zcashd. Note that since this function + // is reused by getblock(), we return the errors expected + // by it (they differ whether a hash or a height was passed) + code: LegacyCode::InvalidParameter as i64, + message: "block height not in best chain".to_string(), + data: None, + }) + })? + else { + return Err(StateServiceError::Custom( + "Unexpected response to BlockHeader request".to_string(), + )); + }; + + let response = if !verbose { + GetBlockHeaderResponse::Raw(HexData(header.zcash_serialize_to_vec()?)) + } else { + let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state + .ready() + .and_then(|service| { + service.call(zebra_state::ReadRequest::SaplingTree(hash_or_height)) + }) + .await? + else { + return Err(StateServiceError::Custom( + "Unexpected response to SaplingTree request".to_string(), + )); + }; + // This could be `None` if there's a chain reorg between state queries. + let sapling_tree = sapling_tree.ok_or_else(|| { + StateServiceError::RpcError(zaino_fetch::jsonrpsee::connector::RpcError { + code: LegacyCode::InvalidParameter as i64, + message: "missing sapling tree for block".to_string(), + data: None, + }) + })?; + + let zebra_state::ReadResponse::Depth(depth) = state + .ready() + .and_then(|service| service.call(zebra_state::ReadRequest::Depth(hash))) + .await? + else { + return Err(StateServiceError::Custom( + "Unexpected response to Depth request".to_string(), + )); + }; + + // From + // TODO: Deduplicate const definition, consider + // refactoring this to avoid duplicate logic + const NOT_IN_BEST_CHAIN_CONFIRMATIONS: i64 = -1; + + // Confirmations are one more than the depth. + // Depth is limited by height, so it will never overflow an i64. + let confirmations = depth + .map(|depth| i64::from(depth) + 1) + .unwrap_or(NOT_IN_BEST_CHAIN_CONFIRMATIONS); + + let mut nonce = *header.nonce; + nonce.reverse(); + + let sapling_activation = NetworkUpgrade::Sapling.activation_height(&network); + let sapling_tree_size = sapling_tree.count(); + let final_sapling_root: [u8; 32] = + if sapling_activation.is_some() && height >= sapling_activation.unwrap() { + let mut root: [u8; 32] = sapling_tree.root().into(); + root.reverse(); + root + } else { + [0; 32] + }; + + let difficulty = header.difficulty_threshold.relative_to_network(&network); + let block_commitments = + header_to_block_commitments(&header, &network, height, final_sapling_root)?; + + let block_header = GetBlockHeaderObject::new( + hash, + confirmations, + height, + header.version, + header.merkle_root, + block_commitments, + final_sapling_root, + sapling_tree_size, + header.time.timestamp(), + nonce, + header.solution, + header.difficulty_threshold, + difficulty, + header.previous_block_hash, + next_block_hash, + ); + + GetBlockHeaderResponse::Object(Box::new(block_header)) + }; + + Ok(response) + } + + /// Returns the requested block header by hash or height, as a [`GetBlockHeaderResponse`] JSON string. + /// If the block is not in Zebra's state, + /// returns [error code `-8`.](https://github.com/zcash/zcash/issues/5758) + /// if a height was passed or -5 if a hash was passed. + /// + /// zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) + /// method: post + /// tags: blockchain + /// + /// # Parameters + /// + /// - `hash_or_height`: (string, required, example="1") The hash or height + /// for the block to be returned. + /// - `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, + /// true for a json object + /// + /// # Notes + /// + /// The undocumented `chainwork` field is not returned. + /// + /// This rpc is used by get_block(verbose), there is currently no + /// plan to offer this RPC publicly. + async fn get_block_header( + &self, + // state: &ReadStateService, + // only used in one place ^ + // of course we're reading the state, we're in state! ugh. + // network: &Network, + // only used in one place ^ + // same place above. + //network: self.config.network.clone(), + hash_or_height: HashOrHeight, + // I'd like to only allow the Hash, but ok. + verbose: Option, + // verbose seems to be required? + ) -> Result { + let mut state = state.clone(); + let verbose = verbose.unwrap_or(true); + let network = network.clone(); + + let zebra_state::ReadResponse::BlockHeader { + header, + hash, + height, + next_block_hash, + } = state + .ready() + .and_then(|service| service.call(zebra_state::ReadRequest::BlockHeader(hash_or_height))) + .await + .map_err(|_| { + StateServiceError::RpcError(RpcError { + // Compatibility with zcashd. Note that since this function + // is reused by getblock(), we return the errors expected + // by it (they differ whether a hash or a height was passed) + code: LegacyCode::InvalidParameter as i64, + message: "block height not in best chain".to_string(), + data: None, + }) + })? + else { + return Err(StateServiceError::Custom( + "Unexpected response to BlockHeader request".to_string(), + )); + }; + + let response = if !verbose { + GetBlockHeaderResponse::Raw(HexData(header.zcash_serialize_to_vec()?)) + } else { + let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state + .ready() + .and_then(|service| { + service.call(zebra_state::ReadRequest::SaplingTree(hash_or_height)) + }) + .await? + else { + return Err(StateServiceError::Custom( + "Unexpected response to SaplingTree request".to_string(), + )); + }; + // This could be `None` if there's a chain reorg between state queries. + let sapling_tree = sapling_tree.ok_or_else(|| { + StateServiceError::RpcError(zaino_fetch::jsonrpsee::connector::RpcError { + code: LegacyCode::InvalidParameter as i64, + message: "missing sapling tree for block".to_string(), + data: None, + }) + })?; + + let zebra_state::ReadResponse::Depth(depth) = state + .ready() + .and_then(|service| service.call(zebra_state::ReadRequest::Depth(hash))) + .await? + else { + return Err(StateServiceError::Custom( + "Unexpected response to Depth request".to_string(), + )); + }; + + // From + // TODO: Deduplicate const definition, consider + // refactoring this to avoid duplicate logic + const NOT_IN_BEST_CHAIN_CONFIRMATIONS: i64 = -1; + + // Confirmations are one more than the depth. + // Depth is limited by height, so it will never overflow an i64. + let confirmations = depth + .map(|depth| i64::from(depth) + 1) + .unwrap_or(NOT_IN_BEST_CHAIN_CONFIRMATIONS); + + let mut nonce = *header.nonce; + nonce.reverse(); + + let sapling_activation = NetworkUpgrade::Sapling.activation_height(&network); + let sapling_tree_size = sapling_tree.count(); + let final_sapling_root: [u8; 32] = + if sapling_activation.is_some() && height >= sapling_activation.unwrap() { + let mut root: [u8; 32] = sapling_tree.root().into(); + root.reverse(); + root + } else { + [0; 32] + }; + + let difficulty = header.difficulty_threshold.relative_to_network(&network); + let block_commitments = + header_to_block_commitments(&header, &network, height, final_sapling_root)?; + + let block_header = GetBlockHeaderObject::new( + hash, + confirmations, + height, + header.version, + header.merkle_root, + block_commitments, + final_sapling_root, + sapling_tree_size, + header.time.timestamp(), + nonce, + header.solution, + header.difficulty_threshold, + difficulty, + header.previous_block_hash, + next_block_hash, + ); + + GetBlockHeaderResponse::Object(Box::new(block_header)) + }; + + Ok(response) + } + + /* /// zcash online RPC docs: /// Returns a string that is serialized, hex-encoded data for blockheader 'hash', or /// if verbose, returns an Object with information about blockheader 'hash'. @@ -961,6 +1117,7 @@ impl ZcashIndexer for StateServiceSubscriber { )) })) } + */ async fn get_difficulty(&self) -> Result { chain_tip_difficulty( @@ -1181,6 +1338,8 @@ impl ZcashIndexer for StateServiceSubscriber { .map_err(Into::into) } + // using get_block_inner using get_block_header + // also not an RPC call as far as I can tell. async fn z_get_block( &self, hash_or_height_string: String, diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 1df20111b..6289909b4 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -14,7 +14,7 @@ use zaino_proto::proto::{ TxFilter, }, }; -use zebra_chain::{block::Height, subtree::NoteCommitmentSubtreeIndex}; +use zebra_chain::{block::Height, parameters::Network, subtree::NoteCommitmentSubtreeIndex}; use zebra_rpc::{ client::{GetSubtreesByIndexResponse, GetTreestateResponse, ValidateAddressResponse}, methods::{ @@ -23,6 +23,7 @@ use zebra_rpc::{ GetRawTransaction, SentTransactionHash, }, }; +use zebra_state::{HashOrHeight, ReadStateService}; use crate::{ status::StatusType, @@ -179,7 +180,26 @@ pub trait ZcashIndexer: Send + Sync + 'static { /// zebra includes several fields not in the zcashd web reference. // TODO Check both zebra and zcashd source // TODO add links to original implementation - async fn get_block_header(&self) -> Result; + async fn get_block_header( + &self, + // state: &ReadStateService, + // only used in one place ^ + // network: &Network, + // only used in one place ^ + //network: self.config.network.clone(), + // zebra request HashOrHeight + hash_or_height: HashOrHeight, + // I'd like to only allow the Hash, but ok. + verbose: Option, + ) -> Result; + + /// a shim to accomdate existing logic using Static methods + async fn get_block_header_static( + state: &ReadStateService, + network: &Network, + hash_or_height: HashOrHeight, + verbose: Option, + ) -> Result; /// Returns the proof-of-work difficulty as a multiple of the minimum difficulty. /// From fafe249d7db24cbffce7d7e96a79a2cdf20df130 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 19 Aug 2025 20:19:44 -0400 Subject: [PATCH 21/33] tidy --- zaino-state/src/backends/state.rs | 10 ---------- zaino-state/src/indexer.rs | 7 ------- 2 files changed, 17 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 4cca41e89..4e8bc0325 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -738,7 +738,6 @@ impl ZcashIndexer for StateServiceSubscriber { async fn get_block_header_static( state: &ReadStateService, network: &Network, - //network: self.config.network.clone(), hash_or_height: HashOrHeight, verbose: Option, ) -> Result { @@ -881,17 +880,8 @@ impl ZcashIndexer for StateServiceSubscriber { /// plan to offer this RPC publicly. async fn get_block_header( &self, - // state: &ReadStateService, - // only used in one place ^ - // of course we're reading the state, we're in state! ugh. - // network: &Network, - // only used in one place ^ - // same place above. - //network: self.config.network.clone(), hash_or_height: HashOrHeight, - // I'd like to only allow the Hash, but ok. verbose: Option, - // verbose seems to be required? ) -> Result { let mut state = state.clone(); let verbose = verbose.unwrap_or(true); diff --git a/zaino-state/src/indexer.rs b/zaino-state/src/indexer.rs index 6289909b4..b1d6b95f6 100644 --- a/zaino-state/src/indexer.rs +++ b/zaino-state/src/indexer.rs @@ -182,14 +182,7 @@ pub trait ZcashIndexer: Send + Sync + 'static { // TODO add links to original implementation async fn get_block_header( &self, - // state: &ReadStateService, - // only used in one place ^ - // network: &Network, - // only used in one place ^ - //network: self.config.network.clone(), - // zebra request HashOrHeight hash_or_height: HashOrHeight, - // I'd like to only allow the Hash, but ok. verbose: Option, ) -> Result; From 2ca369a849ebbacb3f339e2142568d59cce4023a Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 19 Aug 2025 20:21:03 -0400 Subject: [PATCH 22/33] tidy --- zaino-state/src/backends/state.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index 4e8bc0325..e0026e5f9 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -306,7 +306,6 @@ impl Drop for StateService { } } -// TODO - why is this called a fetch service subscriber?! it's in state. /// A fetch service subscriber. /// /// Subscribers should be @@ -584,7 +583,6 @@ impl StateServiceSubscriber { block_info_future ); - // TODO matching against a fetch -type here, this could be wrong or untangled let header_obj = match header? { GetBlockHeaderResponse::Raw(_hex_data) => unreachable!( "`true` was passed to get_block_header, an object should be returned" From bfaca549a00755546a4f5223e115a42d91080c25 Mon Sep 17 00:00:00 2001 From: al amoda Date: Wed, 20 Aug 2025 13:58:32 -0400 Subject: [PATCH 23/33] remove outdated comment --- zaino-state/src/backends/state.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/zaino-state/src/backends/state.rs b/zaino-state/src/backends/state.rs index e0026e5f9..b527aa110 100644 --- a/zaino-state/src/backends/state.rs +++ b/zaino-state/src/backends/state.rs @@ -306,9 +306,6 @@ impl Drop for StateService { } } -/// A fetch service subscriber. -/// -/// Subscribers should be #[derive(Debug, Clone)] pub struct StateServiceSubscriber { /// Remote wrappper functionality for zebra's [`ReadStateService`]. From 27c96a97e6540dc9246a73375ea982f68182ea38 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 00:26:04 -0400 Subject: [PATCH 24/33] expand .cpp archaeology comments, temp patch fetch.rs --- zaino-fetch/src/jsonrpsee/response.rs | 103 +++++++++++++++++++------- zaino-state/src/backends/fetch.rs | 9 ++- 2 files changed, 83 insertions(+), 29 deletions(-) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 792989342..b6bc2a8d9 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1520,40 +1520,91 @@ impl ResponseToError for GetMempoolInfoResponse { } /// The Zcash source code is considered canonical: +/// +/// block.cpp and block.h define the core data structures for blocks and their serialization, validation, and header logic +/// within `class CBlockHeader` the first two lines are enums and do not represent fields: +/// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L30 +/// The HEADER_SIZE enum defines the constant byte size of a block header, +/// while CURRENT_VERSION specifies the default version number used for newly created blocks. +/// The fields begin on this line: +/// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L32 +/// int32_t nVersion; +/// uint256 hashPrevBlock; +/// uint256 hashMerkleRoot; +/// uint256 hashBlockCommitments; +/// uint32_t nTime; +/// uint32_t nBits; +/// uint256 nNonce; +/// std::vector nSolution; +/// +/// SetNull() is used to clear field values: +/// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/primitives/block.h#L60 +/// Cblock represents a full block, and inherits from CBlockHeader: +/// +/// +/// chain.cpp and .h represent the state of the blockchain: structure, indexing, and chain selection /// The function does not modify the state of the object: it is called on `const`, /// with a return type defined as CBlockHeader in chain.h file: /// -/// +/// +/// CBlockHeader GetBlockHeader() const +/// { +/// CBlockHeader header; +/// header.nVersion = nVersion; +/// header.hashPrevBlock = hashPrev; +/// header.hashMerkleRoot = hashMerkleRoot; +/// header.hashBlockCommitments = hashBlockCommitments; +/// header.nTime = nTime; +/// header.nBits = nBits; +/// header.nNonce = nNonce; +/// header.nSolution = nSolution; +/// return header; +/// } +/// matching what's above. /// see also -/// -/// GetBlochHeader() seems to take arg of CBlockHeader (hash of block) and has a return with these fields, -/// including a field of the same data used as argument: -/// { -// TODO: this is different than the online docs, we should drill into zcashd -// maybe setting some default fields when creating the block I don't see here? -/// CBlockHeader block; -/// block.nVersion = nVersion; -/// block.hashPrevBlock = hashPrevBlock; -/// block.hashMerkleRoot = hashMerkleRoot; -/// block.hashBlockCommitments = hashBlockCommitments; -/// block.nTime = nTime; -/// block.nBits = nBits; -/// block.nNonce = nNonce; -/// block.nSolution = nSolution; -/// return block; -/// } /// [chain.cpp link](https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/chain.cpp#L82) +/// +// TODO: compare Chain.cpp, Block.cpp and the online RPC docs. +/// https://zcash.github.io/rpc/getblockheader.html : +/// --has these return fields documented that overlap with the C++ code: +/// version. +/// merkleroot. +/// time. +/// bits. +/// nonce. +/// prev. block hash. +/// --and these that do not: +/// hash (same as RPC provided argument) +/// confirmations (confirmations but only on best-chain, else -1) +/// height +/// finalsaplingroot (The root of the Sapling commitment tree after applying this block): see comment on hashBlockCommitments below. +/// difficulty (x.xxx) +/// next block hash +/// --leaving these in the C++ code unreported in the online docs: +/// nSolution +/// hashBlockCommitments (thought to be an aggregate including the merkleroot, and finalsapling root ) +/// +/// hashBlockCommitments = Merkle roots of transaction commitments, including transparent and shielded ones — into a single value that is effectively committed to by the block. +/// maybe kind of hashsum for all tx in block. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above - version: (), - hash_previous_block: (), - hash_merkle_root: (), - hash_block_commitments: (), - time: (), - bits: (), - nonce: (), - solution: (), + version: (), //number + hash_previous_block: (), //hash + hash_merkle_root: (), //hash + hash_block_commitments: (), //hash + time: (), //number + bits: (), //number + nonce: (), //number + solution: (), //vec (char in C++ often represents bytes, and nSolution appears to mean 'number used once' or a misapplied convention.) +/// int32_t nVersion; +/// uint256 hashPrevBlock; +/// uint256 hashMerkleRoot; +/// uint256 hashBlockCommitments; +/// uint32_t nTime; +/// uint32_t nBits; +/// uint256 nNonce; +/// std::vector nSolution; } impl ResponseToError for GetBlockHeaderResponse { diff --git a/zaino-state/src/backends/fetch.rs b/zaino-state/src/backends/fetch.rs index f7fc34d77..a7b114248 100644 --- a/zaino-state/src/backends/fetch.rs +++ b/zaino-state/src/backends/fetch.rs @@ -231,14 +231,17 @@ impl ZcashIndexer for FetchServiceSubscriber { /// method: post /// tags: blockchain // TODO params are only demos + /* async fn get_block_header_static( - _, - _, + _: _, + _: _, _hash_or_height_demo: HashOrHeight, _verbose: Option, ) -> Result { - Ok(self.fetcher.get_block_header().await?) + unreachable!("so far"); + //Ok(self.fetcher.get_block_header().await?) } + */ /// Returns blockchain state information, as a [`GetBlockchainInfoResponse`] JSON struct. /// From afe49efb276be24449d83c69d435edab86fdf54f Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 00:40:59 -0400 Subject: [PATCH 25/33] add field type comments --- zaino-fetch/src/jsonrpsee/response.rs | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index b6bc2a8d9..ca128946c 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1589,22 +1589,14 @@ impl ResponseToError for GetMempoolInfoResponse { #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above - version: (), //number - hash_previous_block: (), //hash - hash_merkle_root: (), //hash - hash_block_commitments: (), //hash - time: (), //number - bits: (), //number - nonce: (), //number - solution: (), //vec (char in C++ often represents bytes, and nSolution appears to mean 'number used once' or a misapplied convention.) -/// int32_t nVersion; -/// uint256 hashPrevBlock; -/// uint256 hashMerkleRoot; -/// uint256 hashBlockCommitments; -/// uint32_t nTime; -/// uint32_t nBits; -/// uint256 nNonce; -/// std::vector nSolution; + version: (), // int32_t number + hash_previous_block: (), // uint256 hash + hash_merkle_root: (), // uint256 hash + hash_block_commitments: (), // uint256 hash + time: (), // uint32_t number + bits: (), // uint32_t number + nonce: (), // uint256 number + solution: (), // vec (char in C++ often represents raw bytes, and nSolution appears to mean 'number used once' or a misapplied convention.) } impl ResponseToError for GetBlockHeaderResponse { From 8efb649a114f11aead5ae7a4e5f91d57a12d427c Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 00:41:47 -0400 Subject: [PATCH 26/33] adjust rust-toolchain.toml to match .env.testing-artifacts --- rust-toolchain.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index 73cb934de..a83ed2481 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,4 @@ [toolchain] -channel = "stable" +#channel = "stable" +channel = "1.88.0" components = ["rustfmt", "clippy"] From 44d0ab51c20745a3e84c64ed6a350d943fb1dcec Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 16:05:05 -0400 Subject: [PATCH 27/33] comments on u256 considerations --- zaino-fetch/src/jsonrpsee/response.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index ca128946c..873402c45 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -3,6 +3,10 @@ //! These types are redefined rather than imported from zebra_rpc //! to prevent locking consumers into a zebra_rpc version +// TODO: rust does not have a u256 in its standard library. +// try ethnum::U256::from_le_bytes or similar +// or check zebra types + use std::{convert::Infallible, num::ParseIntError}; use hex::FromHex; From 096e9b9ae8f0952b96da743663e57212930d1fbf Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 17:32:24 -0400 Subject: [PATCH 28/33] add realworld zcash-cli RPC returns to doc comments --- zaino-fetch/src/jsonrpsee/response.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 873402c45..8cdce2e3a 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1578,11 +1578,11 @@ impl ResponseToError for GetMempoolInfoResponse { /// nonce. /// prev. block hash. /// --and these that do not: -/// hash (same as RPC provided argument) +/// hash (same as provided RPC argument) /// confirmations (confirmations but only on best-chain, else -1) /// height /// finalsaplingroot (The root of the Sapling commitment tree after applying this block): see comment on hashBlockCommitments below. -/// difficulty (x.xxx) +/// difficulty ("x.xxx" - floating point) /// next block hash /// --leaving these in the C++ code unreported in the online docs: /// nSolution @@ -1590,6 +1590,29 @@ impl ResponseToError for GetMempoolInfoResponse { /// /// hashBlockCommitments = Merkle roots of transaction commitments, including transparent and shielded ones — into a single value that is effectively committed to by the block. /// maybe kind of hashsum for all tx in block. +/// +/// A real return from zcashd 6.3.0 running on mainnet using `zcash-cli` +/// getblockheader 000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3 +/// { +/// "hash": "000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3", +/// "confirmations": 1151, +/// "height": 304, +/// "version": 4, +/// "merkleroot": "670da2a6b2b7bcfce573b21edf8432863f5bf33eb904b0450ae4023a38ef8f70", +/// "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", +/// "time": 1477673429, +/// "nonce": "0000cf5e461e3ed275a3dffecca8ace6c147bd6bcaa6692ad87d29f5aa1d0000", +/// "solution": "00c886a0b5c5853129ec616a66f0686d1656f9e7e02efa3ff27814cea191134a213b5774629c8e7ae3491eab5bee00f5f5b7d726027974c0edd91de72ac07f2d795feea493070b8b46d6e223f15596f402f87ebe056d6934c7037beaef55219d9c3e770a90913f4cf3187cf606c68bc1e1fb0b030c846e63e90d6a8a74e11a12e32667985829267d61f61fa3c49cb6edbc841e2f54eeaa069fd135eee6e3a256bdc0915b2e9b5e92025954d35a89f2cf8ef1637161ddd719c8d3bb6cd14a014ce3f9345925edf705593c35a4530d553c6cb814eb940a0f874de5da31c2d566b10675a2ac7337981c921355aecbae62abee979458724485eeb850b2530365dc2ca08ac2f8a7ac13e33fd7f82a55fcd4d842175e649848869e250a70c630f5604492216cdb366a10e717201957153f21df41bc97be7538d9e2da1f33172b33b9ee8a6704f21b03c0c0a0da11040f690f6600dc0fec2bc0d55ddf54e5c4b673414d854411fba40f805d4ac4ac88cf99d7c2b017b194eba7bc9dfa4f0e8a0e267e6424534133e240194d9f254b32d9c7e51b3a838981e89779b58185bab0def9c2e50ab8f38e024f25adefaebd5b944e854a07d48a6201ce34cff5125aa09784a404e1b3be66a5916bf4adafe4560aa6260bde0d8a560b5f7e3f82a1616f39497b34924179482f8afcde1cf343160ba74182e645de969d15becb0701f7ef0a54070afd74c64c63d655e9f52b5432cf33295ce70b0e5c7935202539b87ede4b4ad89b56bd23e62476649ef9b10b2bd92baa63d62a57e7b5b472300ccb5e0bdf731fb9e0e8ca1fd919fe67001d0abc115d593476cb7424f1a283bced761c20f393493ef0376324f752a7eb6b871125e04378344d84e74cef562e4c45b098cf5c8f68f5c3d857affa5bbd591e78cd318d29f3af1afbc7788f23ae8164cf39ff04748ff600d525ff32084c14fd817b89cc79d7379cf3fdb2a00228a1b8bb2df2e7e277c357feba972566ba2cdc971329aba7132054b5168ee132b131633af3e079f1514115d719f163ab9d3b7db58a993db1f995d1f10f990195a396b612210d8e0bf15424af0a74bcc9cd367a0ee2df0d6f7f6419fe8ca1e86f7451f95bb3f3676526bfd1a802570aa8d85e177d013cca82fc3579244a39e0b425bc96f0ebdbe0b59a65428a4db0cdf8f05b04180d39fb2bc95bdacf3207362048b66d74f93f60079778e2ffaf6dcbb53c880abd4648c28e7857e06c0f89b10d63adc5a9bbace110ae71d6ce746a1dc5c31b219b2cfd19ed88fa69238e4ba4cae6787c749e85046d8d3a04387d65e927c25dd5160b29774b96d8bd25d542221e0c8fdb38f062a3913abc8165e1eb96c405be5d2d4594ab2bcbe6725af82fe3f9f8adbd3f5d5caf33d5939e19ef2a0526f8ccb9c8fe1cfb5652a404f8f04682ce5a4334af2bef30f247978702dc38ae206db5c783e76d53bb85343bd925315d81382e18f11d5479b5254d818b6bf8f6c68fb9879a9b63fcbfb042711b4c372a8e23fd62d87cfee662fa51f0dce80d0ddc91503fdb029334c1b66929d5525a84f534700c38c00e14aad4949f687687aff2feab223712b6f002153967f0281ae9f5a40ce2b55b458b6aac65fd88702c70f4b070b01bc996d2b43a09d4a6466a7234cba405387387e25c4027e9aa409868d2ed627b429e70ff06020198ea5c5bcd61a8010784d49314f60d9fac24086c8c8b6824cdc7e433b9121cffc7fe80ac1d82331491de5cab0f8178ef76140ddaba6fc98a35b5bcaf0c8bfdab520fb807ea6377b1f8edfada6163f95e7714a078e1fe4d11d8e922c17cfa5bd219ecbc392e131bb4158b6c2a0ff16bb462fdf3f576116bc8f335f939d2ae0ca4ad72d39e4c5a93a97920db264f7e67fd", +/// "bits": "1e085354", +/// "difficulty": 245.990748139731, +/// "chainwork": "0000000000000000000000000000000000000000000000000000000006659ef3", +/// "previousblockhash": "000001b5ad3057566497fa4cf1ad5519fa6a39acb0cd249aa23ca7d3b2ebd8f5", +/// "nextblockhash": "0000064be84052d3a4cda52592db6a61cd4cb127e34cd42404bba18d870b1aaa" +/// } +/// +/// this includes all the fields in the online RPC docs, as well as: +/// solution (visble to me in C++ code) +/// chainwork (not seen yet) #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above From d93e1723e2fed7a52a29ca4d1e971c8424748436 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 17:59:27 -0400 Subject: [PATCH 29/33] chainwork field doc comments --- zaino-fetch/src/jsonrpsee/response.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 8cdce2e3a..ad8afb267 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1591,7 +1591,7 @@ impl ResponseToError for GetMempoolInfoResponse { /// hashBlockCommitments = Merkle roots of transaction commitments, including transparent and shielded ones — into a single value that is effectively committed to by the block. /// maybe kind of hashsum for all tx in block. /// -/// A real return from zcashd 6.3.0 running on mainnet using `zcash-cli` +/// A real return using `zcash-cli` from zcashd 6.3.0 running on mainnet: /// getblockheader 000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3 /// { /// "hash": "000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3", @@ -1613,6 +1613,11 @@ impl ResponseToError for GetMempoolInfoResponse { /// this includes all the fields in the online RPC docs, as well as: /// solution (visble to me in C++ code) /// chainwork (not seen yet) +/// ... according to https://zcash.github.io/rpc/getblockchaininfo.html +/// "chainwork": "xxxx" (string) total amount of work in active chain, in hexadecimal +/// this number does increment during chain sync with `getblockchaininfo`, +/// but is a set amount when using getblockheader +/// therefore I think it is likely to be able to be found in the block, somehow. #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above From 6649b35e5eaebf0a1455ca20c573eaa36b912ad8 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 18:08:58 -0400 Subject: [PATCH 30/33] chainwork field doc comments continued --- zaino-fetch/src/jsonrpsee/response.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index ad8afb267..53513a871 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1618,6 +1618,9 @@ impl ResponseToError for GetMempoolInfoResponse { /// this number does increment during chain sync with `getblockchaininfo`, /// but is a set amount when using getblockheader /// therefore I think it is likely to be able to be found in the block, somehow. +/// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L126 +/// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L268 : +/// result.pushKV("chainwork", blockindex->nChainWork.GetHex()); #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above From 615637f845d90bf394be2779af6ad9a7cf79a318 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 18:15:48 -0400 Subject: [PATCH 31/33] getblockdeltas documentation breadcrumb --- zaino-fetch/src/jsonrpsee/response.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 53513a871..4b6a0a460 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1616,6 +1616,7 @@ impl ResponseToError for GetMempoolInfoResponse { /// ... according to https://zcash.github.io/rpc/getblockchaininfo.html /// "chainwork": "xxxx" (string) total amount of work in active chain, in hexadecimal /// this number does increment during chain sync with `getblockchaininfo`, +/// also present in getblockdeltas documentation - but I can confirm the zcash-cli RPC call is not functioning, at least in the same way. /// but is a set amount when using getblockheader /// therefore I think it is likely to be able to be found in the block, somehow. /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L126 From 84f46f79cca22a133ca68f55d03cc6734cbc775b Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 19:18:23 -0400 Subject: [PATCH 32/33] document RPC return for zcash-cli backed by zebrad 2.5.0 --- zaino-fetch/src/jsonrpsee/response.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 4b6a0a460..9a33b20b3 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1622,6 +1622,26 @@ impl ResponseToError for GetMempoolInfoResponse { /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L126 /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L268 : /// result.pushKV("chainwork", blockindex->nChainWork.GetHex()); +/// +/// however, zcash-cli when backed by zebrad 2.5.0 does NOT return chainwork and DOES return blockcommitments: +/// getblockheader 000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3 +/// { +/// "hash": "000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3", +/// "confirmations": 1848585, +/// "height": 304, +/// "version": 4, +/// "merkleroot": "670da2a6b2b7bcfce573b21edf8432863f5bf33eb904b0450ae4023a38ef8f70", +/// "blockcommitments": "0000000000000000000000000000000000000000000000000000000000000000", +/// "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", +/// "time": 1477673429, +/// "nonce": "0000cf5e461e3ed275a3dffecca8ace6c147bd6bcaa6692ad87d29f5aa1d0000", +/// "solution": "00c886a0b5c5853129ec616a66f0686d1656f9e7e02efa3ff27814cea191134a213b5774629c8e7ae3491eab5bee00f5f5b7d726027974c0edd91de72ac07f2d795feea493070b8b46d6e223f15596f402f87ebe056d6934c7037beaef55219d9c3e770a90913f4cf3187cf606c68bc1e1fb0b030c846e63e90d6a8a74e11a12e32667985829267d61f61fa3c49cb6edbc841e2f54eeaa069fd135eee6e3a256bdc0915b2e9b5e92025954d35a89f2cf8ef1637161ddd719c8d3bb6cd14a014ce3f9345925edf705593c35a4530d553c6cb814eb940a0f874de5da31c2d566b10675a2ac7337981c921355aecbae62abee979458724485eeb850b2530365dc2ca08ac2f8a7ac13e33fd7f82a55fcd4d842175e649848869e250a70c630f5604492216cdb366a10e717201957153f21df41bc97be7538d9e2da1f33172b33b9ee8a6704f21b03c0c0a0da11040f690f6600dc0fec2bc0d55ddf54e5c4b673414d854411fba40f805d4ac4ac88cf99d7c2b017b194eba7bc9dfa4f0e8a0e267e6424534133e240194d9f254b32d9c7e51b3a838981e89779b58185bab0def9c2e50ab8f38e024f25adefaebd5b944e854a07d48a6201ce34cff5125aa09784a404e1b3be66a5916bf4adafe4560aa6260bde0d8a560b5f7e3f82a1616f39497b34924179482f8afcde1cf343160ba74182e645de969d15becb0701f7ef0a54070afd74c64c63d655e9f52b5432cf33295ce70b0e5c7935202539b87ede4b4ad89b56bd23e62476649ef9b10b2bd92baa63d62a57e7b5b472300ccb5e0bdf731fb9e0e8ca1fd919fe67001d0abc115d593476cb7424f1a283bced761c20f393493ef0376324f752a7eb6b871125e04378344d84e74cef562e4c45b098cf5c8f68f5c3d857affa5bbd591e78cd318d29f3af1afbc7788f23ae8164cf39ff04748ff600d525ff32084c14fd817b89cc79d7379cf3fdb2a00228a1b8bb2df2e7e277c357feba972566ba2cdc971329aba7132054b5168ee132b131633af3e079f1514115d719f163ab9d3b7db58a993db1f995d1f10f990195a396b612210d8e0bf15424af0a74bcc9cd367a0ee2df0d6f7f6419fe8ca1e86f7451f95bb3f3676526bfd1a802570aa8d85e177d013cca82fc3579244a39e0b425bc96f0ebdbe0b59a65428a4db0cdf8f05b04180d39fb2bc95bdacf3207362048b66d74f93f60079778e2ffaf6dcbb53c880abd4648c28e7857e06c0f89b10d63adc5a9bbace110ae71d6ce746a1dc5c31b219b2cfd19ed88fa69238e4ba4cae6787c749e85046d8d3a04387d65e927c25dd5160b29774b96d8bd25d542221e0c8fdb38f062a3913abc8165e1eb96c405be5d2d4594ab2bcbe6725af82fe3f9f8adbd3f5d5caf33d5939e19ef2a0526f8ccb9c8fe1cfb5652a404f8f04682ce5a4334af2bef30f247978702dc38ae206db5c783e76d53bb85343bd925315d81382e18f11d5479b5254d818b6bf8f6c68fb9879a9b63fcbfb042711b4c372a8e23fd62d87cfee662fa51f0dce80d0ddc91503fdb029334c1b66929d5525a84f534700c38c00e14aad4949f687687aff2feab223712b6f002153967f0281ae9f5a40ce2b55b458b6aac65fd88702c70f4b070b01bc996d2b43a09d4a6466a7234cba405387387e25c4027e9aa409868d2ed627b429e70ff06020198ea5c5bcd61a8010784d49314f60d9fac24086c8c8b6824cdc7e433b9121cffc7fe80ac1d82331491de5cab0f8178ef76140ddaba6fc98a35b5bcaf0c8bfdab520fb807ea6377b1f8edfada6163f95e7714a078e1fe4d11d8e922c17cfa5bd219ecbc392e131bb4158b6c2a0ff16bb462fdf3f576116bc8f335f939d2ae0ca4ad72d39e4c5a93a97920db264f7e67fd", +/// "bits": "1e085354", +/// "difficulty": 245.99074813973095, +/// "previousblockhash": "000001b5ad3057566497fa4cf1ad5519fa6a39acb0cd249aa23ca7d3b2ebd8f5", +/// "nextblockhash": "0000064be84052d3a4cda52592db6a61cd4cb127e34cd42404bba18d870b1aaa" +/// } + #[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)] pub struct GetBlockHeaderResponse { // fields taken from zcashd source code pasted above From 7f7d81a4ddd45bbc9ce03603090ea4f0355efbf5 Mon Sep 17 00:00:00 2001 From: al amoda Date: Tue, 2 Sep 2025 19:28:16 -0400 Subject: [PATCH 33/33] nudge --- zaino-fetch/src/jsonrpsee/response.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/zaino-fetch/src/jsonrpsee/response.rs b/zaino-fetch/src/jsonrpsee/response.rs index 9a33b20b3..c70ba8449 100644 --- a/zaino-fetch/src/jsonrpsee/response.rs +++ b/zaino-fetch/src/jsonrpsee/response.rs @@ -1623,7 +1623,8 @@ impl ResponseToError for GetMempoolInfoResponse { /// https://github.com/zcash/zcash/blob/b65b008a7b334a2f7c2eaae1b028e011f2e21dd1/src/rpc/blockchain.cpp#L268 : /// result.pushKV("chainwork", blockindex->nChainWork.GetHex()); /// -/// however, zcash-cli when backed by zebrad 2.5.0 does NOT return chainwork and DOES return blockcommitments: +/// however, zcash-cli when backed by zebrad 2.5.0 does NOT return chainwork and DOES return blockcommitments +/// (though my example with unsynced zebra was all 000s): /// getblockheader 000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3 /// { /// "hash": "000003f9071a74cd0a1f7dba0614cd3dbd38b8afa401849c41a624c6a7b919a3",