From 108de07a5b6377512e5b3f82ac5a394f47a44bae Mon Sep 17 00:00:00 2001 From: Arya Date: Thu, 24 Oct 2024 23:50:11 -0400 Subject: [PATCH 01/12] Adds getblockheader RPC method --- zebra-rpc/src/methods.rs | 214 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 213 insertions(+), 1 deletion(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 8becc5bb79c..0fed3022e8a 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -11,6 +11,7 @@ use std::{collections::HashSet, fmt::Debug, sync::Arc}; use chrono::Utc; use futures::{stream::FuturesOrdered, FutureExt, StreamExt, TryFutureExt}; use hex::{FromHex, ToHex}; +use hex_data::HexData; use indexmap::IndexMap; use jsonrpc_core::{self, BoxFuture, Error, ErrorCode, Result}; use jsonrpc_derive::rpc; @@ -23,10 +24,11 @@ use zebra_chain::{ block::{self, Height, SerializedBlock}, chain_tip::{ChainTip, NetworkChainTipHeightEstimator}, parameters::{ConsensusBranchId, Network, NetworkUpgrade}, - serialization::ZcashDeserialize, + serialization::{ZcashDeserialize, ZcashSerialize}, subtree::NoteCommitmentSubtreeIndex, transaction::{self, SerializedTransaction, Transaction, UnminedTx}, transparent::{self, Address}, + work::difficulty::ExpandedDifficulty, }; use zebra_node_services::mempool; use zebra_state::{HashOrHeight, MinedTx, OutputIndex, OutputLocation, TransactionLocation}; @@ -166,6 +168,23 @@ pub trait Rpc { verbosity: Option, ) -> BoxFuture>; + /// Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string. + /// + /// 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 + #[rpc(name = "getblockheader")] + fn get_block_header( + &self, + hash_or_height: String, + verbose: Option, + ) -> BoxFuture>; + /// Returns the hash of the current best blockchain tip block, as a [`GetBlockHash`] JSON string. /// /// zcashd reference: [`getbestblockhash`](https://zcash.github.io/rpc/getbestblockhash.html) @@ -919,6 +938,112 @@ where .boxed() } + fn get_block_header( + &self, + hash_or_height: String, + verbose: Option, + ) -> BoxFuture> { + let state = self.state.clone(); + let verbose = verbose.unwrap_or_default(); + + async move { + let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; + let zebra_state::ReadResponse::BlockHeader(block_header) = state + .clone() + .oneshot(zebra_state::ReadRequest::BlockHeader(hash_or_height)) + .await + .map_server_error()? + else { + panic!("unexpected response to BlockHeader request") + }; + + let block_header = block_header + .ok_or_server_error("could not find block with the provided hash or height")?; + + let response = if !verbose { + GetBlockHeader::Raw(HexData( + block_header.zcash_serialize_to_vec().map_server_error()?, + )) + } else { + // TODO: + // - Return block hash and height in BlockHeader response + // - Add the block height to the `getblock` response as well + // - Add a parameter to the BlockHeader request to indicate that the caller is interested in the next block hash? + + // TODO: Get block hash and height from BlockHeader response instead. + let hash = hash_or_height.hash().unwrap(); + let height = hash_or_height.height().unwrap(); + + let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state + .clone() + .oneshot(zebra_state::ReadRequest::SaplingTree(hash_or_height)) + .await + .map_server_error()? + else { + panic!("unexpected response to SaplingTree request") + }; + + // TODO: Double-check that there's an empty Sapling root at Genesis. + let sapling_tree = sapling_tree.expect("should always have a sapling root"); + + let zebra_state::ReadResponse::Depth(depth) = state + .clone() + .oneshot(zebra_state::ReadRequest::Depth(hash)) + .await + .map_server_error()? + else { + panic!("unexpected response to SaplingTree request") + }; + + // 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 block::Header { + version, + previous_block_hash, + merkle_root, + commitment_bytes: _, + time, + difficulty_threshold, + nonce, + solution: _, + } = *block_header; + + let block_header = GetBlockHeaderObject { + hash: GetBlockHash(hash), + confirmations, + height, + version, + merkle_root, + final_sapling_root: sapling_tree, + time: time.timestamp(), + nonce: *nonce, + bits: difficulty_threshold, + difficulty: difficulty_threshold.to_expanded().ok_or_server_error( + "could not convert compact difficulty to expanded difficulty", + )?, + previous_block_hash: GetBlockHash(previous_block_hash), + + // TODO: Add the next block hash to the BlockHeader response too, we can just check the next block height in the same chain, if any. + // This should be an optional field in case the requested block is a chain tip block. + next_block_hash: GetBlockHash(previous_block_hash), + }; + + GetBlockHeader::Object(Box::new(block_header)) + }; + + Ok(response) + } + .boxed() + } + fn get_best_block_hash(&self) -> Result { self.latest_chain_tip .best_tip_hash() @@ -1623,6 +1748,93 @@ impl Default for GetBlock { } } +/// Response to a `getblockheader` RPC request. +/// +/// See the notes for the [`Rpc::get_block_header`] method. +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] +#[serde(untagged)] +pub enum GetBlockHeader { + /// The request block, hex-encoded. + Raw(hex_data::HexData), + + /// The block object. + Object(Box), +} + +#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] +/// Verbose response to a `getblockheader` RPC request. +/// +/// See the notes for the [`Rpc::get_block_header`] method. +pub struct GetBlockHeaderObject { + /// The hash of the requested block. + pub hash: GetBlockHash, + + /// The number of confirmations of this block in the best chain, + /// or -1 if it is not in the best chain. + pub confirmations: i64, + + /// The height of the requested block. + pub height: Height, + + /// The version field of the requested block. + pub version: u32, + + /// The merkle root of the requesteed block. + pub merkle_root: block::merkle::Root, + + /// The root of the Sapling commitment tree after applying this block. + pub final_sapling_root: Arc, + + /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. + pub time: i64, + + /// The nonce of the requested block header + pub nonce: [u8; 32], + + /// The difficulty threshold of the requested block header displayed in compact form. + #[serde(with = "hex")] + pub bits: zebra_chain::work::difficulty::CompactDifficulty, + + /// The difficulty threshold of the requested block header displayed in expanded form. + #[serde(with = "hex")] + pub difficulty: zebra_chain::work::difficulty::ExpandedDifficulty, + + /// The previous block hash of the requested block header. + #[serde(rename = "previousblockhash")] + pub previous_block_hash: GetBlockHash, + + /// The next block hash after the requested block header. + #[serde(rename = "nextblockhash")] + pub next_block_hash: GetBlockHash, +} + +impl Default for GetBlockHeader { + fn default() -> Self { + GetBlockHeader::Object(Box::default()) + } +} + +impl Default for GetBlockHeaderObject { + fn default() -> Self { + let difficulty: ExpandedDifficulty = zebra_chain::work::difficulty::U256::one().into(); + + GetBlockHeaderObject { + hash: GetBlockHash::default(), + confirmations: 0, + height: Height::MIN, + version: 4, + merkle_root: block::merkle::Root([0; 32]), + final_sapling_root: Default::default(), + time: 0, + nonce: [0; 32], + bits: difficulty.to_compact(), + difficulty, + previous_block_hash: Default::default(), + next_block_hash: Default::default(), + } + } +} + /// Response to a `getbestblockhash` and `getblockhash` RPC request. /// /// Contains the hex-encoded hash of the requested block. From 1a71591c48d11c3b618e5a1a1cdc41f54171f601 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 25 Oct 2024 03:05:15 -0400 Subject: [PATCH 02/12] Updates snapshots, adds hash/height/next_block_hash fields to verbose response --- zebra-rpc/src/methods.rs | 80 +++++++------------ zebra-rpc/src/methods/tests/prop.rs | 25 +++--- ...k_verbose_hash_verbosity_2@mainnet_10.snap | 1 + zebra-rpc/src/methods/tests/vectors.rs | 2 +- zebra-state/src/response.rs | 34 +++++++- zebra-state/src/service.rs | 36 ++++++--- 6 files changed, 102 insertions(+), 76 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 0fed3022e8a..990172e90ca 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -567,13 +567,11 @@ where .await .map_server_error()?; - let zebra_state::ReadResponse::BlockHeader(block_header) = response else { + let zebra_state::ReadResponse::BlockHeader { header, .. } = response else { unreachable!("unmatched response to a BlockHeader request") }; - let tip_block_time = block_header - .ok_or_server_error("unexpectedly could not read best chain tip block header")? - .time; + let tip_block_time = header.time; let now = Utc::now(); let zebra_estimated_height = @@ -811,10 +809,6 @@ where } }; - // TODO: look up the height if we only have a hash, - // this needs a new state request for the height -> hash index - let height = hash_or_height.height(); - // # Concurrency // // We look up by block hash so the hash, transaction IDs, and confirmations @@ -892,21 +886,18 @@ where _ => unreachable!("unmatched response to a depth request"), }; - let time = if should_read_block_header { + let (time, height) = if should_read_block_header { let block_header_response = futs.next().await.expect("`futs` should not be empty"); match block_header_response.map_server_error()? { - zebra_state::ReadResponse::BlockHeader(header) => Some( - header - .ok_or_server_error("Block not found")? - .time - .timestamp(), - ), + zebra_state::ReadResponse::BlockHeader { header, height, .. } => { + (Some(header.time.timestamp()), Some(height)) + } _ => unreachable!("unmatched response to a BlockHeader request"), } } else { - None + (None, hash_or_height.height()) }; let sapling = SaplingTrees { @@ -948,7 +939,12 @@ where async move { let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; - let zebra_state::ReadResponse::BlockHeader(block_header) = state + let zebra_state::ReadResponse::BlockHeader { + header, + hash, + height, + next_block_hash, + } = state .clone() .oneshot(zebra_state::ReadRequest::BlockHeader(hash_or_height)) .await @@ -957,23 +953,14 @@ where panic!("unexpected response to BlockHeader request") }; - let block_header = block_header - .ok_or_server_error("could not find block with the provided hash or height")?; - let response = if !verbose { - GetBlockHeader::Raw(HexData( - block_header.zcash_serialize_to_vec().map_server_error()?, - )) + GetBlockHeader::Raw(HexData(header.zcash_serialize_to_vec().map_server_error()?)) } else { // TODO: // - Return block hash and height in BlockHeader response // - Add the block height to the `getblock` response as well // - Add a parameter to the BlockHeader request to indicate that the caller is interested in the next block hash? - // TODO: Get block hash and height from BlockHeader response instead. - let hash = hash_or_height.hash().unwrap(); - let height = hash_or_height.height().unwrap(); - let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state .clone() .oneshot(zebra_state::ReadRequest::SaplingTree(hash_or_height)) @@ -1005,35 +992,24 @@ where .map(|depth| i64::from(depth) + 1) .unwrap_or(NOT_IN_BEST_CHAIN_CONFIRMATIONS); - let block::Header { - version, - previous_block_hash, - merkle_root, - commitment_bytes: _, - time, - difficulty_threshold, - nonce, - solution: _, - } = *block_header; - let block_header = GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations, height, - version, - merkle_root, + version: header.version, + merkle_root: header.merkle_root, final_sapling_root: sapling_tree, - time: time.timestamp(), - nonce: *nonce, - bits: difficulty_threshold, - difficulty: difficulty_threshold.to_expanded().ok_or_server_error( - "could not convert compact difficulty to expanded difficulty", - )?, - previous_block_hash: GetBlockHash(previous_block_hash), - - // TODO: Add the next block hash to the BlockHeader response too, we can just check the next block height in the same chain, if any. - // This should be an optional field in case the requested block is a chain tip block. - next_block_hash: GetBlockHash(previous_block_hash), + time: header.time.timestamp(), + nonce: *header.nonce, + bits: header.difficulty_threshold, + difficulty: header + .difficulty_threshold + .to_expanded() + .ok_or_server_error( + "could not convert compact difficulty to expanded difficulty", + )?, + previous_block_hash: GetBlockHash(header.previous_block_hash), + next_block_hash: next_block_hash.map(GetBlockHash), }; GetBlockHeader::Object(Box::new(block_header)) @@ -1805,7 +1781,7 @@ pub struct GetBlockHeaderObject { /// The next block hash after the requested block header. #[serde(rename = "nextblockhash")] - pub next_block_hash: GetBlockHash, + pub next_block_hash: Option, } impl Default for GetBlockHeader { diff --git a/zebra-rpc/src/methods/tests/prop.rs b/zebra-rpc/src/methods/tests/prop.rs index 409a6aefe52..c94003a770c 100644 --- a/zebra-rpc/src/methods/tests/prop.rs +++ b/zebra-rpc/src/methods/tests/prop.rs @@ -663,16 +663,21 @@ proptest! { .expect_request(zebra_state::ReadRequest::BlockHeader(block_hash.into())) .await .expect("getblockchaininfo should call mock state service with correct request") - .respond(zebra_state::ReadResponse::BlockHeader(Some(Arc::new(block::Header { - time: block_time, - version: Default::default(), - previous_block_hash: Default::default(), - merkle_root: Default::default(), - commitment_bytes: Default::default(), - difficulty_threshold: Default::default(), - nonce: Default::default(), - solution: Default::default() - })))); + .respond(zebra_state::ReadResponse::BlockHeader { + header: Arc::new(block::Header { + time: block_time, + version: Default::default(), + previous_block_hash: Default::default(), + merkle_root: Default::default(), + commitment_bytes: Default::default(), + difficulty_threshold: Default::default(), + nonce: Default::default(), + solution: Default::default() + }), + hash: block::Hash::from([0; 32]), + height: Height::MIN, + next_block_hash: None, + }); } }; diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@mainnet_10.snap index 3bcf968bed5..f18b879f6b3 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@mainnet_10.snap @@ -5,6 +5,7 @@ expression: block { "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, + "height": 1, "time": 1477671596, "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 5b5a21e23d0..ab9665c5da6 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -209,7 +209,7 @@ async fn rpc_getblock() { GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: None, + height: Some(Height(0)), time: Some(block.header.time.timestamp()), tx: block .transactions diff --git a/zebra-state/src/response.rs b/zebra-state/src/response.rs index 77c252b0c75..55c3afad1fc 100644 --- a/zebra-state/src/response.rs +++ b/zebra-state/src/response.rs @@ -52,7 +52,16 @@ pub enum Response { Block(Option>), /// The response to a `BlockHeader` request. - BlockHeader(Option>), + BlockHeader { + /// The header of the requested block + header: Arc, + /// The hash of the requested block + hash: block::Hash, + /// The height of the requested block + height: block::Height, + /// The hash of the next block after the requested block + next_block_hash: Option, + }, /// The response to a `AwaitUtxo` request, from any non-finalized chains, finalized chain, /// pending unverified blocks, or blocks received after the request was sent. @@ -147,7 +156,16 @@ pub enum ReadResponse { Block(Option>), /// The response to a `BlockHeader` request. - BlockHeader(Option>), + BlockHeader { + /// The header of the requested block + header: Arc, + /// The hash of the requested block + hash: block::Hash, + /// The height of the requested block + height: block::Height, + /// The hash of the next block after the requested block + next_block_hash: Option, + }, /// Response to [`ReadRequest::Transaction`] with the specified transaction. Transaction(Option), @@ -287,7 +305,17 @@ impl TryFrom for Response { ReadResponse::BlockHash(hash) => Ok(Response::BlockHash(hash)), ReadResponse::Block(block) => Ok(Response::Block(block)), - ReadResponse::BlockHeader(header) => Ok(Response::BlockHeader(header)), + ReadResponse::BlockHeader { + header, + hash, + height, + next_block_hash + } => Ok(Response::BlockHeader { + header, + hash, + height, + next_block_hash + }), ReadResponse::Transaction(tx_info) => { Ok(Response::Transaction(tx_info.map(|tx_info| tx_info.tx))) } diff --git a/zebra-state/src/service.rs b/zebra-state/src/service.rs index adc61f887ae..be3a78f0772 100644 --- a/zebra-state/src/service.rs +++ b/zebra-state/src/service.rs @@ -1301,20 +1301,36 @@ impl Service for ReadStateService { tokio::task::spawn_blocking(move || { span.in_scope(move || { - let header = state.non_finalized_state_receiver.with_watch_data( - |non_finalized_state| { - read::block_header( - non_finalized_state.best_chain(), - &state.db, - hash_or_height, - ) - }, - ); + let best_chain = state.latest_best_chain(); + + let height = hash_or_height + .height_or_else(|hash| { + read::find::height_by_hash(best_chain.clone(), &state.db, hash) + }) + .ok_or_else(|| BoxError::from("block hash or height not found"))?; + + let hash = hash_or_height + .hash_or_else(|height| { + read::find::hash_by_height(best_chain.clone(), &state.db, height) + }) + .ok_or_else(|| BoxError::from("block hash or height not found"))?; + + let next_height = height.next()?; + let next_block_hash = + read::find::hash_by_height(best_chain.clone(), &state.db, next_height); + + let header = read::block_header(best_chain, &state.db, height.into()) + .ok_or_else(|| BoxError::from("block hash or height not found"))?; // The work is done in the future. timer.finish(module_path!(), line!(), "ReadRequest::Block"); - Ok(ReadResponse::BlockHeader(header)) + Ok(ReadResponse::BlockHeader { + header, + hash, + height, + next_block_hash, + }) }) }) .wait_for_panics() From 91a199c997676f6a25c52f9ce62f158dfcb74803 Mon Sep 17 00:00:00 2001 From: ar Date: Fri, 25 Oct 2024 16:51:17 -0400 Subject: [PATCH 03/12] updates getblock snapshot --- .../snapshots/get_block_verbose_hash_verbosity_2@testnet_10.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@testnet_10.snap index 7ea021d3382..013a4c09b23 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_2@testnet_10.snap @@ -5,6 +5,7 @@ expression: block { "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, + "height": 1, "time": 1477674473, "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" From d693a4966898b722f5fb0d5b155ccd4488a2a6b1 Mon Sep 17 00:00:00 2001 From: ar Date: Fri, 25 Oct 2024 16:53:49 -0400 Subject: [PATCH 04/12] updates getblockheader response type to hex-encode fields, adds ToHex impl for sapling::tree::Root, adds snapshot and vector tests for new RPC method, adds snapshots. --- zebra-chain/src/sapling/tree.rs | 20 ++++ zebra-rpc/src/methods.rs | 7 +- zebra-rpc/src/methods/tests/snapshot.rs | 37 ++++++++ .../get_block_header_hash@mainnet_10.snap | 18 ++++ .../get_block_header_hash@testnet_10.snap | 18 ++++ .../get_block_header_height@mainnet_10.snap | 18 ++++ .../get_block_header_height@testnet_10.snap | 18 ++++ zebra-rpc/src/methods/tests/vectors.rs | 94 +++++++++++++++++++ zebra-state/src/request.rs | 9 ++ 9 files changed, 237 insertions(+), 2 deletions(-) create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap diff --git a/zebra-chain/src/sapling/tree.rs b/zebra-chain/src/sapling/tree.rs index 519d7deeeb9..a532f7dfcda 100644 --- a/zebra-chain/src/sapling/tree.rs +++ b/zebra-chain/src/sapling/tree.rs @@ -147,6 +147,26 @@ impl TryFrom<[u8; 32]> for Root { } } +impl ToHex for &Root { + fn encode_hex>(&self) -> T { + <[u8; 32]>::from(*self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + <[u8; 32]>::from(*self).encode_hex_upper() + } +} + +impl ToHex for Root { + fn encode_hex>(&self) -> T { + (&self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + (&self).encode_hex_upper() + } +} + impl ZcashSerialize for Root { fn zcash_serialize(&self, mut writer: W) -> Result<(), io::Error> { writer.write_all(&<[u8; 32]>::from(*self)[..])?; diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 990172e90ca..0249a4201fe 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -998,7 +998,7 @@ where height, version: header.version, merkle_root: header.merkle_root, - final_sapling_root: sapling_tree, + final_sapling_root: sapling_tree.root(), time: header.time.timestamp(), nonce: *header.nonce, bits: header.difficulty_threshold, @@ -1756,15 +1756,18 @@ pub struct GetBlockHeaderObject { pub version: u32, /// The merkle root of the requesteed block. + #[serde(with = "hex")] pub merkle_root: block::merkle::Root, /// The root of the Sapling commitment tree after applying this block. - pub final_sapling_root: Arc, + #[serde(with = "hex")] + pub final_sapling_root: zebra_chain::sapling::tree::Root, /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. pub time: i64, /// The nonce of the requested block header + #[serde(with = "hex")] pub nonce: [u8; 32], /// The difficulty threshold of the requested block header displayed in compact form. diff --git a/zebra-rpc/src/methods/tests/snapshot.rs b/zebra-rpc/src/methods/tests/snapshot.rs index f4d7804088e..12c4b4df162 100644 --- a/zebra-rpc/src/methods/tests/snapshot.rs +++ b/zebra-rpc/src/methods/tests/snapshot.rs @@ -338,6 +338,34 @@ async fn test_rpc_response_data_for_network(network: &Network) { .expect("We should have a GetBlock struct"); snapshot_rpc_getblock_verbose("hash_verbosity_default", get_block, &settings); + // `getblockheader(hash, verbose = false)` + let get_block_header = rpc + .get_block_header(block_hash.to_string(), None) + .await + .expect("We should have a GetBlock struct"); + snapshot_rpc_getblockheader("hash", get_block_header, &settings); + + // `getblockheader(height, verbose = false)` + let get_block_header = rpc + .get_block_header(BLOCK_HEIGHT.to_string(), None) + .await + .expect("We should have a GetBlock struct"); + snapshot_rpc_getblockheader("height", get_block_header, &settings); + + // `getblockheader(hash, verbose = true)` + let get_block_header = rpc + .get_block_header(block_hash.to_string(), Some(true)) + .await + .expect("We should have a GetBlock struct"); + snapshot_rpc_getblockheader("hash", get_block_header, &settings); + + // `getblockheader(height, verbose = true)` + let get_block_header = rpc + .get_block_header(BLOCK_HEIGHT.to_string(), Some(true)) + .await + .expect("We should have a GetBlock struct"); + snapshot_rpc_getblockheader("height", get_block_header, &settings); + // `getbestblockhash` let get_best_block_hash = rpc .get_best_block_hash() @@ -608,6 +636,15 @@ fn snapshot_rpc_getblock_verbose( settings.bind(|| insta::assert_json_snapshot!(format!("get_block_verbose_{variant}"), block)); } +/// Check valid `getblockheader` response using `cargo insta`. +fn snapshot_rpc_getblockheader( + variant: &'static str, + block: GetBlockHeader, + settings: &insta::Settings, +) { + settings.bind(|| insta::assert_json_snapshot!(format!("get_block_header_{variant}"), block)); +} + /// Check invalid height `getblock` response using `cargo insta`. fn snapshot_rpc_getblock_invalid( variant: &'static str, diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap new file mode 100644 index 00000000000..4658e46999a --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", + "confirmations": 10, + "height": 1, + "version": 4, + "merkle_root": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477671596, + "nonce": "7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790", + "bits": "1f07ffff", + "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap new file mode 100644 index 00000000000..86c6179e681 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", + "confirmations": 10, + "height": 1, + "version": 4, + "merkle_root": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477674473, + "nonce": "000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000", + "bits": "2007ffff", + "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap new file mode 100644 index 00000000000..4658e46999a --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", + "confirmations": 10, + "height": 1, + "version": 4, + "merkle_root": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477671596, + "nonce": "7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790", + "bits": "1f07ffff", + "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap new file mode 100644 index 00000000000..86c6179e681 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", + "confirmations": 10, + "height": 1, + "version": 4, + "merkle_root": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477674473, + "nonce": "000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000", + "bits": "2007ffff", + "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" +} diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index ab9665c5da6..9e98f3af9ec 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -374,6 +374,100 @@ async fn rpc_getblock_missing_error() { assert!(rpc_tx_queue_task_result.is_none()); } +#[tokio::test(flavor = "multi_thread")] +async fn rpc_getblockheader() { + let _init_guard = zebra_test::init(); + + // Create a continuous chain of mainnet blocks from genesis + let blocks: Vec> = zebra_test::vectors::CONTINUOUS_MAINNET_BLOCKS + .iter() + .map(|(_height, block_bytes)| block_bytes.zcash_deserialize_into().unwrap()) + .collect(); + + let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); + // Create a populated state service + let (_state, read_state, latest_chain_tip, _chain_tip_change) = + zebra_state::populated_state(blocks.clone(), &Mainnet).await; + + // Init RPC + let (rpc, rpc_tx_queue_task_handle) = RpcImpl::new( + "RPC test", + "RPC test", + Mainnet, + false, + true, + Buffer::new(mempool.clone(), 1), + read_state.clone(), + latest_chain_tip, + ); + + // Make height calls with verbose=false and check response + for (i, block) in blocks.iter().enumerate() { + let expected_result = GetBlockHeader::Raw(HexData( + block + .header + .clone() + .zcash_serialize_to_vec() + .expect("test block header should serialize"), + )); + + let hash = block.hash(); + let height = Height(i as u32); + + for hash_or_height in [HashOrHeight::from(height), hash.into()] { + let get_block_header = rpc + .get_block_header(hash_or_height.to_string(), None) + .await + .expect("we should have a GetBlockHeader struct"); + assert_eq!(get_block_header, expected_result); + } + + let zebra_state::ReadResponse::SaplingTree(sapling_tree) = read_state + .clone() + .oneshot(zebra_state::ReadRequest::SaplingTree(height.into())) + .await + .expect("should have sapling tree for block hash") + else { + panic!("unexpected response to SaplingTree request") + }; + + let expected_result = GetBlockHeader::Object(Box::new(GetBlockHeaderObject { + hash: GetBlockHash(hash), + confirmations: 11 - i as i64, + height, + version: 4, + merkle_root: block.header.merkle_root, + final_sapling_root: sapling_tree + .expect("should always have sapling root") + .root(), + time: block.header.time.timestamp(), + nonce: *block.header.nonce, + bits: block.header.difficulty_threshold, + difficulty: block + .header + .difficulty_threshold + .to_expanded() + .expect("should have valid difficulty"), + previous_block_hash: GetBlockHash(block.header.previous_block_hash), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + })); + + for hash_or_height in [HashOrHeight::from(Height(i as u32)), block.hash().into()] { + let get_block_header = rpc + .get_block_header(hash_or_height.to_string(), Some(true)) + .await + .expect("we should have a GetBlockHeader struct"); + assert_eq!(get_block_header, expected_result); + } + } + + mempool.expect_no_requests().await; + + // The queue task should continue without errors or panics + let rpc_tx_queue_task_result = rpc_tx_queue_task_handle.now_or_never(); + assert!(rpc_tx_queue_task_result.is_none()); +} + #[tokio::test(flavor = "multi_thread")] async fn rpc_getbestblockhash() { let _init_guard = zebra_test::init(); diff --git a/zebra-state/src/request.rs b/zebra-state/src/request.rs index 56be011d48e..5894b7da55a 100644 --- a/zebra-state/src/request.rs +++ b/zebra-state/src/request.rs @@ -90,6 +90,15 @@ impl HashOrHeight { } } +impl std::fmt::Display for HashOrHeight { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + HashOrHeight::Hash(hash) => write!(f, "{hash}"), + HashOrHeight::Height(height) => write!(f, "{}", height.0), + } + } +} + impl From for HashOrHeight { fn from(hash: block::Hash) -> Self { Self::Hash(hash) From 4379d628a60ab2158b036303eb9acf4cfa0c0774 Mon Sep 17 00:00:00 2001 From: ar Date: Fri, 25 Oct 2024 16:56:37 -0400 Subject: [PATCH 05/12] rustfmt --- zebra-state/src/response.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zebra-state/src/response.rs b/zebra-state/src/response.rs index 55c3afad1fc..daa2fbe2829 100644 --- a/zebra-state/src/response.rs +++ b/zebra-state/src/response.rs @@ -305,7 +305,7 @@ impl TryFrom for Response { ReadResponse::BlockHash(hash) => Ok(Response::BlockHash(hash)), ReadResponse::Block(block) => Ok(Response::Block(block)), - ReadResponse::BlockHeader { + ReadResponse::BlockHeader { header, hash, height, From a48693c20cc3a673a817ecf63deb7b065c61b4df Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 25 Oct 2024 17:47:07 -0400 Subject: [PATCH 06/12] fixes snapshots, matches zcashd more closely --- zebra-rpc/src/methods.rs | 11 +++++++---- zebra-rpc/src/methods/tests/snapshot.rs | 12 ++++++------ .../get_block_header_hash@mainnet_10.snap | 15 +-------------- .../get_block_header_hash@testnet_10.snap | 15 +-------------- ...t_block_header_hash_verbose@mainnet_10.snap | 18 ++++++++++++++++++ ...t_block_header_hash_verbose@testnet_10.snap | 18 ++++++++++++++++++ .../get_block_header_height@mainnet_10.snap | 15 +-------------- .../get_block_header_height@testnet_10.snap | 15 +-------------- ...block_header_height_verbose@mainnet_10.snap | 18 ++++++++++++++++++ ...block_header_height_verbose@testnet_10.snap | 18 ++++++++++++++++++ 10 files changed, 89 insertions(+), 66 deletions(-) create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap create mode 100644 zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 0249a4201fe..d14704c7013 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -935,7 +935,7 @@ where verbose: Option, ) -> BoxFuture> { let state = self.state.clone(); - let verbose = verbose.unwrap_or_default(); + let verbose = verbose.unwrap_or(true); async move { let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; @@ -992,6 +992,9 @@ where .map(|depth| i64::from(depth) + 1) .unwrap_or(NOT_IN_BEST_CHAIN_CONFIRMATIONS); + let mut nonce = *header.nonce; + nonce.reverse(); + let block_header = GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations, @@ -1000,7 +1003,7 @@ where merkle_root: header.merkle_root, final_sapling_root: sapling_tree.root(), time: header.time.timestamp(), - nonce: *header.nonce, + nonce, bits: header.difficulty_threshold, difficulty: header .difficulty_threshold @@ -1756,11 +1759,11 @@ pub struct GetBlockHeaderObject { pub version: u32, /// The merkle root of the requesteed block. - #[serde(with = "hex")] + #[serde(with = "hex", rename = "merkleroot")] pub merkle_root: block::merkle::Root, /// The root of the Sapling commitment tree after applying this block. - #[serde(with = "hex")] + #[serde(with = "hex", rename = "finalsaplingroot")] pub final_sapling_root: zebra_chain::sapling::tree::Root, /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. diff --git a/zebra-rpc/src/methods/tests/snapshot.rs b/zebra-rpc/src/methods/tests/snapshot.rs index 12c4b4df162..512962e93d6 100644 --- a/zebra-rpc/src/methods/tests/snapshot.rs +++ b/zebra-rpc/src/methods/tests/snapshot.rs @@ -340,14 +340,14 @@ async fn test_rpc_response_data_for_network(network: &Network) { // `getblockheader(hash, verbose = false)` let get_block_header = rpc - .get_block_header(block_hash.to_string(), None) + .get_block_header(block_hash.to_string(), Some(false)) .await .expect("We should have a GetBlock struct"); snapshot_rpc_getblockheader("hash", get_block_header, &settings); // `getblockheader(height, verbose = false)` let get_block_header = rpc - .get_block_header(BLOCK_HEIGHT.to_string(), None) + .get_block_header(BLOCK_HEIGHT.to_string(), Some(false)) .await .expect("We should have a GetBlock struct"); snapshot_rpc_getblockheader("height", get_block_header, &settings); @@ -357,14 +357,14 @@ async fn test_rpc_response_data_for_network(network: &Network) { .get_block_header(block_hash.to_string(), Some(true)) .await .expect("We should have a GetBlock struct"); - snapshot_rpc_getblockheader("hash", get_block_header, &settings); + snapshot_rpc_getblockheader("hash_verbose", get_block_header, &settings); - // `getblockheader(height, verbose = true)` + // `getblockheader(height, verbose = true)` where verbose is the default value. let get_block_header = rpc - .get_block_header(BLOCK_HEIGHT.to_string(), Some(true)) + .get_block_header(BLOCK_HEIGHT.to_string(), None) .await .expect("We should have a GetBlock struct"); - snapshot_rpc_getblockheader("height", get_block_header, &settings); + snapshot_rpc_getblockheader("height_verbose", get_block_header, &settings); // `getbestblockhash` let get_best_block_hash = rpc diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap index 4658e46999a..5ab74801c1e 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@mainnet_10.snap @@ -2,17 +2,4 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- -{ - "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", - "confirmations": 10, - "height": 1, - "version": 4, - "merkle_root": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", - "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", - "time": 1477671596, - "nonce": "7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790", - "bits": "1f07ffff", - "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", - "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", - "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" -} +"0400000008ce3d9731b000c08338455c8a4a6bd05da16e26b11daa1b917184ece80f04000946edb9c083c9942d92305444527765fad789c438c717783276a9f7fbf61b850000000000000000000000000000000000000000000000000000000000000000ac7a1358ffff071f7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790fd4005002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b" diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap index 86c6179e681..7942eddd2e2 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash@testnet_10.snap @@ -2,17 +2,4 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- -{ - "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", - "confirmations": 10, - "height": 1, - "version": 4, - "merkle_root": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", - "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", - "time": 1477674473, - "nonce": "000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000", - "bits": "2007ffff", - "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", - "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", - "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" -} +"04000000382c4a332661c7ed0671f32a34d724619f086c61873bce7c99859dd9920aa605755f7c7d27a811596e9fae6dd30ca45be86e901d499909de35b6ff1f699f7ef30000000000000000000000000000000000000000000000000000000000000000e9851358ffff0720000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000fd40050053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8" diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap new file mode 100644 index 00000000000..e0c97d0b311 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", + "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "bits": "1f07ffff", + "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap new file mode 100644 index 00000000000..3c912343723 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", + "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "bits": "2007ffff", + "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap index 4658e46999a..5ab74801c1e 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@mainnet_10.snap @@ -2,17 +2,4 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- -{ - "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", - "confirmations": 10, - "height": 1, - "version": 4, - "merkle_root": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", - "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", - "time": 1477671596, - "nonce": "7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790", - "bits": "1f07ffff", - "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", - "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", - "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" -} +"0400000008ce3d9731b000c08338455c8a4a6bd05da16e26b11daa1b917184ece80f04000946edb9c083c9942d92305444527765fad789c438c717783276a9f7fbf61b850000000000000000000000000000000000000000000000000000000000000000ac7a1358ffff071f7534e8cf161ff2e49d54bdb3bfbcde8cdbf2fc5963c9ec7d86aed4a67e975790fd4005002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b" diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap index 86c6179e681..7942eddd2e2 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height@testnet_10.snap @@ -2,17 +2,4 @@ source: zebra-rpc/src/methods/tests/snapshot.rs expression: block --- -{ - "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", - "confirmations": 10, - "height": 1, - "version": 4, - "merkle_root": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", - "final_sapling_root": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", - "time": 1477674473, - "nonce": "000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000", - "bits": "2007ffff", - "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", - "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", - "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" -} +"04000000382c4a332661c7ed0671f32a34d724619f086c61873bce7c99859dd9920aa605755f7c7d27a811596e9fae6dd30ca45be86e901d499909de35b6ff1f699f7ef30000000000000000000000000000000000000000000000000000000000000000e9851358ffff0720000056c2264c31261d597c6fcea7c5e00160cf6be1cd89ca96a0389473e50000fd40050053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8" diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap new file mode 100644 index 00000000000..e0c97d0b311 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", + "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "bits": "1f07ffff", + "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap new file mode 100644 index 00000000000..3c912343723 --- /dev/null +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap @@ -0,0 +1,18 @@ +--- +source: zebra-rpc/src/methods/tests/snapshot.rs +expression: block +--- +{ + "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", + "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "bits": "2007ffff", + "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" +} From f17b4498ca189ead947cbf8c983bfe24c6591279 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 25 Oct 2024 18:29:59 -0400 Subject: [PATCH 07/12] fixes vectors test --- zebra-rpc/src/methods/tests/vectors.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 9e98f3af9ec..ee1bcf5085e 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -416,7 +416,7 @@ async fn rpc_getblockheader() { for hash_or_height in [HashOrHeight::from(height), hash.into()] { let get_block_header = rpc - .get_block_header(hash_or_height.to_string(), None) + .get_block_header(hash_or_height.to_string(), Some(false)) .await .expect("we should have a GetBlockHeader struct"); assert_eq!(get_block_header, expected_result); @@ -431,6 +431,8 @@ async fn rpc_getblockheader() { panic!("unexpected response to SaplingTree request") }; + let mut expected_nonce = *block.header.nonce; + expected_nonce.reverse(); let expected_result = GetBlockHeader::Object(Box::new(GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations: 11 - i as i64, @@ -441,7 +443,7 @@ async fn rpc_getblockheader() { .expect("should always have sapling root") .root(), time: block.header.time.timestamp(), - nonce: *block.header.nonce, + nonce: expected_nonce, bits: block.header.difficulty_threshold, difficulty: block .header From df7d0a4da646e58ec5fa7be4fec0db33dbb96af5 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 25 Oct 2024 18:49:12 -0400 Subject: [PATCH 08/12] updates lwd failure messages (probably doesn't matter, but seems better to handle it now than risk debugging it later) --- zebrad/tests/common/failure_messages.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zebrad/tests/common/failure_messages.rs b/zebrad/tests/common/failure_messages.rs index 2550f2d21cf..6d41ab024bb 100644 --- a/zebrad/tests/common/failure_messages.rs +++ b/zebrad/tests/common/failure_messages.rs @@ -81,6 +81,8 @@ pub const LIGHTWALLETD_FAILURE_MESSAGES: &[&str] = &[ "error with", // Block error messages "error requesting block: 0: Block not found", + // This shouldn't happen unless lwd starts calling getblock with `verbosity = 2` + "error requesting block: 0: block hash or height not found", "error zcashd getblock rpc", "received overlong message", "received unexpected height block", From 068762b55c86cece549a5bf5a8e5075ec588b20d Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 25 Oct 2024 22:39:00 -0400 Subject: [PATCH 09/12] fixes getblock_rpc test, fixes/reverses finalsaplingroot field byte-order. --- zebra-rpc/src/methods.rs | 7 +++++-- zebra-rpc/src/methods/tests/vectors.rs | 11 +++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index d14704c7013..c9b5ef78021 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -995,13 +995,16 @@ where let mut nonce = *header.nonce; nonce.reverse(); + let mut final_sapling_root: [u8; 32] = sapling_tree.root().into(); + final_sapling_root.reverse(); + let block_header = GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations, height, version: header.version, merkle_root: header.merkle_root, - final_sapling_root: sapling_tree.root(), + final_sapling_root, time: header.time.timestamp(), nonce, bits: header.difficulty_threshold, @@ -1764,7 +1767,7 @@ pub struct GetBlockHeaderObject { /// The root of the Sapling commitment tree after applying this block. #[serde(with = "hex", rename = "finalsaplingroot")] - pub final_sapling_root: zebra_chain::sapling::tree::Root, + pub final_sapling_root: [u8; 32], /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. pub time: i64, diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index ee1bcf5085e..4d969db5212 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -209,7 +209,7 @@ async fn rpc_getblock() { GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: Some(Height(0)), + height: Some(Height(i as u32)), time: Some(block.header.time.timestamp()), tx: block .transactions @@ -433,15 +433,18 @@ async fn rpc_getblockheader() { let mut expected_nonce = *block.header.nonce; expected_nonce.reverse(); + let mut expected_final_sapling_root: [u8; 32] = sapling_tree + .expect("should always have sapling root") + .root() + .into(); + expected_final_sapling_root.reverse(); let expected_result = GetBlockHeader::Object(Box::new(GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations: 11 - i as i64, height, version: 4, merkle_root: block.header.merkle_root, - final_sapling_root: sapling_tree - .expect("should always have sapling root") - .root(), + final_sapling_root: expected_final_sapling_root, time: block.header.time.timestamp(), nonce: expected_nonce, bits: block.header.difficulty_threshold, From 80ea07b6e6631dcbdd07f60ec141b4816762fca5 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 28 Oct 2024 16:34:18 -0400 Subject: [PATCH 10/12] fixes vector test, addresses remaining differences with zcashd (except the `chainwork` field), updates snapshots, and avoids a possible panic when there's a chain reorg between state queries. --- zebra-chain/src/work/difficulty.rs | 22 +++++++ zebra-chain/src/work/equihash.rs | 22 ++++++- zebra-rpc/src/methods.rs | 58 +++++++++++-------- ..._block_header_hash_verbose@mainnet_10.snap | 5 +- ..._block_header_hash_verbose@testnet_10.snap | 5 +- ...lock_header_height_verbose@mainnet_10.snap | 5 +- ...lock_header_height_verbose@testnet_10.snap | 5 +- zebra-rpc/src/methods/tests/vectors.rs | 18 +++--- 8 files changed, 99 insertions(+), 41 deletions(-) diff --git a/zebra-chain/src/work/difficulty.rs b/zebra-chain/src/work/difficulty.rs index 20fc638453e..7e04e9ad8fe 100644 --- a/zebra-chain/src/work/difficulty.rs +++ b/zebra-chain/src/work/difficulty.rs @@ -290,6 +290,28 @@ impl CompactDifficulty { Ok(difficulty) } + + /// Returns a floating-point number representing a difficulty as a multiple + /// of the minimum difficulty for the provided network. + pub fn relative_to_network(&self, network: &Network) -> f64 { + let network_difficulty = network.target_difficulty_limit().to_compact(); + + let [mut n_shift, ..] = self.0.to_be_bytes(); + let [n_shift_amount, ..] = network_difficulty.0.to_be_bytes(); + let mut d_diff = f64::from(network_difficulty.0 << 8) / f64::from(self.0 << 8); + + while n_shift < n_shift_amount { + d_diff *= 256.0; + n_shift += 1; + } + + while n_shift > n_shift_amount { + d_diff /= 256.0; + n_shift -= 1; + } + + d_diff + } } impl fmt::Debug for CompactDifficulty { diff --git a/zebra-chain/src/work/equihash.rs b/zebra-chain/src/work/equihash.rs index f79b9212e53..35aa39f849b 100644 --- a/zebra-chain/src/work/equihash.rs +++ b/zebra-chain/src/work/equihash.rs @@ -2,6 +2,7 @@ use std::{fmt, io}; +use hex::ToHex; use serde_big_array::BigArray; use crate::{ @@ -112,7 +113,6 @@ impl Solution { } /// Returns a [`Solution`] of `[0; SOLUTION_SIZE]` to be used in block proposals. - #[cfg(feature = "getblocktemplate-rpcs")] pub fn for_proposal() -> Self { // TODO: Accept network as an argument, and if it's Regtest, return the shorter null solution. Self::Common([0; SOLUTION_SIZE]) @@ -195,3 +195,23 @@ impl ZcashDeserialize for Solution { Self::from_bytes(&solution) } } + +impl ToHex for &Solution { + fn encode_hex>(&self) -> T { + self.value().encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + self.value().encode_hex_upper() + } +} + +impl ToHex for Solution { + fn encode_hex>(&self) -> T { + (&self).encode_hex() + } + + fn encode_hex_upper>(&self) -> T { + (&self).encode_hex_upper() + } +} diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index c9b5ef78021..dc65dbc8b9d 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -28,7 +28,10 @@ use zebra_chain::{ subtree::NoteCommitmentSubtreeIndex, transaction::{self, SerializedTransaction, Transaction, UnminedTx}, transparent::{self, Address}, - work::difficulty::ExpandedDifficulty, + work::{ + difficulty::{CompactDifficulty, ExpandedDifficulty}, + equihash::Solution, + }, }; use zebra_node_services::mempool; use zebra_state::{HashOrHeight, MinedTx, OutputIndex, OutputLocation, TransactionLocation}; @@ -936,6 +939,7 @@ where ) -> BoxFuture> { let state = self.state.clone(); let verbose = verbose.unwrap_or(true); + let network = self.network.clone(); async move { let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; @@ -956,11 +960,6 @@ where let response = if !verbose { GetBlockHeader::Raw(HexData(header.zcash_serialize_to_vec().map_server_error()?)) } else { - // TODO: - // - Return block hash and height in BlockHeader response - // - Add the block height to the `getblock` response as well - // - Add a parameter to the BlockHeader request to indicate that the caller is interested in the next block hash? - let zebra_state::ReadResponse::SaplingTree(sapling_tree) = state .clone() .oneshot(zebra_state::ReadRequest::SaplingTree(hash_or_height)) @@ -970,8 +969,9 @@ where panic!("unexpected response to SaplingTree request") }; - // TODO: Double-check that there's an empty Sapling root at Genesis. - let sapling_tree = sapling_tree.expect("should always have a sapling root"); + // This could be `None` if there's a chain reorg between state queries. + let sapling_tree = + sapling_tree.ok_or_server_error("missing sapling tree for block")?; let zebra_state::ReadResponse::Depth(depth) = state .clone() @@ -995,8 +995,15 @@ where let mut nonce = *header.nonce; nonce.reverse(); - let mut final_sapling_root: [u8; 32] = sapling_tree.root().into(); - final_sapling_root.reverse(); + let final_sapling_root: [u8; 32] = if sapling_tree.position().is_some() { + 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_header = GetBlockHeaderObject { hash: GetBlockHash(hash), @@ -1007,13 +1014,9 @@ where final_sapling_root, time: header.time.timestamp(), nonce, + solution: header.solution, bits: header.difficulty_threshold, - difficulty: header - .difficulty_threshold - .to_expanded() - .ok_or_server_error( - "could not convert compact difficulty to expanded difficulty", - )?, + difficulty, previous_block_hash: GetBlockHash(header.previous_block_hash), next_block_hash: next_block_hash.map(GetBlockHash), }; @@ -1733,7 +1736,7 @@ impl Default for GetBlock { /// Response to a `getblockheader` RPC request. /// /// See the notes for the [`Rpc::get_block_header`] method. -#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] #[serde(untagged)] pub enum GetBlockHeader { /// The request block, hex-encoded. @@ -1743,7 +1746,7 @@ pub enum GetBlockHeader { Object(Box), } -#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] /// Verbose response to a `getblockheader` RPC request. /// /// See the notes for the [`Rpc::get_block_header`] method. @@ -1772,24 +1775,28 @@ pub struct GetBlockHeaderObject { /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. pub time: i64, - /// The nonce of the requested block header + /// The nonce of the requested block header. #[serde(with = "hex")] pub nonce: [u8; 32], - /// The difficulty threshold of the requested block header displayed in compact form. + /// The Equihash solution in the requested block header. #[serde(with = "hex")] - pub bits: zebra_chain::work::difficulty::CompactDifficulty, + solution: Solution, - /// The difficulty threshold of the requested block header displayed in expanded form. + /// The difficulty threshold of the requested block header displayed in compact form. #[serde(with = "hex")] - pub difficulty: zebra_chain::work::difficulty::ExpandedDifficulty, + pub bits: CompactDifficulty, + + /// Floating point number that represents the difficulty limit for this block as a multiple + /// of the minimum difficulty for the network. + pub difficulty: f64, /// The previous block hash of the requested block header. #[serde(rename = "previousblockhash")] pub previous_block_hash: GetBlockHash, /// The next block hash after the requested block header. - #[serde(rename = "nextblockhash")] + #[serde(rename = "nextblockhash", skip_serializing_if = "Option::is_none")] pub next_block_hash: Option, } @@ -1812,8 +1819,9 @@ impl Default for GetBlockHeaderObject { final_sapling_root: Default::default(), time: 0, nonce: [0; 32], + solution: Solution::for_proposal(), bits: difficulty.to_compact(), - difficulty, + difficulty: 1.0, previous_block_hash: Default::default(), next_block_hash: Default::default(), } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap index e0c97d0b311..723bf78e62e 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@mainnet_10.snap @@ -8,11 +8,12 @@ expression: block "height": 1, "version": 4, "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", - "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "time": 1477671596, "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", "bits": "1f07ffff", - "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "difficulty": 1.0, "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap index 3c912343723..0d76afbbb96 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_hash_verbose@testnet_10.snap @@ -8,11 +8,12 @@ expression: block "height": 1, "version": 4, "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", - "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "time": 1477674473, "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", "bits": "2007ffff", - "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "difficulty": 1.0, "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap index e0c97d0b311..723bf78e62e 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@mainnet_10.snap @@ -8,11 +8,12 @@ expression: block "height": 1, "version": 4, "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", - "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "time": 1477671596, "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", "bits": "1f07ffff", - "difficulty": "0007ffff00000000000000000000000000000000000000000000000000000000", + "difficulty": 1.0, "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap index 3c912343723..0d76afbbb96 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_header_height_verbose@testnet_10.snap @@ -8,11 +8,12 @@ expression: block "height": 1, "version": 4, "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", - "finalsaplingroot": "fbc2f4300c01f0b7820d00e3347c8da4ee614674376cbc45359daa54f9b5493e", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "time": 1477674473, "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", "bits": "2007ffff", - "difficulty": "07ffff0000000000000000000000000000000000000000000000000000000000", + "difficulty": 1.0, "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 4d969db5212..1008189c30d 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -433,11 +433,15 @@ async fn rpc_getblockheader() { let mut expected_nonce = *block.header.nonce; expected_nonce.reverse(); - let mut expected_final_sapling_root: [u8; 32] = sapling_tree - .expect("should always have sapling root") - .root() - .into(); - expected_final_sapling_root.reverse(); + let sapling_tree = sapling_tree.expect("should always have sapling root"); + let expected_final_sapling_root: [u8; 32] = if sapling_tree.position().is_some() { + let mut root: [u8; 32] = sapling_tree.root().into(); + root.reverse(); + root + } else { + [0; 32] + }; + let expected_result = GetBlockHeader::Object(Box::new(GetBlockHeaderObject { hash: GetBlockHash(hash), confirmations: 11 - i as i64, @@ -447,12 +451,12 @@ async fn rpc_getblockheader() { final_sapling_root: expected_final_sapling_root, time: block.header.time.timestamp(), nonce: expected_nonce, + solution: block.header.solution, bits: block.header.difficulty_threshold, difficulty: block .header .difficulty_threshold - .to_expanded() - .expect("should have valid difficulty"), + .relative_to_network(&Mainnet), previous_block_hash: GetBlockHash(block.header.previous_block_hash), next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), })); From 37ddd6e19422c56cea6ed0f7742ba7b299179e75 Mon Sep 17 00:00:00 2001 From: Arya Date: Mon, 4 Nov 2024 20:09:28 -0500 Subject: [PATCH 11/12] Adds a comment noting that the `relative_to_network()` method was copied from zcashd --- zebra-chain/src/work/difficulty.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/zebra-chain/src/work/difficulty.rs b/zebra-chain/src/work/difficulty.rs index 7e04e9ad8fe..bb48760d92b 100644 --- a/zebra-chain/src/work/difficulty.rs +++ b/zebra-chain/src/work/difficulty.rs @@ -293,6 +293,7 @@ impl CompactDifficulty { /// Returns a floating-point number representing a difficulty as a multiple /// of the minimum difficulty for the provided network. + // Copied from pub fn relative_to_network(&self, network: &Network) -> f64 { let network_difficulty = network.target_difficulty_limit().to_compact(); From f415a5ab023cc72c1f8128a939ba5cb933355f61 Mon Sep 17 00:00:00 2001 From: Arya Date: Fri, 8 Nov 2024 11:15:42 -0500 Subject: [PATCH 12/12] Apply suggestions from code review Co-authored-by: Alfredo Garcia --- zebra-chain/src/work/difficulty.rs | 1 + zebra-rpc/src/methods.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/zebra-chain/src/work/difficulty.rs b/zebra-chain/src/work/difficulty.rs index bb48760d92b..cda4fa926ff 100644 --- a/zebra-chain/src/work/difficulty.rs +++ b/zebra-chain/src/work/difficulty.rs @@ -294,6 +294,7 @@ impl CompactDifficulty { /// Returns a floating-point number representing a difficulty as a multiple /// of the minimum difficulty for the provided network. // Copied from + // TODO: Explain here what this ported code is doing and why, request help to do so with the ECC team. pub fn relative_to_network(&self, network: &Network) -> f64 { let network_difficulty = network.target_difficulty_limit().to_compact(); diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index dc65dbc8b9d..76167df92e1 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -1739,10 +1739,10 @@ impl Default for GetBlock { #[derive(Clone, Debug, PartialEq, serde::Serialize)] #[serde(untagged)] pub enum GetBlockHeader { - /// The request block, hex-encoded. + /// The request block header, hex-encoded. Raw(hex_data::HexData), - /// The block object. + /// The block header object. Object(Box), }