diff --git a/Cargo.lock b/Cargo.lock index 1e6704c9cef..e597babdb90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2564,9 +2564,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" +checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" [[package]] name = "oorandom" diff --git a/book/src/dev/zebra-checkpoints.md b/book/src/dev/zebra-checkpoints.md index 5ca2b19c158..84363be4f07 100644 --- a/book/src/dev/zebra-checkpoints.md +++ b/book/src/dev/zebra-checkpoints.md @@ -1,6 +1,6 @@ # zebra-checkpoints -`zebra-checkpoints` uses a local `zcashd` instance to generate a list of checkpoints for Zebra's checkpoint verifier. +`zebra-checkpoints` uses a local `zebrad` or `zcashd` instance to generate a list of checkpoints for Zebra's checkpoint verifier. Developers should run this tool every few months to add new checkpoints to Zebra. (By default, Zebra uses these checkpoints to sync to the chain tip.) diff --git a/zebra-consensus/Cargo.toml b/zebra-consensus/Cargo.toml index c95e3aa05a6..845d9811fa3 100644 --- a/zebra-consensus/Cargo.toml +++ b/zebra-consensus/Cargo.toml @@ -23,7 +23,7 @@ chrono = { version = "0.4.23", default-features = false, features = ["clock", "s dirs = "4.0.0" displaydoc = "0.2.3" lazy_static = "1.4.0" -once_cell = "1.16.0" +once_cell = "1.17.0" serde = { version = "1.0.152", features = ["serde_derive"] } futures = "0.3.25" diff --git a/zebra-consensus/src/checkpoint/README.md b/zebra-consensus/src/checkpoint/README.md index ddb7d1ca199..a5a47fc5d37 100644 --- a/zebra-consensus/src/checkpoint/README.md +++ b/zebra-consensus/src/checkpoint/README.md @@ -22,7 +22,7 @@ Or jump straight to [the exact commands for updating the lists](https://github.c ### Use the `zebra-checkpoints` utility -`zebra-checkpoints` is the program we use to collect checkpoints. Currently this program uses `zcash-cli` to get the hashes. `zcash-cli` must be available in your machine and it must be connected to a synchronized (Mainnet or Testnet) instance of `zcashd` to get the most recent hashes. +`zebra-checkpoints` is the program we use to collect checkpoints. Currently this program uses `zcash-cli` to get the hashes. `zcash-cli` must be available in your machine and it must be connected to a synchronized (Mainnet or Testnet) instance of `zebrad` or `zcashd` to get the most recent hashes. First, [build the `zebra-checkpoints` binary](https://github.com/ZcashFoundation/zebra/tree/main/zebra-utils/README.md#zebra-checkpoints). @@ -43,7 +43,7 @@ $ zebra-checkpoints --last-checkpoint $(tail -1 zebra-consensus/src/checkpoint/m ... ``` -If we are looking to update the testnet hashes we must make sure the cli is connected with a testnet chain. If we have our `zcashd` running locally we can make this by starting with `zcashd -testnet`. +If we are looking to update the testnet hashes we must make sure the cli is connected with a testnet chain. If we are using `zcashd` as the backend and this is running locally, we can make this by starting with `zcashd -testnet`. If we are using `zebrad` as the backend, then we must start with a configuration file where the `network` field of the `[network]` section is `Testnet`. Anything we add after `--` will pass through into the `zcash-cli` program so we can specify the testnet here. diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 4b4fd72888f..eabb84e0fa4 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -24,7 +24,7 @@ use zebra_chain::{ orchard, parameters::{ConsensusBranchId, Network, NetworkUpgrade}, sapling, - serialization::{SerializationError, ZcashDeserialize}, + serialization::{SerializationError, ZcashDeserialize, ZcashSerialize}, transaction::{self, SerializedTransaction, Transaction, UnminedTx}, transparent::{self, Address}, }; @@ -139,7 +139,9 @@ pub trait Rpc { /// /// With verbosity=1, [`lightwalletd` only reads the `tx` field of the /// result](https://github.com/zcash/lightwalletd/blob/dfac02093d85fb31fb9a8475b884dd6abca966c7/common/common.go#L152), - /// so we only return that for now. + /// so we return that. + /// + /// Additionally, we return block height, hash and size to be compatible with our `zebra-checkpoints` utility. /// /// `lightwalletd` only requests blocks by height, so we don't support /// getting blocks by hash. (But we parse the height as a JSON string, not an integer). @@ -575,29 +577,29 @@ where data: None, })?; - if verbosity == 0 { - let request = zebra_state::ReadRequest::Block(hash_or_height); - let response = state - .ready() - .and_then(|service| service.call(request)) - .await - .map_err(|error| Error { - code: ErrorCode::ServerError(0), - message: error.to_string(), - data: None, - })?; + let request = zebra_state::ReadRequest::Block(hash_or_height); + let response = state + .ready() + .and_then(|service| service.call(request)) + .await + .map_err(|error| Error { + code: ErrorCode::ServerError(0), + message: error.to_string(), + data: None, + })?; - match response { - zebra_state::ReadResponse::Block(Some(block)) => { - Ok(GetBlock::Raw(block.into())) - } - zebra_state::ReadResponse::Block(None) => Err(Error { - code: MISSING_BLOCK_ERROR_CODE, - message: "Block not found".to_string(), - data: None, - }), - _ => unreachable!("unmatched response to a block request"), - } + let block = match response { + zebra_state::ReadResponse::Block(Some(block)) => Ok(block), + zebra_state::ReadResponse::Block(None) => Err(Error { + code: MISSING_BLOCK_ERROR_CODE, + message: "Block not found".to_string(), + data: None, + }), + _ => unreachable!("unmatched response to a block request"), + }?; + + if verbosity == 0 { + Ok(GetBlock::Raw(block.into())) } else if verbosity == 1 { let request = zebra_state::ReadRequest::TransactionIdsForBlock(hash_or_height); let response = state @@ -613,7 +615,14 @@ where match response { zebra_state::ReadResponse::TransactionIdsForBlock(Some(tx_ids)) => { let tx_ids = tx_ids.iter().map(|tx_id| tx_id.encode_hex()).collect(); - Ok(GetBlock::Object { tx: tx_ids }) + Ok(GetBlock::Object { + hash: block.hash(), + height: block + .coinbase_height() + .expect("all blocks should have a coinbase height"), + size: block.zcash_serialized_size(), + tx: tx_ids, + }) } zebra_state::ReadResponse::TransactionIdsForBlock(None) => Err(Error { code: MISSING_BLOCK_ERROR_CODE, @@ -1182,6 +1191,13 @@ pub enum GetBlock { Raw(#[serde(with = "hex")] SerializedBlock), /// The block object. Object { + /// Requested block hash. + #[serde(with = "hex")] + hash: block::Hash, + /// Requested block height. + height: Height, + /// Requested block size. + size: usize, /// List of transaction IDs in block order, hex-encoded. tx: Vec, }, diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@mainnet_10.snap index b9fc9794fa8..db2abe7b931 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@mainnet_10.snap @@ -3,6 +3,9 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- { + "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", + "height": 1, + "size": 1617, "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ] diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@testnet_10.snap index dbc2ce43d5e..86efdf8e2f8 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose@testnet_10.snap @@ -3,6 +3,9 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- { + "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", + "height": 1, + "size": 1618, "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ] diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 465917319da..ef91b442a6d 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -113,7 +113,12 @@ async fn rpc_getblock() { .transactions .iter() .map(|tx| tx.hash().encode_hex()) - .collect() + .collect(), + height: block + .coinbase_height() + .expect("test block should have coinbase height"), + hash: block.hash(), + size: block.zcash_serialized_size(), } ); } diff --git a/zebra-rpc/src/tests/vectors.rs b/zebra-rpc/src/tests/vectors.rs index 45eb4e2d67b..326353bb710 100644 --- a/zebra-rpc/src/tests/vectors.rs +++ b/zebra-rpc/src/tests/vectors.rs @@ -30,8 +30,11 @@ pub fn test_block_serialization() { let expected_tx = GetBlock::Object { tx: vec!["42".into()], + height: zebra_chain::block::Height(1), + hash: zebra_chain::block::Hash([0; 32]), + size: 1, }; - let expected_json = r#"{"tx":["42"]}"#; + let expected_json = r#"{"hash":"0000000000000000000000000000000000000000000000000000000000000000","height":1,"size":1,"tx":["42"]}"#; let j = serde_json::to_string(&expected_tx).unwrap(); assert_eq!(j, expected_json); diff --git a/zebra-state/Cargo.toml b/zebra-state/Cargo.toml index df86eb0a42f..d9c9f69cbff 100644 --- a/zebra-state/Cargo.toml +++ b/zebra-state/Cargo.toml @@ -58,7 +58,7 @@ color-eyre = "0.6.2" # Enable a feature that makes tinyvec compile much faster. tinyvec = { version = "1.6.0", features = ["rustc_1_55"] } -once_cell = "1.16.0" +once_cell = "1.17.0" spandoc = "0.2.2" hex = { version = "0.4.3", features = ["serde"] } diff --git a/zebra-test/Cargo.toml b/zebra-test/Cargo.toml index 4e35d2f046c..3d525a3e5c6 100644 --- a/zebra-test/Cargo.toml +++ b/zebra-test/Cargo.toml @@ -13,7 +13,7 @@ indexmap = "1.9.2" lazy_static = "1.4.0" insta = "1.23.0" proptest = "0.10.1" -once_cell = "1.16.0" +once_cell = "1.17.0" rand = { version = "0.8.5", package = "rand" } regex = "1.7.0" diff --git a/zebra-utils/README.md b/zebra-utils/README.md index ae4730ab235..54acfbd58ff 100644 --- a/zebra-utils/README.md +++ b/zebra-utils/README.md @@ -15,7 +15,7 @@ Binaries are easier to use if they are located in your system execution path. This command generates a list of zebra checkpoints, and writes them to standard output. Each checkpoint consists of a block height and hash. -To create checkpoints, you need a synchronized instance of `zcashd`, and the `zcash-cli` RPC client. +To create checkpoints, you need a synchronized instance of `zebrad` or `zcashd`, and the `zcash-cli` RPC client. `zebra-checkpoints` is a standalone rust binary, you can compile it using: diff --git a/zebra-utils/src/bin/zebra-checkpoints/main.rs b/zebra-utils/src/bin/zebra-checkpoints/main.rs index ce9dd27d517..63c53b62113 100644 --- a/zebra-utils/src/bin/zebra-checkpoints/main.rs +++ b/zebra-utils/src/bin/zebra-checkpoints/main.rs @@ -66,9 +66,14 @@ fn main() -> Result<()> { // get the current block count let mut cmd = passthrough_cmd(); - cmd.arg("getblockcount"); + cmd.arg("getblockchaininfo"); + + let output = cmd_output(&mut cmd)?; + let get_block_chain_info: Value = serde_json::from_str(&output)?; + // calculate the maximum height - let height_limit: block::Height = cmd_output(&mut cmd)?.trim().parse()?; + let height_limit = block::Height(get_block_chain_info["blocks"].as_u64().unwrap() as u32); + assert!(height_limit <= block::Height::MAX); // Checkpoints must be on the main chain, so we skip blocks that are within the // Zcash reorg limit. @@ -102,8 +107,9 @@ fn main() -> Result<()> { let mut cmd = passthrough_cmd(); // get block data - cmd.args(["getblock", &x.to_string()]); + cmd.args(["getblock", &x.to_string(), "1"]); let output = cmd_output(&mut cmd)?; + // parse json let v: Value = serde_json::from_str(&output)?; diff --git a/zebrad/Cargo.toml b/zebrad/Cargo.toml index c9e05d4662f..dc2c124f718 100644 --- a/zebrad/Cargo.toml +++ b/zebrad/Cargo.toml @@ -167,7 +167,7 @@ tonic-build = { version = "0.8.0", optional = true } [dev-dependencies] abscissa_core = { version = "0.5", features = ["testing"] } hex = "0.4.3" -once_cell = "1.16.0" +once_cell = "1.17.0" regex = "1.7.0" semver = "1.0.16"