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