From e720c8a70ad6ad456c103013f66384270a3f5221 Mon Sep 17 00:00:00 2001 From: Hamza Khalid Date: Fri, 29 Nov 2024 11:46:53 +0500 Subject: [PATCH] Add ProviderConfig for auth --- packages/ciphernode/config/src/app_config.rs | 2 +- .../ciphernode/enclave_node/src/aggregator.rs | 9 +- .../ciphernode/enclave_node/src/ciphernode.rs | 5 +- .../evm/src/ciphernode_registry_sol.rs | 6 +- packages/ciphernode/evm/src/enclave_sol.rs | 7 +- .../ciphernode/evm/src/enclave_sol_writer.rs | 11 +- packages/ciphernode/evm/src/helpers.rs | 186 ++++++++++++------ .../ciphernode/evm/src/registry_filter_sol.rs | 13 +- 8 files changed, 150 insertions(+), 89 deletions(-) diff --git a/packages/ciphernode/config/src/app_config.rs b/packages/ciphernode/config/src/app_config.rs index b3c33527..de225b04 100644 --- a/packages/ciphernode/config/src/app_config.rs +++ b/packages/ciphernode/config/src/app_config.rs @@ -45,7 +45,7 @@ pub struct ContractAddresses { pub filter_registry: Contract, } -#[derive(Debug, Deserialize, Serialize, PartialEq)] +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] #[serde(tag = "type", content = "credentials")] pub enum RpcAuth { None, diff --git a/packages/ciphernode/enclave_node/src/aggregator.rs b/packages/ciphernode/enclave_node/src/aggregator.rs index e466b53b..a90ce4f5 100644 --- a/packages/ciphernode/enclave_node/src/aggregator.rs +++ b/packages/ciphernode/enclave_node/src/aggregator.rs @@ -5,7 +5,7 @@ use config::AppConfig; use enclave_core::EventBus; use evm::{ helpers::{ - create_provider_with_signer, create_readonly_provider, get_signer_from_repository, RPC, + get_signer_from_repository, RPC, ProviderConfig }, CiphernodeRegistrySol, EnclaveSol, RegistryFilterSol, }; @@ -46,9 +46,10 @@ pub async fn setup_aggregator( { let rpc_url = RPC::from_url(&chain.rpc_url).map_err(|e| { anyhow::anyhow!("Failed to parse RPC URL for chain {}: {}", chain.name, e) - })?; - let read_provider = create_readonly_provider(&rpc_url.as_ws_url()).await?; - let write_provider = create_provider_with_signer(&rpc_url.as_http_url(), &signer).await?; + })?; + let provider_config = ProviderConfig::new(rpc_url, chain.rpc_auth.clone().into()); + let read_provider = provider_config.create_readonly_provider().await?; + let write_provider = provider_config.create_ws_signer_provider(&signer).await?; EnclaveSol::attach( &bus, diff --git a/packages/ciphernode/enclave_node/src/ciphernode.rs b/packages/ciphernode/enclave_node/src/ciphernode.rs index bd7d95d6..3edece4c 100644 --- a/packages/ciphernode/enclave_node/src/ciphernode.rs +++ b/packages/ciphernode/enclave_node/src/ciphernode.rs @@ -5,7 +5,7 @@ use cipher::Cipher; use config::AppConfig; use enclave_core::{get_tag, EventBus}; use evm::{ - helpers::{create_readonly_provider, RPC}, + helpers::{RPC, ProviderConfig}, CiphernodeRegistrySol, EnclaveSolReader, }; use logger::SimpleLogger; @@ -47,7 +47,8 @@ pub async fn setup_ciphernode( let rpc_url = RPC::from_url(&chain.rpc_url).map_err(|e| { anyhow::anyhow!("Failed to parse RPC URL for chain {}: {}", chain.name, e) })?; - let read_provider = create_readonly_provider(&rpc_url.as_ws_url()).await?; + let provider_config = ProviderConfig::new(rpc_url, chain.rpc_auth.clone().into()); + let read_provider = provider_config.create_readonly_provider().await?; EnclaveSolReader::attach( &bus, &read_provider, diff --git a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs index d88e6552..5367487e 100644 --- a/packages/ciphernode/evm/src/ciphernode_registry_sol.rs +++ b/packages/ciphernode/evm/src/ciphernode_registry_sol.rs @@ -7,7 +7,7 @@ use actix::{Actor, Addr}; use alloy::{ primitives::{LogData, B256}, sol, - sol_types::SolEvent, + sol_types::SolEvent, transports::BoxTransport, }; use anyhow::Result; use data::Repository; @@ -102,7 +102,7 @@ pub struct CiphernodeRegistrySolReader; impl CiphernodeRegistrySolReader { pub async fn attach( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, contract_address: &str, repository: &Repository, start_block: Option, @@ -128,7 +128,7 @@ pub struct CiphernodeRegistrySol; impl CiphernodeRegistrySol { pub async fn attach( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, contract_address: &str, repository: &Repository, start_block: Option, diff --git a/packages/ciphernode/evm/src/enclave_sol.rs b/packages/ciphernode/evm/src/enclave_sol.rs index ed1f76bc..a766bcde 100644 --- a/packages/ciphernode/evm/src/enclave_sol.rs +++ b/packages/ciphernode/evm/src/enclave_sol.rs @@ -2,9 +2,10 @@ use crate::{ enclave_sol_reader::EnclaveSolReader, enclave_sol_writer::EnclaveSolWriter, event_reader::EvmEventReaderState, - helpers::{ReadonlyProvider, SignerProvider, WithChainId}, + helpers::{ReadonlyProvider, SignerProvider, WithChainId, RpcWSClient}, }; use actix::Addr; +use alloy::transports::BoxTransport; use anyhow::Result; use data::Repository; use enclave_core::EventBus; @@ -13,8 +14,8 @@ pub struct EnclaveSol; impl EnclaveSol { pub async fn attach( bus: &Addr, - read_provider: &WithChainId, - write_provider: &WithChainId, + read_provider: &WithChainId, + write_provider: &WithChainId, RpcWSClient>, contract_address: &str, repository: &Repository, start_block: Option, diff --git a/packages/ciphernode/evm/src/enclave_sol_writer.rs b/packages/ciphernode/evm/src/enclave_sol_writer.rs index 77d53ab7..9e595198 100644 --- a/packages/ciphernode/evm/src/enclave_sol_writer.rs +++ b/packages/ciphernode/evm/src/enclave_sol_writer.rs @@ -1,5 +1,4 @@ -use crate::helpers::SignerProvider; -use crate::helpers::WithChainId; +use crate::helpers::{SignerProvider, WithChainId, RpcWSClient}; use actix::prelude::*; use actix::Addr; use alloy::{primitives::Address, sol}; @@ -21,7 +20,7 @@ sol!( /// Consumes events from the event bus and calls EVM methods on the Enclave.sol contract pub struct EnclaveSolWriter { - provider: WithChainId, + provider: WithChainId, RpcWSClient>, contract_address: Address, bus: Addr, } @@ -29,7 +28,7 @@ pub struct EnclaveSolWriter { impl EnclaveSolWriter { pub fn new( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, RpcWSClient>, contract_address: Address, ) -> Result { Ok(Self { @@ -41,7 +40,7 @@ impl EnclaveSolWriter { pub async fn attach( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, RpcWSClient>, contract_address: &str, ) -> Result> { let addr = EnclaveSolWriter::new(bus, provider, contract_address.parse()?)?.start(); @@ -108,7 +107,7 @@ impl Handler for EnclaveSolWriter { } async fn publish_plaintext_output( - provider: WithChainId, + provider: WithChainId, RpcWSClient>, contract_address: Address, e3_id: E3id, decrypted_output: Vec, diff --git a/packages/ciphernode/evm/src/helpers.rs b/packages/ciphernode/evm/src/helpers.rs index fc844071..3f104b4e 100644 --- a/packages/ciphernode/evm/src/helpers.rs +++ b/packages/ciphernode/evm/src/helpers.rs @@ -86,44 +86,6 @@ impl RPC { } } -/// We need to cache the chainId so we can easily use it in a non-async situation -/// This wrapper just stores the chain_id with the Provider -#[derive(Clone)] -// We have to be generic over T as the transport provider in order to handle different transport -// mechanisms such as the HttpClient etc. -pub struct WithChainId -where - P: Provider, - T: Transport + Clone, -{ - provider: Arc

