Skip to content

Commit

Permalink
Processor scanner tests for Ethereum
Browse files Browse the repository at this point in the history
  • Loading branch information
kayabaNerve committed May 10, 2024
1 parent 5501de1 commit 0c9dd50
Show file tree
Hide file tree
Showing 10 changed files with 309 additions and 87 deletions.
6 changes: 5 additions & 1 deletion common/request/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ impl Client {
fn connector() -> Connector {
let mut res = HttpConnector::new();
res.set_keepalive(Some(core::time::Duration::from_secs(60)));
res.set_nodelay(true);
res.set_reuse_address(true);
#[cfg(feature = "tls")]
let res = HttpsConnectorBuilder::new()
.with_native_roots()
Expand All @@ -68,7 +70,9 @@ impl Client {
pub fn with_connection_pool() -> Client {
Client {
connection: Connection::ConnectionPool(
HyperClient::builder(TokioExecutor::new()).build(Self::connector()),
HyperClient::builder(TokioExecutor::new())
.pool_idle_timeout(core::time::Duration::from_secs(60))
.build(Self::connector()),
),
}
}
Expand Down
2 changes: 1 addition & 1 deletion orchestration/dev/coins/ethereum/run.sh
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
#!/bin/sh

~/.foundry/bin/anvil --no-mining --slots-in-an-epoch 32
~/.foundry/bin/anvil --host 0.0.0.0 --no-cors --no-mining --slots-in-an-epoch 32 --silent
2 changes: 1 addition & 1 deletion processor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ serai-docker-tests = { path = "../tests/docker" }
secp256k1 = ["k256", "frost/secp256k1"]
bitcoin = ["dep:secp256k1", "secp256k1", "bitcoin-serai", "serai-client/bitcoin"]

ethereum = ["secp256k1", "ethereum-serai"]
ethereum = ["secp256k1", "ethereum-serai/tests"]

ed25519 = ["dalek-ff-group", "frost/ed25519"]
monero = ["ed25519", "monero-serai", "serai-client/monero"]
Expand Down
69 changes: 40 additions & 29 deletions processor/src/networks/ethereum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ impl SignableTransaction for RouterCommand {
}

#[async_trait]
impl<D: fmt::Debug + Db> TransactionTrait<Ethereum<D>> for Transaction {
impl<D: Db> TransactionTrait<Ethereum<D>> for Transaction {
type Id = [u8; 32];
fn id(&self) -> Self::Id {
self.hash.0
Expand Down Expand Up @@ -157,7 +157,7 @@ impl Epoch {
}

#[async_trait]
impl<D: fmt::Debug + Db> Block<Ethereum<D>> for Epoch {
impl<D: Db> Block<Ethereum<D>> for Epoch {
type Id = [u8; 32];
fn id(&self) -> [u8; 32] {
self.end_hash
Expand All @@ -170,7 +170,7 @@ impl<D: fmt::Debug + Db> Block<Ethereum<D>> for Epoch {
}
}

impl<D: fmt::Debug + Db> Output<Ethereum<D>> for EthereumInInstruction {
impl<D: Db> Output<Ethereum<D>> for EthereumInInstruction {
type Id = [u8; 32];

fn kind(&self) -> OutputType {
Expand Down Expand Up @@ -282,8 +282,8 @@ impl EventualityTrait for Eventuality {
}
}

#[derive(Clone, Debug)]
pub struct Ethereum<D: fmt::Debug + Db> {
#[derive(Clone)]
pub struct Ethereum<D: Db> {
// This DB is solely used to access the first key generated, as needed to determine the Router's
// address. Accordingly, all methods present are consistent to a Serai chain with a finalized
// first key (regardless of local state), and this is safe.
Expand All @@ -292,20 +292,26 @@ pub struct Ethereum<D: fmt::Debug + Db> {
deployer: Deployer,
router: Arc<RwLock<Option<Router>>>,
}
impl<D: fmt::Debug + Db> PartialEq for Ethereum<D> {
impl<D: Db> PartialEq for Ethereum<D> {
fn eq(&self, _other: &Ethereum<D>) -> bool {
true
}
}
impl<D: fmt::Debug + Db> Ethereum<D> {
impl<D: Db> fmt::Debug for Ethereum<D> {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt
.debug_struct("Ethereum")
.field("deployer", &self.deployer)
.field("router", &self.router)
.finish_non_exhaustive()
}
}
impl<D: Db> Ethereum<D> {
pub async fn new(db: D, url: String) -> Self {
let provider = Arc::new(RootProvider::new(
ClientBuilder::default().transport(SimpleRequest::new(url), true),
));

#[cfg(test)] // TODO: Move to test code
provider.raw_request::<_, ()>("evm_setAutomine".into(), false).await.unwrap();

let mut deployer = Deployer::new(provider.clone()).await;
while !matches!(deployer, Ok(Some(_))) {
log::error!("Deployer wasn't deployed yet or networking error");
Expand Down Expand Up @@ -362,7 +368,7 @@ impl<D: fmt::Debug + Db> Ethereum<D> {
}

#[async_trait]
impl<D: fmt::Debug + Db> Network for Ethereum<D> {
impl<D: Db> Network for Ethereum<D> {
type Curve = Secp256k1;

type Transaction = Transaction;
Expand Down Expand Up @@ -479,7 +485,8 @@ impl<D: fmt::Debug + Db> Network for Ethereum<D> {
// Grab the key at the end of the epoch
let key_at_end_of_block = loop {
match router.key_at_end_of_block(block.start + 31).await {
Ok(key) => break key,
Ok(Some(key)) => break key,
Ok(None) => return vec![],
Err(e) => {
log::error!("couldn't connect to router for the key at the end of the block: {e:?}");
sleep(Duration::from_secs(5)).await;
Expand All @@ -491,17 +498,7 @@ impl<D: fmt::Debug + Db> Network for Ethereum<D> {
let mut all_events = vec![];
let mut top_level_txids = HashSet::new();
for erc20_addr in [DAI] {
let erc20 = loop {
let Ok(Some(erc20)) = Erc20::new(self.provider.clone(), erc20_addr).await else {
log::error!(
"couldn't connect to Ethereum node for an ERC20: {}",
hex::encode(erc20_addr)
);
sleep(Duration::from_secs(5)).await;
continue;
};
break erc20;
};
let erc20 = Erc20::new(self.provider.clone(), erc20_addr);

for block in block.start .. (block.start + 32) {
let transfers = loop {
Expand Down Expand Up @@ -821,6 +818,7 @@ impl<D: fmt::Debug + Db> Network for Ethereum<D> {
.provider
.get_transaction_by_hash(log.clone().transaction_hash.unwrap())
.await
.unwrap()
.unwrap();
};

Expand All @@ -830,20 +828,26 @@ impl<D: fmt::Debug + Db> Network for Ethereum<D> {
.to_block(((block + 1) * 32) - 1)
.topic1(nonce);
let logs = self.provider.get_logs(&filter).await.unwrap();
self.provider.get_transaction_by_hash(logs[0].transaction_hash.unwrap()).await.unwrap()
self
.provider
.get_transaction_by_hash(logs[0].transaction_hash.unwrap())
.await
.unwrap()
.unwrap()
}
}
}

#[cfg(test)]
async fn mine_block(&self) {
self.provider.raw_request::<_, ()>("anvil_mine".into(), [32]).await.unwrap();
self.provider.raw_request::<_, ()>("anvil_mine".into(), [96]).await.unwrap();
}

#[cfg(test)]
async fn test_send(&self, send_to: Self::Address) -> Self::Block {
use rand_core::OsRng;
use ciphersuite::group::ff::Field;
use ethereum_serai::alloy_sol_types::SolCall;

let key = <Secp256k1 as Ciphersuite>::F::random(&mut OsRng);
let address = ethereum_serai::crypto::address(&(Secp256k1::generator() * key));
Expand All @@ -858,15 +862,22 @@ impl<D: fmt::Debug + Db> Network for Ethereum<D> {
.await
.unwrap();

let value = U256::from_str_radix("1000000000000000000", 10).unwrap();
let tx = ethereum_serai::alloy_consensus::TxLegacy {
chain_id: None,
nonce: 0,
gas_price: 100_000_000_000u128,
gas_limit: 21_0000u128,
gas_price: 1_000_000_000u128,
gas_limit: 200_000u128,
to: ethereum_serai::alloy_core::primitives::TxKind::Call(send_to.0.into()),
// 1 ETH
value: U256::from_str_radix("1000000000000000000", 10).unwrap(),
input: vec![].into(),
value,
input: ethereum_serai::router::abi::inInstructionCall::new((
[0; 20].into(),
value,
vec![].into(),
))
.abi_encode()
.into(),
};

use ethereum_serai::alloy_consensus::SignableTransaction;
Expand Down
11 changes: 7 additions & 4 deletions processor/src/tests/addresses.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use core::time::Duration;
use core::{time::Duration, pin::Pin, future::Future};
use std::collections::HashMap;

use rand_core::OsRng;
Expand Down Expand Up @@ -82,8 +82,9 @@ async fn spend<N: UtxoNetwork, D: Db>(
}
}

pub async fn test_addresses<N: UtxoNetwork>(network: N)
where
pub async fn test_addresses<N: UtxoNetwork>(
new_network: impl Fn(MemDb) -> Pin<Box<dyn Send + Future<Output = N>>>,
) where
<N::Scheduler as Scheduler<N>>::Addendum: From<()>,
{
let mut keys = frost::tests::key_gen::<_, N::Curve>(&mut OsRng);
Expand All @@ -92,12 +93,14 @@ where
}
let key = keys[&Participant::new(1).unwrap()].group_key();

let mut db = MemDb::new();
let network = new_network(db.clone()).await;

// Mine blocks so there's a confirmed block
for _ in 0 .. N::CONFIRMATIONS {
network.mine_block().await;
}

let mut db = MemDb::new();
let (mut scanner, current_keys) = Scanner::new(network.clone(), db.clone());
assert!(current_keys.is_empty());
let mut txn = db.txn();
Expand Down
Loading

0 comments on commit 0c9dd50

Please sign in to comment.