mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat(rpc): add EthSubscriptionIdProvider (#1721)
This commit is contained in:
@ -379,6 +379,7 @@ pub struct Builder<B = Identity, L = ()> {
|
||||
settings: Settings,
|
||||
resources: Resources,
|
||||
logger: L,
|
||||
/// Subscription ID provider.
|
||||
id_provider: Arc<dyn IdProvider>,
|
||||
service_builder: tower::ServiceBuilder<B>,
|
||||
}
|
||||
|
||||
@ -58,13 +58,15 @@ use jsonrpsee::{
|
||||
server::{host_filtering::AllowHosts, rpc_module::Methods},
|
||||
Error as RpcError,
|
||||
},
|
||||
server::{Server, ServerHandle},
|
||||
server::{IdProvider, Server, ServerHandle},
|
||||
RpcModule,
|
||||
};
|
||||
use reth_ipc::server::IpcServer;
|
||||
use reth_network_api::{NetworkInfo, Peers};
|
||||
use reth_provider::{BlockProvider, EvmEnvProvider, HeaderProvider, StateProviderFactory};
|
||||
use reth_rpc::{AdminApi, DebugApi, EthApi, EthFilter, NetApi, TraceApi, Web3Api};
|
||||
use reth_rpc::{
|
||||
AdminApi, DebugApi, EthApi, EthFilter, EthSubscriptionIdProvider, NetApi, TraceApi, Web3Api,
|
||||
};
|
||||
use reth_rpc_api::servers::*;
|
||||
use reth_transaction_pool::TransactionPool;
|
||||
use serde::{Deserialize, Serialize, Serializer};
|
||||
@ -670,11 +672,17 @@ impl RpcServerConfig {
|
||||
pub fn ipc(config: IpcServerBuilder) -> Self {
|
||||
Self::default().with_ipc(config)
|
||||
}
|
||||
|
||||
/// Configures the http server
|
||||
///
|
||||
/// Note: this always configures an [EthSubscriptionIdProvider] [IdProvider] for convenience.
|
||||
/// To set a custom [IdProvider], please use [Self::with_id_provider].
|
||||
pub fn with_http(mut self, config: ServerBuilder) -> Self {
|
||||
self.http_server_config = Some(config.http_only());
|
||||
self.http_server_config =
|
||||
Some(config.http_only().set_id_provider(EthSubscriptionIdProvider::default()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Configure the corsdomains
|
||||
pub fn with_cors(mut self, cors_domain: String) -> Self {
|
||||
self.http_cors_domains = Some(cors_domain);
|
||||
@ -682,8 +690,12 @@ impl RpcServerConfig {
|
||||
}
|
||||
|
||||
/// Configures the ws server
|
||||
///
|
||||
/// Note: this always configures an [EthSubscriptionIdProvider] [IdProvider] for convenience.
|
||||
/// To set a custom [IdProvider], please use [Self::with_id_provider].
|
||||
pub fn with_ws(mut self, config: ServerBuilder) -> Self {
|
||||
self.ws_server_config = Some(config.ws_only());
|
||||
self.ws_server_config =
|
||||
Some(config.ws_only().set_id_provider(EthSubscriptionIdProvider::default()));
|
||||
self
|
||||
}
|
||||
|
||||
@ -704,8 +716,31 @@ impl RpcServerConfig {
|
||||
}
|
||||
|
||||
/// Configures the ipc server
|
||||
///
|
||||
/// Note: this always configures an [EthSubscriptionIdProvider] [IdProvider] for convenience.
|
||||
/// To set a custom [IdProvider], please use [Self::with_id_provider].
|
||||
pub fn with_ipc(mut self, mut config: IpcServerBuilder) -> Self {
|
||||
self.ipc_server_config = Some(config);
|
||||
self.ipc_server_config = Some(config.set_id_provider(EthSubscriptionIdProvider::default()));
|
||||
self
|
||||
}
|
||||
|
||||
/// Sets a custom [IdProvider] for all configured transports.
|
||||
///
|
||||
/// By default all transports use [EthSubscriptionIdProvider]
|
||||
pub fn with_id_provider<I>(mut self, id_provider: I) -> Self
|
||||
where
|
||||
I: IdProvider + Clone + 'static,
|
||||
{
|
||||
if let Some(http) = self.http_server_config {
|
||||
self.http_server_config = Some(http.set_id_provider(id_provider.clone()));
|
||||
}
|
||||
if let Some(ws) = self.ws_server_config {
|
||||
self.ws_server_config = Some(ws.set_id_provider(id_provider.clone()));
|
||||
}
|
||||
if let Some(ipc) = self.ipc_server_config {
|
||||
self.ipc_server_config = Some(ipc.set_id_provider(id_provider));
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
|
||||
67
crates/rpc/rpc/src/eth/id_provider.rs
Normal file
67
crates/rpc/rpc/src/eth/id_provider.rs
Normal file
@ -0,0 +1,67 @@
|
||||
use jsonrpsee::types::SubscriptionId;
|
||||
use std::fmt::Write;
|
||||
|
||||
/// An [IdProvider](jsonrpsee::core::traits::IdProvider) for ethereum subscription ids.
|
||||
///
|
||||
/// Returns new hex-string [QUANTITY](https://ethereum.org/en/developers/docs/apis/json-rpc/#quantities-encoding) ids
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
#[non_exhaustive]
|
||||
pub struct EthSubscriptionIdProvider;
|
||||
|
||||
impl jsonrpsee::core::traits::IdProvider for EthSubscriptionIdProvider {
|
||||
fn next_id(&self) -> SubscriptionId<'static> {
|
||||
to_quantity(rand::random::<u128>())
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a hex quantity string for the given value
|
||||
///
|
||||
/// Strips all leading zeros, `0` is returned as `0x0`
|
||||
#[inline(always)]
|
||||
fn to_quantity(val: u128) -> SubscriptionId<'static> {
|
||||
let bytes = val.to_be_bytes();
|
||||
let b = bytes.as_slice();
|
||||
let non_zero = b.iter().take_while(|b| **b == 0).count();
|
||||
let b = &b[non_zero..];
|
||||
if b.is_empty() {
|
||||
return SubscriptionId::Str("0x0".into())
|
||||
}
|
||||
|
||||
let mut id = String::with_capacity(2 * b.len() + 2);
|
||||
id.push_str("0x");
|
||||
let first_byte = b[0];
|
||||
write!(id, "{first_byte:x}").unwrap();
|
||||
|
||||
for byte in &b[1..] {
|
||||
write!(id, "{byte:02x}").unwrap();
|
||||
}
|
||||
id.into()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use reth_primitives::U128;
|
||||
|
||||
#[test]
|
||||
fn test_id_provider_quantity() {
|
||||
let id = to_quantity(0);
|
||||
assert_eq!(id, SubscriptionId::Str("0x0".into()));
|
||||
let id = to_quantity(1);
|
||||
assert_eq!(id, SubscriptionId::Str("0x1".into()));
|
||||
|
||||
for _ in 0..1000 {
|
||||
let val = rand::random::<u128>();
|
||||
let id = to_quantity(val);
|
||||
match id {
|
||||
SubscriptionId::Str(id) => {
|
||||
let from_hex: U128 = id.parse().unwrap();
|
||||
assert_eq!(from_hex, U128::from(val));
|
||||
}
|
||||
SubscriptionId::Num(_) => {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,9 +4,11 @@ mod api;
|
||||
pub mod cache;
|
||||
pub(crate) mod error;
|
||||
mod filter;
|
||||
mod id_provider;
|
||||
mod pubsub;
|
||||
mod signer;
|
||||
|
||||
pub use api::{EthApi, EthApiSpec};
|
||||
pub use filter::EthFilter;
|
||||
pub use id_provider::EthSubscriptionIdProvider;
|
||||
pub use pubsub::EthPubSub;
|
||||
|
||||
@ -23,7 +23,7 @@ mod web3;
|
||||
pub use admin::AdminApi;
|
||||
pub use debug::DebugApi;
|
||||
pub use engine::EngineApi;
|
||||
pub use eth::{EthApi, EthApiSpec, EthFilter, EthPubSub};
|
||||
pub use eth::{EthApi, EthApiSpec, EthFilter, EthPubSub, EthSubscriptionIdProvider};
|
||||
pub use layers::{AuthLayer, AuthValidator, JwtAuthValidator, JwtError, JwtSecret};
|
||||
pub use net::NetApi;
|
||||
pub use trace::TraceApi;
|
||||
|
||||
Reference in New Issue
Block a user