Skip to content

Commit

Permalink
Add ProviderConfig for auth
Browse files Browse the repository at this point in the history
  • Loading branch information
hmzakhalid committed Nov 29, 2024
1 parent d86468f commit e720c8a
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 89 deletions.
2 changes: 1 addition & 1 deletion packages/ciphernode/config/src/app_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
9 changes: 5 additions & 4 deletions packages/ciphernode/enclave_node/src/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
Expand Down
5 changes: 3 additions & 2 deletions packages/ciphernode/enclave_node/src/ciphernode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down
6 changes: 3 additions & 3 deletions packages/ciphernode/evm/src/ciphernode_registry_sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -102,7 +102,7 @@ pub struct CiphernodeRegistrySolReader;
impl CiphernodeRegistrySolReader {
pub async fn attach(
bus: &Addr<EventBus>,
provider: &WithChainId<ReadonlyProvider>,
provider: &WithChainId<ReadonlyProvider, BoxTransport>,
contract_address: &str,
repository: &Repository<EvmEventReaderState>,
start_block: Option<u64>,
Expand All @@ -128,7 +128,7 @@ pub struct CiphernodeRegistrySol;
impl CiphernodeRegistrySol {
pub async fn attach(
bus: &Addr<EventBus>,
provider: &WithChainId<ReadonlyProvider>,
provider: &WithChainId<ReadonlyProvider, BoxTransport>,
contract_address: &str,
repository: &Repository<EvmEventReaderState>,
start_block: Option<u64>,
Expand Down
7 changes: 4 additions & 3 deletions packages/ciphernode/evm/src/enclave_sol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -13,8 +14,8 @@ pub struct EnclaveSol;
impl EnclaveSol {
pub async fn attach(
bus: &Addr<EventBus>,
read_provider: &WithChainId<ReadonlyProvider>,
write_provider: &WithChainId<SignerProvider>,
read_provider: &WithChainId<ReadonlyProvider, BoxTransport>,
write_provider: &WithChainId<SignerProvider<RpcWSClient>, RpcWSClient>,
contract_address: &str,
repository: &Repository<EvmEventReaderState>,
start_block: Option<u64>,
Expand Down
11 changes: 5 additions & 6 deletions packages/ciphernode/evm/src/enclave_sol_writer.rs
Original file line number Diff line number Diff line change
@@ -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};
Expand All @@ -21,15 +20,15 @@ sol!(

/// Consumes events from the event bus and calls EVM methods on the Enclave.sol contract
pub struct EnclaveSolWriter {
provider: WithChainId<SignerProvider>,
provider: WithChainId<SignerProvider<RpcWSClient>, RpcWSClient>,
contract_address: Address,
bus: Addr<EventBus>,
}

impl EnclaveSolWriter {
pub fn new(
bus: &Addr<EventBus>,
provider: &WithChainId<SignerProvider>,
provider: &WithChainId<SignerProvider<RpcWSClient>, RpcWSClient>,
contract_address: Address,
) -> Result<Self> {
Ok(Self {
Expand All @@ -41,7 +40,7 @@ impl EnclaveSolWriter {

pub async fn attach(
bus: &Addr<EventBus>,
provider: &WithChainId<SignerProvider>,
provider: &WithChainId<SignerProvider<RpcWSClient>, RpcWSClient>,
contract_address: &str,
) -> Result<Addr<EnclaveSolWriter>> {
let addr = EnclaveSolWriter::new(bus, provider, contract_address.parse()?)?.start();
Expand Down Expand Up @@ -108,7 +107,7 @@ impl Handler<Shutdown> for EnclaveSolWriter {
}

async fn publish_plaintext_output(
provider: WithChainId<SignerProvider>,
provider: WithChainId<SignerProvider<RpcWSClient>, RpcWSClient>,
contract_address: Address,
e3_id: E3id,
decrypted_output: Vec<u8>,
Expand Down
186 changes: 123 additions & 63 deletions packages/ciphernode/evm/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<P, T = BoxTransport>
where
P: Provider<T>,
T: Transport + Clone,
{
provider: Arc<P>,
chain_id: u64,
_t: PhantomData<T>,
}

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

pub fn get_provider(&self) -> Arc<P> {
self.provider.clone()
}

pub fn get_chain_id(&self) -> u64 {
self.chain_id
}
}

#[derive(Clone)]
pub enum RpcAuth {
None,
Expand Down Expand Up @@ -181,44 +143,142 @@ impl From<RpcAuth> for ConfigRpcAuth {
}
}

pub type ReadonlyProvider = RootProvider<BoxTransport>;

pub async fn create_readonly_provider(
rpc_url: &str,
) -> Result<WithChainId<ReadonlyProvider, BoxTransport>> {
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<P, T>
where
P: Provider<T>,
T: Transport + Clone,
{
provider: Arc<P>,
chain_id: u64,
_t: PhantomData<T>,
}

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

pub fn get_provider(&self) -> Arc<P> {
self.provider.clone()
}

pub fn get_chain_id(&self) -> u64 {
self.chain_id
}
}

pub type RpcWSClient = PubSubFrontend;
pub type RpcHttpClient = Http<Client>;
pub type SignerProvider<T> = FillProvider<
JoinFill<
JoinFill<
Identity,
JoinFill<GasFiller, JoinFill<BlobGasFiller, JoinFill<NonceFiller, ChainIdFiller>>>,
>,
WalletFiller<EthereumWallet>,
>,
RootProvider<BoxTransport>,
BoxTransport,
RootProvider<T>,
T,
Ethereum,
>;

pub async fn create_provider_with_signer(
rpc_url: &str,
signer: &Arc<PrivateKeySigner>,
) -> Result<WithChainId<SignerProvider, BoxTransport>> {
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<BoxTransport>;


#[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<RootProvider<BoxTransport>> {
Ok(ProviderBuilder::new()
.on_ws(self.create_ws_connect())
.await?
.boxed())
}

async fn create_http_provider(&self) -> Result<RootProvider<BoxTransport>> {
Ok(ProviderBuilder::new()
.on_client(self.create_http_client()?)
.boxed())
}


pub async fn create_readonly_provider(&self) -> Result<WithChainId<ReadonlyProvider, BoxTransport>> {
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<PrivateKeySigner>,
) -> Result<WithChainId<SignerProvider<RpcWSClient>, 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<PrivateKeySigner>,
) -> Result<WithChainId<SignerProvider<RpcHttpClient>, 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<RpcClient<Http<Client>>> {
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<Arc<PrivateKeySigner>> {
Expand Down
Loading

0 comments on commit e720c8a

Please sign in to comment.