diff --git a/api/bin/chainflip-ingress-egress-tracker/src/main.rs b/api/bin/chainflip-ingress-egress-tracker/src/main.rs index b4830a1c54..584ddb1048 100644 --- a/api/bin/chainflip-ingress-egress-tracker/src/main.rs +++ b/api/bin/chainflip-ingress-egress-tracker/src/main.rs @@ -1,7 +1,7 @@ use chainflip_engine::settings::{HttpBasicAuthEndpoint, WsHttpEndpoints}; use futures::FutureExt; use jsonrpsee::{core::Error, server::ServerBuilder, RpcModule}; -use std::{env, io::Write, net::SocketAddr, path::PathBuf}; +use std::{env, net::SocketAddr}; use tracing::log; use utilities::task_scope; @@ -10,8 +10,6 @@ mod witnessing; #[derive(Clone)] pub struct DepositTrackerSettings { eth_node: WsHttpEndpoints, - // The key shouldn't be necessary, but the current witnesser wants this - eth_key_path: PathBuf, dot_node: WsHttpEndpoints, state_chain_ws_endpoint: String, btc: HttpBasicAuthEndpoint, @@ -83,13 +81,6 @@ async fn start( #[tokio::main] async fn main() -> anyhow::Result<()> { - // Temporary hack: we don't actually use eth key, but the current witnesser is - // expecting a path with a valid key, so we create a temporary dummy key file here: - let mut eth_key_temp_file = tempfile::NamedTempFile::new()?; - eth_key_temp_file - .write_all(b"0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef") - .unwrap(); - let settings = DepositTrackerSettings { eth_node: WsHttpEndpoints { ws_endpoint: env::var("ETH_WS_ENDPOINT") @@ -99,7 +90,6 @@ async fn main() -> anyhow::Result<()> { .unwrap_or("http://localhost:8545".to_string()) .into(), }, - eth_key_path: eth_key_temp_file.path().into(), dot_node: WsHttpEndpoints { ws_endpoint: env::var("DOT_WS_ENDPOINT") .unwrap_or("ws://localhost:9947".to_string()) diff --git a/api/bin/chainflip-ingress-egress-tracker/src/witnessing/eth.rs b/api/bin/chainflip-ingress-egress-tracker/src/witnessing/eth.rs index c1d116c9a6..2b93ac59c0 100644 --- a/api/bin/chainflip-ingress-egress-tracker/src/witnessing/eth.rs +++ b/api/bin/chainflip-ingress-egress-tracker/src/witnessing/eth.rs @@ -4,7 +4,7 @@ use cf_primitives::chains::assets::eth::Asset; use utilities::task_scope; use chainflip_engine::{ - eth::retry_rpc::EthersRetryRpcClient, + eth::{retry_rpc::EthRetryRpcClient, rpc::EthRpcClient}, settings::NodeContainer, state_chain_observer::client::{StateChainClient, StateChainStreamApi}, witness::{ @@ -40,12 +40,7 @@ where let eth_client = { let nodes = NodeContainer { primary: settings.eth_node.clone(), backup: None }; - EthersRetryRpcClient::new( - scope, - settings.eth_key_path, - nodes, - env_params.eth_chain_id.into(), - )? + EthRetryRpcClient::::new(scope, nodes, env_params.eth_chain_id.into())? }; let vaults = epoch_source.vaults().await; diff --git a/engine/src/eth/retry_rpc.rs b/engine/src/eth/retry_rpc.rs index 1fc02a584f..d2b3c14613 100644 --- a/engine/src/eth/retry_rpc.rs +++ b/engine/src/eth/retry_rpc.rs @@ -5,11 +5,11 @@ use ethers::{ types::{transaction::eip2930::AccessList, TransactionReceipt}, }; +use futures_core::Future; use utilities::task_scope::Scope; use crate::{ - common::option_inner, - eth::rpc::EthRpcApi, + eth::rpc::{EthRpcApi, EthSigningRpcApi}, retrier::{Attempt, RequestLog, RetrierClient}, settings::{NodeContainer, WsHttpEndpoints}, witness::common::chain_source::{ChainClient, Header}, @@ -17,7 +17,7 @@ use crate::{ use std::{path::PathBuf, time::Duration}; use super::{ - rpc::{EthRpcClient, ReconnectSubscriptionClient}, + rpc::{EthRpcClient, EthRpcSigningClient, ReconnectSubscriptionClient}, ConscientiousEthWebsocketBlockHeaderStream, }; use crate::eth::rpc::ReconnectSubscribeApi; @@ -26,8 +26,8 @@ use cf_chains::Ethereum; use anyhow::{Context, Result}; #[derive(Clone)] -pub struct EthersRetryRpcClient { - rpc_retry_client: RetrierClient, +pub struct EthRetryRpcClient { + rpc_retry_client: RetrierClient, sub_retry_client: RetrierClient, } @@ -36,29 +36,23 @@ const MAX_CONCURRENT_SUBMISSIONS: u32 = 100; const MAX_BROADCAST_RETRIES: Attempt = 2; -impl EthersRetryRpcClient { - pub fn new( +impl EthRetryRpcClient { + fn from_inner_clients + Send + 'static>( scope: &Scope<'_, anyhow::Error>, - private_key_file: PathBuf, nodes: NodeContainer, expected_chain_id: U256, - ) -> Result { - let f_create_clients = |endpoints: WsHttpEndpoints| { - Result::<_, anyhow::Error>::Ok(( - EthRpcClient::new( - private_key_file.clone(), - endpoints.http_endpoint, - expected_chain_id.as_u64(), - )?, - ReconnectSubscriptionClient::new(endpoints.ws_endpoint, expected_chain_id), - )) - }; - - let (rpc_client, sub_client) = f_create_clients(nodes.primary)?; - let (backup_rpc_client, backup_sub_client) = - option_inner(nodes.backup.map(f_create_clients).transpose()?); - - Ok(Self { + rpc_client: ClientFut, + backup_rpc_client: Option, + ) -> Self { + let sub_client = + ReconnectSubscriptionClient::new(nodes.primary.ws_endpoint, expected_chain_id); + + let backup_sub_client = nodes + .backup + .as_ref() + .map(|ep| ReconnectSubscriptionClient::new(ep.ws_endpoint.clone(), expected_chain_id)); + + Self { rpc_retry_client: RetrierClient::new( scope, "eth_rpc", @@ -75,17 +69,60 @@ impl EthersRetryRpcClient { ETHERS_RPC_TIMEOUT, MAX_CONCURRENT_SUBMISSIONS, ), - }) + } + } +} + +impl EthRetryRpcClient { + pub fn new( + scope: &Scope<'_, anyhow::Error>, + nodes: NodeContainer, + expected_chain_id: U256, + ) -> Result { + let rpc_client = + EthRpcClient::new(nodes.primary.http_endpoint.clone(), expected_chain_id.as_u64())?; + + let backup_rpc_client = nodes + .backup + .as_ref() + .map(|ep| EthRpcClient::new(ep.http_endpoint.clone(), expected_chain_id.as_u64())) + .transpose()?; + + Ok(Self::from_inner_clients(scope, nodes, expected_chain_id, rpc_client, backup_rpc_client)) + } +} + +impl EthRetryRpcClient { + pub fn new( + scope: &Scope<'_, anyhow::Error>, + private_key_file: PathBuf, + nodes: NodeContainer, + expected_chain_id: U256, + ) -> Result { + let rpc_client = EthRpcSigningClient::new( + private_key_file.clone(), + nodes.primary.http_endpoint.clone(), + expected_chain_id.as_u64(), + )?; + + let backup_rpc_client = nodes + .backup + .as_ref() + .map(|ep| { + EthRpcSigningClient::new( + private_key_file.clone(), + ep.http_endpoint.clone(), + expected_chain_id.as_u64(), + ) + }) + .transpose()?; + + Ok(Self::from_inner_clients(scope, nodes, expected_chain_id, rpc_client, backup_rpc_client)) } } #[async_trait::async_trait] pub trait EthersRetryRpcApi: Clone { - async fn broadcast_transaction( - &self, - tx: cf_chains::evm::Transaction, - ) -> anyhow::Result; - async fn get_logs(&self, block_hash: H256, contract_address: H160) -> Vec; async fn chain_id(&self) -> U256; @@ -107,68 +144,15 @@ pub trait EthersRetryRpcApi: Clone { } #[async_trait::async_trait] -impl EthersRetryRpcApi for EthersRetryRpcClient { - /// Estimates gas and then sends the transaction to the network. +pub trait EthersRetrySigningRpcApi: EthersRetryRpcApi { async fn broadcast_transaction( &self, tx: cf_chains::evm::Transaction, - ) -> anyhow::Result { - let log = RequestLog::new("broadcast_transaction".to_string(), Some(format!("{tx:?}"))); - self.rpc_retry_client - .request_with_limit( - Box::pin(move |client| { - let tx = tx.clone(); - #[allow(clippy::redundant_async_block)] - Box::pin(async move { - let mut transaction_request = Eip1559TransactionRequest { - to: Some(NameOrAddress::Address(tx.contract)), - data: Some(tx.data.into()), - chain_id: Some(tx.chain_id.into()), - value: Some(tx.value), - max_fee_per_gas: tx.max_fee_per_gas, - max_priority_fee_per_gas: tx.max_priority_fee_per_gas, - // geth uses the latest block gas limit as an upper bound - gas: None, - access_list: AccessList::default(), - from: Some(client.address()), - nonce: None, - }; - - let estimated_gas = client - .estimate_gas(&transaction_request) - .await - .context("Failed to estimate gas")?; - - transaction_request.gas = Some(match tx.gas_limit { - Some(gas_limit) => - if estimated_gas > gas_limit { - return Err(anyhow::anyhow!( - "Estimated gas is greater than the gas limit" - )) - } else { - gas_limit - }, - None => { - // increase the estimate by 33% for normal transactions - estimated_gas - .saturating_mul(U256::from(4u64)) - .checked_div(U256::from(3u64)) - .unwrap() - }, - }); - - client - .send_transaction(transaction_request) - .await - .context("Failed to send ETH transaction") - }) - }), - log, - MAX_BROADCAST_RETRIES, - ) - .await - } + ) -> anyhow::Result; +} +#[async_trait::async_trait] +impl EthersRetryRpcApi for EthRetryRpcClient { async fn get_logs(&self, block_hash: H256, contract_address: H160) -> Vec { self.rpc_retry_client .request( @@ -275,13 +259,77 @@ impl EthersRetryRpcApi for EthersRetryRpcClient { } } +#[async_trait::async_trait] +impl EthersRetrySigningRpcApi for EthRetryRpcClient { + /// Estimates gas and then sends the transaction to the network. + async fn broadcast_transaction( + &self, + tx: cf_chains::evm::Transaction, + ) -> anyhow::Result { + let log = RequestLog::new("broadcast_transaction".to_string(), Some(format!("{tx:?}"))); + self.rpc_retry_client + .request_with_limit( + Box::pin(move |client| { + let tx = tx.clone(); + #[allow(clippy::redundant_async_block)] + Box::pin(async move { + let mut transaction_request = Eip1559TransactionRequest { + to: Some(NameOrAddress::Address(tx.contract)), + data: Some(tx.data.into()), + chain_id: Some(tx.chain_id.into()), + value: Some(tx.value), + max_fee_per_gas: tx.max_fee_per_gas, + max_priority_fee_per_gas: tx.max_priority_fee_per_gas, + // geth uses the latest block gas limit as an upper bound + gas: None, + access_list: AccessList::default(), + from: Some(client.address()), + nonce: None, + }; + + let estimated_gas = client + .estimate_gas(&transaction_request) + .await + .context("Failed to estimate gas")?; + + transaction_request.gas = Some(match tx.gas_limit { + Some(gas_limit) => + if estimated_gas > gas_limit { + return Err(anyhow::anyhow!( + "Estimated gas is greater than the gas limit" + )) + } else { + gas_limit + }, + None => { + // increase the estimate by 33% for normal transactions + estimated_gas + .saturating_mul(U256::from(4u64)) + .checked_div(U256::from(3u64)) + .unwrap() + }, + }); + + client + .send_transaction(transaction_request) + .await + .context("Failed to send ETH transaction") + }) + }), + log, + MAX_BROADCAST_RETRIES, + ) + .await + } +} + #[async_trait::async_trait] pub trait EthersRetrySubscribeApi { async fn subscribe_blocks(&self) -> ConscientiousEthWebsocketBlockHeaderStream; } #[async_trait::async_trait] -impl EthersRetrySubscribeApi for EthersRetryRpcClient { +impl EthersRetrySubscribeApi for EthRetryRpcClient { async fn subscribe_blocks(&self) -> ConscientiousEthWebsocketBlockHeaderStream { self.sub_retry_client .request( @@ -296,7 +344,7 @@ impl EthersRetrySubscribeApi for EthersRetryRpcClient { } #[async_trait::async_trait] -impl ChainClient for EthersRetryRpcClient { +impl ChainClient for EthRetryRpcClient { type Index = ::ChainBlockNumber; type Hash = H256; @@ -349,12 +397,17 @@ pub mod mocks { } #[async_trait::async_trait] - impl EthersRetryRpcApi for EthRetryRpcClient { + impl EthersRetrySigningRpcApi for EthRetryRpcClient { async fn broadcast_transaction( &self, tx: cf_chains::evm::Transaction, ) -> anyhow::Result; + } + + #[async_trait::async_trait] + impl EthersRetryRpcApi for EthRetryRpcClient { + async fn get_logs(&self, block_hash: H256, contract_address: H160) -> Vec; async fn chain_id(&self) -> U256; @@ -392,7 +445,7 @@ mod tests { async move { let settings = Settings::new_test().unwrap(); - let retry_client = EthersRetryRpcClient::new( + let retry_client = EthRetryRpcClient::::new( scope, settings.eth.private_key_file, settings.eth.nodes, diff --git a/engine/src/eth/retry_rpc/address_checker.rs b/engine/src/eth/retry_rpc/address_checker.rs index 2341320076..73cfedba33 100644 --- a/engine/src/eth/retry_rpc/address_checker.rs +++ b/engine/src/eth/retry_rpc/address_checker.rs @@ -1,8 +1,11 @@ use ethers::prelude::*; -use crate::eth::rpc::address_checker::{AddressCheckerRpcApi, *}; +use crate::eth::rpc::{ + address_checker::{AddressCheckerRpcApi, *}, + EthRpcApi, +}; -use super::EthersRetryRpcClient; +use super::EthRetryRpcClient; use crate::eth::retry_rpc::RequestLog; @@ -24,7 +27,7 @@ pub trait AddressCheckerRetryRpcApi { } #[async_trait::async_trait] -impl AddressCheckerRetryRpcApi for EthersRetryRpcClient { +impl AddressCheckerRetryRpcApi for EthRetryRpcClient { async fn address_states( &self, block_hash: H256, diff --git a/engine/src/eth/rpc.rs b/engine/src/eth/rpc.rs index c6c9a73547..cba14a5ebd 100644 --- a/engine/src/eth/rpc.rs +++ b/engine/src/eth/rpc.rs @@ -20,25 +20,17 @@ struct NonceInfo { #[derive(Clone)] pub struct EthRpcClient { - signer: SignerMiddleware>, LocalWallet>, - nonce_info: Arc>>, + provider: Arc>, } impl EthRpcClient { pub fn new( - private_key_file: PathBuf, http_endpoint: SecretUrl, expected_chain_id: u64, - ) -> Result> { + ) -> anyhow::Result> { let provider = Arc::new(Provider::::try_from(http_endpoint.as_ref())?); - let wallet = - read_clean_and_decode_hex_str_file(&private_key_file, "Ethereum Private Key", |key| { - ethers::signers::Wallet::from_str(key).map_err(anyhow::Error::new) - })?; - - let signer = SignerMiddleware::new(provider, wallet.with_chain_id(expected_chain_id)); - let client = Self { signer, nonce_info: Arc::new(Mutex::new(None)) }; + let client = EthRpcClient { provider }; Ok(async move { // We don't want to return an error here. Returning an error means that we'll exit the @@ -64,6 +56,93 @@ impl EthRpcClient { } }) } +} + +#[async_trait::async_trait] +impl EthRpcApi for EthRpcClient { + async fn estimate_gas(&self, req: &Eip1559TransactionRequest) -> Result { + Ok(self + .provider + .estimate_gas(&TypedTransaction::Eip1559(req.clone()), None) + .await?) + } + + async fn get_logs(&self, filter: Filter) -> Result> { + Ok(self.provider.get_logs(&filter).await?) + } + + async fn chain_id(&self) -> Result { + Ok(self.provider.get_chainid().await?) + } + + async fn transaction_receipt(&self, tx_hash: TxHash) -> Result { + self.provider.get_transaction_receipt(tx_hash).await?.ok_or_else(|| { + anyhow!("Getting ETH transaction receipt for tx hash {tx_hash} returned None") + }) + } + + /// Gets block, returning error when either: + /// - Request fails + /// - Request succeeds, but doesn't return a block + async fn block(&self, block_number: U64) -> Result> { + self.provider.get_block(block_number).await?.ok_or_else(|| { + anyhow!("Getting ETH block for block number {block_number} returned None") + }) + } + + async fn block_with_txs(&self, block_number: U64) -> Result> { + self.provider.get_block_with_txs(block_number).await?.ok_or_else(|| { + anyhow!("Getting ETH block with txs for block number {block_number} returned None") + }) + } + + async fn fee_history( + &self, + block_count: U256, + last_block: BlockNumber, + reward_percentiles: &[f64], + ) -> Result { + Ok(self.provider.fee_history(block_count, last_block, reward_percentiles).await?) + } + + async fn get_transaction(&self, tx_hash: H256) -> Result { + self.provider + .get_transaction(tx_hash) + .await? + .ok_or_else(|| anyhow!("Getting ETH transaction for tx hash {tx_hash} returned None")) + } +} + +#[derive(Clone)] +pub struct EthRpcSigningClient { + signer: SignerMiddleware>, LocalWallet>, + rpc_client: EthRpcClient, + nonce_info: Arc>>, +} + +impl EthRpcSigningClient { + pub fn new( + private_key_file: PathBuf, + http_endpoint: SecretUrl, + expected_chain_id: u64, + ) -> Result> { + let rpc_client_fut = EthRpcClient::new(http_endpoint, expected_chain_id)?; + + let wallet = + read_clean_and_decode_hex_str_file(&private_key_file, "Ethereum Private Key", |key| { + ethers::signers::Wallet::from_str(key).map_err(anyhow::Error::new) + })?; + + Ok(async move { + let rpc_client = rpc_client_fut.await; + + let signer = SignerMiddleware::new( + rpc_client.provider.clone(), + wallet.with_chain_id(expected_chain_id), + ); + Self { signer, nonce_info: Arc::new(Mutex::new(None)), rpc_client } + }) + } async fn get_next_nonce(&self) -> Result { let mut nonce_info_lock = self.nonce_info.lock().await; @@ -99,13 +178,9 @@ impl EthRpcClient { } #[async_trait::async_trait] -pub trait EthRpcApi: Send { - fn address(&self) -> H160; - +pub trait EthRpcApi: Send + Sync + Clone + 'static { async fn estimate_gas(&self, req: &Eip1559TransactionRequest) -> Result; - async fn send_transaction(&self, tx: Eip1559TransactionRequest) -> Result; - async fn get_logs(&self, filter: Filter) -> Result>; async fn chain_id(&self) -> Result; @@ -130,56 +205,39 @@ pub trait EthRpcApi: Send { } #[async_trait::async_trait] -impl EthRpcApi for EthRpcClient { - fn address(&self) -> H160 { - self.signer.address() - } - - async fn estimate_gas(&self, req: &Eip1559TransactionRequest) -> Result { - Ok(self.signer.estimate_gas(&TypedTransaction::Eip1559(req.clone()), None).await?) - } - - async fn send_transaction(&self, mut tx: Eip1559TransactionRequest) -> Result { - tx.nonce = Some(self.get_next_nonce().await?); - - let res = self.signer.send_transaction(tx, None).await; +pub trait EthSigningRpcApi: EthRpcApi { + fn address(&self) -> H160; - if res.is_err() { - // Reset the nonce just in case (it will be re-requested during next broadcast) - tracing::warn!("Resetting eth broadcaster nonce due to error"); - *self.nonce_info.lock().await = None; - } + async fn send_transaction(&self, tx: Eip1559TransactionRequest) -> Result; +} - Ok(res?.tx_hash()) +#[async_trait::async_trait] +impl EthRpcApi for EthRpcSigningClient { + async fn estimate_gas(&self, req: &Eip1559TransactionRequest) -> Result { + self.rpc_client.estimate_gas(req).await } async fn get_logs(&self, filter: Filter) -> Result> { - Ok(self.signer.get_logs(&filter).await?) + self.rpc_client.get_logs(filter).await } async fn chain_id(&self) -> Result { - Ok(self.signer.get_chainid().await?) + self.rpc_client.chain_id().await } async fn transaction_receipt(&self, tx_hash: TxHash) -> Result { - self.signer.get_transaction_receipt(tx_hash).await?.ok_or_else(|| { - anyhow!("Getting ETH transaction receipt for tx hash {tx_hash} returned None") - }) + self.rpc_client.transaction_receipt(tx_hash).await } /// Gets block, returning error when either: /// - Request fails /// - Request succeeds, but doesn't return a block async fn block(&self, block_number: U64) -> Result> { - self.signer.get_block(block_number).await?.ok_or_else(|| { - anyhow!("Getting ETH block for block number {block_number} returned None") - }) + self.rpc_client.block(block_number).await } async fn block_with_txs(&self, block_number: U64) -> Result> { - self.signer.get_block_with_txs(block_number).await?.ok_or_else(|| { - anyhow!("Getting ETH block with txs for block number {block_number} returned None") - }) + self.rpc_client.block_with_txs(block_number).await } async fn fee_history( @@ -188,14 +246,31 @@ impl EthRpcApi for EthRpcClient { last_block: BlockNumber, reward_percentiles: &[f64], ) -> Result { - Ok(self.signer.fee_history(block_count, last_block, reward_percentiles).await?) + self.rpc_client.fee_history(block_count, last_block, reward_percentiles).await } async fn get_transaction(&self, tx_hash: H256) -> Result { - self.signer - .get_transaction(tx_hash) - .await? - .ok_or_else(|| anyhow!("Getting ETH transaction for tx hash {tx_hash} returned None")) + self.rpc_client.get_transaction(tx_hash).await + } +} + +#[async_trait::async_trait] +impl EthSigningRpcApi for EthRpcSigningClient { + fn address(&self) -> H160 { + self.signer.address() + } + + async fn send_transaction(&self, mut tx: Eip1559TransactionRequest) -> Result { + tx.nonce = Some(self.get_next_nonce().await?); + + let res = self.signer.send_transaction(tx, None).await; + if res.is_err() { + // Reset the nonce just in case (it will be re-requested during next broadcast) + tracing::warn!("Resetting eth broadcaster nonce due to error"); + *self.nonce_info.lock().await = None; + } + + Ok(res?.tx_hash()) } } @@ -266,7 +341,7 @@ mod tests { async fn eth_rpc_test() { let settings = Settings::new_test().unwrap(); - let client = EthRpcClient::new( + let client = EthRpcSigningClient::new( settings.eth.private_key_file, settings.eth.nodes.primary.http_endpoint, 2u64, diff --git a/engine/src/eth/rpc/address_checker.rs b/engine/src/eth/rpc/address_checker.rs index accb41b336..69be5336fd 100644 --- a/engine/src/eth/rpc/address_checker.rs +++ b/engine/src/eth/rpc/address_checker.rs @@ -2,7 +2,7 @@ use ethers::prelude::*; use anyhow::{Ok, Result}; -use super::EthRpcClient; +use super::{EthRpcClient, EthRpcSigningClient}; abigen!(AddressChecker, "$CF_ETH_CONTRACT_ABI_ROOT/$CF_ETH_CONTRACT_ABI_TAG/IAddressChecker.json"); @@ -31,7 +31,7 @@ impl AddressCheckerRpcApi for EthRpcClient { contract_address: H160, addresses: Vec, ) -> Result> { - Ok(AddressChecker::new(contract_address, self.signer.inner().clone()) + Ok(AddressChecker::new(contract_address, self.provider.clone()) .address_states(addresses) .block(BlockId::Hash(block_hash)) .call() @@ -44,10 +44,31 @@ impl AddressCheckerRpcApi for EthRpcClient { contract_address: H160, addresses: Vec, ) -> Result> { - Ok(AddressChecker::new(contract_address, self.signer.inner().clone()) + Ok(AddressChecker::new(contract_address, self.provider.clone()) .native_balances(addresses) .block(BlockId::Hash(block_hash)) .call() .await?) } } + +#[async_trait::async_trait] +impl AddressCheckerRpcApi for EthRpcSigningClient { + async fn address_states( + &self, + block_hash: H256, + contract_address: H160, + addresses: Vec, + ) -> Result> { + self.rpc_client.address_states(block_hash, contract_address, addresses).await + } + + async fn balances( + &self, + block_hash: H256, + contract_address: H160, + addresses: Vec, + ) -> Result> { + self.rpc_client.balances(block_hash, contract_address, addresses).await + } +} diff --git a/engine/src/main.rs b/engine/src/main.rs index a620fa7dd5..37efa7f8b8 100644 --- a/engine/src/main.rs +++ b/engine/src/main.rs @@ -5,7 +5,7 @@ use chainflip_engine::{ btc::retry_rpc::BtcRetryRpcClient, db::{KeyStore, PersistentKeyDB}, dot::retry_rpc::DotRetryRpcClient, - eth::retry_rpc::EthersRetryRpcClient, + eth::{retry_rpc::EthRetryRpcClient, rpc::EthRpcSigningClient}, health, p2p, settings::{CommandLineOptions, Settings, DEFAULT_SETTINGS_DIR}, state_chain_observer::{ @@ -175,7 +175,7 @@ async fn run_main(settings: Settings) -> anyhow::Result<()> { .await .expect(STATE_CHAIN_CONNECTION), ); - EthersRetryRpcClient::new( + EthRetryRpcClient::::new( scope, settings.eth.private_key_file, settings.eth.nodes, diff --git a/engine/src/state_chain_observer/sc_observer/mod.rs b/engine/src/state_chain_observer/sc_observer/mod.rs index 179719f7df..c7c540050d 100644 --- a/engine/src/state_chain_observer/sc_observer/mod.rs +++ b/engine/src/state_chain_observer/sc_observer/mod.rs @@ -26,7 +26,7 @@ use tracing::{debug, error, info, info_span, Instrument}; use crate::{ btc::retry_rpc::BtcRetryRpcApi, dot::retry_rpc::DotRetryRpcApi, - eth::retry_rpc::EthersRetryRpcApi, + eth::retry_rpc::EthersRetrySigningRpcApi, p2p::{PeerInfo, PeerUpdate}, state_chain_observer::client::{ extrinsic_api::{ @@ -238,7 +238,7 @@ pub async fn start< ) -> Result<(), anyhow::Error> where BlockStream: StateChainStreamApi, - EthRpc: EthersRetryRpcApi + Send + Sync + 'static, + EthRpc: EthersRetrySigningRpcApi + Send + Sync + 'static, DotRpc: DotRetryRpcApi + Send + Sync + 'static, BtcRpc: BtcRetryRpcApi + Send + Sync + 'static, EthMultisigClient: MultisigClientApi + Send + Sync + 'static, diff --git a/engine/src/witness/eth.rs b/engine/src/witness/eth.rs index 94a89944de..69c1d5454f 100644 --- a/engine/src/witness/eth.rs +++ b/engine/src/witness/eth.rs @@ -16,7 +16,7 @@ use utilities::task_scope::Scope; use crate::{ db::PersistentKeyDB, - eth::retry_rpc::EthersRetryRpcClient, + eth::{retry_rpc::EthRetryRpcClient, rpc::EthRpcSigningClient}, state_chain_observer::client::{ chain_api::ChainApi, extrinsic_api::signed::SignedExtrinsicApi, storage_api::StorageApi, StateChainStreamApi, @@ -43,7 +43,7 @@ pub async fn start< PrewitnessFut, >( scope: &Scope<'_, anyhow::Error>, - eth_client: EthersRetryRpcClient, + eth_client: EthRetryRpcClient, process_call: ProcessCall, prewitness_call: PrewitnessCall, state_chain_client: Arc, diff --git a/engine/src/witness/eth/ethereum_deposits.rs b/engine/src/witness/eth/ethereum_deposits.rs index 36407e0abf..705139a161 100644 --- a/engine/src/witness/eth/ethereum_deposits.rs +++ b/engine/src/witness/eth/ethereum_deposits.rs @@ -226,7 +226,10 @@ pub fn eth_ingresses_at_block< #[cfg(test)] mod tests { use crate::{ - eth::retry_rpc::{EthersRetryRpcApi, EthersRetryRpcClient}, + eth::{ + retry_rpc::{EthRetryRpcClient, EthersRetryRpcApi}, + rpc::EthRpcClient, + }, settings::Settings, witness::common::chain_source::Header, }; @@ -304,7 +307,7 @@ mod tests { ); } - #[ignore = "requries connection to a node"] + #[ignore = "requires connection to a node"] #[tokio::test] async fn test_get_ingress_contract() { task_scope::task_scope(|scope| { @@ -315,9 +318,8 @@ mod tests { "e7f1725E7734CE288F8367e1Bb143E90bb3F0512".parse::
().unwrap(); let settings = Settings::new_test().unwrap(); - let client = EthersRetryRpcClient::new( + let client = EthRetryRpcClient::::new( scope, - settings.eth.private_key_file, settings.eth.nodes, U256::from(1337u64), ) diff --git a/engine/src/witness/eth/key_manager.rs b/engine/src/witness/eth/key_manager.rs index 7a5bb601b6..21a6ab27f4 100644 --- a/engine/src/witness/eth/key_manager.rs +++ b/engine/src/witness/eth/key_manager.rs @@ -186,8 +186,8 @@ mod tests { use super::super::eth_source::EthSource; use crate::{ - eth::retry_rpc::EthersRetryRpcClient, - settings::{self, NodeContainer, WsHttpEndpoints}, + eth::{retry_rpc::EthRetryRpcClient, rpc::EthRpcClient}, + settings::{NodeContainer, WsHttpEndpoints}, state_chain_observer::client::StateChainClient, witness::common::{chain_source::extension::ChainSourceExt, epoch_source::EpochSource}, }; @@ -197,21 +197,15 @@ mod tests { async fn test_key_manager_witnesser() { task_scope(|scope| { async { - let eth_settings = settings::Eth { - nodes: NodeContainer { + let retry_client = EthRetryRpcClient::::new( + scope, + NodeContainer { primary: WsHttpEndpoints { ws_endpoint: "ws://localhost:8546".into(), http_endpoint: "http://localhost:8545".into(), }, backup: None, }, - private_key_file: PathBuf::from_str("/some/key/file").unwrap(), - }; - - let retry_client = EthersRetryRpcClient::new( - scope, - eth_settings.private_key_file, - eth_settings.nodes, U256::from(1337u64), ) .unwrap(); diff --git a/engine/src/witness/start.rs b/engine/src/witness/start.rs index 629868fcd0..533024b68b 100644 --- a/engine/src/witness/start.rs +++ b/engine/src/witness/start.rs @@ -6,7 +6,7 @@ use crate::{ btc::retry_rpc::BtcRetryRpcClient, db::PersistentKeyDB, dot::retry_rpc::DotRetryRpcClient, - eth::retry_rpc::EthersRetryRpcClient, + eth::{retry_rpc::EthRetryRpcClient, rpc::EthRpcSigningClient}, state_chain_observer::client::{ extrinsic_api::signed::SignedExtrinsicApi, storage_api::StorageApi, StateChainStreamApi, }, @@ -25,7 +25,7 @@ use anyhow::Result; // point it means that on start up this will block, and the state chain observer will not start. pub async fn start( scope: &Scope<'_, anyhow::Error>, - eth_client: EthersRetryRpcClient, + eth_client: EthRetryRpcClient, btc_client: BtcRetryRpcClient, dot_client: DotRetryRpcClient, state_chain_client: Arc,