From 3a5eb48a8d62fe49a30b1095397347b3a6b8dec7 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Fri, 8 Nov 2024 16:20:42 -0300 Subject: [PATCH 1/8] rpc: align getblock with zcashd behaviour --- zebra-rpc/src/constants.rs | 4 + zebra-rpc/src/methods.rs | 248 +++++++++++++++++- ...k_verbose_hash_verbosity_1@mainnet_10.snap | 13 +- ...k_verbose_hash_verbosity_1@testnet_10.snap | 13 +- ...k_verbose_hash_verbosity_2@mainnet_10.snap | 13 +- ...k_verbose_hash_verbosity_2@testnet_10.snap | 13 +- ...ose_hash_verbosity_default@mainnet_10.snap | 13 +- ...ose_hash_verbosity_default@testnet_10.snap | 13 +- ...verbose_height_verbosity_1@mainnet_10.snap | 12 +- ...verbose_height_verbosity_1@testnet_10.snap | 12 +- ...verbose_height_verbosity_2@mainnet_10.snap | 13 +- ...verbose_height_verbosity_2@testnet_10.snap | 13 +- ...e_height_verbosity_default@mainnet_10.snap | 12 +- ...e_height_verbosity_default@testnet_10.snap | 12 +- zebra-rpc/src/methods/tests/vectors.rs | 229 +++++++++++++++- zebra-utils/zcash-rpc-diff | 13 +- 16 files changed, 606 insertions(+), 40 deletions(-) diff --git a/zebra-rpc/src/constants.rs b/zebra-rpc/src/constants.rs index e8be508595f..14f89df6618 100644 --- a/zebra-rpc/src/constants.rs +++ b/zebra-rpc/src/constants.rs @@ -11,6 +11,10 @@ use jsonrpc_core::{Error, ErrorCode}; /// pub const INVALID_PARAMETERS_ERROR_CODE: ErrorCode = ErrorCode::ServerError(-1); +/// The RPC error code used by `zcashd` for missing blocks, when looked up +/// by hash. +pub const INVALID_ADDRESS_OR_KEY_ERROR_CODE: ErrorCode = ErrorCode::ServerError(-5); + /// The RPC error code used by `zcashd` for missing blocks. /// /// `lightwalletd` expects error code `-8` when a block is not found: diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index cb01ca8bbd3..d0d3ea468f1 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -37,7 +37,9 @@ use zebra_node_services::mempool; use zebra_state::{HashOrHeight, MinedTx, OutputIndex, OutputLocation, TransactionLocation}; use crate::{ - constants::{INVALID_PARAMETERS_ERROR_CODE, MISSING_BLOCK_ERROR_CODE}, + constants::{ + INVALID_ADDRESS_OR_KEY_ERROR_CODE, INVALID_PARAMETERS_ERROR_CODE, MISSING_BLOCK_ERROR_CODE, + }, methods::trees::{GetSubtrees, GetTreestate, SubtreeRpcData}, queue::Queue, }; @@ -145,7 +147,8 @@ pub trait Rpc { /// Returns the requested block by hash or height, as a [`GetBlock`] JSON string. /// If the block is not in Zebra's state, returns - /// [error code `-8`.](https://github.com/zcash/zcash/issues/5758) + /// [error code `-8`.](https://github.com/zcash/zcash/issues/5758) if a height was + /// passed or -5 if a hash was passed. /// /// zcashd reference: [`getblock`](https://zcash.github.io/rpc/getblock.html) /// method: post @@ -154,16 +157,19 @@ pub trait Rpc { /// # Parameters /// /// - `hash_or_height`: (string, required, example="1") The hash or height for the block to be returned. - /// - `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data. + /// - `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data, and 3 for a partially filled json object (which is faster and useful for lightwalletd-only usage) /// /// # Notes /// - /// With verbosity=1, [`lightwalletd` only reads the `tx` field of the - /// result](https://github.com/zcash/lightwalletd/blob/dfac02093d85fb31fb9a8475b884dd6abca966c7/common/common.go#L152), - /// and other clients only read the `hash` and `confirmations` fields, - /// so we only return a few fields for now. + /// Zebra previously partially supported verbosity=1 by returning only the + /// fields required by lightwalletd ([`lightwalletd` only reads the `tx` + /// field of the + /// result](https://github.com/zcash/lightwalletd/blob/dfac02093d85fb31fb9a8475b884dd6abca966c7/common/common.go#L152)). + /// That verbosity level was migrated to "3"; so while lightwalletd will + /// still work by using verbosity=1, it will sync faster if it is changed to + /// use verbosity=3. /// - /// `lightwalletd` and mining clients also do not use verbosity=2, so we don't support it. + /// The undocumented `chainwork` field is not returned. #[rpc(name = "getblock")] fn get_block( &self, @@ -172,6 +178,9 @@ pub trait Rpc { ) -> BoxFuture>; /// Returns the requested block header by hash or height, as a [`GetBlockHeader`] JSON string. + /// If the block is not in Zebra's state, + /// returns [error code `-8`.](https://github.com/zcash/zcash/issues/5758) + /// if a height was passed or -5 if a hash was passed. /// /// zcashd reference: [`getblockheader`](https://zcash.github.io/rpc/getblockheader.html) /// method: post @@ -181,6 +190,10 @@ pub trait Rpc { /// /// - `hash_or_height`: (string, required, example="1") The hash or height for the block to be returned. /// - `verbose`: (bool, optional, default=false, example=true) false for hex encoded data, true for a json object + /// + /// # Notes + /// + /// The undocumented `chainwork` field is not returned. #[rpc(name = "getblockheader")] fn get_block_header( &self, @@ -738,7 +751,9 @@ where let mut state = self.state.clone(); let verbosity = verbosity.unwrap_or(DEFAULT_GETBLOCK_VERBOSITY); + let self_clone = self.clone(); + let original_hash_or_height = hash_or_height.clone(); async move { let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; @@ -766,6 +781,99 @@ where _ => unreachable!("unmatched response to a block request"), } } else if verbosity == 1 || verbosity == 2 { + let r: Result = self_clone + .get_block_header(original_hash_or_height, Some(true)) + .await; + + let GetBlockHeader::Object(h) = r? else { + panic!("must return Object") + }; + let hash = h.hash.0; + + // # Concurrency + // + // We look up by block hash so the hash, transaction IDs, and confirmations + // are consistent. + let requests = vec![ + // Get transaction IDs from the transaction index by block hash + // + // # Concurrency + // + // A block's transaction IDs are never modified, so all possible responses are + // valid. Clients that query block heights must be able to handle chain forks, + // including getting transaction IDs from any chain fork. + zebra_state::ReadRequest::TransactionIdsForBlock(hash.into()), + // Sapling trees + zebra_state::ReadRequest::SaplingTree(hash.into()), + // Orchard trees + zebra_state::ReadRequest::OrchardTree(hash.into()), + ]; + + let mut futs = FuturesOrdered::new(); + + for request in requests { + futs.push_back(state.clone().oneshot(request)); + } + + let tx_ids_response = futs.next().await.expect("`futs` should not be empty"); + let tx = match tx_ids_response.map_server_error()? { + zebra_state::ReadResponse::TransactionIdsForBlock(tx_ids) => tx_ids + .ok_or_server_error("Block not found")? + .iter() + .map(|tx_id| tx_id.encode_hex()) + .collect(), + _ => unreachable!("unmatched response to a transaction_ids_for_block request"), + }; + + let sapling_tree_response = futs.next().await.expect("`futs` should not be empty"); + let sapling_note_commitment_tree_count = + match sapling_tree_response.map_server_error()? { + zebra_state::ReadResponse::SaplingTree(Some(nct)) => nct.count(), + zebra_state::ReadResponse::SaplingTree(None) => 0, + _ => unreachable!("unmatched response to a SaplingTree request"), + }; + + let orchard_tree_response = futs.next().await.expect("`futs` should not be empty"); + let orchard_note_commitment_tree_count = + match orchard_tree_response.map_server_error()? { + zebra_state::ReadResponse::OrchardTree(Some(nct)) => nct.count(), + zebra_state::ReadResponse::OrchardTree(None) => 0, + _ => unreachable!("unmatched response to a OrchardTree request"), + }; + + let sapling = SaplingTrees { + size: sapling_note_commitment_tree_count, + }; + + let orchard = OrchardTrees { + size: orchard_note_commitment_tree_count, + }; + + let trees = GetBlockTrees { sapling, orchard }; + + Ok(GetBlock::Object { + hash: h.hash, + confirmations: h.confirmations, + height: Some(h.height), + version: Some(h.version), + merkle_root: Some(h.merkle_root), + time: Some(h.time), + nonce: Some(h.nonce), + solution: Some(h.solution), + bits: Some(h.bits), + difficulty: Some(h.difficulty), + // TODO + tx, + trees, + // TODO + size: None, + final_sapling_root: Some(h.final_sapling_root), + // TODO + final_orchard_root: None, + previous_block_hash: Some(h.previous_block_hash), + next_block_hash: h.next_block_hash, + }) + } else if verbosity == 3 { // # Performance // // This RPC is used in `lightwalletd`'s initial sync of 2 million blocks, @@ -920,6 +1028,17 @@ where time, tx, trees, + size: None, + version: None, + merkle_root: None, + final_sapling_root: None, + final_orchard_root: None, + nonce: None, + bits: None, + difficulty: None, + previous_block_hash: None, + next_block_hash: None, + solution: None, }) } else { Err(Error { @@ -952,7 +1071,18 @@ where .clone() .oneshot(zebra_state::ReadRequest::BlockHeader(hash_or_height)) .await - .map_server_error()? + .map_err(|_| Error { + // Compatibility with zcashd. Note that since this function + // is reused by getblock(), we return the errors expected + // by it (they differ whether a hash or a height was passed) + code: if hash_or_height.hash().is_some() { + INVALID_ADDRESS_OR_KEY_ERROR_CODE + } else { + MISSING_BLOCK_ERROR_CODE + }, + message: "block height not in best chain".to_string(), + data: None, + })? else { panic!("unexpected response to BlockHeader request") }; @@ -1736,8 +1866,9 @@ impl Default for SentTransactionHash { /// Response to a `getblock` RPC request. /// /// See the notes for the [`Rpc::get_block`] method. -#[derive(Clone, Debug, Eq, PartialEq, serde::Serialize)] +#[derive(Clone, Debug, PartialEq, serde::Serialize)] #[serde(untagged)] +#[allow(clippy::large_enum_variant)] //TODO: create a struct for the Object and Box it pub enum GetBlock { /// The request block, hex-encoded. Raw(#[serde(with = "hex")] SerializedBlock), @@ -1750,21 +1881,84 @@ pub enum GetBlock { /// or -1 if it is not in the best chain. confirmations: i64, + /// The block size. TODO: fill it + #[serde(skip_serializing_if = "Option::is_none")] + size: Option, + /// The height of the requested block. #[serde(skip_serializing_if = "Option::is_none")] height: Option, - /// The height of the requested block. + /// The version field of the requested block. #[serde(skip_serializing_if = "Option::is_none")] - time: Option, + version: Option, + /// The merkle root of the requesteed block. + #[serde(with = "opthex", rename = "merkleroot")] + #[serde(skip_serializing_if = "Option::is_none")] + merkle_root: Option, + + // `blockcommitments` would be here. Undocumented. TODO: decide if we want to support it + // `authdataroot` would be here. Undocumented. TODO: decide if we want to support it + // + /// The root of the Sapling commitment tree after applying this block. + #[serde(with = "opthex", rename = "finalsaplingroot")] + #[serde(skip_serializing_if = "Option::is_none")] + final_sapling_root: Option<[u8; 32]>, + + /// The root of the Orchard commitment tree after applying this block. + #[serde(with = "opthex", rename = "finalorchardroot")] + #[serde(skip_serializing_if = "Option::is_none")] + final_orchard_root: Option<[u8; 32]>, + + // `chainhistoryroot` would be here. Undocumented. TODO: decide if we want to support it + // /// List of transaction IDs in block order, hex-encoded. // // TODO: use a typed Vec here + // TODO: support Objects tx: Vec, + /// The height of the requested block. + #[serde(skip_serializing_if = "Option::is_none")] + time: Option, + + /// The nonce of the requested block header. + #[serde(with = "opthex")] + #[serde(skip_serializing_if = "Option::is_none")] + nonce: Option<[u8; 32]>, + + /// The Equihash solution in the requested block header. + /// Note: presence of this field in getblock is not documented in zcashd. + #[serde(with = "opthex")] + #[serde(skip_serializing_if = "Option::is_none")] + solution: Option, + + /// The difficulty threshold of the requested block header displayed in compact form. + #[serde(with = "opthex")] + #[serde(skip_serializing_if = "Option::is_none")] + bits: Option, + + /// Floating point number that represents the difficulty limit for this block as a multiple + /// of the minimum difficulty for the network. + #[serde(skip_serializing_if = "Option::is_none")] + difficulty: Option, + + // `chainwork` would be here, but we don't plan on supporting it + // `anchor` would be here. Undocumented. TODO: decide if we want to support it + // `chainSupply` would be here, TODO: implement + // `valuePools` would be here, TODO: implement + // /// Information about the note commitment trees. trees: GetBlockTrees, + + /// The previous block hash of the requested block header. + #[serde(rename = "previousblockhash", skip_serializing_if = "Option::is_none")] + previous_block_hash: Option, + + /// The next block hash after the requested block header. + #[serde(rename = "nextblockhash", skip_serializing_if = "Option::is_none")] + next_block_hash: Option, }, } @@ -1777,6 +1971,17 @@ impl Default for GetBlock { time: None, tx: Vec::new(), trees: GetBlockTrees::default(), + size: None, + version: None, + merkle_root: None, + final_sapling_root: None, + final_orchard_root: None, + nonce: None, + bits: None, + difficulty: None, + previous_block_hash: None, + next_block_hash: None, + solution: None, } } } @@ -2156,3 +2361,22 @@ pub fn height_from_signed_int(index: i32, tip_height: Height) -> Result Ok(Height(sanitized_height)) } } + +mod opthex { + use hex::ToHex; + use serde::Serializer; + + pub fn serialize(data: &Option, serializer: S) -> Result + where + S: Serializer, + T: ToHex, + { + match data { + Some(data) => { + let s = data.encode_hex::(); + serializer.serialize_str(&s) + } + None => serializer.serialize_none(), + } + } +} diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@mainnet_10.snap index 6bed7d59cd2..93010ad42d4 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@mainnet_10.snap @@ -5,8 +5,19 @@ expression: block { "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@testnet_10.snap index fe2c9527562..5bd22590f1b 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_1@testnet_10.snap @@ -5,8 +5,19 @@ expression: block { "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } 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 f18b879f6b3..93010ad42d4 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 @@ -6,9 +6,18 @@ expression: block "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, "height": 1, - "time": 1477671596, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } 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 013a4c09b23..5bd22590f1b 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 @@ -6,9 +6,18 @@ expression: block "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, "height": 1, - "time": 1477674473, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@mainnet_10.snap index 6bed7d59cd2..93010ad42d4 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@mainnet_10.snap @@ -5,8 +5,19 @@ expression: block { "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@testnet_10.snap index fe2c9527562..5bd22590f1b 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_hash_verbosity_default@testnet_10.snap @@ -5,8 +5,19 @@ expression: block { "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, + "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@mainnet_10.snap index 3d66b2dffa2..93010ad42d4 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@mainnet_10.snap @@ -6,8 +6,18 @@ expression: block "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@testnet_10.snap index f79a4283b50..5bd22590f1b 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_1@testnet_10.snap @@ -6,8 +6,18 @@ expression: block "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@mainnet_10.snap index f18b879f6b3..93010ad42d4 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@mainnet_10.snap @@ -6,9 +6,18 @@ expression: block "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, "height": 1, - "time": 1477671596, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@testnet_10.snap index 013a4c09b23..5bd22590f1b 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_2@testnet_10.snap @@ -6,9 +6,18 @@ expression: block "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, "height": 1, - "time": 1477674473, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@mainnet_10.snap index 3d66b2dffa2..93010ad42d4 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@mainnet_10.snap @@ -6,8 +6,18 @@ expression: block "hash": "0007bc227e1c57a4a70e237cad00e7b7ce565155ab49166bc57397a26d339283", "confirmations": 10, "height": 1, + "version": 4, + "merkleroot": "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "851bf6fbf7a976327817c738c489d7fa657752445430922d94c983c0b9ed4609" ], - "trees": {} + "time": 1477671596, + "nonce": "9057977ea6d4ae867decc96359fcf2db8cdebcbfb3bd549de4f21f16cfe83475", + "solution": "002b2ee0d2f5d0c1ebf5a265b6f5b428f2fdc9aaea07078a6c5cab4f1bbfcd56489863deae6ea3fd8d3d0762e8e5295ff2670c9e90d8e8c68a54a40927e82a65e1d44ced20d835818e172d7b7f5ffe0245d0c3860a3f11af5658d68b6a7253b4684ffef5242fefa77a0bfc3437e8d94df9dc57510f5a128e676dd9ddf23f0ef75b460090f507499585541ab53a470c547ea02723d3a979930941157792c4362e42d3b9faca342a5c05a56909b046b5e92e2870fca7c932ae2c2fdd97d75b6e0ecb501701c1250246093c73efc5ec2838aeb80b59577741aa5ccdf4a631b79f70fc419e28714fa22108d991c29052b2f5f72294c355b57504369313470ecdd8e0ae97fc48e243a38c2ee7315bb05b7de9602047e97449c81e46746513221738dc729d7077a1771cea858865d85261e71e82003ccfbba2416358f023251206d6ef4c5596bc35b2b5bce3e9351798aa2c9904723034e5815c7512d260cc957df5db6adf9ed7272483312d1e68c60955a944e713355089876a704aef06359238f6de5a618f7bd0b4552ba72d05a6165e582f62d55ff2e1b76991971689ba3bee16a520fd85380a6e5a31de4dd4654d561101ce0ca390862d5774921eae2c284008692e9e08562144e8aa1f399a9d3fab0c4559c1f12bc945e626f7a89668613e8829767f4116ee9a4f832cf7c3ade3a7aba8cb04de39edd94d0d05093ed642adf9fbd9d373a80832ffd1c62034e4341546b3515f0e42e6d8570393c6754be5cdb7753b4709527d3f164aebf3d315934f7b3736a1b31052f6cc5699758950331163b3df05b9772e9bf99c8c77f8960e10a15edb06200106f45742d740c422c86b7e4f5a52d3732aa79ee54cfc92f76e03c268ae226477c19924e733caf95b8f350233a5312f4ed349d3ad76f032358f83a6d0d6f83b2a456742aad7f3e615fa72286300f0ea1c9793831ef3a5a4ae08640a6e32f53d1cba0be284b25e923d0d110ba227e54725632efcbbe17c05a9cde976504f6aece0c461b562cfae1b85d5f6782ee27b3e332ac0775f681682ce524b32889f1dc4231226f1aada0703beaf8d41732c9647a0a940a86f8a1be7f239c44fcaa7ed7a055506bdbe1df848f9e047226bee1b6d788a03f6e352eead99b419cfc41741942dbeb7a5c55788d5a3e636d8aab7b36b4db71d16700373bbc1cdeba8f9b1db10bf39a621bc737ea4f4e333698d6e09b51ac7a97fb6fd117ccad1d6b6b3a7451699d5bfe448650396d7b58867b3b0872be13ad0b43da267df0ad77025155f04e20c56d6a9befb3e9c7d23b82cbf3a534295ebda540682cc81be9273781b92519c858f9c25294fbacf75c3b3c15bda6d36de1c83336f93e96910dbdcb190d6ef123c98565ff6df1e903f57d4e4df167ba6b829d6d9713eb2126b0cf869940204137babcc6a1b7cb2f0b94318a7460e5d1a605c249bd2e72123ebad332332c18adcb285ed8874dbde084ebcd4f744465350d57110f037fffed1569d642c258749e65b0d13e117eaa37014a769b5ab479b7c77178880e77099f999abe712e543dbbf626ca9bcfddc42ff2f109d21c8bd464894e55ae504fdf81e1a7694180225da7dac8879abd1036cf26bb50532b8cf138b337a1a1bd1a43f8dd70b7399e2690c8e7a5a1fe099026b8f2a6f65fc0dbedda15ba65e0abd66c7176fb426980549892b4817de78e345a7aeab05744c3def4a2f283b4255b02c91c1af7354a368c67a11703c642a385c7453131ce3a78b24c5e22ab7e136a38498ce82082181884418cb4d6c2920f258a3ad20cfbe7104af1c6c6cb5e58bf29a9901721ad19c0a260cd09a3a772443a45aea4a5c439a95834ef5dc2e26343278947b7b796f796ae9bcadb29e2899a1d7313e6f7bfb6f8b", + "bits": "1f07ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "00040fe8ec8471911baa1db1266ea15dd06b4a8a5c453883c000b031973dce08", + "nextblockhash": "0002a26c902619fc964443264feb16f1e3e2d71322fc53dcb81cc5d797e273ed" } diff --git a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@testnet_10.snap index f79a4283b50..5bd22590f1b 100644 --- a/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshots/get_block_verbose_height_verbosity_default@testnet_10.snap @@ -6,8 +6,18 @@ expression: block "hash": "025579869bcf52a989337342f5f57a84f3a28b968f7d6a8307902b065a668d23", "confirmations": 10, "height": 1, + "version": 4, + "merkleroot": "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75", + "finalsaplingroot": "0000000000000000000000000000000000000000000000000000000000000000", "tx": [ "f37e9f691fffb635de0999491d906ee85ba40cd36dae9f6e5911a8277d7c5f75" ], - "trees": {} + "time": 1477674473, + "nonce": "0000e5739438a096ca89cde16bcf6001e0c5a7ce6f7c591d26314c26c2560000", + "solution": "0053f4438864bc5d6dfc009d4bba545ac5e5feaaf46f9455b975b02115f842a966e26517ce678f1c074d09cc8d0049a190859eb505af5f3e760312fbbe54da115db2bc03c96408f39b679891790b539d2d9d17a801dc6af9af14ca3f6ba060edce2a1dd45aa45f11fe37dbaf1eb2647ae7c393f6680c3d5d7e53687e34530f48edf58924a04d3e0231c150b1c8218998f674bc171edd222bcb4ac4ba4ea52d7baa86399f371d5284043e1e166f9069dd0f2904ff94c7922a70fa7c660e0553cc40a20d9ee08eb3f47278485801ddae9c270411360773f0b74e03db2d92c50952c9bd4924bbca2a260e1235e99df51fe71e75744232f2d641ef94f394110a5ad05f51a057e4cb515b92c16cb1404a8cdcc43d4a4bb2caa54ca35dccf41aa7d832da65123b7029223c46ed2a13387d598d445435d3cb32fdad9e27672903864c90d86353b162033078327b5b7aaffc89b40096ae004f2d5c6bd2c99188574348518db66e9b6020f93f12ee1c06f7b00fe346fefceaffb1da9e3cdf08285057f549733eb10825737fcd1431bfdfb155f323f24e95a869212baacf445b30f2670206645779110e6547d5da90a5f2fe5151da911d5ecd5a833023661d1356b6c395d85968947678d53efd4db7b06f23b21125e74492644277ea0c1131b80d6a4e3e8093b82332556fbb3255a55ac3f0b7e4844c0e12bf577c37fd02323ae5ef4781772ed501d63b568032a3d31576c5104a48c01ac54f715286932351a8adc8cf2467a84a0572e99f366ee00f82c3735545fd4bb941d591ce70070425a81304272db89887949bc7dd8236bb7e82190f9815da938cd6e8fec7660e91354326a7a9bfe38120e97997fca3c289d54513ed00286c2b825fbe84f91a39528f335674b5e957425a6edfdd00f2feb2c2df575616197998c1e964e069875d4d934f419a9b02b100848d023b76d47bd4e284c3895ef9227a40d8ea8826e86c7155d6aa95b8f9175812523a32cd611efc700688e03f7c245c5bff01718281b5d75cefe8318b2c08962236b14a0bf79534c203df735fd9cced97cbae07c2b4ee9cda8c9993f3f6277ff3fec261fb94d3961c4befe4b0893dcf67b312c7d8d6ff7adc8539cb2b1d3534fccf109efddd07a9f1e77b94ab1e505b164221dca1c34621b1e9d234c31a032a401267d95f65b800d579a2482638dfeade804149c81e95d7ef5510ac0b6212231506b1c635a2e1d2f0c9712989f9f246762fadb4c55c20f707dcc0e510a33e9465fc5d5bdbfa524dab0d7a1c6a1baaa36869cf542aa2257c5c44ef07547a570343442c6091e13bc04d559dc0e6db5b001861914bf956816edce2a86b274bd97f27e2dbb08608c16a3e5d8595952faa91fb162d7fa6a7a47e849a1ad8fab3ba620ee3295a04fe13e5fb655ac92ae60d01020b8999526af8d56b28733e69c9ffb285de27c61edc0bf62261ac0787eff347d0fcd62257301ede9603106ea41650a3e3119bd5c4e86a7f6a3f00934f3a545f7f21d41699f3e35d38cf925a8bdaf2bf7eedea11c31c3d8bf6c527c77c6378281cdf02211a58fa5e46d28d7e7c5fb79d69b31703fd752395da115845952cf99aaeb2155c2ab951a69f67d938f223185567e52cfa3e57b62c790bf78674c4b02c12b7d3225fe8f705b408ba11c24245b3924482e2f3480994461b550641a88cd941d371139f3498afacdcba1249631402b20695760eaada5376e68df0e45139c410700effc9420dc3726515e7fcb3f349320f30511451964bd9b6530682efec65910ceb548aa2ab05ac3309e803161697213631ae8e13cc7d223ac28446c1bf94a19a8782ac16ff57df7ee4f10fb6e488c02c68d6b6dee6987f6d2c39227da366c59f54ff67e312ca530e7c467c3dc8", + "bits": "2007ffff", + "difficulty": 1.0, + "trees": {}, + "previousblockhash": "05a60a92d99d85997cce3b87616c089f6124d7342af37106edc76126334a2c38", + "nextblockhash": "00f1a49e54553ac3ef735f2eb1d8247c9a87c22a47dbd7823ae70adcd6c21a18" } diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index d5a923516c0..213c4d2152c 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -55,6 +55,37 @@ async fn rpc_getinfo() { assert!(rpc_tx_queue_task_result.is_none()); } +// Helper function that returns the nonce and final sapling root of a given +// Block. +async fn get_block_data( + read_state: &ReadStateService, + block: Arc, + height: usize, +) -> ([u8; 32], [u8; 32]) { + let zebra_state::ReadResponse::SaplingTree(sapling_tree) = read_state + .clone() + .oneshot(zebra_state::ReadRequest::SaplingTree(HashOrHeight::Height( + (height as u32).try_into().unwrap(), + ))) + .await + .expect("should have sapling tree for block hash") + else { + panic!("unexpected response to SaplingTree request") + }; + + let mut expected_nonce = *block.header.nonce; + expected_nonce.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] + }; + (expected_nonce, expected_final_sapling_root) +} + #[tokio::test(flavor = "multi_thread")] async fn rpc_getblock() { let _init_guard = zebra_test::init(); @@ -78,7 +109,7 @@ async fn rpc_getblock() { false, true, Buffer::new(mempool.clone(), 1), - read_state, + read_state.clone(), latest_chain_tip, ); @@ -125,6 +156,76 @@ async fn rpc_getblock() { let orchard = OrchardTrees { size: 0 }; let trees = GetBlockTrees { sapling, orchard }; + // Make height calls with verbosity=3 and check response + for (i, block) in blocks.iter().enumerate() { + let get_block = rpc + .get_block(i.to_string(), Some(3u8)) + .await + .expect("We should have a GetBlock struct"); + + assert_eq!( + get_block, + GetBlock::Object { + hash: GetBlockHash(block.hash()), + confirmations: (blocks.len() - i).try_into().expect("valid i64"), + height: Some(Height(i.try_into().expect("valid u32"))), + time: None, + tx: block + .transactions + .iter() + .map(|tx| tx.hash().encode_hex()) + .collect(), + trees, + size: None, + version: None, + merkle_root: None, + final_sapling_root: None, + final_orchard_root: None, + nonce: None, + solution: None, + bits: None, + difficulty: None, + previous_block_hash: None, + next_block_hash: None + } + ); + } + + // Make hash calls with verbosity=3 and check response + for (i, block) in blocks.iter().enumerate() { + let get_block = rpc + .get_block(blocks[i].hash().to_string(), Some(3u8)) + .await + .expect("We should have a GetBlock struct"); + + assert_eq!( + get_block, + GetBlock::Object { + hash: GetBlockHash(block.hash()), + confirmations: (blocks.len() - i).try_into().expect("valid i64"), + height: None, + time: None, + tx: block + .transactions + .iter() + .map(|tx| tx.hash().encode_hex()) + .collect(), + trees, + size: None, + version: None, + merkle_root: None, + final_sapling_root: None, + final_orchard_root: None, + nonce: None, + solution: None, + bits: None, + difficulty: None, + previous_block_hash: None, + next_block_hash: None + } + ); + } + // Make height calls with verbosity=1 and check response for (i, block) in blocks.iter().enumerate() { let get_block = rpc @@ -132,19 +233,38 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), height: Some(Height(i.try_into().expect("valid u32"))), - time: None, + time: Some(block.header.time.timestamp()), tx: block .transactions .iter() .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } @@ -156,19 +276,38 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: None, - time: None, + height: Some(Height(i.try_into().expect("valid u32"))), + time: Some(block.header.time.timestamp()), tx: block .transactions .iter() .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } @@ -180,6 +319,9 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { @@ -193,6 +335,22 @@ async fn rpc_getblock() { .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } @@ -204,6 +362,9 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { @@ -217,6 +378,22 @@ async fn rpc_getblock() { .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } @@ -228,19 +405,38 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), height: Some(Height(i.try_into().expect("valid u32"))), - time: None, + time: Some(block.header.time.timestamp()), tx: block .transactions .iter() .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } @@ -252,19 +448,38 @@ async fn rpc_getblock() { .await .expect("We should have a GetBlock struct"); + let (expected_nonce, expected_final_sapling_root) = + get_block_data(&read_state, block.clone(), i).await; + assert_eq!( get_block, GetBlock::Object { hash: GetBlockHash(block.hash()), confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: None, - time: None, + height: Some(Height(i.try_into().expect("valid u32"))), + time: Some(block.header.time.timestamp()), tx: block .transactions .iter() .map(|tx| tx.hash().encode_hex()) .collect(), trees, + size: None, + version: Some(block.header.version), + merkle_root: Some(block.header.merkle_root), + final_sapling_root: Some(expected_final_sapling_root), + final_orchard_root: None, + nonce: Some(expected_nonce), + bits: Some(block.header.difficulty_threshold), + difficulty: Some( + block + .header + .difficulty_threshold + .relative_to_network(&Mainnet) + ), + previous_block_hash: Some(GetBlockHash(block.header.previous_block_hash)), + next_block_hash: blocks.get(i + 1).map(|b| GetBlockHash(b.hash())), + solution: Some(block.header.solution), } ); } diff --git a/zebra-utils/zcash-rpc-diff b/zebra-utils/zcash-rpc-diff index 57cd5c42cca..8d1507f2dee 100755 --- a/zebra-utils/zcash-rpc-diff +++ b/zebra-utils/zcash-rpc-diff @@ -22,6 +22,9 @@ JQ="${JQ:-jq}" # - Use `-rpccookiefile=your/cookie/file` for a cookie file. # - Use `-rpcpassword=your-password` for a password. ZCASHD_EXTRA_ARGS="${ZCASHD_EXTRA_ARGS:-}" +# Zebrad authentication modes: +# - Use `-rpccookiefile=your/cookie/file` for a cookie file. +ZEBRAD_EXTRA_ARGS="${ZEBRAD_EXTRA_ARGS:-}" # We show this many lines of data, removing excess lines from the middle or end of the output. OUTPUT_DATA_LINE_LIMIT="${OUTPUT_DATA_LINE_LIMIT:-40}" # When checking different mempools, we show this many different transactions. @@ -49,7 +52,7 @@ ZEBRAD_RELEASE_INFO="$ZCASH_RPC_TMP_DIR/first-node-check-getinfo.json" ZCASHD_RELEASE_INFO="$ZCASH_RPC_TMP_DIR/second-node-check-getinfo.json" echo "Checking first node release info..." -$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getinfo > "$ZEBRAD_RELEASE_INFO" +$ZCASH_CLI $ZEBRAD_EXTRA_ARGS -rpcport="$ZEBRAD_RPC_PORT" getinfo > "$ZEBRAD_RELEASE_INFO" ZEBRAD_NAME=$(cat "$ZEBRAD_RELEASE_INFO" | grep '"subversion"' | cut -d: -f2 | cut -d/ -f2 | \ tr 'A-Z' 'a-z' | sed 's/magicbean/zcashd/ ; s/zebra$/zebrad/') @@ -74,7 +77,7 @@ ZEBRAD_BLOCKCHAIN_INFO="$ZCASH_RPC_TMP_DIR/$ZEBRAD_NAME-check-getblockchaininfo. ZCASHD_BLOCKCHAIN_INFO="$ZCASH_RPC_TMP_DIR/$ZCASHD_NAME-check-getblockchaininfo.json" echo "Checking $ZEBRAD network and tip height..." -$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getblockchaininfo > "$ZEBRAD_BLOCKCHAIN_INFO" +$ZCASH_CLI $ZEBRAD_EXTRA_ARGS -rpcport="$ZEBRAD_RPC_PORT" getblockchaininfo > "$ZEBRAD_BLOCKCHAIN_INFO" ZEBRAD_NET=$(cat "$ZEBRAD_BLOCKCHAIN_INFO" | grep '"chain"' | cut -d: -f2 | tr -d ' ,"') ZEBRAD_HEIGHT=$(cat "$ZEBRAD_BLOCKCHAIN_INFO" | grep '"blocks"' | cut -d: -f2 | tr -d ' ,"') @@ -109,7 +112,7 @@ echo "$@" echo echo "Querying $ZEBRAD $ZEBRAD_NET chain at height >=$ZEBRAD_HEIGHT..." -time $ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_RESPONSE" +time $ZCASH_CLI $ZEBRAD_EXTRA_ARGS -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_RESPONSE" echo echo "Querying $ZCASHD $ZCASHD_NET chain at height >=$ZCASHD_HEIGHT..." @@ -166,7 +169,7 @@ echo "$@" echo echo "Querying $ZEBRAD $ZEBRAD_NET chain at height >=$ZEBRAD_HEIGHT..." -$ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_CHECK_RESPONSE" +$ZCASH_CLI $ZEBRAD_EXTRA_ARGS -rpcport="$ZEBRAD_RPC_PORT" "$@" > "$ZEBRAD_CHECK_RESPONSE" echo "Querying $ZCASHD $ZCASHD_NET chain at height >=$ZCASHD_HEIGHT..." $ZCASH_CLI $ZCASHD_EXTRA_ARGS "$@" > "$ZCASHD_CHECK_RESPONSE" @@ -257,7 +260,7 @@ if [ "$1" == "getrawmempool" ] && [ $CHECK_EXIT_STATUS != 0 ]; then for TRANSACTION_ID in $ZEBRAD_TRANSACTION_IDS; do TRANSACTION_HEX_FILE="$ZCASH_RPC_TMP_DIR/$ZEBRAD_NAME-$ZEBRAD_NET-$ZEBRAD_HEIGHT-$TRANSACTION_ID.json" - $ZCASH_CLI -rpcport="$ZEBRAD_RPC_PORT" getrawtransaction $TRANSACTION_ID 0 > $TRANSACTION_HEX_FILE + $ZCASH_CLI $ZEBRAD_EXTRA_ARGS -rpcport="$ZEBRAD_RPC_PORT" getrawtransaction $TRANSACTION_ID 0 > $TRANSACTION_HEX_FILE echo "## Displaying transaction $TRANSACTION_ID from zebrad (limited to ${OUTPUT_DATA_LINE_LIMIT} lines)" echo From ba9c7057d3c68a6c59576407f3ab541c3c17bbd3 Mon Sep 17 00:00:00 2001 From: Arya Date: Tue, 12 Nov 2024 17:55:34 -0500 Subject: [PATCH 2/8] Removes handling for verbosity = 3 in getblock method, adds finalorchardroot field, removes unnecessary state request. (#9008) --- zebra-rpc/src/methods.rs | 265 ++++++------------------- zebra-rpc/src/methods/tests/vectors.rs | 1 + 2 files changed, 63 insertions(+), 203 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index d0d3ea468f1..0488f864f5f 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -780,151 +780,38 @@ where }), _ => unreachable!("unmatched response to a block request"), } - } else if verbosity == 1 || verbosity == 2 { - let r: Result = self_clone + } else if matches!(verbosity, 1 | 2) { + let get_block_header_result: Result = self_clone .get_block_header(original_hash_or_height, Some(true)) .await; - let GetBlockHeader::Object(h) = r? else { + let GetBlockHeader::Object(block_header) = get_block_header_result? else { panic!("must return Object") }; - let hash = h.hash.0; - // # Concurrency - // - // We look up by block hash so the hash, transaction IDs, and confirmations - // are consistent. - let requests = vec![ - // Get transaction IDs from the transaction index by block hash - // - // # Concurrency - // - // A block's transaction IDs are never modified, so all possible responses are - // valid. Clients that query block heights must be able to handle chain forks, - // including getting transaction IDs from any chain fork. - zebra_state::ReadRequest::TransactionIdsForBlock(hash.into()), - // Sapling trees - zebra_state::ReadRequest::SaplingTree(hash.into()), - // Orchard trees - zebra_state::ReadRequest::OrchardTree(hash.into()), - ]; - - let mut futs = FuturesOrdered::new(); - - for request in requests { - futs.push_back(state.clone().oneshot(request)); - } - - let tx_ids_response = futs.next().await.expect("`futs` should not be empty"); - let tx = match tx_ids_response.map_server_error()? { - zebra_state::ReadResponse::TransactionIdsForBlock(tx_ids) => tx_ids - .ok_or_server_error("Block not found")? - .iter() - .map(|tx_id| tx_id.encode_hex()) - .collect(), - _ => unreachable!("unmatched response to a transaction_ids_for_block request"), - }; - - let sapling_tree_response = futs.next().await.expect("`futs` should not be empty"); - let sapling_note_commitment_tree_count = - match sapling_tree_response.map_server_error()? { - zebra_state::ReadResponse::SaplingTree(Some(nct)) => nct.count(), - zebra_state::ReadResponse::SaplingTree(None) => 0, - _ => unreachable!("unmatched response to a SaplingTree request"), - }; - - let orchard_tree_response = futs.next().await.expect("`futs` should not be empty"); - let orchard_note_commitment_tree_count = - match orchard_tree_response.map_server_error()? { - zebra_state::ReadResponse::OrchardTree(Some(nct)) => nct.count(), - zebra_state::ReadResponse::OrchardTree(None) => 0, - _ => unreachable!("unmatched response to a OrchardTree request"), - }; - - let sapling = SaplingTrees { - size: sapling_note_commitment_tree_count, - }; - - let orchard = OrchardTrees { - size: orchard_note_commitment_tree_count, - }; - - let trees = GetBlockTrees { sapling, orchard }; - - Ok(GetBlock::Object { - hash: h.hash, - confirmations: h.confirmations, - height: Some(h.height), - version: Some(h.version), - merkle_root: Some(h.merkle_root), - time: Some(h.time), - nonce: Some(h.nonce), - solution: Some(h.solution), - bits: Some(h.bits), - difficulty: Some(h.difficulty), - // TODO - tx, - trees, - // TODO - size: None, - final_sapling_root: Some(h.final_sapling_root), - // TODO - final_orchard_root: None, - previous_block_hash: Some(h.previous_block_hash), - next_block_hash: h.next_block_hash, - }) - } else if verbosity == 3 { - // # Performance - // - // This RPC is used in `lightwalletd`'s initial sync of 2 million blocks, - // so it needs to load all its fields very efficiently. - // - // Currently, we get the block hash and transaction IDs from indexes, - // which is much more efficient than loading all the block data, - // then hashing the block header and all the transactions. - - // Get the block hash from the height -> hash index, if needed - // - // # Concurrency - // - // For consistency, this lookup must be performed first, then all the other - // lookups must be based on the hash. - // - // All possible responses are valid, even if the best chain changes. Clients - // must be able to handle chain forks, including a hash for a block that is - // later discovered to be on a side chain. - - let should_read_block_header = verbosity == 2; - - let hash = match hash_or_height { - HashOrHeight::Hash(hash) => hash, - HashOrHeight::Height(height) => { - let request = zebra_state::ReadRequest::BestChainBlockHash(height); - let response = state - .ready() - .and_then(|service| service.call(request)) - .await - .map_server_error()?; - - match response { - zebra_state::ReadResponse::BlockHash(Some(hash)) => hash, - zebra_state::ReadResponse::BlockHash(None) => { - return Err(Error { - code: MISSING_BLOCK_ERROR_CODE, - message: "block height not in best chain".to_string(), - data: None, - }) - } - _ => unreachable!("unmatched response to a block hash request"), - } - } - }; + let GetBlockHeaderObject { + hash, + confirmations, + height, + version, + merkle_root, + final_sapling_root, + sapling_tree_size, + time, + nonce, + solution, + bits, + difficulty, + previous_block_hash, + next_block_hash, + } = *block_header; // # Concurrency // // We look up by block hash so the hash, transaction IDs, and confirmations // are consistent. - let mut requests = vec![ + let hash_or_height = hash.0.into(); + let requests = vec![ // Get transaction IDs from the transaction index by block hash // // # Concurrency @@ -932,27 +819,11 @@ where // A block's transaction IDs are never modified, so all possible responses are // valid. Clients that query block heights must be able to handle chain forks, // including getting transaction IDs from any chain fork. - zebra_state::ReadRequest::TransactionIdsForBlock(hash.into()), - // Sapling trees - zebra_state::ReadRequest::SaplingTree(hash.into()), + zebra_state::ReadRequest::TransactionIdsForBlock(hash_or_height), // Orchard trees - zebra_state::ReadRequest::OrchardTree(hash.into()), - // Get block confirmations from the block height index - // - // # Concurrency - // - // All possible responses are valid, even if a block is added to the chain, or - // the best chain changes. Clients must be able to handle chain forks, including - // different confirmation values before or after added blocks, and switching - // between -1 and multiple different confirmation values. - zebra_state::ReadRequest::Depth(hash), + zebra_state::ReadRequest::OrchardTree(hash_or_height), ]; - if should_read_block_header { - // Block header - requests.push(zebra_state::ReadRequest::BlockHeader(hash.into())) - } - let mut futs = FuturesOrdered::new(); for request in requests { @@ -969,76 +840,56 @@ where _ => unreachable!("unmatched response to a transaction_ids_for_block request"), }; - let sapling_tree_response = futs.next().await.expect("`futs` should not be empty"); - let sapling_note_commitment_tree_count = - match sapling_tree_response.map_server_error()? { - zebra_state::ReadResponse::SaplingTree(Some(nct)) => nct.count(), - zebra_state::ReadResponse::SaplingTree(None) => 0, - _ => unreachable!("unmatched response to a SaplingTree request"), - }; - let orchard_tree_response = futs.next().await.expect("`futs` should not be empty"); - let orchard_note_commitment_tree_count = - match orchard_tree_response.map_server_error()? { - zebra_state::ReadResponse::OrchardTree(Some(nct)) => nct.count(), - zebra_state::ReadResponse::OrchardTree(None) => 0, - _ => unreachable!("unmatched response to a OrchardTree request"), - }; - - // From - const NOT_IN_BEST_CHAIN_CONFIRMATIONS: i64 = -1; - - let depth_response = futs.next().await.expect("`futs` should not be empty"); - let confirmations = match depth_response.map_server_error()? { - // Confirmations are one more than the depth. - // Depth is limited by height, so it will never overflow an i64. - zebra_state::ReadResponse::Depth(Some(depth)) => i64::from(depth) + 1, - zebra_state::ReadResponse::Depth(None) => NOT_IN_BEST_CHAIN_CONFIRMATIONS, - _ => unreachable!("unmatched response to a depth request"), + let zebra_state::ReadResponse::OrchardTree(orchard_tree) = + orchard_tree_response.map_server_error()? + else { + unreachable!("unmatched response to a OrchardTree request"); }; - let (time, height) = if should_read_block_header { - let block_header_response = - futs.next().await.expect("`futs` should not be empty"); + // This could be `None` if there's a chain reorg between state queries. + let orchard_tree = + orchard_tree.ok_or_server_error("missing sapling tree for block")?; - match block_header_response.map_server_error()? { - zebra_state::ReadResponse::BlockHeader { header, height, .. } => { - (Some(header.time.timestamp()), Some(height)) - } - _ => unreachable!("unmatched response to a BlockHeader request"), - } + let orchard_tree_size = orchard_tree.count(); + let final_orchard_root: [u8; 32] = if orchard_tree_size != 0 { + let mut root: [u8; 32] = orchard_tree.root().into(); + root.reverse(); + root } else { - (None, hash_or_height.height()) + [0; 32] }; let sapling = SaplingTrees { - size: sapling_note_commitment_tree_count, + size: sapling_tree_size, }; let orchard = OrchardTrees { - size: orchard_note_commitment_tree_count, + size: orchard_tree_size, }; let trees = GetBlockTrees { sapling, orchard }; Ok(GetBlock::Object { - hash: GetBlockHash(hash), + hash, confirmations, - height, - time, + height: Some(height), + version: Some(version), + merkle_root: Some(merkle_root), + time: Some(time), + nonce: Some(nonce), + solution: Some(solution), + bits: Some(bits), + difficulty: Some(difficulty), + // TODO tx, trees, + // TODO size: None, - version: None, - merkle_root: None, - final_sapling_root: None, - final_orchard_root: None, - nonce: None, - bits: None, - difficulty: None, - previous_block_hash: None, - next_block_hash: None, - solution: None, + final_sapling_root: Some(final_sapling_root), + final_orchard_root: Some(final_orchard_root), + previous_block_hash: Some(previous_block_hash), + next_block_hash, }) } else { Err(Error { @@ -1125,7 +976,8 @@ where let mut nonce = *header.nonce; nonce.reverse(); - let final_sapling_root: [u8; 32] = if sapling_tree.position().is_some() { + let sapling_tree_size = sapling_tree.count(); + let final_sapling_root: [u8; 32] = if sapling_tree_size != 0 { let mut root: [u8; 32] = sapling_tree.root().into(); root.reverse(); root @@ -1142,6 +994,7 @@ where version: header.version, merkle_root: header.merkle_root, final_sapling_root, + sapling_tree_size, time: header.time.timestamp(), nonce, solution: header.solution, @@ -2025,6 +1878,11 @@ pub struct GetBlockHeaderObject { #[serde(with = "hex", rename = "finalsaplingroot")] pub final_sapling_root: [u8; 32], + /// The number of Sapling notes in the Sapling note commitment tree + /// after applying this block. Used by the `getblock` RPC method. + #[serde(skip)] + pub sapling_tree_size: u64, + /// The block time of the requested block header in non-leap seconds since Jan 1 1970 GMT. pub time: i64, @@ -2070,6 +1928,7 @@ impl Default for GetBlockHeaderObject { version: 4, merkle_root: block::merkle::Root([0; 32]), final_sapling_root: Default::default(), + sapling_tree_size: Default::default(), time: 0, nonce: [0; 32], solution: Solution::for_proposal(), diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 213c4d2152c..1f8cffa07a4 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -664,6 +664,7 @@ async fn rpc_getblockheader() { version: 4, merkle_root: block.header.merkle_root, final_sapling_root: expected_final_sapling_root, + sapling_tree_size: sapling_tree.count(), time: block.header.time.timestamp(), nonce: expected_nonce, solution: block.header.solution, From 682ec3f6e79c8188918aea9b0ff4cdf3326242cc Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Wed, 13 Nov 2024 14:24:17 -0300 Subject: [PATCH 3/8] align final(sapling|orchard)root with zcashd behaviour --- zebra-rpc/src/methods.rs | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 0488f864f5f..b7242ae72cc 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -847,23 +847,24 @@ where unreachable!("unmatched response to a OrchardTree request"); }; + let nu5_activation = NetworkUpgrade::Nu5.activation_height(&self_clone.network); + // This could be `None` if there's a chain reorg between state queries. let orchard_tree = - orchard_tree.ok_or_server_error("missing sapling tree for block")?; + orchard_tree.ok_or_server_error("missing orchard tree for block")?; - let orchard_tree_size = orchard_tree.count(); - let final_orchard_root: [u8; 32] = if orchard_tree_size != 0 { - let mut root: [u8; 32] = orchard_tree.root().into(); - root.reverse(); - root - } else { - [0; 32] - }; + let final_orchard_root = + if nu5_activation.is_some() && height >= nu5_activation.unwrap() { + Some(orchard_tree.root().into()) + } else { + None + }; let sapling = SaplingTrees { size: sapling_tree_size, }; + let orchard_tree_size = orchard_tree.count(); let orchard = OrchardTrees { size: orchard_tree_size, }; @@ -887,7 +888,7 @@ where // TODO size: None, final_sapling_root: Some(final_sapling_root), - final_orchard_root: Some(final_orchard_root), + final_orchard_root, previous_block_hash: Some(previous_block_hash), next_block_hash, }) @@ -976,14 +977,16 @@ where let mut nonce = *header.nonce; nonce.reverse(); + let sapling_activation = NetworkUpgrade::Sapling.activation_height(&network); let sapling_tree_size = sapling_tree.count(); - let final_sapling_root: [u8; 32] = if sapling_tree_size != 0 { - let mut root: [u8; 32] = sapling_tree.root().into(); - root.reverse(); - root - } else { - [0; 32] - }; + let final_sapling_root: [u8; 32] = + if sapling_activation.is_some() && height >= sapling_activation.unwrap() { + let mut root: [u8; 32] = sapling_tree.root().into(); + root.reverse(); + root + } else { + [0; 32] + }; let difficulty = header.difficulty_threshold.relative_to_network(&network); From 1d848d7cd256d61ecc37970ef10ff01b9026b01c Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Wed, 13 Nov 2024 18:18:46 -0300 Subject: [PATCH 4/8] fix test --- zebra-rpc/src/methods/tests/vectors.rs | 70 -------------------------- 1 file changed, 70 deletions(-) diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index 1f8cffa07a4..007a89ee893 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -156,76 +156,6 @@ async fn rpc_getblock() { let orchard = OrchardTrees { size: 0 }; let trees = GetBlockTrees { sapling, orchard }; - // Make height calls with verbosity=3 and check response - for (i, block) in blocks.iter().enumerate() { - let get_block = rpc - .get_block(i.to_string(), Some(3u8)) - .await - .expect("We should have a GetBlock struct"); - - assert_eq!( - get_block, - GetBlock::Object { - hash: GetBlockHash(block.hash()), - confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: Some(Height(i.try_into().expect("valid u32"))), - time: None, - tx: block - .transactions - .iter() - .map(|tx| tx.hash().encode_hex()) - .collect(), - trees, - size: None, - version: None, - merkle_root: None, - final_sapling_root: None, - final_orchard_root: None, - nonce: None, - solution: None, - bits: None, - difficulty: None, - previous_block_hash: None, - next_block_hash: None - } - ); - } - - // Make hash calls with verbosity=3 and check response - for (i, block) in blocks.iter().enumerate() { - let get_block = rpc - .get_block(blocks[i].hash().to_string(), Some(3u8)) - .await - .expect("We should have a GetBlock struct"); - - assert_eq!( - get_block, - GetBlock::Object { - hash: GetBlockHash(block.hash()), - confirmations: (blocks.len() - i).try_into().expect("valid i64"), - height: None, - time: None, - tx: block - .transactions - .iter() - .map(|tx| tx.hash().encode_hex()) - .collect(), - trees, - size: None, - version: None, - merkle_root: None, - final_sapling_root: None, - final_orchard_root: None, - nonce: None, - solution: None, - bits: None, - difficulty: None, - previous_block_hash: None, - next_block_hash: None - } - ); - } - // Make height calls with verbosity=1 and check response for (i, block) in blocks.iter().enumerate() { let get_block = rpc From 529012f57286fa203d039f8c119a9dda64a59071 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 19 Nov 2024 12:16:29 -0300 Subject: [PATCH 5/8] Apply suggestions from code review Co-authored-by: Alfredo Garcia --- zebra-rpc/src/methods.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index b7242ae72cc..0fff8be8024 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -163,8 +163,7 @@ pub trait Rpc { /// /// Zebra previously partially supported verbosity=1 by returning only the /// fields required by lightwalletd ([`lightwalletd` only reads the `tx` - /// field of the - /// result](https://github.com/zcash/lightwalletd/blob/dfac02093d85fb31fb9a8475b884dd6abca966c7/common/common.go#L152)). + /// field of the result](https://github.com/zcash/lightwalletd/blob/dfac02093d85fb31fb9a8475b884dd6abca966c7/common/common.go#L152)). /// That verbosity level was migrated to "3"; so while lightwalletd will /// still work by using verbosity=1, it will sync faster if it is changed to /// use verbosity=3. @@ -1749,7 +1748,7 @@ pub enum GetBlock { #[serde(skip_serializing_if = "Option::is_none")] version: Option, - /// The merkle root of the requesteed block. + /// The merkle root of the requested block. #[serde(with = "opthex", rename = "merkleroot")] #[serde(skip_serializing_if = "Option::is_none")] merkle_root: Option, @@ -2224,6 +2223,7 @@ pub fn height_from_signed_int(index: i32, tip_height: Height) -> Result } } +/// A helper module to serialize `Option` as a hex string. mod opthex { use hex::ToHex; use serde::Serializer; From 1013611ef7225000c32f17b7c202cbe22f277ad6 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Tue, 19 Nov 2024 12:18:02 -0300 Subject: [PATCH 6/8] restore getblock docs; remove unneeded TODOs --- zebra-rpc/src/methods.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 0fff8be8024..d5f3b372886 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -157,7 +157,7 @@ pub trait Rpc { /// # Parameters /// /// - `hash_or_height`: (string, required, example="1") The hash or height for the block to be returned. - /// - `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data, and 3 for a partially filled json object (which is faster and useful for lightwalletd-only usage) + /// - `verbosity`: (number, optional, default=1, example=1) 0 for hex encoded data, 1 for a json object, and 2 for json object with transaction data. /// /// # Notes /// @@ -881,10 +881,8 @@ where solution: Some(solution), bits: Some(bits), difficulty: Some(difficulty), - // TODO tx, trees, - // TODO size: None, final_sapling_root: Some(final_sapling_root), final_orchard_root, From 58d31357caeb00de93ab9d0c2cf3db6a1a464e11 Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Fri, 22 Nov 2024 13:21:54 -0300 Subject: [PATCH 7/8] Update zebra-rpc/src/methods.rs Co-authored-by: Arya --- zebra-rpc/src/methods.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index d5f3b372886..2a1638d5696 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -852,12 +852,12 @@ where let orchard_tree = orchard_tree.ok_or_server_error("missing orchard tree for block")?; - let final_orchard_root = - if nu5_activation.is_some() && height >= nu5_activation.unwrap() { + let final_orchard_root = match nu5_activation { + Some(activation_height) if height >= activation_height => { Some(orchard_tree.root().into()) - } else { - None - }; + } + _other => None, + }; let sapling = SaplingTrees { size: sapling_tree_size, From 46385efc5ff93c7307811fc001de33685587ea69 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 29 Nov 2024 13:32:01 -0300 Subject: [PATCH 8/8] get rif of cloning self (#9044) --- zebra-rpc/src/methods.rs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 2a1638d5696..52f28d606b3 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -750,9 +750,16 @@ where let mut state = self.state.clone(); let verbosity = verbosity.unwrap_or(DEFAULT_GETBLOCK_VERBOSITY); - let self_clone = self.clone(); - + let network = self.network.clone(); let original_hash_or_height = hash_or_height.clone(); + + // If verbosity requires a call to `get_block_header`, resolve it here + let get_block_header_future = if matches!(verbosity, 1 | 2) { + Some(self.get_block_header(original_hash_or_height.clone(), Some(true))) + } else { + None + }; + async move { let hash_or_height: HashOrHeight = hash_or_height.parse().map_server_error()?; @@ -779,10 +786,8 @@ where }), _ => unreachable!("unmatched response to a block request"), } - } else if matches!(verbosity, 1 | 2) { - let get_block_header_result: Result = self_clone - .get_block_header(original_hash_or_height, Some(true)) - .await; + } else if let Some(get_block_header_future) = get_block_header_future { + let get_block_header_result: Result = get_block_header_future.await; let GetBlockHeader::Object(block_header) = get_block_header_result? else { panic!("must return Object") @@ -846,7 +851,7 @@ where unreachable!("unmatched response to a OrchardTree request"); }; - let nu5_activation = NetworkUpgrade::Nu5.activation_height(&self_clone.network); + let nu5_activation = NetworkUpgrade::Nu5.activation_height(&network); // This could be `None` if there's a chain reorg between state queries. let orchard_tree =