diff --git a/zebra-rpc/src/methods.rs b/zebra-rpc/src/methods.rs index e34e1ba3c..c5bc253c1 100644 --- a/zebra-rpc/src/methods.rs +++ b/zebra-rpc/src/methods.rs @@ -96,7 +96,7 @@ pub trait Rpc { /// /// zcashd reference: [`getbestblockhash`](https://zcash.github.io/rpc/getbestblockhash.html) #[rpc(name = "getbestblockhash")] - fn get_best_block_hash(&self) -> BoxFuture>; + fn get_best_block_hash(&self) -> Result; /// Returns all transaction ids in the memory pool, as a JSON array. /// @@ -126,7 +126,6 @@ where state: State, /// Allows efficient access to the best tip of the blockchain. - #[allow(dead_code)] latest_chain_tip: Tip, /// The configured network for this RPC service. @@ -282,32 +281,15 @@ where .boxed() } - fn get_best_block_hash(&self) -> BoxFuture> { - let mut state = self.state.clone(); - - async move { - let request = zebra_state::Request::Tip; - let response = state - .ready() - .and_then(|service| service.call(request)) - .await - .map_err(|error| Error { - code: ErrorCode::ServerError(0), - message: error.to_string(), - data: None, - })?; - - match response { - zebra_state::Response::Tip(Some((_height, hash))) => Ok(GetBestBlockHash(hash)), - zebra_state::Response::Tip(None) => Err(Error { - code: ErrorCode::ServerError(0), - message: "No blocks in state".to_string(), - data: None, - }), - _ => unreachable!("unmatched response to a tip request"), - } - } - .boxed() + fn get_best_block_hash(&self) -> Result { + self.latest_chain_tip + .best_tip_hash() + .map(GetBestBlockHash) + .ok_or(Error { + code: ErrorCode::ServerError(0), + message: "No blocks in state".to_string(), + data: None, + }) } fn get_raw_mempool(&self) -> BoxFuture>> { diff --git a/zebra-rpc/src/methods/tests/vectors.rs b/zebra-rpc/src/methods/tests/vectors.rs index d75ed6e19..17df18722 100644 --- a/zebra-rpc/src/methods/tests/vectors.rs +++ b/zebra-rpc/src/methods/tests/vectors.rs @@ -5,9 +5,7 @@ use std::sync::Arc; use tower::buffer::Buffer; use zebra_chain::{ - block::Block, - chain_tip::NoChainTip, - parameters::Network::{self, *}, + block::Block, chain_tip::NoChainTip, parameters::Network::*, serialization::ZcashDeserializeInto, }; use zebra_network::constants::USER_AGENT; @@ -61,14 +59,15 @@ async fn rpc_getblock() { let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); // Create a populated state service - let state = zebra_state::populated_state(blocks.clone(), Network::Mainnet).await; + let (_state, read_state, latest_chain_tip, _chain_tip_change) = + zebra_state::populated_state(blocks.clone(), Mainnet).await; // Init RPC let rpc = RpcImpl::new( "RPC test", Buffer::new(mempool.clone(), 1), - state, - NoChainTip, + read_state, + latest_chain_tip, Mainnet, ); @@ -131,21 +130,21 @@ async fn rpc_getbestblockhash() { // Get a mempool handle let mut mempool: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests(); // Create a populated state service, the tip will be in `NUMBER_OF_BLOCKS`. - let state = zebra_state::populated_state(blocks.clone(), Network::Mainnet).await; + let (_state, read_state, latest_chain_tip, _chain_tip_change) = + zebra_state::populated_state(blocks.clone(), Mainnet).await; // Init RPC let rpc = RpcImpl::new( "RPC test", Buffer::new(mempool.clone(), 1), - state, - NoChainTip, + read_state, + latest_chain_tip, Mainnet, ); // Get the tip hash using RPC method `get_best_block_hash` let get_best_block_hash = rpc .get_best_block_hash() - .await .expect("We should have a GetBestBlockHash struct"); let response_hash = get_best_block_hash.0; diff --git a/zebra-state/src/service.rs b/zebra-state/src/service.rs index ccfe64e36..956d6300c 100644 --- a/zebra-state/src/service.rs +++ b/zebra-state/src/service.rs @@ -859,12 +859,6 @@ impl Service for ReadStateService { .boxed() } - // Used by get_best_block_hash & get_blockchain_info (#3143) RPCs. - // - // These RPC methods could use the ChainTip struct instead, - // if that's easier or more consistent. - Request::Tip => unimplemented!("ReadStateService doesn't Tip yet"), - // TODO: implement for lightwalletd as part of these tickets // get_raw_transaction (#3145) @@ -885,6 +879,9 @@ impl Service for ReadStateService { // Out of Scope // TODO: delete when splitting the Request enum + // Use ChainTip instead. + Request::Tip => unreachable!("ReadStateService doesn't need to Tip"), + // These requests don't need better performance at the moment. Request::FindBlockHashes { known_blocks: _, diff --git a/zebra-state/src/service/arbitrary.rs b/zebra-state/src/service/arbitrary.rs index 98b95b407..eeb2b0920 100644 --- a/zebra-state/src/service/arbitrary.rs +++ b/zebra-state/src/service/arbitrary.rs @@ -20,7 +20,9 @@ use zebra_chain::{ }; use crate::{ - arbitrary::Prepare, init_test, service::check, BoxError, PreparedBlock, Request, Response, + arbitrary::Prepare, + service::{check, ReadStateService, StateService}, + BoxError, ChainTipChange, Config, LatestChainTip, PreparedBlock, Request, Response, }; pub use zebra_chain::block::arbitrary::MAX_PARTIAL_CHAIN_BLOCKS; @@ -166,16 +168,27 @@ impl Strategy for PreparedChain { } } -/// Initialize a state service with blocks. +/// Initialize a state service with blocks, and return: +/// - a read-write [`StateService`] +/// - a read-only [`ReadStateService`] +/// - a [`LatestChainTip`] +/// - a [`ChainTipChange`] tracker pub async fn populated_state( blocks: impl IntoIterator>, network: Network, -) -> Buffer, Request> { +) -> ( + Buffer, Request>, + ReadStateService, + LatestChainTip, + ChainTipChange, +) { let requests = blocks .into_iter() .map(|block| Request::CommitFinalizedBlock(block.into())); - let mut state = init_test(network); + let (state, read_state, latest_chain_tip, chain_tip_change) = + StateService::new(Config::ephemeral(), network); + let mut state = Buffer::new(BoxService::new(state), 1); let mut responses = FuturesUnordered::new(); @@ -188,5 +201,5 @@ pub async fn populated_state( rsp.expect("blocks should commit just fine"); } - state + (state, read_state, latest_chain_tip, chain_tip_change) } diff --git a/zebra-state/src/service/tests.rs b/zebra-state/src/service/tests.rs index 22898fa0c..1893cd1f2 100644 --- a/zebra-state/src/service/tests.rs +++ b/zebra-state/src/service/tests.rs @@ -196,7 +196,7 @@ async fn test_populated_state_responds_correctly( #[tokio::main] async fn populate_and_check(blocks: Vec>) -> Result<()> { - let state = populated_state(blocks, Network::Mainnet).await; + let (state, _, _, _) = populated_state(blocks, Network::Mainnet).await; test_populated_state_responds_correctly(state).await?; Ok(()) }