Implement flyclient prover functionality#9693
Implement flyclient prover functionality#9693Metalcape wants to merge 9 commits intoZcashFoundation:mainfrom
Conversation
commit 22314a9 Author: Dario Capecchi <[email protected]> Date: Wed Jul 9 08:42:57 2025 +0000 Fix serialization tests commit 1296c70 Merge: f348b06 76eeecc Author: Dario Capecchi <[email protected]> Date: Wed Jul 9 10:09:13 2025 +0200 Merge branch 'ZcashFoundation:main' into flyclient commit f348b06 Merge: 301ef3a 70909eb Author: Dario Capecchi <[email protected]> Date: Tue Jul 8 08:53:17 2025 +0000 Merge branch 'main' into flyclient commit 301ef3a Author: Metalcape <[email protected]> Date: Fri Jul 4 14:46:42 2025 +0200 Fix more errors commit 7123d85 Author: Metalcape <[email protected]> Date: Fri Jul 4 11:10:45 2025 +0200 Fix errors and format after merge commit 2d25be1 Merge: c36a8b2 5bac400 Author: Metalcape <[email protected]> Date: Fri Jul 4 10:58:16 2025 +0200 Merge branch 'main' into flyclient commit c36a8b2 Merge: 5456d19 1ab3b0f Author: Dario Capecchi <[email protected]> Date: Tue Jun 3 17:24:19 2025 +0200 Merge branch 'ZcashFoundation:main' into flyclient commit 5456d19 Merge: 205740b 806fcab Author: Dario Capecchi <[email protected]> Date: Tue May 27 12:42:31 2025 +0200 Merge branch 'ZcashFoundation:main' into flyclient commit 205740b Author: Metalcape <[email protected]> Date: Fri May 23 17:31:46 2025 +0200 fix: add_history_nodes verification using incorrect height values commit 9ae0669 Merge: cf6ab07 cbd1bb7 Author: Dario Capecchi <[email protected]> Date: Fri May 23 12:32:57 2025 +0200 Merge branch 'ZcashFoundation:main' into flyclient commit cf6ab07 Merge: 62baf1a a77de50 Author: Dario Capecchi <[email protected]> Date: Sun May 18 12:53:05 2025 +0200 Merge branch 'ZcashFoundation:main' into flyclient commit 62baf1a Author: Metalcape <[email protected]> Date: Sat May 17 19:38:37 2025 +0200 fix: history node finalization when height is zero commit 95f4697 Author: Metalcape <[email protected]> Date: Sat May 17 19:37:30 2025 +0200 add_history_nodes: verify update against block commitments commit 33af2d3 Author: Metalcape <[email protected]> Date: Fri May 16 15:06:45 2025 +0200 cargo fmt commit 6aa97bc Author: Metalcape <[email protected]> Date: Fri May 16 15:05:16 2025 +0200 Update flyclient implementation - (fix) correctly update non-finalized state - store new history nodes as part of treestate - revert changes to db upgrade trait - add_history_nodes: verify tree at all heights - remove unused db access functions commit 68e6ba2 Merge: de4e7ff 89f8252 Author: Metalcape <[email protected]> Date: Sun May 11 11:13:10 2025 +0200 Merge branch 'main' into flyclient commit de4e7ff Author: Metalcape <[email protected]> Date: Thu May 8 14:59:31 2025 +0200 Update Cargo.lock commit a4bebd4 Merge: fb71684 ca51c39 Author: Metalcape <[email protected]> Date: Thu May 8 14:52:40 2025 +0200 Merge branch 'main' into flyclient commit fb71684 Author: Metalcape <[email protected]> Date: Thu May 8 14:50:05 2025 +0200 - fix: history tree db request off-by-one error - fix: history_tree leaf/peak functions being confusing - cargo fmt commit 226cf43 Merge: 7f35aaf 7cd1858 Author: Metalcape <[email protected]> Date: Thu May 8 13:01:52 2025 +0200 Merge branch 'main' into flyclient commit 7f35aaf Author: Metalcape <[email protected]> Date: Sun Apr 13 16:56:30 2025 +0200 Add RPC method to fetch history nodes commit 8cac881 Merge: 3bcf9f3 32de8ef Author: Metalcape <[email protected]> Date: Mon Mar 24 13:13:06 2025 +0100 Merge branch 'ZcashFoundation:main' into flyclient commit 3bcf9f3 Author: Metalcape <[email protected]> Date: Mon Mar 24 13:12:40 2025 +0100 Correcly upgrade database format to store history nodes - Fix off-by-one error in peaks and leaves number calculation for history trees - Rewrite run and check functions for upgrade - Fix writing new nodes when committing blocks to finalized state - Add additional checks to `append_history_nodes` commit 242d363 Author: Metalcape <[email protected]> Date: Tue Mar 18 22:10:18 2025 +0100 Fix column family names commit 1a7f0f5 Author: Metalcape <[email protected]> Date: Tue Mar 18 17:26:35 2025 +0100 Add `chainhistoryroot` to `getblockheader` rpc commit 6481ba2 Merge: 62cb355 619c01c Author: Metalcape <[email protected]> Date: Tue Mar 18 14:47:33 2025 +0100 Merge branch 'history-db' into flyclient commit 619c01c Author: Metalcape <[email protected]> Date: Tue Mar 18 14:39:38 2025 +0100 clippy commit 62cb355 Merge: be7a3b9 f0140a4 Author: Metalcape <[email protected]> Date: Tue Mar 18 14:38:03 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit 44426b1 Merge: a821734 49741e8 Author: Metalcape <[email protected]> Date: Thu Mar 13 18:11:57 2025 +0100 Merge branch 'ZcashFoundation:main' into history-db commit be7a3b9 Merge: f235914 49741e8 Author: Metalcape <[email protected]> Date: Thu Mar 13 18:11:46 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit a821734 Author: Metalcape <[email protected]> Date: Thu Mar 13 18:11:14 2025 +0100 Upgrade database version for history nodes - Handle upgrade from previous version - Fix incorrect write to database on block commit - Add history tree functions to calculate leaf and node index of a block - Add history tree function to get the peak indexes at a certain block height - Update write_block function to handle history nodes commit 7578d6c Author: Metalcape <[email protected]> Date: Mon Mar 10 19:46:07 2025 +0100 Add function to read history nodes from state commit 3c715da Merge: 5c36142 f873aa1 Author: Metalcape <[email protected]> Date: Mon Mar 10 19:06:12 2025 +0100 Merge branch 'ZcashFoundation:main' into history-db commit f235914 Merge: 6988d13 f873aa1 Author: Metalcape <[email protected]> Date: Mon Mar 10 19:06:04 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit 5c36142 Author: Metalcape <[email protected]> Date: Wed Mar 5 18:03:34 2025 +0100 Update history nodes: - When blocks are added to the non finalized chaintip; - When blocks are added to the finalized chaintip. commit 4ce98e3 Merge: b49a160 de7e5b5 Author: Metalcape <[email protected]> Date: Tue Mar 4 16:56:51 2025 +0100 Merge branch 'ZcashFoundation:main' into history-db commit 6988d13 Merge: c3430cc de7e5b5 Author: Metalcape <[email protected]> Date: Tue Mar 4 16:56:40 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit b49a160 Author: Metalcape <[email protected]> Date: Tue Mar 4 16:55:58 2025 +0100 Store full history tree - Add database column family for history tree nodes - Add functions for reading and writing to finalized state - Add functions for tracking nodes in non finalized state - Modify the `push` function for history trees to return newly added nodes commit c3430cc Merge: b003012 29ed501 Author: Metalcape <[email protected]> Date: Fri Feb 28 12:01:59 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit b003012 Merge: b503876 361fa65 Author: Metalcape <[email protected]> Date: Sun Feb 23 11:16:19 2025 +0100 Merge branch 'ZcashFoundation:main' into get_block commit b503876 Merge: 33502d0 5cf5178 Author: Metalcape <[email protected]> Date: Tue Feb 18 10:33:46 2025 +0100 Merge remote-tracking branch 'origin/main' into get_block commit 33502d0 Author: Metalcape <[email protected]> Date: Mon Feb 17 22:34:13 2025 +0100 Added `chainhistoryroot` to `getblock` - Modified the GetBlock and GetBlockHeader response objects - Added a state ReadRequest to obtain the history tree for a given block or height (used for blocks from NU5 and onwards) - Updated tests and snapshots
|
Thank you for the great contribution! It might take a bit until we're ready to review this, but we'll get to it eventually. |
commit e36497a Author: Metalcape <[email protected]> Date: Sat Nov 1 11:13:42 2025 +0100 Fix clippy warnings commit 6ceb1a6 Author: Metalcape <[email protected]> Date: Wed Oct 29 16:18:08 2025 +0100 Remove unnecessary RPC method commit 0ec9223 Author: Metalcape <[email protected]> Date: Wed Oct 29 16:12:25 2025 +0100 Fix height of inner tree in `history_tree_by_height` commit 7435fa8 Author: Metalcape <[email protected]> Date: Sun Oct 19 12:50:14 2025 +0200 Handle edge case in `first_block_with_total_work` commit c1fd2ea Author: Metalcape <[email protected]> Date: Wed Oct 8 11:05:15 2025 +0200 Implement rpc methods for difficulty-aware sampling of blocks - `gettotalwork` - `getfirstblockwithtotalwork` commit 18e107e Author: Metalcape <[email protected]> Date: Sat Sep 13 13:27:30 2025 +0200 Handle edge case for activation blocks when reading history trees commit f6e907b Author: Metalcape <[email protected]> Date: Sat Sep 13 13:27:04 2025 +0200 Fix some terminology commit 8222be6 Author: Metalcape <[email protected]> Date: Wed Sep 10 19:35:49 2025 +0200 Serialize as hex commit 6d12291 Author: Metalcape <[email protected]> Date: Wed Sep 10 19:15:24 2025 +0200 Add RPC methods - `getauthdataroot` for protocol correctness - `getshieldedtxcount` to calculate leaf nodes from downloaded headers - Fixed some typos and clippy warnings
|
Updated to include the progress we've made in the last couple of months, as of now it should be more or less complete in terms of features (bare minimum that a client needs to validate the blockchain using the protocol). |
- Fix clippy warnings in db upgrade task - Fix a bug `get_first_block_with_total_work` on pending upgrades - Remove some hardcoded references to NU6 instead of current upgrade
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟠 ❄️ releae 4.0.0 [Scheduled Freeze]Waiting for scheduled freeze to end.A freeze on the repository is scheduled for the following reason: releae 4.0.0
|
There was a problem hiding this comment.
Pull request overview
This pull request implements flyclient prover functionality for zebrad, enabling the generation of proofs that allow sublinear blockchain validation using the history tree/chainhistoryroot commitment. The implementation spans multiple layers of the Zebra architecture, adding database storage for history tree nodes, new state service operations, and RPC methods to support the difficulty-aware Flyclient protocol.
Changes:
- Added database storage for history tree MMR nodes with automated upgrade for version 27.1.0
- Modified
HistoryTree::pushto return the list of entries added, enabling tracking of new nodes - Implemented four new RPC methods:
gethistorynode,getauthdataroot,gettotalwork, andgetfirstblockwithtotalwork - Added
chainhistoryrootfield to allgetblockandgetblockheaderverbose responses
Reviewed changes
Copilot reviewed 50 out of 51 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| zebra-test/src/command.rs | Style update: use format string interpolation |
| zebra-state/src/service/read/tree.rs | Add functions to read history trees by height, history nodes, and calculate total work |
| zebra-state/src/service/read/find.rs | Implement binary search to find first block with given total work threshold |
| zebra-state/src/service/read/block.rs | Add function to retrieve auth data root for blocks |
| zebra-state/src/service/read.rs | Export new read functions for history nodes and trees |
| zebra-state/src/service/non_finalized_state/tests/prop.rs | Update test to include history_nodes_by_height field |
| zebra-state/src/service/non_finalized_state/chain.rs | Add history node tracking to non-finalized chain state |
| zebra-state/src/service/finalized_state/zebra_db/shielded.rs | Write history nodes when finalizing blocks |
| zebra-state/src/service/finalized_state/zebra_db/chain.rs | Add history_node column family and methods to read/write/rebuild history trees |
| zebra-state/src/service/finalized_state/zebra_db/block.rs | Add method to retrieve auth_data_root from blocks |
| zebra-state/src/service/finalized_state/disk_format/upgrade/add_history_nodes.rs | Implement database upgrade to generate and store history nodes from existing blocks |
| zebra-state/src/service/finalized_state/disk_format/upgrade.rs | Register new database format upgrade for version 27.1.0 |
| zebra-state/src/service/finalized_state/disk_format/tests/snapshots/*.snap | Update test snapshots to include new history_node column family |
| zebra-state/src/service/finalized_state/disk_format/chain.rs | Implement serialization for NetworkUpgrade, HistoryNodeIndex, and Entry types |
| zebra-state/src/service/finalized_state.rs | Update block finalization to capture and store new history nodes |
| zebra-state/src/service.rs | Add request handlers for new read operations (HistoryTree, HistoryNode, AuthDataRoot, TotalWork) |
| zebra-state/src/response.rs | Add response types for new read requests |
| zebra-state/src/request.rs | Add request types and update Treestate to include new_history_nodes |
| zebra-state/src/constants.rs | Bump database minor version to 27.1 |
| zebra-rpc/tests/vectors/getblock_response_1.json | Add chainhistoryroot field to test vector |
| zebra-rpc/tests/serialization_tests.rs | Update tests to verify chainhistoryroot field in responses |
| zebra-rpc/src/methods/tests/vectors.rs | Update test helper and assertions to handle chainhistoryroot |
| zebra-rpc/src/methods/tests/snapshots/*.snap | Update all snapshot tests to include chainhistoryroot field |
| zebra-rpc/src/methods.rs | Implement four new RPC methods and add chainhistoryroot to block/header responses |
| zebra-rpc/Cargo.toml | Add dependencies for zcash_history and bytemuck |
| zebra-network/proptest-regressions/peer_set/set/tests/prop.txt | Add proptest regression seed |
| zebra-chain/src/primitives/zcash_history.rs | Add Entry::inner(), From<&Vec> for Entry, HistoryNodeIndex, and root_node_data() method |
| zebra-chain/src/history_tree.rs | Modify push() to return entries, add MMR navigation functions and HistoryNodeData type |
| // Binary search over subtree_total_work within this upgrade | ||
| while start_height != end_height { | ||
| let middle = Height(((start_height.as_usize() + end_height.as_usize()) / 2) as u32); |
There was a problem hiding this comment.
The binary search implementation has a potential integer overflow issue. On line 730, (start_height.as_usize() + end_height.as_usize()) / 2 could overflow if both heights are large (close to u32::MAX). While this is unlikely in practice for block heights, it's a pattern that should be avoided.
Consider using the overflow-safe pattern: start_height.as_usize() + (end_height.as_usize() - start_height.as_usize()) / 2, or verify that this overflow cannot occur with a comment explaining the invariant.
| timer.finish(module_path!(), line!(), "ReadRequest::HistoryNode"); | ||
|
|
||
| Ok(ReadResponse::AuthDataRoot(auth_data_root)) | ||
| }) | ||
| }) | ||
| .wait_for_panics() | ||
| } | ||
|
|
||
| ReadRequest::FirstBlockWithTotalWork(threshold) => { | ||
| let state = self.clone(); | ||
|
|
||
| tokio::task::spawn_blocking(move || { | ||
| span.in_scope(move || { | ||
| let block_index = | ||
| state.non_finalized_state_receiver.with_watch_data(|_| { | ||
| read::first_block_with_total_work(&state.db, threshold) | ||
| }); | ||
|
|
||
| // The work is done in the future. | ||
| timer.finish(module_path!(), line!(), "ReadRequest::HistoryNode"); | ||
|
|
||
| Ok(ReadResponse::FirstBlockWithTotalWork(block_index)) | ||
| }) | ||
| }) | ||
| .wait_for_panics() | ||
| } | ||
|
|
||
| ReadRequest::TotalWork(hash_or_height) => { | ||
| let state = self.clone(); | ||
|
|
||
| tokio::task::spawn_blocking(move || { | ||
| span.in_scope(move || { | ||
| let total_work = state | ||
| .non_finalized_state_receiver | ||
| .with_watch_data(|_| read::total_work(&state.db, hash_or_height)); | ||
|
|
||
| // The work is done in the future. | ||
| timer.finish(module_path!(), line!(), "ReadRequest::HistoryNode"); |
There was a problem hiding this comment.
The timer finish calls on lines 1847, 1872, 1896, 1915, and 1933 use incorrect labels. Lines 1896, 1915, and 1933 all say "ReadRequest::HistoryNode" but should be "ReadRequest::AuthDataRoot", "ReadRequest::FirstBlockWithTotalWork", and "ReadRequest::TotalWork" respectively. This will make performance debugging and metrics confusing.
| .await | ||
| .map_misc_error()? | ||
| else { | ||
| panic!("unexpected response to HistoryNode request") |
There was a problem hiding this comment.
The panic message on line 2309 says "unexpected response to HistoryNode request" but this is actually handling an AuthDataRoot request. This will be confusing during debugging. It should say "unexpected response to AuthDataRoot request".
| panic!("unexpected response to HistoryNode request") | |
| panic!("unexpected response to AuthDataRoot request") |
| .await | ||
| .map_misc_error()? | ||
| else { | ||
| panic!("unexpected response to HistoryNode request") |
There was a problem hiding this comment.
The panic message says "unexpected response to HistoryNode request" but this is handling a FirstBlockWithTotalWork request. It should say "unexpected response to FirstBlockWithTotalWork request".
| panic!("unexpected response to HistoryNode request") | |
| panic!("unexpected response to FirstBlockWithTotalWork request") |
| let block = self.block(HashOrHeight::Height( | ||
| Height::try_from(temp_tree_height.as_usize() as u32).ok()?, | ||
| ))?; | ||
| let sapling_root = self | ||
| .sapling_tree_by_height(&Height::try_from(temp_tree_height.as_usize() as u32).ok()?)? | ||
| .root(); | ||
| let orchard_root = self | ||
| .orchard_tree_by_height(&Height::try_from(temp_tree_height.as_usize() as u32).ok()?)? | ||
| .root(); |
There was a problem hiding this comment.
There are redundant Height conversions here - temp_tree_height is already a Height, so converting it .as_usize() as u32 and then back with Height::try_from() is unnecessary. You can use temp_tree_height directly in the function calls.
| let entry_object = | ||
| zcash_history::Entry::<V1>::from_bytes(branch_id.into(), entry.inner()) | ||
| .expect("entry object should be valid"); | ||
| let node_bytes = match entry_object.leaf() { | ||
| true => entry.inner().split_at(1).1, | ||
| false => entry.inner().split_at(9).1, | ||
| }; | ||
| let mut cursor = Cursor::new(&node_bytes); | ||
| let node = V1::read(branch_id.into(), &mut cursor) | ||
| .expect("node data should be valid"); | ||
| let mut total_work: [u8; 32] = bytemuck::cast(node.subtree_total_work.0); | ||
| total_work.reverse(); | ||
| GetHistoryNodeObject { | ||
| subtree_commitment: node.subtree_commitment, | ||
| consensus_branch_id: ConsensusBranchIdHex( | ||
| node.consensus_branch_id.into(), | ||
| ), | ||
| start_time: node.start_time, | ||
| end_time: node.end_time, | ||
| start_target: node.start_target, | ||
| end_target: node.end_target, | ||
| start_sapling_root: node.start_sapling_root, | ||
| end_sapling_root: node.end_sapling_root, | ||
| subtree_total_work: total_work, | ||
| start_height: node.start_height, | ||
| end_height: node.end_height, | ||
| sapling_tx: node.sapling_tx, | ||
| start_orchard_root: [0; 32], | ||
| end_orchard_root: [0; 32], | ||
| orchard_tx: 0, | ||
| } | ||
| } | ||
| _ => { | ||
| let entry_object = | ||
| zcash_history::Entry::<V2>::from_bytes(branch_id.into(), entry.inner()) | ||
| .expect("entry object should be valid"); | ||
| let node_bytes = match entry_object.leaf() { | ||
| true => entry.inner().split_at(1).1, | ||
| false => entry.inner().split_at(9).1, | ||
| }; | ||
| let mut cursor = Cursor::new(&node_bytes); | ||
| let node = V2::read(branch_id.into(), &mut cursor) | ||
| .expect("node data should be valid"); |
There was a problem hiding this comment.
The .expect() calls at lines 2220, 2227, 2253, and 2260 could panic if the database contains corrupted data. Since this data comes from the database (which could potentially be corrupted or malicious in some scenarios), these should be converted to proper error handling that returns an error to the RPC caller instead of panicking.
Consider replacing these expects with proper error handling using map_err or similar patterns to return an appropriate RPC error.
| ) | ||
| })?; | ||
|
|
||
| let branch_id = network_upgrade.branch_id().unwrap(); |
There was a problem hiding this comment.
The .unwrap() on line 2197 could panic if the network upgrade doesn't have a branch_id. While the current network upgrades in the UPGRADE_LIST all have branch IDs, this creates a potential future maintenance hazard. Consider handling this case explicitly with proper error handling.
| fn history_nodes_at_chain_tip(&self) -> Option<Vec<Entry>> { | ||
| let mut result = Vec::<Entry>::new(); | ||
|
|
||
| if self.history_nodes_by_height.is_empty() { | ||
| return None; | ||
| } | ||
|
|
||
| for (_key, mut entries) in self.history_nodes_by_height.clone() { | ||
| result.append(&mut entries); | ||
| } | ||
|
|
||
| Some(result) |
There was a problem hiding this comment.
This method clones the entire history_nodes_by_height BTreeMap and then iterates over it, which is inefficient. The clone is unnecessary here - you can iterate directly over the BTreeMap values using .values() and then .flatten() or collect into the result vector.
Consider changing to: self.history_nodes_by_height.values().flatten().cloned().collect() to avoid the BTreeMap clone.
| .await | ||
| .map_misc_error()? | ||
| else { | ||
| panic!("unexpected response to TotalWork request") |
There was a problem hiding this comment.
Similarly to line 2309, the panic message here says "unexpected response to HistoryNode request" but this is actually handling a TotalWork request. It should say "unexpected response to TotalWork request".
| | ReadResponse::HistoryTree(_) | ||
| | ReadResponse::HistoryNode(_) | ||
| | ReadResponse::AuthDataRoot(_) | ||
| | ReadResponse:: FirstBlockWithTotalWork(_) |
There was a problem hiding this comment.
There's an extra space before FirstBlockWithTotalWork on line 545. It should be ReadResponse::FirstBlockWithTotalWork(_) without the double colon spacing.
| | ReadResponse:: FirstBlockWithTotalWork(_) | |
| | ReadResponse::FirstBlockWithTotalWork(_) |
This is what I've done so far on flyclient, as discussed on discord (sorry for the delay). I'm publishing this as draft mainly for discussion and feedback on the general implementation.
Update (Nov 1 2025): Added RPC methods for retrieving
authdatarootand to support the difficulty-aware Flyclient protocol.Motivation
Zcash already supports flyclient through the history tree/
chainhistoryrootcommitment, but zebrad is not currently able to generate a proof that allows a sublinear client to validate the blockchain with it. This PR implements the necessary state changes that zebrad needs to generate a flyclient proof using history tree nodes, and also a new RPC method that can be used by clients to request the nodes.Solution
zebra-state:HistoryNodecolumn which stores all MMR nodes, indexed by network upgrade and node index; this is to be kept consistent with the chaintip history treezebra-chain:HistoryTree::pushreturn the list of entries added to the tree by the pushzebra-rpc:gethistorynodemethod to request a single MMR node from the databasechainhistoryrootfield to allgetblockandgetblockheaderverbose responsesgetauthdataroot) to download the auth data root of a block, used to validate itschainhistoryrootagainst theblockcommitmentsfield.gettotalworkandgetfirstblockwithtotalwork) needed to implement difficulty-aware flyclient bootstrapping.Existing tests have been updated to take these changes into account.
Tests
Testing mostly requires a full sync so I mainly tested manually using a client script that simulates the flyclient protocol bootstrap, sampling random blocks and then downloading MMR ancestry proofs for those blocks. I'm open to suggestions for automated tests.
Specifications & References
Follow-up Work
Needs a testing strategy for the new state changes and RPC methods. There is also a temporary workaround I did in the
get_history_nodemethod implementation, which can be replaced as soon as thezcash_historycrate is updated with the changes I contributed in zcash/librustzcash#1809 .PR Checklist