2a. refactor(rpc): Add the ChainTip and Network to RpcImpl (#3863)
* Add the ChainTip and Network to RpcImpl * Add the new RpcImpl fields to the tests * Simplify RPC version field using generics * Temporarily allow unused struct fields
This commit is contained in:
parent
5c62dd62cd
commit
641f488915
|
@ -14,6 +14,8 @@ use tower::{buffer::Buffer, Service, ServiceExt};
|
|||
|
||||
use zebra_chain::{
|
||||
block::{self, SerializedBlock},
|
||||
chain_tip::ChainTip,
|
||||
parameters::Network,
|
||||
serialization::{SerializationError, ZcashDeserialize},
|
||||
transaction::{self, Transaction},
|
||||
};
|
||||
|
@ -104,7 +106,7 @@ pub trait Rpc {
|
|||
}
|
||||
|
||||
/// RPC method implementations.
|
||||
pub struct RpcImpl<Mempool, State>
|
||||
pub struct RpcImpl<Mempool, State, Tip>
|
||||
where
|
||||
Mempool: Service<mempool::Request, Response = mempool::Response, Error = BoxError>,
|
||||
State: Service<
|
||||
|
@ -112,16 +114,27 @@ where
|
|||
Response = zebra_state::Response,
|
||||
Error = zebra_state::BoxError,
|
||||
>,
|
||||
Tip: ChainTip,
|
||||
{
|
||||
/// Zebra's application version.
|
||||
app_version: String,
|
||||
|
||||
/// A handle to the mempool service.
|
||||
mempool: Buffer<Mempool, mempool::Request>,
|
||||
|
||||
/// A handle to the state service.
|
||||
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.
|
||||
#[allow(dead_code)]
|
||||
network: Network,
|
||||
}
|
||||
|
||||
impl<Mempool, State> RpcImpl<Mempool, State>
|
||||
impl<Mempool, State, Tip> RpcImpl<Mempool, State, Tip>
|
||||
where
|
||||
Mempool: Service<mempool::Request, Response = mempool::Response, Error = BoxError>,
|
||||
State: Service<
|
||||
|
@ -129,22 +142,30 @@ where
|
|||
Response = zebra_state::Response,
|
||||
Error = zebra_state::BoxError,
|
||||
>,
|
||||
Tip: ChainTip + Send + Sync,
|
||||
{
|
||||
/// Create a new instance of the RPC handler.
|
||||
pub fn new(
|
||||
app_version: String,
|
||||
pub fn new<Version>(
|
||||
app_version: Version,
|
||||
mempool: Buffer<Mempool, mempool::Request>,
|
||||
state: State,
|
||||
) -> Self {
|
||||
latest_chain_tip: Tip,
|
||||
network: Network,
|
||||
) -> Self
|
||||
where
|
||||
Version: ToString,
|
||||
{
|
||||
RpcImpl {
|
||||
app_version,
|
||||
app_version: app_version.to_string(),
|
||||
mempool,
|
||||
state,
|
||||
latest_chain_tip,
|
||||
network,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<Mempool, State> Rpc for RpcImpl<Mempool, State>
|
||||
impl<Mempool, State, Tip> Rpc for RpcImpl<Mempool, State, Tip>
|
||||
where
|
||||
Mempool:
|
||||
tower::Service<mempool::Request, Response = mempool::Response, Error = BoxError> + 'static,
|
||||
|
@ -158,6 +179,7 @@ where
|
|||
+ Sync
|
||||
+ 'static,
|
||||
State::Future: Send,
|
||||
Tip: ChainTip + Send + Sync + 'static,
|
||||
{
|
||||
fn get_info(&self) -> Result<GetInfo> {
|
||||
let response = GetInfo {
|
||||
|
@ -170,6 +192,8 @@ where
|
|||
|
||||
fn get_blockchain_info(&self) -> Result<GetBlockChainInfo> {
|
||||
// TODO: dummy output data, fix in the context of #3143
|
||||
// use self.latest_chain_tip.estimate_network_chain_tip_height()
|
||||
// to estimate the current block height on the network
|
||||
let response = GetBlockChainInfo {
|
||||
chain: "TODO: main".to_string(),
|
||||
};
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
//! Randomised property tests for RPC methods.
|
||||
|
||||
use std::collections::HashSet;
|
||||
|
||||
use hex::ToHex;
|
||||
|
@ -7,6 +9,8 @@ use thiserror::Error;
|
|||
use tower::buffer::Buffer;
|
||||
|
||||
use zebra_chain::{
|
||||
chain_tip::NoChainTip,
|
||||
parameters::Network::*,
|
||||
serialization::{ZcashDeserialize, ZcashSerialize},
|
||||
transaction::{Transaction, UnminedTx, UnminedTxId},
|
||||
};
|
||||
|
@ -27,9 +31,11 @@ proptest! {
|
|||
let mut mempool = MockService::build().for_prop_tests();
|
||||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
let hash = SentTransactionHash(transaction.hash());
|
||||
|
||||
|
@ -73,9 +79,11 @@ proptest! {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let transaction_bytes = transaction
|
||||
|
@ -124,9 +132,11 @@ proptest! {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let transaction_bytes = transaction
|
||||
|
@ -183,9 +193,11 @@ proptest! {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let send_task = tokio::spawn(rpc.send_raw_transaction(non_hex_string));
|
||||
|
@ -231,9 +243,11 @@ proptest! {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let send_task = tokio::spawn(rpc.send_raw_transaction(hex::encode(random_bytes)));
|
||||
|
@ -278,9 +292,11 @@ proptest! {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_prop_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test".to_owned(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let call_task = tokio::spawn(rpc.get_raw_mempool());
|
||||
|
|
|
@ -4,7 +4,12 @@ use std::sync::Arc;
|
|||
|
||||
use tower::buffer::Buffer;
|
||||
|
||||
use zebra_chain::{block::Block, parameters::Network, serialization::ZcashDeserializeInto};
|
||||
use zebra_chain::{
|
||||
block::Block,
|
||||
chain_tip::NoChainTip,
|
||||
parameters::Network::{self, *},
|
||||
serialization::ZcashDeserializeInto,
|
||||
};
|
||||
use zebra_network::constants::USER_AGENT;
|
||||
use zebra_node_services::BoxError;
|
||||
|
||||
|
@ -23,16 +28,18 @@ async fn rpc_getinfo() {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||
|
||||
let rpc = RpcImpl::new(
|
||||
"Zebra version test".to_string(),
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
let get_info = rpc.get_info().expect("We should have a GetInfo struct");
|
||||
|
||||
// make sure there is a `build` field in the response,
|
||||
// and that is equal to the provided string.
|
||||
assert_eq!(get_info.build, "Zebra version test");
|
||||
assert_eq!(get_info.build, "RPC test");
|
||||
|
||||
// make sure there is a `subversion` field,
|
||||
// and that is equal to the Zebra user agent.
|
||||
|
@ -57,11 +64,13 @@ async fn rpc_getblock() {
|
|||
let state = zebra_state::populated_state(blocks.clone(), Network::Mainnet).await;
|
||||
|
||||
// Init RPC
|
||||
let rpc = RpcImpl {
|
||||
app_version: "Zebra version test".to_string(),
|
||||
mempool: Buffer::new(mempool.clone(), 1),
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
state,
|
||||
};
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
// Make calls and check response
|
||||
for (i, block) in blocks.into_iter().enumerate() {
|
||||
|
@ -84,11 +93,13 @@ async fn rpc_getblock_error() {
|
|||
let mut state: MockService<_, _, _, BoxError> = MockService::build().for_unit_tests();
|
||||
|
||||
// Init RPC
|
||||
let rpc = RpcImpl {
|
||||
app_version: "Zebra version test".to_string(),
|
||||
mempool: Buffer::new(mempool.clone(), 1),
|
||||
state: Buffer::new(state.clone(), 1),
|
||||
};
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
Buffer::new(state.clone(), 1),
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
// Make sure we get an error if Zebra can't parse the block height.
|
||||
assert!(rpc
|
||||
|
@ -123,11 +134,13 @@ async fn rpc_getbestblockhash() {
|
|||
let state = zebra_state::populated_state(blocks.clone(), Network::Mainnet).await;
|
||||
|
||||
// Init RPC
|
||||
let rpc = RpcImpl {
|
||||
app_version: "Zebra version test".to_string(),
|
||||
mempool: Buffer::new(mempool.clone(), 1),
|
||||
let rpc = RpcImpl::new(
|
||||
"RPC test",
|
||||
Buffer::new(mempool.clone(), 1),
|
||||
state,
|
||||
};
|
||||
NoChainTip,
|
||||
Mainnet,
|
||||
);
|
||||
|
||||
// Get the tip hash using RPC method `get_best_block_hash`
|
||||
let get_best_block_hash = rpc
|
||||
|
|
|
@ -13,6 +13,7 @@ use tower::{buffer::Buffer, Service};
|
|||
use tracing::*;
|
||||
use tracing_futures::Instrument;
|
||||
|
||||
use zebra_chain::{chain_tip::ChainTip, parameters::Network};
|
||||
use zebra_node_services::{mempool, BoxError};
|
||||
|
||||
use crate::{
|
||||
|
@ -29,13 +30,16 @@ pub struct RpcServer;
|
|||
|
||||
impl RpcServer {
|
||||
/// Start a new RPC server endpoint
|
||||
pub fn spawn<Mempool, State>(
|
||||
pub fn spawn<Version, Mempool, State, Tip>(
|
||||
config: Config,
|
||||
app_version: String,
|
||||
app_version: Version,
|
||||
mempool: Buffer<Mempool, mempool::Request>,
|
||||
state: State,
|
||||
latest_chain_tip: Tip,
|
||||
network: Network,
|
||||
) -> tokio::task::JoinHandle<()>
|
||||
where
|
||||
Version: ToString,
|
||||
Mempool: tower::Service<mempool::Request, Response = mempool::Response, Error = BoxError>
|
||||
+ 'static,
|
||||
Mempool::Future: Send,
|
||||
|
@ -48,12 +52,13 @@ impl RpcServer {
|
|||
+ Sync
|
||||
+ 'static,
|
||||
State::Future: Send,
|
||||
Tip: ChainTip + Send + Sync + 'static,
|
||||
{
|
||||
if let Some(listen_addr) = config.listen_addr {
|
||||
info!("Trying to open RPC endpoint at {}...", listen_addr,);
|
||||
|
||||
// Initialize the rpc methods with the zebra version
|
||||
let rpc_impl = RpcImpl::new(app_version, mempool, state);
|
||||
let rpc_impl = RpcImpl::new(app_version, mempool, state, latest_chain_tip, network);
|
||||
|
||||
// Create handler compatible with V1 and V2 RPC protocols
|
||||
let mut io =
|
||||
|
|
|
@ -162,9 +162,11 @@ impl StartCmd {
|
|||
// Launch RPC server
|
||||
let rpc_task_handle = RpcServer::spawn(
|
||||
config.rpc,
|
||||
app_version().to_string(),
|
||||
app_version(),
|
||||
mempool.clone(),
|
||||
read_only_state_service,
|
||||
latest_chain_tip.clone(),
|
||||
config.network.network,
|
||||
);
|
||||
|
||||
let setup_data = InboundSetupData {
|
||||
|
|
Loading…
Reference in New Issue