From 17d7f914a8fae07fd3b63e05b4f35e18500d53d1 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 5 Sep 2024 18:28:11 +0000 Subject: [PATCH 1/5] build(deps): bump tj-actions/changed-files in the devops group (#8835) Bumps the devops group with 1 update: [tj-actions/changed-files](https://github.com/tj-actions/changed-files). Updates `tj-actions/changed-files` from 45.0.0 to 45.0.1 - [Release notes](https://github.com/tj-actions/changed-files/releases) - [Changelog](https://github.com/tj-actions/changed-files/blob/main/HISTORY.md) - [Commits](https://github.com/tj-actions/changed-files/compare/v45.0.0...v45.0.1) --- updated-dependencies: - dependency-name: tj-actions/changed-files dependency-type: direct:production update-type: version-update:semver-patch dependency-group: devops ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/ci-lint.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci-lint.yml b/.github/workflows/ci-lint.yml index 3137dee49db..87b60204746 100644 --- a/.github/workflows/ci-lint.yml +++ b/.github/workflows/ci-lint.yml @@ -44,7 +44,7 @@ jobs: - name: Rust files id: changed-files-rust - uses: tj-actions/changed-files@v45.0.0 + uses: tj-actions/changed-files@v45.0.1 with: files: | **/*.rs @@ -56,7 +56,7 @@ jobs: - name: Workflow files id: changed-files-workflows - uses: tj-actions/changed-files@v45.0.0 + uses: tj-actions/changed-files@v45.0.1 with: files: | .github/workflows/*.yml From 151199782912d085d1ab0bfc6fa68cd061e0e867 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Fri, 6 Sep 2024 12:24:15 -0300 Subject: [PATCH 2/5] fix clippy lints (#8855) --- zebra-state/src/service/finalized_state/zebra_db/block.rs | 1 + zebrad/src/components/mempool/downloads.rs | 1 + zebrad/tests/common/checkpoints.rs | 2 +- zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs | 2 +- zebrad/tests/common/get_block_template_rpcs/submit_block.rs | 2 +- zebrad/tests/common/lightwalletd/send_transaction_test.rs | 2 +- 6 files changed, 6 insertions(+), 4 deletions(-) diff --git a/zebra-state/src/service/finalized_state/zebra_db/block.rs b/zebra-state/src/service/finalized_state/zebra_db/block.rs index e10fd3b43b4..4dc3a801ef3 100644 --- a/zebra-state/src/service/finalized_state/zebra_db/block.rs +++ b/zebra-state/src/service/finalized_state/zebra_db/block.rs @@ -290,6 +290,7 @@ impl ZebraDb { /// /// - Propagates any errors from writing to the DB /// - Propagates any errors from updating history and note commitment trees + #[allow(clippy::unwrap_in_result)] pub(in super::super) fn write_block( &mut self, finalized: FinalizedBlock, diff --git a/zebrad/src/components/mempool/downloads.rs b/zebrad/src/components/mempool/downloads.rs index b37f988dcc8..eeda6bd9567 100644 --- a/zebrad/src/components/mempool/downloads.rs +++ b/zebrad/src/components/mempool/downloads.rs @@ -240,6 +240,7 @@ where /// /// Returns the action taken in response to the queue request. #[instrument(skip(self, gossiped_tx), fields(txid = %gossiped_tx.id()))] + #[allow(clippy::unwrap_in_result)] pub fn download_if_needed_and_verify( &mut self, gossiped_tx: Gossip, diff --git a/zebrad/tests/common/checkpoints.rs b/zebrad/tests/common/checkpoints.rs index 602525fd926..c1c0ae44716 100644 --- a/zebrad/tests/common/checkpoints.rs +++ b/zebrad/tests/common/checkpoints.rs @@ -136,7 +136,7 @@ pub async fn run(network: Network) -> Result<()> { ?zebra_rpc_address, "waiting for zebrad to open its RPC port...", ); - zebrad.expect_stdout_line_matches(&format!("Opened RPC endpoint at {zebra_rpc_address}"))?; + zebrad.expect_stdout_line_matches(format!("Opened RPC endpoint at {zebra_rpc_address}"))?; tracing::info!( ?network, diff --git a/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs b/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs index 4ca0bc797ad..dd30954948c 100644 --- a/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs +++ b/zebrad/tests/common/get_block_template_rpcs/get_peer_info.rs @@ -34,7 +34,7 @@ pub(crate) async fn run() -> Result<()> { let rpc_address = zebra_rpc_address.expect("getpeerinfo test must have RPC port"); // Wait until port is open. - zebrad.expect_stdout_line_matches(&format!("Opened RPC endpoint at {rpc_address}"))?; + zebrad.expect_stdout_line_matches(format!("Opened RPC endpoint at {rpc_address}"))?; tracing::info!(?rpc_address, "zebrad opened its RPC port",); diff --git a/zebrad/tests/common/get_block_template_rpcs/submit_block.rs b/zebrad/tests/common/get_block_template_rpcs/submit_block.rs index 28f48fb2c14..399efc8d99e 100644 --- a/zebrad/tests/common/get_block_template_rpcs/submit_block.rs +++ b/zebrad/tests/common/get_block_template_rpcs/submit_block.rs @@ -59,7 +59,7 @@ pub(crate) async fn run() -> Result<()> { ?rpc_address, "spawned isolated zebrad with shorter chain, waiting for zebrad to open its RPC port..." ); - zebrad.expect_stdout_line_matches(&format!("Opened RPC endpoint at {rpc_address}"))?; + zebrad.expect_stdout_line_matches(format!("Opened RPC endpoint at {rpc_address}"))?; tracing::info!(?rpc_address, "zebrad opened its RPC port",); diff --git a/zebrad/tests/common/lightwalletd/send_transaction_test.rs b/zebrad/tests/common/lightwalletd/send_transaction_test.rs index f9087771595..bee6cf78356 100644 --- a/zebrad/tests/common/lightwalletd/send_transaction_test.rs +++ b/zebrad/tests/common/lightwalletd/send_transaction_test.rs @@ -118,7 +118,7 @@ pub async fn run() -> Result<()> { ?zebra_rpc_address, "spawned isolated zebrad with shorter chain, waiting for zebrad to open its RPC port..." ); - zebrad.expect_stdout_line_matches(&format!("Opened RPC endpoint at {zebra_rpc_address}"))?; + zebrad.expect_stdout_line_matches(format!("Opened RPC endpoint at {zebra_rpc_address}"))?; tracing::info!( ?zebra_rpc_address, From 554a37d20a08f02312508bc6c4e18844ec44ff21 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 9 Sep 2024 10:02:35 -0300 Subject: [PATCH 3/5] feat(rpc): Add a `stop` rpc method (#8839) * add a `stop` rpc method * add todo comment * add a ticket number to the TODO Co-authored-by: Marek --------- Co-authored-by: Marek Co-authored-by: Pili Guerra --- openapi.yaml | 85 +++++++++++++------ zebra-rpc/src/methods.rs | 25 ++++++ zebra-utils/src/bin/openapi-generator/main.rs | 1 + 3 files changed, 85 insertions(+), 26 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index 10ac6bfdf61..e7793967118 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -28,7 +28,7 @@ paths: default: getinfo id: type: string - default: VuJXrxLSw8 + default: QWlDS9bxlK params: type: array items: {} @@ -61,7 +61,7 @@ paths: default: getblockchaininfo id: type: string - default: HDVqYXM9m6 + default: XSg3wvZykA params: type: array items: {} @@ -99,7 +99,7 @@ paths: default: getaddressbalance id: type: string - default: Xw5TDBKXGl + default: GEd1QJWprH params: type: array items: {} @@ -147,7 +147,7 @@ paths: default: sendrawtransaction id: type: string - default: QaJv2bXyZu + default: nhQi7D6Oru params: type: array items: {} @@ -196,7 +196,7 @@ paths: default: getblock id: type: string - default: k0DACJrgZs + default: qIEYMzgbJZ params: type: array items: {} @@ -239,7 +239,7 @@ paths: default: getbestblockhash id: type: string - default: rIFaLhZwHF + default: P9UBS8IXXU params: type: array items: {} @@ -272,7 +272,7 @@ paths: default: getbestblockheightandhash id: type: string - default: oxrhh1swvh + default: gQNhsomx7N params: type: array items: {} @@ -305,7 +305,7 @@ paths: default: getrawmempool id: type: string - default: E7oUD34jk2 + default: c2ScL31PtX params: type: array items: {} @@ -343,7 +343,7 @@ paths: default: z_gettreestate id: type: string - default: Hp22XK728i + default: JQ0mENKbdm params: type: array items: {} @@ -393,7 +393,7 @@ paths: default: z_getsubtreesbyindex id: type: string - default: Cs69hg68pl + default: bZUCv4t0f4 params: type: array items: {} @@ -432,7 +432,7 @@ paths: default: getrawtransaction id: type: string - default: iu395PEErc + default: I0FAejAi4r params: type: array items: {} @@ -480,7 +480,7 @@ paths: default: getaddresstxids id: type: string - default: z3lOKfsQdp + default: '3fMzDHOglf' params: type: array items: {} @@ -528,7 +528,7 @@ paths: default: getaddressutxos id: type: string - default: '7U4Q4dSxej' + default: LE2AR8Tr6X params: type: array items: {} @@ -554,6 +554,39 @@ paths: error: type: string default: Invalid parameters + /stop: + post: + tags: + - control + description: Stop the running zebrad process. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + method: + type: string + default: stop + id: + type: string + default: PbxxqB0ZpF + params: + type: array + items: {} + default: '[]' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + result: + type: object + default: 'null' /getblockcount: post: tags: @@ -571,7 +604,7 @@ paths: default: getblockcount id: type: string - default: '8yw3EX7Cwi' + default: WO6BAIKSCg params: type: array items: {} @@ -609,7 +642,7 @@ paths: default: getblockhash id: type: string - default: ndDYksCl9E + default: vHpKNIQRLF params: type: array items: {} @@ -657,7 +690,7 @@ paths: default: getblocktemplate id: type: string - default: lJi2hfxty1 + default: L04jp5F2QW params: type: array items: {} @@ -695,7 +728,7 @@ paths: default: submitblock id: type: string - default: '9fEFOdTQle' + default: Izn7vhiMaA params: type: array items: {} @@ -728,7 +761,7 @@ paths: default: getmininginfo id: type: string - default: Dytpq4f3lF + default: SgyuBQbMik params: type: array items: {} @@ -761,7 +794,7 @@ paths: default: getnetworksolps id: type: string - default: yX3woRnOaN + default: FXg2iH3eaX params: type: array items: {} @@ -794,7 +827,7 @@ paths: default: getnetworkhashps id: type: string - default: AyAZMtbezv + default: '2PWjf8QqfI' params: type: array items: {} @@ -827,7 +860,7 @@ paths: default: getpeerinfo id: type: string - default: nNcrsu3ZAR + default: OE9s5wkP0w params: type: array items: {} @@ -865,7 +898,7 @@ paths: default: validateaddress id: type: string - default: LGyfO7zTjW + default: '6FS4iGA4Ht' params: type: array items: {} @@ -903,7 +936,7 @@ paths: default: z_validateaddress id: type: string - default: '2Q09a2Nh4N' + default: utp8tN61yU params: type: array items: {} @@ -941,7 +974,7 @@ paths: default: getblocksubsidy id: type: string - default: nv6lOWCRso + default: dgNZGo7lNa params: type: array items: {} @@ -984,7 +1017,7 @@ paths: default: getdifficulty id: type: string - default: '2O3A0PF1SS' + default: KEJv30D2MI params: type: array items: {} @@ -1022,7 +1055,7 @@ paths: default: z_listunifiedreceivers id: type: string - default: XYgGcDIx2X + default: lfBqvYghGm params: type: array items: {} diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index 471d542922c..cb894182c1f 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -301,6 +301,18 @@ pub trait Rpc { &self, address_strings: AddressStrings, ) -> BoxFuture>>; + + #[rpc(name = "stop")] + /// Stop the running zebrad process. + /// + /// # Notes + /// + /// Only works if the network of the running zebrad process is `Regtest`. + /// + /// zcashd reference: [`stop`](https://zcash.github.io/rpc/stop.html) + /// method: post + /// tags: control + fn stop(&self) -> Result<()>; } /// RPC method implementations. @@ -1344,6 +1356,19 @@ where } .boxed() } + + fn stop(&self) -> Result<()> { + if self.network.is_regtest() { + // TODO: Use graceful termination in `stop` RPC (#8850) + std::process::exit(0); + } else { + Err(Error { + code: ErrorCode::MethodNotFound, + message: "stop is only available on regtest networks".to_string(), + data: None, + }) + } + } } /// Returns the best chain tip height of `latest_chain_tip`, diff --git a/zebra-utils/src/bin/openapi-generator/main.rs b/zebra-utils/src/bin/openapi-generator/main.rs index fd0e9fe9b2b..15e5446d855 100644 --- a/zebra-utils/src/bin/openapi-generator/main.rs +++ b/zebra-utils/src/bin/openapi-generator/main.rs @@ -543,6 +543,7 @@ fn get_default_properties(method_name: &str) -> Result default_property(type_, items.clone(), GetInfo::default())?, + "stop" => default_property(type_, items.clone(), ())?, // transaction "sendrawtransaction" => { default_property(type_, items.clone(), SentTransactionHash::default())? From 082cdad1c1f00a622d21c83a84cb4bfa6797fe06 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Mon, 9 Sep 2024 18:51:37 -0300 Subject: [PATCH 4/5] feat(rpc): Add a `generate` rpc method (#8849) * implement `generate` rpc method * update openapi --------- Co-authored-by: Pili Guerra --- openapi.yaml | 102 +++++++++++++----- .../src/methods/get_block_template_rpcs.rs | 77 ++++++++++++- 2 files changed, 150 insertions(+), 29 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index e7793967118..abc70299814 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -28,7 +28,7 @@ paths: default: getinfo id: type: string - default: QWlDS9bxlK + default: dX2SRjFwfc params: type: array items: {} @@ -61,7 +61,7 @@ paths: default: getblockchaininfo id: type: string - default: XSg3wvZykA + default: LoRrjyRM4l params: type: array items: {} @@ -99,7 +99,7 @@ paths: default: getaddressbalance id: type: string - default: GEd1QJWprH + default: WWIvpPiJo0 params: type: array items: {} @@ -147,7 +147,7 @@ paths: default: sendrawtransaction id: type: string - default: nhQi7D6Oru + default: '5tVg2R9ZeI' params: type: array items: {} @@ -196,7 +196,7 @@ paths: default: getblock id: type: string - default: qIEYMzgbJZ + default: vZ5KPOdiue params: type: array items: {} @@ -239,7 +239,7 @@ paths: default: getbestblockhash id: type: string - default: P9UBS8IXXU + default: IifeYgN2ZK params: type: array items: {} @@ -272,7 +272,7 @@ paths: default: getbestblockheightandhash id: type: string - default: gQNhsomx7N + default: tNLKsWqtNW params: type: array items: {} @@ -305,7 +305,7 @@ paths: default: getrawmempool id: type: string - default: c2ScL31PtX + default: IZ6todle9t params: type: array items: {} @@ -343,7 +343,7 @@ paths: default: z_gettreestate id: type: string - default: JQ0mENKbdm + default: SSZAwyUO6t params: type: array items: {} @@ -393,7 +393,7 @@ paths: default: z_getsubtreesbyindex id: type: string - default: bZUCv4t0f4 + default: '3fJMQ0Hfxt' params: type: array items: {} @@ -432,7 +432,7 @@ paths: default: getrawtransaction id: type: string - default: I0FAejAi4r + default: RTdE1YnNxy params: type: array items: {} @@ -480,7 +480,7 @@ paths: default: getaddresstxids id: type: string - default: '3fMzDHOglf' + default: ifahwzVoYe params: type: array items: {} @@ -528,7 +528,7 @@ paths: default: getaddressutxos id: type: string - default: LE2AR8Tr6X + default: PcPdZ7aiKy params: type: array items: {} @@ -571,7 +571,7 @@ paths: default: stop id: type: string - default: PbxxqB0ZpF + default: rWlJLGe7VJ params: type: array items: {} @@ -604,7 +604,7 @@ paths: default: getblockcount id: type: string - default: WO6BAIKSCg + default: f4p3Cb4sDu params: type: array items: {} @@ -642,7 +642,7 @@ paths: default: getblockhash id: type: string - default: vHpKNIQRLF + default: '3QXvqbEWqb' params: type: array items: {} @@ -690,7 +690,7 @@ paths: default: getblocktemplate id: type: string - default: L04jp5F2QW + default: GXKjn81k0D params: type: array items: {} @@ -728,7 +728,7 @@ paths: default: submitblock id: type: string - default: Izn7vhiMaA + default: cwGy92Mwn9 params: type: array items: {} @@ -761,7 +761,7 @@ paths: default: getmininginfo id: type: string - default: SgyuBQbMik + default: '4ZFY9ljh5I' params: type: array items: {} @@ -794,7 +794,7 @@ paths: default: getnetworksolps id: type: string - default: FXg2iH3eaX + default: tJlKGzARjU params: type: array items: {} @@ -827,7 +827,7 @@ paths: default: getnetworkhashps id: type: string - default: '2PWjf8QqfI' + default: '7pUkOt26PB' params: type: array items: {} @@ -860,7 +860,7 @@ paths: default: getpeerinfo id: type: string - default: OE9s5wkP0w + default: JjnSrPKeyS params: type: array items: {} @@ -898,7 +898,7 @@ paths: default: validateaddress id: type: string - default: '6FS4iGA4Ht' + default: pxZQt6VQ9U params: type: array items: {} @@ -936,7 +936,7 @@ paths: default: z_validateaddress id: type: string - default: utp8tN61yU + default: x2R2oRhdZE params: type: array items: {} @@ -974,7 +974,7 @@ paths: default: getblocksubsidy id: type: string - default: dgNZGo7lNa + default: vkhYJS3FH8 params: type: array items: {} @@ -1017,7 +1017,7 @@ paths: default: getdifficulty id: type: string - default: KEJv30D2MI + default: bC6q9c3xYO params: type: array items: {} @@ -1055,7 +1055,7 @@ paths: default: z_listunifiedreceivers id: type: string - default: lfBqvYghGm + default: EQvPXkcJC2 params: type: array items: {} @@ -1071,3 +1071,51 @@ paths: result: type: object default: '{"orchard":"orchard address if any","sapling":"sapling address if any","p2pkh":"p2pkh address if any","p2sh":"p2sh address if any"}' + /generate: + post: + tags: + - generating + description: |- + Mine blocks immediately. Returns the block hashes of the generated blocks. + + **Request body `params` arguments:** + + - `num_blocks` - Number of blocks to be generated. + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + method: + type: string + default: generate + id: + type: string + default: w41FKROii3 + params: + type: array + items: {} + default: '[1]' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + result: + type: object + default: '{}' + '400': + description: Bad request + content: + application/json: + schema: + type: object + properties: + error: + type: string + default: Invalid parameters diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index c8c83e9315a..826f8d3e930 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -19,7 +19,7 @@ use zebra_chain::{ Network, NetworkKind, NetworkUpgrade, POW_AVERAGING_WINDOW, }, primitives, - serialization::ZcashDeserializeInto, + serialization::{ZcashDeserializeInto, ZcashSerialize}, transparent::{ self, EXTRA_ZEBRA_COINBASE_DATA, MAX_COINBASE_DATA_LEN, MAX_COINBASE_HEIGHT_DATA_LEN, }, @@ -47,7 +47,9 @@ use crate::methods::{ // TODO: move the types/* modules directly under get_block_template_rpcs, // and combine any modules with the same names. types::{ - get_block_template::GetBlockTemplate, + get_block_template::{ + proposal::TimeSource, proposal_block_from_template, GetBlockTemplate, + }, get_mining_info, long_poll::LongPollInput, peer_info::PeerInfo, @@ -283,6 +285,22 @@ pub trait GetBlockTemplateRpc { &self, address: String, ) -> BoxFuture>; + + #[rpc(name = "generate")] + /// Mine blocks immediately. Returns the block hashes of the generated blocks. + /// + /// # Parameters + /// + /// - `num_blocks`: (numeric, required, example=1) Number of blocks to be generated. + /// + /// # Notes + /// + /// Only works if the network of the running zebrad process is `Regtest`. + /// + /// zcashd reference: [`generate`](https://zcash.github.io/rpc/generate.html) + /// method: post + /// tags: generating + fn generate(&self, num_blocks: u32) -> BoxFuture>>; } /// RPC method implementations. @@ -1357,6 +1375,61 @@ where } .boxed() } + + fn generate(&self, num_blocks: u32) -> BoxFuture>> { + let rpc: GetBlockTemplateRpcImpl< + Mempool, + State, + Tip, + BlockVerifierRouter, + SyncStatus, + AddressBook, + > = self.clone(); + let network = self.network.clone(); + + async move { + if !network.is_regtest() { + return Err(Error { + code: ErrorCode::ServerError(0), + message: "generate is only supported on regtest".to_string(), + data: None, + }); + } + + let mut block_hashes = Vec::new(); + for _ in 0..num_blocks { + let block_template = rpc.get_block_template(None).await.map_server_error()?; + + let get_block_template::Response::TemplateMode(block_template) = block_template + else { + return Err(Error { + code: ErrorCode::ServerError(0), + message: "error generating block template".to_string(), + data: None, + }); + }; + + let proposal_block = proposal_block_from_template( + &block_template, + TimeSource::CurTime, + NetworkUpgrade::current(&network, Height(block_template.height)), + ) + .map_server_error()?; + let hex_proposal_block = + HexData(proposal_block.zcash_serialize_to_vec().map_server_error()?); + + let _submit = rpc + .submit_block(hex_proposal_block, None) + .await + .map_server_error()?; + + block_hashes.push(GetBlockHash(proposal_block.hash())); + } + + Ok(block_hashes) + } + .boxed() + } } // Put support functions in a submodule, to keep this file small. From 3f94303bb24e23f5ee4c3aff39c65d6d3d813243 Mon Sep 17 00:00:00 2001 From: Alfredo Garcia Date: Wed, 18 Sep 2024 08:05:25 -0300 Subject: [PATCH 5/5] feat(rpc): Add more fields to `getmininginfo` call (#8860) * add additional fields to getmininginfo * update openapi spec * fix zebra-state standalone build * make sure fields are not present when tip is 0 --- openapi.yaml | 58 +++++++++---------- zebra-chain/src/chain_tip/mock.rs | 2 +- .../src/methods/get_block_template_rpcs.rs | 30 ++++++++++ .../types/get_mining_info.rs | 23 +++++++- .../snapshots/get_mining_info@mainnet_10.snap | 2 + .../snapshots/get_mining_info@testnet_10.snap | 2 + zebra-state/src/request.rs | 7 +++ zebra-state/src/response.rs | 6 +- zebra-state/src/service.rs | 43 ++++++++++++++ 9 files changed, 141 insertions(+), 32 deletions(-) diff --git a/openapi.yaml b/openapi.yaml index abc70299814..58a754c9731 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -28,7 +28,7 @@ paths: default: getinfo id: type: string - default: dX2SRjFwfc + default: uf2E54tQkk params: type: array items: {} @@ -61,7 +61,7 @@ paths: default: getblockchaininfo id: type: string - default: LoRrjyRM4l + default: Sbre3vivr8 params: type: array items: {} @@ -99,7 +99,7 @@ paths: default: getaddressbalance id: type: string - default: WWIvpPiJo0 + default: f5qarOBgzK params: type: array items: {} @@ -147,7 +147,7 @@ paths: default: sendrawtransaction id: type: string - default: '5tVg2R9ZeI' + default: IlNHvAcSMS params: type: array items: {} @@ -196,7 +196,7 @@ paths: default: getblock id: type: string - default: vZ5KPOdiue + default: s9678BM3Lc params: type: array items: {} @@ -239,7 +239,7 @@ paths: default: getbestblockhash id: type: string - default: IifeYgN2ZK + default: FGQPJY8Tp8 params: type: array items: {} @@ -272,7 +272,7 @@ paths: default: getbestblockheightandhash id: type: string - default: tNLKsWqtNW + default: c2MfkL7xP9 params: type: array items: {} @@ -305,7 +305,7 @@ paths: default: getrawmempool id: type: string - default: IZ6todle9t + default: BugnNFhJpA params: type: array items: {} @@ -343,7 +343,7 @@ paths: default: z_gettreestate id: type: string - default: SSZAwyUO6t + default: fCUQvR1BVa params: type: array items: {} @@ -393,7 +393,7 @@ paths: default: z_getsubtreesbyindex id: type: string - default: '3fJMQ0Hfxt' + default: TtPnptV6EU params: type: array items: {} @@ -432,7 +432,7 @@ paths: default: getrawtransaction id: type: string - default: RTdE1YnNxy + default: QqYeOGSzje params: type: array items: {} @@ -480,7 +480,7 @@ paths: default: getaddresstxids id: type: string - default: ifahwzVoYe + default: AsWWVyqp8x params: type: array items: {} @@ -528,7 +528,7 @@ paths: default: getaddressutxos id: type: string - default: PcPdZ7aiKy + default: Qscn5dUFgD params: type: array items: {} @@ -571,7 +571,7 @@ paths: default: stop id: type: string - default: rWlJLGe7VJ + default: WuIaPXV5fO params: type: array items: {} @@ -604,7 +604,7 @@ paths: default: getblockcount id: type: string - default: f4p3Cb4sDu + default: '5F9M7Wp0oI' params: type: array items: {} @@ -642,7 +642,7 @@ paths: default: getblockhash id: type: string - default: '3QXvqbEWqb' + default: f7hdgVjctr params: type: array items: {} @@ -690,7 +690,7 @@ paths: default: getblocktemplate id: type: string - default: GXKjn81k0D + default: pq0uXn3YGs params: type: array items: {} @@ -728,7 +728,7 @@ paths: default: submitblock id: type: string - default: cwGy92Mwn9 + default: bs4v4JmVw3 params: type: array items: {} @@ -761,7 +761,7 @@ paths: default: getmininginfo id: type: string - default: '4ZFY9ljh5I' + default: pp5xV6v3pm params: type: array items: {} @@ -776,7 +776,7 @@ paths: properties: result: type: object - default: '{"networksolps":0,"networkhashps":0,"chain":"","testnet":false}' + default: '{"blocks":0,"networksolps":0,"networkhashps":0,"chain":"","testnet":false}' /getnetworksolps: post: tags: @@ -794,7 +794,7 @@ paths: default: getnetworksolps id: type: string - default: tJlKGzARjU + default: '7bU98TeCV6' params: type: array items: {} @@ -827,7 +827,7 @@ paths: default: getnetworkhashps id: type: string - default: '7pUkOt26PB' + default: fskOJeXqjo params: type: array items: {} @@ -860,7 +860,7 @@ paths: default: getpeerinfo id: type: string - default: JjnSrPKeyS + default: jPV8ufjDdt params: type: array items: {} @@ -898,7 +898,7 @@ paths: default: validateaddress id: type: string - default: pxZQt6VQ9U + default: xOyxICseV9 params: type: array items: {} @@ -936,7 +936,7 @@ paths: default: z_validateaddress id: type: string - default: x2R2oRhdZE + default: xa6PoC4uN6 params: type: array items: {} @@ -974,7 +974,7 @@ paths: default: getblocksubsidy id: type: string - default: vkhYJS3FH8 + default: vYEVtnVK9o params: type: array items: {} @@ -1017,7 +1017,7 @@ paths: default: getdifficulty id: type: string - default: bC6q9c3xYO + default: tVzSTZu2sD params: type: array items: {} @@ -1055,7 +1055,7 @@ paths: default: z_listunifiedreceivers id: type: string - default: EQvPXkcJC2 + default: le2NmJBmPt params: type: array items: {} @@ -1093,7 +1093,7 @@ paths: default: generate id: type: string - default: w41FKROii3 + default: vVVOWxHqlN params: type: array items: {} diff --git a/zebra-chain/src/chain_tip/mock.rs b/zebra-chain/src/chain_tip/mock.rs index 46ca5e89e5e..f1fc8fb6e27 100644 --- a/zebra-chain/src/chain_tip/mock.rs +++ b/zebra-chain/src/chain_tip/mock.rs @@ -106,7 +106,7 @@ impl ChainTip for MockChainTip { } fn best_tip_mined_transaction_ids(&self) -> Arc<[transaction::Hash]> { - unreachable!("Method not used in tests"); + Arc::new([]) } fn estimate_distance_to_network_chain_tip( diff --git a/zebra-rpc/src/methods/get_block_template_rpcs.rs b/zebra-rpc/src/methods/get_block_template_rpcs.rs index 826f8d3e930..2d50552cfec 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs.rs @@ -1012,9 +1012,39 @@ where fn get_mining_info(&self) -> BoxFuture> { let network = self.network.clone(); + let mut state = self.state.clone(); + + let chain_tip = self.latest_chain_tip.clone(); + let tip_height = chain_tip.best_tip_height().unwrap_or(Height(0)).0; + + let mut current_block_tx = None; + if tip_height > 0 { + let mined_tx_ids = chain_tip.best_tip_mined_transaction_ids(); + current_block_tx = + (!mined_tx_ids.is_empty()).then(|| mined_tx_ids.len().saturating_sub(1)); + } + let solution_rate_fut = self.get_network_sol_ps(None, None); async move { + // Get the current block size. + let mut current_block_size = None; + if tip_height > 0 { + let request = zebra_state::ReadRequest::TipBlockSize; + let response: zebra_state::ReadResponse = state + .ready() + .and_then(|service| service.call(request)) + .await + .map_server_error()?; + current_block_size = match response { + zebra_state::ReadResponse::TipBlockSize(Some(block_size)) => Some(block_size), + _ => None, + }; + } + Ok(get_mining_info::Response::new( + tip_height, + current_block_size, + current_block_tx, network, solution_rate_fut.await?, )) diff --git a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_mining_info.rs b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_mining_info.rs index a14d4a081e7..21627d509db 100644 --- a/zebra-rpc/src/methods/get_block_template_rpcs/types/get_mining_info.rs +++ b/zebra-rpc/src/methods/get_block_template_rpcs/types/get_mining_info.rs @@ -5,6 +5,18 @@ use zebra_chain::parameters::Network; /// Response to a `getmininginfo` RPC request. #[derive(Debug, Default, PartialEq, Eq, serde::Serialize)] pub struct Response { + /// The current tip height. + #[serde(rename = "blocks")] + tip_height: u32, + + /// The size of the last mined block if any. + #[serde(rename = "currentblocksize", skip_serializing_if = "Option::is_none")] + current_block_size: Option, + + /// The number of transactions in the last mined block if any. + #[serde(rename = "currentblocktx", skip_serializing_if = "Option::is_none")] + current_block_tx: Option, + /// The estimated network solution rate in Sol/s. networksolps: u64, @@ -20,8 +32,17 @@ pub struct Response { impl Response { /// Creates a new `getmininginfo` response - pub fn new(network: Network, networksolps: u64) -> Self { + pub fn new( + tip_height: u32, + current_block_size: Option, + current_block_tx: Option, + network: Network, + networksolps: u64, + ) -> Self { Self { + tip_height, + current_block_size, + current_block_tx, networksolps, networkhashps: networksolps, chain: network.bip70_network_name(), diff --git a/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@mainnet_10.snap b/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@mainnet_10.snap index 67ffde393c4..de309513443 100644 --- a/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@mainnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@mainnet_10.snap @@ -3,6 +3,8 @@ source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs expression: get_mining_info --- { + "blocks": 1687104, + "currentblocksize": 1617, "networksolps": 2, "networkhashps": 2, "chain": "main", diff --git a/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@testnet_10.snap b/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@testnet_10.snap index fc728a8540f..2051e6913ce 100644 --- a/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@testnet_10.snap +++ b/zebra-rpc/src/methods/tests/snapshot/snapshots/get_mining_info@testnet_10.snap @@ -3,6 +3,8 @@ source: zebra-rpc/src/methods/tests/snapshot/get_block_template_rpcs.rs expression: get_mining_info --- { + "blocks": 1842420, + "currentblocksize": 1618, "networksolps": 0, "networkhashps": 0, "chain": "test", diff --git a/zebra-state/src/request.rs b/zebra-state/src/request.rs index 28740a336bb..1863c56b2ed 100644 --- a/zebra-state/src/request.rs +++ b/zebra-state/src/request.rs @@ -1063,6 +1063,11 @@ pub enum ReadRequest { /// Returns [`ReadResponse::ValidBlockProposal`] when successful, or an error if /// the block fails contextual validation. CheckBlockProposalValidity(SemanticallyVerifiedBlock), + + #[cfg(feature = "getblocktemplate-rpcs")] + /// Returns [`ReadResponse::TipBlockSize(usize)`](ReadResponse::TipBlockSize) + /// with the current best chain tip block size in bytes. + TipBlockSize, } impl ReadRequest { @@ -1098,6 +1103,8 @@ impl ReadRequest { ReadRequest::SolutionRate { .. } => "solution_rate", #[cfg(feature = "getblocktemplate-rpcs")] ReadRequest::CheckBlockProposalValidity(_) => "check_block_proposal_validity", + #[cfg(feature = "getblocktemplate-rpcs")] + ReadRequest::TipBlockSize => "tip_block_size", } } diff --git a/zebra-state/src/response.rs b/zebra-state/src/response.rs index 22e610838de..77c252b0c75 100644 --- a/zebra-state/src/response.rs +++ b/zebra-state/src/response.rs @@ -229,6 +229,10 @@ pub enum ReadResponse { #[cfg(feature = "getblocktemplate-rpcs")] /// Response to [`ReadRequest::CheckBlockProposalValidity`] ValidBlockProposal, + + #[cfg(feature = "getblocktemplate-rpcs")] + /// Response to [`ReadRequest::TipBlockSize`] + TipBlockSize(Option), } /// A structure with the information needed from the state to build a `getblocktemplate` RPC response. @@ -315,7 +319,7 @@ impl TryFrom for Response { ReadResponse::ValidBlockProposal => Ok(Response::ValidBlockProposal), #[cfg(feature = "getblocktemplate-rpcs")] - ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) => { + ReadResponse::ChainInfo(_) | ReadResponse::SolutionRate(_) | ReadResponse::TipBlockSize(_) => { Err("there is no corresponding Response for this ReadResponse") } } diff --git a/zebra-state/src/service.rs b/zebra-state/src/service.rs index 2116ab10470..4f970be89d4 100644 --- a/zebra-state/src/service.rs +++ b/zebra-state/src/service.rs @@ -39,6 +39,9 @@ use zebra_chain::{ subtree::NoteCommitmentSubtreeIndex, }; +#[cfg(feature = "getblocktemplate-rpcs")] +use zebra_chain::{block::Height, serialization::ZcashSerialize}; + use crate::{ constants::{ MAX_FIND_BLOCK_HASHES_RESULTS, MAX_FIND_BLOCK_HEADERS_RESULTS_FOR_ZEBRA, @@ -1905,6 +1908,46 @@ impl Service for ReadStateService { }) .wait_for_panics() } + + #[cfg(feature = "getblocktemplate-rpcs")] + ReadRequest::TipBlockSize => { + let state = self.clone(); + + tokio::task::spawn_blocking(move || { + span.in_scope(move || { + // Get the best chain tip height. + let tip_height = state + .non_finalized_state_receiver + .with_watch_data(|non_finalized_state| { + read::tip_height(non_finalized_state.best_chain(), &state.db) + }) + .unwrap_or(Height(0)); + + // Get the block at the best chain tip height. + let block = state.non_finalized_state_receiver.with_watch_data( + |non_finalized_state| { + read::block( + non_finalized_state.best_chain(), + &state.db, + tip_height.into(), + ) + }, + ); + + // The work is done in the future. + timer.finish(module_path!(), line!(), "ReadRequest::TipBlockSize"); + + // Respond with the length of the obtained block if any. + match block { + Some(b) => Ok(ReadResponse::TipBlockSize(Some( + b.zcash_serialize_to_vec()?.len(), + ))), + None => Ok(ReadResponse::TipBlockSize(None)), + } + }) + }) + .wait_for_panics() + } } } }