, - chain_id: u64, - _t: PhantomData, -} - -impl WithChainId -where - P: Provider, - T: Transport + Clone, -{ - pub async fn new(provider: P) -> Result { - let chain_id = provider.get_chain_id().await?; - Ok(Self { - provider: Arc::new(provider), - chain_id, - _t: PhantomData, - }) - } - - pub fn get_provider(&self) -> Arc

{ - self.provider.clone() - } - - pub fn get_chain_id(&self) -> u64 { - self.chain_id - } -} - #[derive(Clone)] pub enum RpcAuth { None, @@ -181,20 +143,48 @@ impl From for ConfigRpcAuth { } } -pub type ReadonlyProvider = RootProvider; -pub async fn create_readonly_provider( - rpc_url: &str, -) -> Result> { - let provider = ProviderBuilder::new() - .on_builtin(rpc_url) - .await - .context("Could not create ReadOnlyProvider")? - .into(); - Ok(WithChainId::new(provider).await?) +/// We need to cache the chainId so we can easily use it in a non-async situation +/// This wrapper just stores the chain_id with the Provider +#[derive(Clone)] +// We have to be generic over T as the transport provider in order to handle different transport +// mechanisms such as the HttpClient etc. +pub struct WithChainId +where + P: Provider, + T: Transport + Clone, +{ + provider: Arc

, + chain_id: u64, + _t: PhantomData, } -pub type SignerProvider = FillProvider< +impl WithChainId +where + P: Provider, + T: Transport + Clone, +{ + pub async fn new(provider: P) -> Result { + let chain_id = provider.get_chain_id().await?; + Ok(Self { + provider: Arc::new(provider), + chain_id, + _t: PhantomData, + }) + } + + pub fn get_provider(&self) -> Arc

{ + self.provider.clone() + } + + pub fn get_chain_id(&self) -> u64 { + self.chain_id + } +} + +pub type RpcWSClient = PubSubFrontend; +pub type RpcHttpClient = Http; +pub type SignerProvider = FillProvider< JoinFill< JoinFill< Identity, @@ -202,23 +192,93 @@ pub type SignerProvider = FillProvider< >, WalletFiller, >, - RootProvider, - BoxTransport, + RootProvider, + T, Ethereum, >; -pub async fn create_provider_with_signer( - rpc_url: &str, - signer: &Arc, -) -> Result> { - let wallet = EthereumWallet::from(signer.clone()); - let provider = ProviderBuilder::new() - .with_recommended_fillers() - .wallet(wallet) - .on_builtin(rpc_url) - .await?; - - Ok(WithChainId::new(provider).await?) +pub type ReadonlyProvider = RootProvider; + + +#[derive(Clone)] +pub struct ProviderConfig { + rpc: RPC, + auth: RpcAuth, +} + +impl ProviderConfig { + pub fn new(rpc: RPC, auth: RpcAuth) -> Self { + Self { rpc, auth } + } + + async fn create_ws_provider(&self) -> Result> { + Ok(ProviderBuilder::new() + .on_ws(self.create_ws_connect()) + .await? + .boxed()) + } + + async fn create_http_provider(&self) -> Result> { + Ok(ProviderBuilder::new() + .on_client(self.create_http_client()?) + .boxed()) + } + + + pub async fn create_readonly_provider(&self) -> Result> { + let provider = if self.rpc.is_websocket() { + self.create_ws_provider().await? + } else { + self.create_http_provider().await? + }; + WithChainId::new(provider).await + } + + pub async fn create_ws_signer_provider( + &self, + signer: &Arc, + ) -> Result, RpcWSClient>> { + let wallet = EthereumWallet::from(signer.clone()); + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(wallet) + .on_ws(self.create_ws_connect()) + .await.context("Failed to create WS signer provider")?; + + WithChainId::new(provider).await + } + + pub async fn create_http_signer_provider( + &self, + signer: &Arc, + ) -> Result, RpcHttpClient>> { + let wallet = EthereumWallet::from(signer.clone()); + let provider = ProviderBuilder::new() + .with_recommended_fillers() + .wallet(wallet) + .on_client(self.create_http_client()?); + WithChainId::new(provider).await + } + + fn create_ws_connect(&self) -> WsConnect { + if let Some(ws_auth) = self.auth.to_ws_auth() { + WsConnect::new(self.rpc.as_ws_url()).with_auth(ws_auth) + } else { + WsConnect::new(self.rpc.as_ws_url()) + } + } + + fn create_http_client(&self) -> Result>> { + let mut headers = HeaderMap::new(); + if let Some(auth_header) = self.auth.to_header_value() { + headers.insert(AUTHORIZATION, auth_header); + } + let client = Client::builder() + .default_headers(headers) + .build()?; + let http = Http::with_client(client, self.rpc.as_http_url().parse()?); + Ok(RpcClient::new(http, false)) + } } pub async fn pull_eth_signer_from_env(var: &str) -> Result> { diff --git a/packages/ciphernode/evm/src/registry_filter_sol.rs b/packages/ciphernode/evm/src/registry_filter_sol.rs index 2c8dedf9..7360e05e 100644 --- a/packages/ciphernode/evm/src/registry_filter_sol.rs +++ b/packages/ciphernode/evm/src/registry_filter_sol.rs @@ -1,10 +1,9 @@ -use crate::helpers::{SignerProvider, WithChainId}; +use crate::helpers::{SignerProvider, WithChainId, RpcWSClient}; use actix::prelude::*; use alloy::{ primitives::{Address, Bytes, U256}, rpc::types::TransactionReceipt, sol, - transports::BoxTransport, }; use anyhow::Result; use enclave_core::{ @@ -20,7 +19,7 @@ sol!( ); pub struct RegistryFilterSolWriter { - provider: WithChainId, + provider: WithChainId, RpcWSClient>, contract_address: Address, bus: Addr, } @@ -28,7 +27,7 @@ pub struct RegistryFilterSolWriter { impl RegistryFilterSolWriter { pub async fn new( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, RpcWSClient>, contract_address: Address, ) -> Result { Ok(Self { @@ -40,7 +39,7 @@ impl RegistryFilterSolWriter { pub async fn attach( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, RpcWSClient>, contract_address: &str, ) -> Result> { let addr = RegistryFilterSolWriter::new(bus, provider, contract_address.parse()?) @@ -107,7 +106,7 @@ impl Handler for RegistryFilterSolWriter { } pub async fn publish_committee( - provider: WithChainId, + provider: WithChainId, RpcWSClient>, contract_address: Address, e3_id: E3id, nodes: OrderedSet, @@ -129,7 +128,7 @@ pub struct RegistryFilterSol; impl RegistryFilterSol { pub async fn attach( bus: &Addr, - provider: &WithChainId, + provider: &WithChainId, RpcWSClient>, contract_address: &str, ) -> Result<()> { RegistryFilterSolWriter::attach(bus, provider, contract_address).await?;