From a5c30207e916e267bbfe1ea360cae83b88d773e8 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 11 Feb 2025 21:28:57 +0200 Subject: [PATCH 01/26] dev to use anvil instead of geth for evm chains --- docker-compose.yml | 47 +++++++++------------------------------------- 1 file changed, 9 insertions(+), 38 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 736363dcf..372720c47 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -76,26 +76,12 @@ services: - grpc chain-2-evm: - image: 'ethereum/client-go:v1.14.11' + image: 'ghcr.io/foundry-rs/foundry:latest' command: - - '--dev' - - '--dev.gaslimit=30000000' - - '--ipcdisable' - - '--dev.period=2' - - '--rpc.txfeecap=0' - - '--rpc.allow-unprotected-txs=true' - - '--http' - - '--http.addr=0.0.0.0' - - '--http.port=8545' - - '--http.vhosts=*' - - '--http.corsdomain=*' - - '--http.api=eth,debug,admin,txpool,web3,net' - - '--ws' - - '--ws.addr=0.0.0.0' - - '--ws.port=8545' - - '--ws.origins=*' - - '--ws.api=eth,debug,admin,txpool,web3,net' - - '--verbosity=4' + - 'anvil -b 2' + environment: + ANVIL_IP_ADDR: '0.0.0.0' + profiles: profiles: - evm @@ -117,26 +103,11 @@ services: - evm chain-3-evm: - image: 'ethereum/client-go:v1.14.11' + image: 'ghcr.io/foundry-rs/foundry:latest' command: - - '--dev' - - '--dev.gaslimit=30000000' - - '--ipcdisable' - - '--dev.period=2' - - '--rpc.txfeecap=0' - - '--rpc.allow-unprotected-txs=true' - - '--http' - - '--http.addr=0.0.0.0' - - '--http.port=8545' - - '--http.vhosts=*' - - '--http.corsdomain=*' - - '--http.api=eth,debug,admin,txpool,web3,net' - - '--ws' - - '--ws.addr=0.0.0.0' - - '--ws.port=8545' - - '--ws.origins=*' - - '--ws.api=eth,debug,admin,txpool,web3,net' - - '--verbosity=4' + - 'anvil -b 2' + environment: + ANVIL_IP_ADDR: '0.0.0.0' profiles: - evm From 74735cd3ea7fd4206d7a01f06919b7f5cb8bc558 Mon Sep 17 00:00:00 2001 From: Alexander Gryaznov Date: Tue, 11 Feb 2025 21:57:34 +0200 Subject: [PATCH 02/26] fix --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 372720c47..5a8533452 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -82,7 +82,6 @@ services: environment: ANVIL_IP_ADDR: '0.0.0.0' profiles: - profiles: - evm chronicle-2-evm: From 3ce9f34d9396bfe43bfeabe3c6c20f8a168e5382 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 10:29:32 +0100 Subject: [PATCH 03/26] Refactor faucet. --- gmp/evm/src/lib.rs | 11 +---------- gmp/grpc/src/lib.rs | 4 ++-- gmp/grpc/src/main.rs | 7 +++++-- gmp/grpc/src/proto.rs | 4 +++- gmp/rust/src/lib.rs | 6 ++---- primitives/src/gmp.rs | 2 +- tc-cli/src/config.rs | 1 + tc-cli/src/lib.rs | 4 +++- 8 files changed, 18 insertions(+), 21 deletions(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 32ac21845..5ea2308e1 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -426,16 +426,7 @@ impl IChain for Connector { (config.currency_decimals, config.currency_symbol) } /// Uses a faucet to fund the account when possible. - async fn faucet(&self) -> Result<()> { - let balance = match self.network_id() { - 6 => 10u128.pow(25), // astar - 2 => 10u128.pow(29), // ethereum - 3 => 10u128.pow(29), // ethereum - network_id => { - tracing::info!("network {network_id} doesn't support faucet"); - return Ok(()); - }, - }; + async fn faucet(&self, balance: u128) -> Result<()> { self.wallet.faucet(balance, None).await?; Ok(()) } diff --git a/gmp/grpc/src/lib.rs b/gmp/grpc/src/lib.rs index 65a668d6a..924103a89 100644 --- a/gmp/grpc/src/lib.rs +++ b/gmp/grpc/src/lib.rs @@ -98,8 +98,8 @@ impl IChain for Connector { self.address } /// Uses a faucet to fund the account when possible. - async fn faucet(&self) -> Result<()> { - let request = Request::new(proto::FaucetRequest {}); + async fn faucet(&self, balance: u128) -> Result<()> { + let request = Request::new(proto::FaucetRequest { balance }); self.client.lock().await.faucet(request).await?; Ok(()) } diff --git a/gmp/grpc/src/main.rs b/gmp/grpc/src/main.rs index b3fd032d5..ba1875122 100644 --- a/gmp/grpc/src/main.rs +++ b/gmp/grpc/src/main.rs @@ -54,8 +54,11 @@ impl Gmp for ConnectorWrapper { &self, request: Request, ) -> GmpResult { - let (connector, _) = self.connector(request)?; - connector.faucet().await.map_err(|err| Status::unknown(err.to_string()))?; + let (connector, msg) = self.connector(request)?; + connector + .faucet(msg.balance) + .await + .map_err(|err| Status::unknown(err.to_string()))?; Ok(Response::new(proto::FaucetResponse {})) } diff --git a/gmp/grpc/src/proto.rs b/gmp/grpc/src/proto.rs index 350d8dae4..81d783b89 100644 --- a/gmp/grpc/src/proto.rs +++ b/gmp/grpc/src/proto.rs @@ -6,7 +6,9 @@ use time_primitives::{ }; #[derive(Serialize, Deserialize)] -pub struct FaucetRequest {} +pub struct FaucetRequest { + pub balance: u128, +} #[derive(Serialize, Deserialize)] pub struct FaucetResponse {} diff --git a/gmp/rust/src/lib.rs b/gmp/rust/src/lib.rs index d5d8c9926..d9a899da9 100644 --- a/gmp/rust/src/lib.rs +++ b/gmp/rust/src/lib.rs @@ -23,7 +23,6 @@ use time_primitives::{ const BLOCK_TIME: u64 = 1; const FINALIZATION_TIME: u64 = 2; -const FAUCET: u128 = 1_000_000_000; const BLOCKS: TableDefinition = TableDefinition::new("blocks"); const BALANCE: TableDefinition = TableDefinition::new("balance"); @@ -193,12 +192,11 @@ impl IChain for Connector { currency() } - async fn faucet(&self) -> Result<()> { + async fn faucet(&self, balance: u128) -> Result<()> { let tx = self.db.begin_write()?; { let mut t = tx.open_table(BALANCE)?; - let balance = read_balance(&t, self.address)?; - t.insert(self.address, balance + FAUCET)?; + t.insert(self.address, balance)?; } tx.commit()?; Ok(()) diff --git a/primitives/src/gmp.rs b/primitives/src/gmp.rs index d8e9ba010..c42210a2b 100644 --- a/primitives/src/gmp.rs +++ b/primitives/src/gmp.rs @@ -354,7 +354,7 @@ pub trait IChain: Send + Sync + 'static { /// Human readable connector account identifier. fn address(&self) -> Address; /// Uses a faucet to fund the account when possible. - async fn faucet(&self) -> Result<()>; + async fn faucet(&self, balance: u128) -> Result<()>; /// Transfers an amount to an account. async fn transfer(&self, address: Address, amount: u128) -> Result<()>; /// Queries the account balance. diff --git a/tc-cli/src/config.rs b/tc-cli/src/config.rs index cefafc845..c71dfbd8a 100644 --- a/tc-cli/src/config.rs +++ b/tc-cli/src/config.rs @@ -135,6 +135,7 @@ pub struct NetworkConfig { pub route_base_fee: u128, pub shard_size: u16, pub shard_threshold: u16, + pub faucet: Option, } #[cfg(test)] diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index e96ac31e1..c17df8849 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -215,7 +215,9 @@ impl Tc { } pub async fn faucet(&self, network: NetworkId) -> Result<()> { - self.connector(network)?.faucet().await + let config = self.config.network(network)?; + let faucet = config.faucet.context("faucet not supported, please prefund account")?; + self.connector(network)?.faucet(faucet).await } pub async fn balance(&self, network: Option, address: Address) -> Result { From 0cb4690c0d840bb4de65573c7bc083008fba65dd Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 11:01:15 +0100 Subject: [PATCH 04/26] Use reexported crates. --- Cargo.lock | 24 ++++-------------------- gmp/evm/Cargo.toml | 7 ++----- gmp/evm/src/lib.rs | 27 ++++++++++++--------------- 3 files changed, 18 insertions(+), 40 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 87ba68d6f..31dc3f1df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5596,10 +5596,6 @@ dependencies = [ "hex", "reqwest", "rosetta-client", - "rosetta-ethereum-backend", - "rosetta-ethereum-types", - "rosetta-server", - "rosetta-server-ethereum", "serde", "serde_json", "sha3", @@ -14158,7 +14154,6 @@ dependencies = [ [[package]] name = "rosetta-client" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14169,11 +14164,15 @@ dependencies = [ "futures-util", "getrandom 0.2.15", "hex", + "hex-literal", "js-sys", "log", "num-traits", "rosetta-config-ethereum", "rosetta-core", + "rosetta-ethereum-backend", + "rosetta-ethereum-types", + "rosetta-server", "rosetta-server-astar", "rosetta-server-ethereum", "rosetta-server-polkadot", @@ -14189,7 +14188,6 @@ dependencies = [ [[package]] name = "rosetta-config-astar" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "rosetta-core", @@ -14199,7 +14197,6 @@ dependencies = [ [[package]] name = "rosetta-config-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "const-hex", @@ -14219,7 +14216,6 @@ dependencies = [ [[package]] name = "rosetta-config-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "rosetta-core", @@ -14230,7 +14226,6 @@ dependencies = [ [[package]] name = "rosetta-core" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14247,7 +14242,6 @@ dependencies = [ [[package]] name = "rosetta-crypto" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "bech32", @@ -14273,7 +14267,6 @@ dependencies = [ [[package]] name = "rosetta-ethereum-backend" version = "0.1.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "async-trait", "auto_impl", @@ -14289,7 +14282,6 @@ dependencies = [ [[package]] name = "rosetta-ethereum-types" version = "0.2.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "bytes", "const-hex", @@ -14323,7 +14315,6 @@ dependencies = [ [[package]] name = "rosetta-server" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14346,7 +14337,6 @@ dependencies = [ [[package]] name = "rosetta-server-astar" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14370,7 +14360,6 @@ dependencies = [ [[package]] name = "rosetta-server-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14399,7 +14388,6 @@ dependencies = [ [[package]] name = "rosetta-server-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "async-trait", @@ -14420,7 +14408,6 @@ dependencies = [ [[package]] name = "rosetta-tx-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "rosetta-config-ethereum", @@ -14431,7 +14418,6 @@ dependencies = [ [[package]] name = "rosetta-tx-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "anyhow", "blake2-rfc", @@ -14445,7 +14431,6 @@ dependencies = [ [[package]] name = "rosetta-types" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "serde", "serde_json", @@ -14454,7 +14439,6 @@ dependencies = [ [[package]] name = "rosetta-utils" version = "0.1.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=37e2cd1#37e2cd13b9a958542137a6674ea26314f39e59d7" dependencies = [ "bytes", "futures-timer", diff --git a/gmp/evm/Cargo.toml b/gmp/evm/Cargo.toml index d698910fd..ca55c6577 100644 --- a/gmp/evm/Cargo.toml +++ b/gmp/evm/Cargo.toml @@ -16,11 +16,8 @@ async-trait.workspace = true futures.workspace = true hex.workspace = true reqwest = { version = "0.12.7", default-features = false, features = ["json", "rustls-tls-native-roots"] } -rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } -rosetta-server = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } -rosetta-server-ethereum = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } -rosetta-ethereum-backend = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } -rosetta-ethereum-types = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } +#rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } +rosetta-client = { path = "../../../chain-connectors/rosetta-client" } sha3 = { version = "0.10", default-features = false } serde.workspace = true serde_json = "1.0.127" diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 5ea2308e1..c3862acbc 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -5,13 +5,15 @@ use async_trait::async_trait; use futures::Stream; use reqwest::Client; use rosetta_client::{ - query::GetLogs, types::AccountIdentifier, AtBlock, CallResult, FilterBlockOption, - GetTransactionCount, SubmitResult, TransactionReceipt, Wallet, -}; -use rosetta_ethereum_backend::{jsonrpsee::Adapter, EthereumRpc}; -use rosetta_server::ws::{default_client, DefaultClient}; -use rosetta_server_ethereum::utils::{ - DefaultFeeEstimatorConfig, EthereumRpcExt, PolygonFeeEstimatorConfig, + query::GetLogs, + rosetta_ethereum_backend::{jsonrpsee::Adapter, EthereumRpc}, + rosetta_server::ws::{default_client, DefaultClient}, + rosetta_server_ethereum::utils::{ + DefaultFeeEstimatorConfig, EthereumRpcExt, PolygonFeeEstimatorConfig, + }, + types::AccountIdentifier, + AtBlock, CallResult, FilterBlockOption, GetTransactionCount, SubmitResult, TransactionReceipt, + Wallet, }; use serde::Deserialize; use sha3::{Digest, Keccak256}; @@ -596,10 +598,8 @@ impl IConnectorAdmin for Connector { // check if uf already deployed let config: DeploymentConfig = serde_json::from_slice(additional_params)?; let factory_address = a_addr(self.parse_address(&config.factory_address)?).0 .0; - let is_factory_deployed = self - .backend - .get_code(factory_address.into(), rosetta_ethereum_types::AtBlock::Latest) - .await?; + let is_factory_deployed = + self.backend.get_code(factory_address.into(), AtBlock::Latest).await?; if is_factory_deployed.is_empty() { self.deploy_factory(&config).await?; @@ -609,10 +609,7 @@ impl IConnectorAdmin for Connector { let proxy_addr = self.compute_proxy_address(&config, proxy)?; // check if proxy is deployed - let is_proxy_deployed = self - .backend - .get_code(proxy_addr.into(), rosetta_ethereum_types::AtBlock::Latest) - .await?; + let is_proxy_deployed = self.backend.get_code(proxy_addr.into(), AtBlock::Latest).await?; if !is_proxy_deployed.is_empty() { tracing::debug!("Proxy already deployed, Please upgrade the gateway contract"); From f3be40e418d2a0f844b4eb524efd1eca730a51b4 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 11:05:22 +0100 Subject: [PATCH 05/26] Update configs. --- config/envs/local/config.yaml | 8 ++++++-- config/envs/local/local-evm.yaml | 6 ++++-- config/envs/local/local-grpc-tss.yaml | 2 ++ config/envs/local/local-grpc.yaml | 2 ++ tc-cli/src/config.rs | 2 +- tc-cli/src/lib.rs | 12 +++++++++--- 6 files changed, 24 insertions(+), 8 deletions(-) diff --git a/config/envs/local/config.yaml b/config/envs/local/config.yaml index 4aa924dbd..622f67454 100644 --- a/config/envs/local/config.yaml +++ b/config/envs/local/config.yaml @@ -29,6 +29,7 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 100. 1: backend: "grpc" blockchain: "rust" @@ -45,9 +46,10 @@ networks: route_base_fee: 1715000000000 shard_size: 1 shard_threshold: 1 + faucet: 100. 2: backend: "evm" - blockchain: "ethereum" + blockchain: "anvil" network: "dev" url: "ws://chain-2-evm:8545" gateway_funds: 1. @@ -61,9 +63,10 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 10. 3: backend: "evm" - blockchain: "ethereum" + blockchain: "anvil" network: "dev" url: "ws://chain-3-evm:8545" gateway_funds: 1. @@ -77,6 +80,7 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 10. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-1-grpc-1:8080 diff --git a/config/envs/local/local-evm.yaml b/config/envs/local/local-evm.yaml index 53428c76a..008580374 100644 --- a/config/envs/local/local-evm.yaml +++ b/config/envs/local/local-evm.yaml @@ -11,7 +11,7 @@ contracts: networks: 2: backend: "evm" - blockchain: "ethereum" + blockchain: "anvil" network: "dev" url: "ws://chain-2-evm:8545" gateway_funds: 1. @@ -25,9 +25,10 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 10. 3: backend: "evm" - blockchain: "ethereum" + blockchain: "anvil" network: "dev" url: "ws://chain-3-evm:8545" gateway_funds: 1. @@ -41,6 +42,7 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 10. chronicles: - http://timechain-chronicle-2-evm-1:8080 - http://timechain-chronicle-3-evm-1:8080 diff --git a/config/envs/local/local-grpc-tss.yaml b/config/envs/local/local-grpc-tss.yaml index 3b4788893..af1d164d6 100644 --- a/config/envs/local/local-grpc-tss.yaml +++ b/config/envs/local/local-grpc-tss.yaml @@ -29,6 +29,7 @@ networks: route_base_fee: 1400000000 shard_size: 3 shard_threshold: 2 + faucet: 100. 1: backend: "grpc" blockchain: "rust" @@ -45,6 +46,7 @@ networks: route_base_fee: 1715000000000 shard_size: 3 shard_threshold: 2 + faucet: 100. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-0-grpc-2:8080 diff --git a/config/envs/local/local-grpc.yaml b/config/envs/local/local-grpc.yaml index 930ab5609..740ec978a 100644 --- a/config/envs/local/local-grpc.yaml +++ b/config/envs/local/local-grpc.yaml @@ -29,6 +29,7 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 + faucet: 100. 1: backend: "grpc" blockchain: "rust" @@ -45,6 +46,7 @@ networks: route_base_fee: 1715000000000 shard_size: 1 shard_threshold: 1 + faucet: 100. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-1-grpc-1:8080 diff --git a/tc-cli/src/config.rs b/tc-cli/src/config.rs index c71dfbd8a..3b107b54d 100644 --- a/tc-cli/src/config.rs +++ b/tc-cli/src/config.rs @@ -135,7 +135,7 @@ pub struct NetworkConfig { pub route_base_fee: u128, pub shard_size: u16, pub shard_threshold: u16, - pub faucet: Option, + pub faucet: Option, } #[cfg(test)] diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index c17df8849..661a8c0e8 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -216,7 +216,14 @@ impl Tc { pub async fn faucet(&self, network: NetworkId) -> Result<()> { let config = self.config.network(network)?; - let faucet = config.faucet.context("faucet not supported, please prefund account")?; + let faucet = + config.faucet.as_ref().context("faucet not supported, please prefund account")?; + let faucet = self.parse_balance(Some(network), faucet)?; + self.println( + None, + format!("faucet {network} {}", self.format_balance(Some(network), faucet)?), + ) + .await?; self.connector(network)?.faucet(faucet).await } @@ -669,7 +676,7 @@ impl Tc { self.set_network_config(network).await?; gateway } else { - self.println(None, "deploying gateway").await?; + self.println(None, format!("deploying gateway {network}")).await?; let (gateway, block) = connector .deploy_gateway(&contracts.additional_params, &contracts.proxy, &contracts.gateway) .await?; @@ -851,7 +858,6 @@ impl Tc { pub async fn deploy_network(&self, network: NetworkId) -> Result { let config = self.config.network(network)?; if self.balance(Some(network), self.address(Some(network))?).await? == 0 { - self.println(None, "admin target balance is 0, using faucet").await?; self.faucet(network).await?; } let gateway = self.register_network(network).await?; From 554e097556bf59553b746d36824fb40bead796f5 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 11:40:41 +0100 Subject: [PATCH 06/26] Refactor faucet. --- Cargo.lock | 16 ++++++++++++++++ config/envs/development/config.yaml | 23 +++++++++++++++-------- config/envs/integration/config.yaml | 6 +++--- config/envs/local/config.yaml | 18 +++++++++--------- config/envs/local/local-evm.yaml | 10 +++++----- config/envs/local/local-grpc-tss.yaml | 10 +++++----- config/envs/local/local-grpc.yaml | 10 +++++----- gmp/evm/Cargo.toml | 3 +-- tc-cli/src/config.rs | 6 +++--- tc-cli/src/lib.rs | 24 ++++++++++++++---------- 10 files changed, 76 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 31dc3f1df..2d05df7b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14154,6 +14154,7 @@ dependencies = [ [[package]] name = "rosetta-client" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14188,6 +14189,7 @@ dependencies = [ [[package]] name = "rosetta-config-astar" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "rosetta-core", @@ -14197,6 +14199,7 @@ dependencies = [ [[package]] name = "rosetta-config-ethereum" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "const-hex", @@ -14216,6 +14219,7 @@ dependencies = [ [[package]] name = "rosetta-config-polkadot" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "rosetta-core", @@ -14226,6 +14230,7 @@ dependencies = [ [[package]] name = "rosetta-core" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14242,6 +14247,7 @@ dependencies = [ [[package]] name = "rosetta-crypto" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "bech32", @@ -14267,6 +14273,7 @@ dependencies = [ [[package]] name = "rosetta-ethereum-backend" version = "0.1.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "async-trait", "auto_impl", @@ -14282,6 +14289,7 @@ dependencies = [ [[package]] name = "rosetta-ethereum-types" version = "0.2.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "bytes", "const-hex", @@ -14315,6 +14323,7 @@ dependencies = [ [[package]] name = "rosetta-server" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14337,6 +14346,7 @@ dependencies = [ [[package]] name = "rosetta-server-astar" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14360,6 +14370,7 @@ dependencies = [ [[package]] name = "rosetta-server-ethereum" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14388,6 +14399,7 @@ dependencies = [ [[package]] name = "rosetta-server-polkadot" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "async-trait", @@ -14408,6 +14420,7 @@ dependencies = [ [[package]] name = "rosetta-tx-ethereum" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "rosetta-config-ethereum", @@ -14418,6 +14431,7 @@ dependencies = [ [[package]] name = "rosetta-tx-polkadot" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "anyhow", "blake2-rfc", @@ -14431,6 +14445,7 @@ dependencies = [ [[package]] name = "rosetta-types" version = "0.6.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "serde", "serde_json", @@ -14439,6 +14454,7 @@ dependencies = [ [[package]] name = "rosetta-utils" version = "0.1.0" +source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" dependencies = [ "bytes", "futures-timer", diff --git a/config/envs/development/config.yaml b/config/envs/development/config.yaml index 624baa8ff..8b2e5e1d8 100644 --- a/config/envs/development/config.yaml +++ b/config/envs/development/config.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 1. + chronicle_funds: 1. timechain_url: 'wss://rpc.development.analog.one' prices_path: 'prices.csv' contracts: @@ -14,8 +14,9 @@ networks: blockchain: "rust" network: "0" url: "https://gmp-grpc-1.development.analog.one:443" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -31,8 +32,9 @@ networks: blockchain: "rust" network: "1" url: "https://gmp-grpc-2.development.analog.one:443" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -48,8 +50,9 @@ networks: blockchain: "rust" network: "0" url: "https://gmp-grpc-3.development.analog.one:443" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -65,8 +68,9 @@ networks: blockchain: "rust" network: "1" url: "https://gmp-grpc-4.development.analog.one:443" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -82,8 +86,9 @@ networks: blockchain: "ethereum" network: "sepolia" url: "wss://ethereum-sepolia-rpc.publicnode.com" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: .1 + chronicle_funds: .1 batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -99,8 +104,9 @@ networks: blockchain: "astar" network: "shibuya" url: "wss://rpc.shibuya.astar.network" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: .1 + chronicle_funds: .1 batch_size: 256 batch_offset: 0 batch_gas_limit: 10000 @@ -116,8 +122,9 @@ networks: blockchain: "ethereum" network: "dev" url: "wss://eth-local.development.analog.one" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: .1 + chronicle_funds: .1 batch_size: 256 batch_offset: 0 batch_gas_limit: 10000 diff --git a/config/envs/integration/config.yaml b/config/envs/integration/config.yaml index 42daabb9d..6ba54dee2 100644 --- a/config/envs/integration/config.yaml +++ b/config/envs/integration/config.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 10. + chronicle_funds: 10. timechain_url: 'wss://archive.integration.analog.one' prices_path: 'prices.csv' contracts: @@ -15,7 +15,7 @@ networks: network: "sepolia" url: "wss://ethereum-sepolia-rpc.publicnode.com" gateway_funds: 1. - chronicle_target_funds: .1 + chronicle_funds: .1 batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -31,7 +31,7 @@ networks: network: "shibuya" url: "wss://rpc.shibuya.astar.network" gateway_funds: 1. - chronicle_target_funds: .1 + chronicle_funds: .1 batch_size: 256 batch_offset: 0 batch_gas_limit: 10000 diff --git a/config/envs/local/config.yaml b/config/envs/local/config.yaml index 622f67454..258aa1528 100644 --- a/config/envs/local/config.yaml +++ b/config/envs/local/config.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 10. + chronicle_funds: 10. timechain_url: 'ws://validator:9944' prices_path: 'prices.csv' contracts: @@ -14,8 +14,9 @@ networks: blockchain: "rust" network: "0" url: "http://chain-0-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -29,14 +30,14 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 100. 1: backend: "grpc" blockchain: "rust" network: "1" url: "http://chain-1-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -46,14 +47,14 @@ networks: route_base_fee: 1715000000000 shard_size: 1 shard_threshold: 1 - faucet: 100. 2: backend: "evm" blockchain: "anvil" network: "dev" url: "ws://chain-2-evm:8545" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: 1. + chronicle_funds: 1. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000000 @@ -63,14 +64,14 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 10. 3: backend: "evm" blockchain: "anvil" network: "dev" url: "ws://chain-3-evm:8545" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: 1. + chronicle_funds: 1. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000000 @@ -80,7 +81,6 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 10. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-1-grpc-1:8080 diff --git a/config/envs/local/local-evm.yaml b/config/envs/local/local-evm.yaml index 008580374..c925c4b52 100644 --- a/config/envs/local/local-evm.yaml +++ b/config/envs/local/local-evm.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 10. + chronicle_funds: 10. timechain_url: 'ws://validator:9944' prices_path: 'prices.csv' contracts: @@ -14,8 +14,9 @@ networks: blockchain: "anvil" network: "dev" url: "ws://chain-2-evm:8545" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: 1. + chronicle_funds: 1. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000000 @@ -25,14 +26,14 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 10. 3: backend: "evm" blockchain: "anvil" network: "dev" url: "ws://chain-3-evm:8545" + admin_funds: 100. gateway_funds: 1. - chronicle_target_funds: 1. + chronicle_funds: 1. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000000 @@ -42,7 +43,6 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 10. chronicles: - http://timechain-chronicle-2-evm-1:8080 - http://timechain-chronicle-3-evm-1:8080 diff --git a/config/envs/local/local-grpc-tss.yaml b/config/envs/local/local-grpc-tss.yaml index af1d164d6..6354d7521 100644 --- a/config/envs/local/local-grpc-tss.yaml +++ b/config/envs/local/local-grpc-tss.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 10. + chronicle_funds: 10. timechain_url: 'ws://validator:9944' prices_path: 'prices.csv' contracts: @@ -14,8 +14,9 @@ networks: blockchain: "rust" network: "0" url: "http://chain-0-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -29,14 +30,14 @@ networks: route_base_fee: 1400000000 shard_size: 3 shard_threshold: 2 - faucet: 100. 1: backend: "grpc" blockchain: "rust" network: "1" url: "http://chain-1-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -46,7 +47,6 @@ networks: route_base_fee: 1715000000000 shard_size: 3 shard_threshold: 2 - faucet: 100. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-0-grpc-2:8080 diff --git a/config/envs/local/local-grpc.yaml b/config/envs/local/local-grpc.yaml index 740ec978a..602ea618a 100644 --- a/config/envs/local/local-grpc.yaml +++ b/config/envs/local/local-grpc.yaml @@ -1,5 +1,5 @@ config: - chronicle_timechain_funds: 10. + chronicle_funds: 10. timechain_url: 'ws://validator:9944' prices_path: 'prices.csv' contracts: @@ -14,8 +14,9 @@ networks: blockchain: "rust" network: "0" url: "http://chain-0-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -29,14 +30,14 @@ networks: route_base_fee: 1400000000 shard_size: 1 shard_threshold: 1 - faucet: 100. 1: backend: "grpc" blockchain: "rust" network: "1" url: "http://chain-1-grpc:3000" + admin_funds: 100. gateway_funds: 10. - chronicle_target_funds: 10. + chronicle_funds: 10. batch_size: 64 batch_offset: 0 batch_gas_limit: 10000 @@ -46,7 +47,6 @@ networks: route_base_fee: 1715000000000 shard_size: 1 shard_threshold: 1 - faucet: 100. chronicles: - http://timechain-chronicle-0-grpc-1:8080 - http://timechain-chronicle-1-grpc-1:8080 diff --git a/gmp/evm/Cargo.toml b/gmp/evm/Cargo.toml index ca55c6577..aeaa51eec 100644 --- a/gmp/evm/Cargo.toml +++ b/gmp/evm/Cargo.toml @@ -16,8 +16,7 @@ async-trait.workspace = true futures.workspace = true hex.workspace = true reqwest = { version = "0.12.7", default-features = false, features = ["json", "rustls-tls-native-roots"] } -#rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "37e2cd1" } -rosetta-client = { path = "../../../chain-connectors/rosetta-client" } +rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "84df6f5" } sha3 = { version = "0.10", default-features = false } serde.workspace = true serde_json = "1.0.127" diff --git a/tc-cli/src/config.rs b/tc-cli/src/config.rs index 3b107b54d..8e51f0b4b 100644 --- a/tc-cli/src/config.rs +++ b/tc-cli/src/config.rs @@ -96,7 +96,7 @@ struct ConfigYaml { #[serde(deny_unknown_fields)] pub struct GlobalConfig { prices_path: PathBuf, - pub chronicle_timechain_funds: String, + pub chronicle_funds: String, pub timechain_url: String, } @@ -124,8 +124,9 @@ pub struct NetworkConfig { pub blockchain: String, pub network: String, pub url: String, + pub admin_funds: Option, pub gateway_funds: String, - pub chronicle_target_funds: String, + pub chronicle_funds: String, pub batch_size: u32, pub batch_offset: u32, pub batch_gas_limit: u128, @@ -135,7 +136,6 @@ pub struct NetworkConfig { pub route_base_fee: u128, pub shard_size: u16, pub shard_threshold: u16, - pub faucet: Option, } #[cfg(test)] diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 661a8c0e8..8df54b78c 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -216,9 +216,15 @@ impl Tc { pub async fn faucet(&self, network: NetworkId) -> Result<()> { let config = self.config.network(network)?; - let faucet = - config.faucet.as_ref().context("faucet not supported, please prefund account")?; - let faucet = self.parse_balance(Some(network), faucet)?; + let Some(admin_funds) = config.admin_funds.as_ref() else { + return Ok(()); + }; + let admin_funds = self.parse_balance(Some(network), admin_funds)?; + let current_admin_funds = self.balance(Some(network), self.address(Some(network))?).await?; + let faucet = admin_funds - current_admin_funds; + if faucet <= 0 { + return Ok(()); + } self.println( None, format!("faucet {network} {}", self.format_balance(Some(network), faucet)?), @@ -857,9 +863,7 @@ impl Tc { impl Tc { pub async fn deploy_network(&self, network: NetworkId) -> Result { let config = self.config.network(network)?; - if self.balance(Some(network), self.address(Some(network))?).await? == 0 { - self.faucet(network).await?; - } + self.faucet(network).await?; let gateway = self.register_network(network).await?; let gateway_funds = self.parse_balance(Some(network), &config.gateway_funds)?; self.fund(Some(network), gateway, gateway_funds, "gateway").await?; @@ -868,16 +872,16 @@ impl Tc { pub async fn deploy_chronicle(&self, chronicle: &str) -> Result<()> { let chronicle = self.wait_for_chronicle(chronicle).await?; - let funds = self.parse_balance(None, &self.config.global().chronicle_timechain_funds)?; + let funds = self.parse_balance(None, &self.config.global().chronicle_funds)?; self.fund(None, chronicle.account.clone().into(), funds, "chronicle timechain account") .await?; let config = self.config.network(chronicle.network)?; - let chronicle_target_funds = - self.parse_balance(Some(chronicle.network), &config.chronicle_target_funds)?; + let chronicle_funds = + self.parse_balance(Some(chronicle.network), &config.chronicle_funds)?; self.fund( Some(chronicle.network), chronicle.address, - chronicle_target_funds, + chronicle_funds, "chronicle target account", ) .await?; From a6ec4ff57502cdb11d0538f469160ecc1dca27fa Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 12:32:40 +0100 Subject: [PATCH 07/26] Fix clippy. --- tc-cli/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 8df54b78c..03497f99d 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -222,7 +222,7 @@ impl Tc { let admin_funds = self.parse_balance(Some(network), admin_funds)?; let current_admin_funds = self.balance(Some(network), self.address(Some(network))?).await?; let faucet = admin_funds - current_admin_funds; - if faucet <= 0 { + if faucet == 0 { return Ok(()); } self.println( From 3c654f3e91aca16bd3f551d38aceb9117e9599a9 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 12:40:33 +0100 Subject: [PATCH 08/26] Enable tracing. --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5a8533452..fe8774dd2 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -78,7 +78,7 @@ services: chain-2-evm: image: 'ghcr.io/foundry-rs/foundry:latest' command: - - 'anvil -b 2' + - 'anvil -b 2 --steps-tracing' environment: ANVIL_IP_ADDR: '0.0.0.0' profiles: @@ -104,7 +104,7 @@ services: chain-3-evm: image: 'ghcr.io/foundry-rs/foundry:latest' command: - - 'anvil -b 2' + - 'anvil -b 2 --steps-tracing' environment: ANVIL_IP_ADDR: '0.0.0.0' profiles: From 6fc8ca92e91c02e1bf044b6c064072b631afd117 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 14:53:09 +0100 Subject: [PATCH 09/26] Use relative paths. --- analog-gmp/foundry.toml | 2 +- analog-gmp/remappings.txt | 8 -------- analog-gmp/src/GatewayProxy.sol | 2 +- analog-gmp/test/Batching.t.sol | 4 ++-- analog-gmp/test/GatewayProxy.t.sol | 4 ++-- analog-gmp/test/GmpTestTools.sol | 2 +- analog-gmp/test/MockERC20.sol | 2 +- analog-gmp/test/TestUtils.sol | 8 ++++---- analog-gmp/test/utils/BaseTest.sol | 6 +++--- 9 files changed, 15 insertions(+), 23 deletions(-) delete mode 100644 analog-gmp/remappings.txt diff --git a/analog-gmp/foundry.toml b/analog-gmp/foundry.toml index 82cb75a8d..3f1eb27e5 100644 --- a/analog-gmp/foundry.toml +++ b/analog-gmp/foundry.toml @@ -21,7 +21,7 @@ solc = '0.8.28' # - https://ethereumclassic.org/knowledge/history evm_version = 'shanghai' optimizer = true -optimizer_runs = 200000 +optimizer_runs = 500000 ############### # EVM options # diff --git a/analog-gmp/remappings.txt b/analog-gmp/remappings.txt deleted file mode 100644 index bf85bb85a..000000000 --- a/analog-gmp/remappings.txt +++ /dev/null @@ -1,8 +0,0 @@ -forge-std/=lib/forge-std/src/ -@frost-evm/=lib/frost-evm/sol/ -@solmate/=lib/solmate/src/ -ds-test/=lib/solmate/lib/ds-test/src/ -@universal-factory/=lib/universal-factory/src/ -@evm-interpreter/=lib/evm-interpreter/src/ -@analog-gmp/=src/ -@analog-gmp-testing/=test/ diff --git a/analog-gmp/src/GatewayProxy.sol b/analog-gmp/src/GatewayProxy.sol index e6bf128b0..65566d251 100644 --- a/analog-gmp/src/GatewayProxy.sol +++ b/analog-gmp/src/GatewayProxy.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.0; import {ERC1967} from "./utils/ERC1967.sol"; -import {Context, CreateKind, IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; +import {Context, CreateKind, IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol"; contract GatewayProxy { /** diff --git a/analog-gmp/test/Batching.t.sol b/analog-gmp/test/Batching.t.sol index 573103f3a..5de543620 100644 --- a/analog-gmp/test/Batching.t.sol +++ b/analog-gmp/test/Batching.t.sol @@ -5,8 +5,8 @@ pragma solidity >=0.8.0; import {Test, console, Vm} from "forge-std/Test.sol"; import {VmSafe} from "forge-std/Vm.sol"; -import {FactoryUtils} from "@universal-factory/FactoryUtils.sol"; -import {IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; +import {FactoryUtils} from "../lib/universal-factory/src/FactoryUtils.sol"; +import {IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol"; import {TestUtils, SigningKey, SigningUtils} from "./TestUtils.sol"; import {GasSpender} from "./utils/GasSpender.sol"; import {BaseTest} from "./utils/BaseTest.sol"; diff --git a/analog-gmp/test/GatewayProxy.t.sol b/analog-gmp/test/GatewayProxy.t.sol index 66e904997..5d6c97cac 100644 --- a/analog-gmp/test/GatewayProxy.t.sol +++ b/analog-gmp/test/GatewayProxy.t.sol @@ -3,8 +3,8 @@ pragma solidity >=0.8.0; -import {IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; -import {FactoryUtils} from "@universal-factory/FactoryUtils.sol"; +import {IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol"; +import {FactoryUtils} from "../lib/universal-factory/src/FactoryUtils.sol"; import {Test, console} from "forge-std/Test.sol"; import {VmSafe} from "forge-std/Vm.sol"; import {TestUtils, SigningKey, SigningUtils} from "./TestUtils.sol"; diff --git a/analog-gmp/test/GmpTestTools.sol b/analog-gmp/test/GmpTestTools.sol index eded8415e..c00c087c3 100644 --- a/analog-gmp/test/GmpTestTools.sol +++ b/analog-gmp/test/GmpTestTools.sol @@ -11,7 +11,7 @@ import {GatewayProxy} from "../src/GatewayProxy.sol"; import {IGateway} from "../src/interfaces/IGateway.sol"; import {BranchlessMath} from "../src/utils/BranchlessMath.sol"; import {GmpMessage, TssKey, Network, Signature, GmpSender, PrimitiveUtils} from "../src/Primitives.sol"; -import {IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; +import {IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol"; library GmpTestTools { /** diff --git a/analog-gmp/test/MockERC20.sol b/analog-gmp/test/MockERC20.sol index d7c39b246..22fad2006 100644 --- a/analog-gmp/test/MockERC20.sol +++ b/analog-gmp/test/MockERC20.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.0; -import {ERC20} from "@solmate/tokens/ERC20.sol"; +import {ERC20} from "../lib/solmate/src/tokens/ERC20.sol"; import {IGmpReceiver} from "../src/interfaces/IGmpReceiver.sol"; import {IGateway} from "../src/interfaces/IGateway.sol"; diff --git a/analog-gmp/test/TestUtils.sol b/analog-gmp/test/TestUtils.sol index bbeaf7a07..6ec189582 100644 --- a/analog-gmp/test/TestUtils.sol +++ b/analog-gmp/test/TestUtils.sol @@ -5,11 +5,11 @@ pragma solidity >=0.8.0; import {VmSafe, Vm} from "forge-std/Vm.sol"; import {console} from "forge-std/console.sol"; -import {Schnorr} from "@frost-evm/Schnorr.sol"; -import {SECP256K1} from "@frost-evm/SECP256K1.sol"; +import {Schnorr} from "../lib/frost-evm/sol/Schnorr.sol"; +import {SECP256K1} from "../lib/frost-evm/sol/SECP256K1.sol"; import {BranchlessMath} from "../src/utils/BranchlessMath.sol"; -import {IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; -import {FactoryUtils} from "@universal-factory/FactoryUtils.sol"; +import {IUniversalFactory} from "../lib/universal-factory/src/IUniversalFactory.sol"; +import {FactoryUtils} from "../lib/universal-factory/src/FactoryUtils.sol"; import {IGateway} from "../src/interfaces/IGateway.sol"; import {Gateway, GatewayEIP712} from "../src/Gateway.sol"; import {GatewayProxy} from "../src/GatewayProxy.sol"; diff --git a/analog-gmp/test/utils/BaseTest.sol b/analog-gmp/test/utils/BaseTest.sol index 9559308ec..1eeedbb6e 100644 --- a/analog-gmp/test/utils/BaseTest.sol +++ b/analog-gmp/test/utils/BaseTest.sol @@ -3,9 +3,9 @@ pragma solidity >=0.8.0; -import {IUniversalFactory} from "@universal-factory/IUniversalFactory.sol"; -import {FactoryUtils} from "@universal-factory/FactoryUtils.sol"; -import {Interpreter} from "@evm-interpreter/Interpreter.sol"; +import {IUniversalFactory} from "../../lib/universal-factory/src/IUniversalFactory.sol"; +import {FactoryUtils} from "../../lib/universal-factory/src/FactoryUtils.sol"; +import {Interpreter} from "../../lib/evm-interpreter/src/Interpreter.sol"; import {Test, console, Vm} from "forge-std/Test.sol"; import {VmSafe} from "forge-std/Vm.sol"; From f435efd692783f943ca32dc349367eb81cb044be Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 15:03:23 +0100 Subject: [PATCH 10/26] Fix tests. --- gmp/rust/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gmp/rust/src/lib.rs b/gmp/rust/src/lib.rs index d9a899da9..a5d9a33e2 100644 --- a/gmp/rust/src/lib.rs +++ b/gmp/rust/src/lib.rs @@ -601,8 +601,8 @@ mod tests { let chain = connector(network, 0).await?; let shard = MockTssSigner::new(0); assert_eq!(chain.balance(chain.address()).await?, 0); - chain.faucet().await?; - assert_eq!(chain.balance(chain.address()).await?, FAUCET); + chain.faucet(100_000).await?; + assert_eq!(chain.balance(chain.address()).await?, 100_000); let (gateway, block) = chain.deploy_gateway("".as_ref(), "".as_ref(), "".as_ref()).await?; chain.transfer(gateway, 10_000).await?; assert_eq!(chain.balance(gateway).await?, 10_000); From fbe9f957e5a6fbf730996885aed9e99873dfda7a Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 12:51:31 +0100 Subject: [PATCH 11/26] Add debug-transaction command. --- primitives/src/gmp.rs | 4 ++++ tc-cli/src/lib.rs | 5 +++++ tc-cli/src/main.rs | 12 +++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/primitives/src/gmp.rs b/primitives/src/gmp.rs index c42210a2b..768850d07 100644 --- a/primitives/src/gmp.rs +++ b/primitives/src/gmp.rs @@ -425,6 +425,10 @@ pub trait IConnectorAdmin: IConnector { async fn block_gas_limit(&self) -> Result; /// Withdraw gateway funds. async fn withdraw_funds(&self, gateway: Address, amount: u128, address: Address) -> Result<()>; + /// Debug a transaction. + async fn debug_transaction(&self, _tx: Hash) -> Result { + anyhow::bail!("debugging transactions is not supported on this backend"); + } } #[cfg(feature = "std")] diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 03497f99d..6a51b4ab9 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -1103,4 +1103,9 @@ impl Tc { let logs = loki::logs(query, since).await?; self.print_table(None, "logs", logs).await } + + pub async fn debug_transaction(&self, network: NetworkId, hash: Hash) -> Result { + let connector = self.connector(network)?; + connector.debug_transaction(hash).await + } } diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index d5c802c91..ef04ec7c6 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -5,7 +5,7 @@ use std::collections::HashSet; use std::path::PathBuf; use std::str::FromStr; use tc_cli::{Query, Sender, Tc}; -use time_primitives::{BatchId, GmpMessage, NetworkId, ShardId, TaskId}; +use time_primitives::{BatchId, GmpMessage, Hash, NetworkId, ShardId, TaskId}; use tracing_subscriber::filter::EnvFilter; #[derive(Clone, Debug)] @@ -174,6 +174,10 @@ enum Command { ForceShardOffline { shard_id: ShardId, }, + DebugTransaction { + network: NetworkId, + hash: String, + }, } #[tokio::main] @@ -461,6 +465,12 @@ async fn real_main() -> Result<()> { let address = tc.parse_address(Some(network), &address)?; tc.withdraw_funds(network, amount, address).await?; }, + Command::DebugTransaction { network, hash } => { + let hash: Hash = + hex::decode(&hash)?.try_into().map_err(|_| anyhow::anyhow!("invalid hash"))?; + let output = tc.debug_transaction(network, hash).await?; + tc.println(None, output).await?; + }, } tracing::info!("executed query in {}s", now.elapsed().unwrap().as_secs()); Ok(()) From a379046d4f23ba2767d34bb7e5ad259aa1c2f917 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 15:52:16 +0100 Subject: [PATCH 12/26] Implement debug_transaction. --- config/docker/Dockerfile.tc-cli | 3 +++ gmp/evm/src/lib.rs | 21 ++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/config/docker/Dockerfile.tc-cli b/config/docker/Dockerfile.tc-cli index f68b94a0d..c0d250160 100644 --- a/config/docker/Dockerfile.tc-cli +++ b/config/docker/Dockerfile.tc-cli @@ -1,8 +1,11 @@ FROM alpine:latest as certs RUN apk --update add ca-certificates +FROM ghcr.io/foundry-rs/foundry:latest as foundry + FROM scratch COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=foundry /usr/local/bin/cast cast COPY tc-cli tc-cli COPY envs /etc/envs ENTRYPOINT ["/tc-cli"] diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index c3862acbc..d860bd4d3 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -20,10 +20,11 @@ use sha3::{Digest, Keccak256}; use sol::{u256, Network, TssKey}; use std::ops::Range; use std::pin::Pin; +use std::process::Command; use std::sync::Arc; use thiserror::Error; use time_primitives::{ - Address, BatchId, ConnectorParams, Gateway, GatewayMessage, GmpEvent, GmpMessage, IChain, + Address, BatchId, ConnectorParams, Gateway, GatewayMessage, GmpEvent, GmpMessage, Hash, IChain, IConnector, IConnectorAdmin, IConnectorBuilder, MessageId, NetworkId, Route, TssPublicKey, TssSignature, }; @@ -54,6 +55,7 @@ pub struct Connector { network_id: NetworkId, wallet: Arc, backend: Adapter, + url: String, cctp_sender: Option, cctp_attestation: String, cctp_queue: Arc>>, @@ -395,6 +397,7 @@ impl IConnectorBuilder for Connector { network_id: params.network_id, wallet, backend: adapter, + url: params.url, cctp_sender: params.cctp_sender, cctp_attestation: params.cctp_attestation.unwrap_or("".into()), cctp_queue: Default::default(), @@ -777,6 +780,22 @@ impl IConnectorAdmin for Connector { self.evm_call(gateway, call, 0, None, None).await?; Ok(()) } + /// Debug a transaction. + async fn debug_transaction(&self, hash: Hash) -> Result { + let output = Command::new("cast") + .arg("run") + .arg("--rpc-url") + .arg(&self.url) + .arg(hex::encode(hash)) + .output() + .context("failed to run cast")?; + if !output.status.success() { + let err = std::str::from_utf8(&output.stderr).ok().unwrap_or_default(); + anyhow::bail!("cast exited with {}: {err}", output.status); + } + let stdout = std::str::from_utf8(&output.stdout)?; + Ok(stdout.into()) + } } fn compute_create2_address( From ef1733068fb3e260d20f49a1e91cef2373340dc8 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 16:26:23 +0100 Subject: [PATCH 13/26] Cleanup gmp-evm txs. --- gmp/evm/src/lib.rs | 90 +++++++++++++++++++++++++--------------------- tc-cli/src/main.rs | 2 +- 2 files changed, 50 insertions(+), 42 deletions(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index d860bd4d3..7a17df56b 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -75,6 +75,38 @@ impl Connector { .await } + async fn raw_evm_call( + &self, + contract: [u8; 20], + call: Vec, + amount: u128, + nonce: Option, + gas_limit: Option, + ) -> Result<(Vec, TransactionReceipt, [u8; 32])> { + let result = self.wallet.eth_send_call(contract, call, amount, nonce, gas_limit).await?; + let (result, receipt, tx_hash) = match result { + SubmitResult::Executed { result, receipt, tx_hash } => (result, receipt, tx_hash), + SubmitResult::Timeout { tx_hash } => { + anyhow::bail!("tx 0x{} timed out", hex::encode(tx_hash)) + }, + }; + let result = match result { + CallResult::Success(result) => { + tracing::info!("tx 0x{} succeeded", hex::encode(tx_hash)); + result + }, + CallResult::Revert(reason) => { + anyhow::bail!( + "tx 0x{} reverted because {}", + hex::encode(tx_hash), + hex::encode(reason) + ); + }, + CallResult::Error => anyhow::bail!("tx 0x{} failed", hex::encode(tx_hash)), + }; + Ok((result, receipt, tx_hash.into())) + } + async fn evm_call( &self, contract: Address, @@ -84,20 +116,9 @@ impl Connector { gas_limit: Option, ) -> Result<(T::Return, TransactionReceipt, [u8; 32])> { let contract: [u8; 20] = contract[12..32].try_into().unwrap(); - let result = self - .wallet - .eth_send_call(contract, call.abi_encode(), amount, nonce, gas_limit) - .await?; - let SubmitResult::Executed { - result: CallResult::Success(result), - receipt, - tx_hash, - } = result - else { - anyhow::bail!("{:?}", result) - }; - tracing::info!("evm_call success: {:?}", tx_hash); - Ok((T::abi_decode_returns(&result, true)?, receipt, tx_hash.into())) + let (result, receipt, tx_hash) = + self.raw_evm_call(contract, call.abi_encode(), amount, nonce, gas_limit).await?; + Ok((T::abi_decode_returns(&result, true)?, receipt, tx_hash)) } async fn evm_view( @@ -134,33 +155,20 @@ impl Connector { factory_address: [u8; 20], call: Vec, ) -> Result<(AlloyAddress, u64)> { - let result = self - .wallet - .eth_send_call(factory_address, call, 0, None, Some(20_000_000)) - .await?; - let SubmitResult::Executed { result, receipt, tx_hash } = result else { - anyhow::bail!("tx timed out"); - }; - match result { - CallResult::Success(_) => { - let log = receipt - .logs - .iter() - .find(|log| log.address.as_bytes() == factory_address) - .with_context(|| format!("Log with factory address not found: {}", tx_hash))?; - let topic = log - .topics - .first() - .with_context(|| "Unable to find topics in tx receipt")? - .as_bytes(); - let contract_address = AlloyAddress::from_slice(&topic[12..]); - Ok((contract_address, receipt.block_number.unwrap())) - }, - CallResult::Revert(reason) => { - anyhow::bail!("Deployment reverted: {tx_hash:?}: {:?}", hex::encode(reason)) - }, - CallResult::Error => anyhow::bail!("Failed to deploy contract"), - } + let (_, receipt, tx_hash) = + self.raw_evm_call(factory_address, call, 0, None, Some(20_000_000)).await?; + let log = receipt + .logs + .iter() + .find(|log| log.address.as_bytes() == factory_address) + .with_context(|| format!("tx {} logs not found", hex::encode(tx_hash)))?; + let topic = log + .topics + .first() + .with_context(|| format!("tx {} topic not found", hex::encode(tx_hash)))? + .as_bytes(); + let contract_address = AlloyAddress::from_slice(&topic[12..]); + Ok((contract_address, receipt.block_number.unwrap())) } async fn deploy_factory(&self, config: &DeploymentConfig) -> Result<()> { diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index ef04ec7c6..27aeb5d5d 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -194,7 +194,7 @@ async fn main() { } async fn real_main() -> Result<()> { - let filter = EnvFilter::from_default_env().add_directive("tc_cli=info".parse()?); + let filter = EnvFilter::from_default_env().add_directive("tc_cli=info,gmp_evm=info".parse()?); tracing_subscriber::fmt().with_env_filter(filter).init(); let sender = Sender::new(); let args = Args::parse(); From b10c59119fba9b199ccf7bbb7d57444aad0ea89d Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 16:39:40 +0100 Subject: [PATCH 14/26] More cleanup. --- gmp/evm/src/lib.rs | 6 +++--- tc-cli/src/main.rs | 4 +++- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 7a17df56b..3c19c77f1 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -183,7 +183,7 @@ impl Connector { //Step3: send eth_rawTransaction let tx_hash = self.backend.send_raw_transaction(tx.into()).await?; - tracing::info!("factory deployed with tx: {:?}", tx_hash); + tracing::info!("factory deployed with tx {}", tx_hash); Ok(()) } @@ -213,7 +213,7 @@ impl Connector { let factory_address = a_addr(self.parse_address(&config.factory_address)?).0 .0; let (gateway_address, _) = self.deploy_contract_with_factory(factory_address, gateway_create_call).await?; - tracing::info!("gateway deployed at: {:?}", gateway_address); + tracing::info!("gateway deployed at {}", gateway_address); Ok(gateway_address) } @@ -292,7 +292,7 @@ impl Connector { proxy_address ); } - tracing::info!("proxy deployed at: {}", proxy_address); + tracing::info!("proxy deployed at {}", proxy_address); Ok((proxy_address, block)) } diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index 27aeb5d5d..7bfbe7c5b 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -194,7 +194,9 @@ async fn main() { } async fn real_main() -> Result<()> { - let filter = EnvFilter::from_default_env().add_directive("tc_cli=info,gmp_evm=info".parse()?); + let filter = EnvFilter::from_default_env() + .add_directive("tc_cli=info".parse().unwrap()) + .add_directive("gmp_evm=info".parse().unwrap()); tracing_subscriber::fmt().with_env_filter(filter).init(); let sender = Sender::new(); let args = Args::parse(); From 75cde96362d94a6647930b85aef8989a1bf43439 Mon Sep 17 00:00:00 2001 From: David Craven Date: Wed, 12 Feb 2025 17:04:49 +0100 Subject: [PATCH 15/26] Get it working. --- config/docker/Dockerfile.tc-cli | 12 ++++-------- tc-cli/src/main.rs | 3 ++- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/config/docker/Dockerfile.tc-cli b/config/docker/Dockerfile.tc-cli index c0d250160..3805d572d 100644 --- a/config/docker/Dockerfile.tc-cli +++ b/config/docker/Dockerfile.tc-cli @@ -1,11 +1,7 @@ -FROM alpine:latest as certs -RUN apk --update add ca-certificates - FROM ghcr.io/foundry-rs/foundry:latest as foundry -FROM scratch -COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=foundry /usr/local/bin/cast cast -COPY tc-cli tc-cli +FROM ubuntu:22.04 +COPY --from=foundry /usr/local/bin/cast /bin/cast +COPY tc-cli /bin/tc-cli COPY envs /etc/envs -ENTRYPOINT ["/tc-cli"] +ENTRYPOINT ["/bin/tc-cli"] diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index 7bfbe7c5b..66ff079a7 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -468,8 +468,9 @@ async fn real_main() -> Result<()> { tc.withdraw_funds(network, amount, address).await?; }, Command::DebugTransaction { network, hash } => { + let hash = hash.strip_prefix("0x").unwrap_or(&hash); let hash: Hash = - hex::decode(&hash)?.try_into().map_err(|_| anyhow::anyhow!("invalid hash"))?; + hex::decode(hash)?.try_into().map_err(|_| anyhow::anyhow!("invalid hash"))?; let output = tc.debug_transaction(network, hash).await?; tc.println(None, output).await?; }, From 61dc23826e5dbf6ecb8483012510e4b56b7f915f Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 09:42:52 +0100 Subject: [PATCH 16/26] Add source debugging. --- config/docker/Dockerfile.tc-cli | 2 ++ gmp/evm/src/lib.rs | 4 ++++ scripts/build_docker.sh | 2 ++ 3 files changed, 8 insertions(+) diff --git a/config/docker/Dockerfile.tc-cli b/config/docker/Dockerfile.tc-cli index 3805d572d..fe65bdba7 100644 --- a/config/docker/Dockerfile.tc-cli +++ b/config/docker/Dockerfile.tc-cli @@ -4,4 +4,6 @@ FROM ubuntu:22.04 COPY --from=foundry /usr/local/bin/cast /bin/cast COPY tc-cli /bin/tc-cli COPY envs /etc/envs +COPY analog-gmp /analog-gmp +ENV ANALOG_GMP_DIR /analog-gmp ENTRYPOINT ["/bin/tc-cli"] diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 3c19c77f1..1ea5592ce 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -790,10 +790,14 @@ impl IConnectorAdmin for Connector { } /// Debug a transaction. async fn debug_transaction(&self, hash: Hash) -> Result { + let analog_gmp_dir = + std::env::var("ANALOG_GMP_DIR").context("failed to find ANALOG_GMP_DIR")?; let output = Command::new("cast") + .current_dir(analog_gmp_dir) .arg("run") .arg("--rpc-url") .arg(&self.url) + .arg("--with-local-artifacts") .arg(hex::encode(hash)) .output() .context("failed to run cast")?; diff --git a/scripts/build_docker.sh b/scripts/build_docker.sh index c2ffb2089..eaeb8a11e 100755 --- a/scripts/build_docker.sh +++ b/scripts/build_docker.sh @@ -68,6 +68,8 @@ forge build --root analog-gmp mkdir -p target/docker/tc-cli rm -rf target/docker/tc-cli/envs cp -rL config/envs target/docker/tc-cli/envs +rm -rf target/docker/tc-cli/analog-gmp +cp -r analog-gmp target/docker/tc-cli/analog-gmp build_image () { local TARGET="target/$rustTarget/$profile/$1" From e1955c199d0d8c66dbd03fd47c6621bfdba61328 Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 09:43:05 +0100 Subject: [PATCH 17/26] Nits logs. --- gmp/evm/src/lib.rs | 8 +++++++- tc-cli/src/lib.rs | 10 +++++----- tc-cli/src/main.rs | 5 +++-- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 1ea5592ce..c0e36c142 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -145,6 +145,12 @@ impl Connector { let tx_receipt = self.wallet.eth_transaction_receipt(tx_hash).await?.unwrap(); let address = tx_receipt.contract_address.unwrap(); let block_number = tx_receipt.block_number.unwrap(); + tracing::info!( + "contract deployed at {:?} in block {} with tx {:?}", + address, + block_number, + tx_hash + ); Ok((t_addr(address.0.into()), block_number)) } @@ -183,7 +189,7 @@ impl Connector { //Step3: send eth_rawTransaction let tx_hash = self.backend.send_raw_transaction(tx.into()).await?; - tracing::info!("factory deployed with tx {}", tx_hash); + tracing::info!("factory deployed with tx {:?}", tx_hash); Ok(()) } diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 6a51b4ab9..81921b211 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -954,15 +954,15 @@ impl Tc { let connector = self.connector(msg.src_network)?; let dest_network = msg.dest_network; let dest = msg.dest; - let gas_cost = msg.gas_cost; + let gas_cost = self.format_balance(Some(msg.src_network), msg.gas_cost)?; let id = self .println( None, format!( - "send message to {} {} @{}gas", + "send message to {} {} with {}", dest_network, self.format_address(Some(dest_network), dest)?, - gas_cost, + &gas_cost, ), ) .await?; @@ -970,11 +970,11 @@ impl Tc { self.println( Some(id), format!( - "sent message {} to {} {} @{}gas", + "sent message {} to {} {} with {}", hex::encode(msg_id), dest_network, self.format_address(Some(dest_network), dest)?, - gas_cost, + &gas_cost, ), ) .await?; diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index 66ff079a7..ffc639910 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -440,14 +440,15 @@ async fn real_main() -> Result<()> { let num_received = num_messages - msgs.len() as u16; let blocks = block - start; let throughput = num_received as f64 / blocks as f64; - let avg_gas_cost = gas_cost / num_messages as u128; + let avg_msg_cost = gas_cost / num_messages as u128; + let avg_msg_cost = tc.format_balance(Some(src), avg_msg_cost)?; id = Some( tc.println( id, format!( r#"{num_received} out of {num_messages} received in {blocks} blocks throughput {throughput:.3} msgs/block - avg gas cost {avg_gas_cost}"# + avg msg cost {avg_msg_cost}"# ), ) .await?, From 527f0cc4a0e0384c7d8e9f43a4fa4533d2ff090f Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 18:22:40 +0100 Subject: [PATCH 18/26] Estimate gas limit. --- gmp/evm/src/lib.rs | 70 +++++++++++++++++++++++++++++++++++-------- gmp/evm/src/sol.rs | 7 +++++ gmp/grpc/build.rs | 1 + gmp/grpc/src/lib.rs | 54 +++++++++++++++++++++++++++++---- gmp/grpc/src/main.rs | 23 ++++++++++++-- gmp/grpc/src/proto.rs | 26 ++++++++++++++-- gmp/rust/src/lib.rs | 65 ++++++++++++++++++++++++++++++---------- primitives/src/gmp.rs | 26 ++++++++++++++-- tc-cli/src/lib.rs | 33 ++++++++++++-------- tc-cli/src/main.rs | 16 +++------- 10 files changed, 257 insertions(+), 64 deletions(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index c0e36c142..0e648f2c2 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -695,15 +695,47 @@ impl IConnectorAdmin for Connector { self.evm_call(gateway, call, 0, None, None).await?; Ok(()) } + /// Estimates the message gas limit. + async fn estimate_message_gas_limit( + &self, + contract: Address, + src_network: NetworkId, + src: Address, + payload: Vec, + ) -> Result { + let call = sol::IGmpReceiver::onGmpReceivedCall { + id: [0; 32].into(), + network: src_network.into(), + source: src.into(), + payload: payload.into(), + }; + let gas_limit = self + .wallet + .eth_send_call_estimate_gas(a_addr(contract).into(), call.abi_encode(), 0) + .await?; + Ok(gas_limit) + } /// Estimates the message cost. - async fn estimate_message_cost(&self, gateway: Address, msg: &GmpMessage) -> Result { - let dest = msg.dest_network; - let gas_limit = msg.gas_limit; - let msg: sol::GmpMessage = msg.clone().into(); - let bytes = msg.abi_encode(); + async fn estimate_message_cost( + &self, + gateway: Address, + dest_network: NetworkId, + gas_limit: u128, + payload: Vec, + ) -> Result { + let msg = sol::GmpMessage { + source: [0; 32].into(), + srcNetwork: 0, + dest: [0; 20].into(), + destNetwork: 0, + gasLimit: 0, + nonce: 0, + data: payload.into(), + }; let call = sol::Gateway::estimateMessageCostCall { - networkid: dest, - messageSize: U256::from(bytes.len()), + networkid: dest_network, + // abi_encoded_size returns the size without the 4 byte selector + messageSize: U256::from(msg.abi_encoded_size() + 4), gasLimit: U256::from(gas_limit), }; let result = self.evm_view(gateway, call, None).await?; @@ -716,12 +748,26 @@ impl IConnectorAdmin for Connector { .await } /// Sends a message using the test contract. - async fn send_message(&self, msg: GmpMessage) -> Result { - anyhow::ensure!(msg.src_network == self.network_id, "invalid source network id"); - let src = msg.src; - let gas_cost = msg.gas_cost; + async fn send_message( + &self, + contract: Address, + dest_network: NetworkId, + dest: Address, + gas_limit: u128, + gas_cost: u128, + payload: Vec, + ) -> Result { + let msg = sol::GmpMessage { + srcNetwork: self.network_id, + source: contract.into(), + destNetwork: dest_network, + dest: a_addr(dest), + nonce: 0, + gasLimit: gas_limit as _, + data: payload.into(), + }; let call = sol::GmpTester::sendMessageCall { msg: msg.into() }; - let result = self.evm_call(src, call, gas_cost, None, None).await?; + let result = self.evm_call(contract, call, gas_cost, None, None).await?; let id: MessageId = *result.0._0; Ok(id) } diff --git a/gmp/evm/src/sol.rs b/gmp/evm/src/sol.rs index bf8e396dd..1e0eb6067 100644 --- a/gmp/evm/src/sol.rs +++ b/gmp/evm/src/sol.rs @@ -184,6 +184,13 @@ alloy_sol_types::sol! { payable returns (address); } + + interface IGmpReceiver { + function onGmpReceived(bytes32 id, uint128 network, bytes32 source, bytes calldata payload) + external + payable + returns (bytes32); + } } pub fn u256(bytes: &[u8]) -> U256 { diff --git a/gmp/grpc/build.rs b/gmp/grpc/build.rs index cf469d2a7..968e58ec2 100644 --- a/gmp/grpc/build.rs +++ b/gmp/grpc/build.rs @@ -29,6 +29,7 @@ fn main() { .method(method("routes", "Routes").build()) .method(method("set_route", "SetRoute").build()) .method(method("deploy_test", "DeployTest").build()) + .method(method("estimate_message_gas_limit", "EstimateMessageGasLimit").build()) .method(method("estimate_message_cost", "EstimateMessageCost").build()) .method(method("send_message", "SendMessage").build()) .method(method("recv_messages", "RecvMessages").build()) diff --git a/gmp/grpc/src/lib.rs b/gmp/grpc/src/lib.rs index 924103a89..186971cae 100644 --- a/gmp/grpc/src/lib.rs +++ b/gmp/grpc/src/lib.rs @@ -255,15 +255,59 @@ impl IConnectorAdmin for Connector { let response = self.client.lock().await.deploy_test(request).await?.into_inner(); Ok((response.address, response.block)) } + /// Estimates the message gas limit. + async fn estimate_message_gas_limit( + &self, + contract: Address, + src_network: NetworkId, + src: Address, + payload: Vec, + ) -> Result { + let request = Request::new(proto::EstimateMessageGasLimitRequest { + contract, + src_network, + src, + payload, + }); + let response = + self.client.lock().await.estimate_message_gas_limit(request).await?.into_inner(); + Ok(response.gas_limit) + } /// Estimates the message cost. - async fn estimate_message_cost(&self, gateway: Address, msg: &GmpMessage) -> Result { - let request = Request::new(proto::EstimateMessageCostRequest { gateway, msg: msg.clone() }); + async fn estimate_message_cost( + &self, + gateway: Address, + dest_network: NetworkId, + gas_limit: u128, + payload: Vec, + ) -> Result { + let request = Request::new(proto::EstimateMessageCostRequest { + gateway, + dest_network, + gas_limit, + payload, + }); let response = self.client.lock().await.estimate_message_cost(request).await?.into_inner(); Ok(response.cost) } - /// Sends a message using the test contract. - async fn send_message(&self, msg: GmpMessage) -> Result { - let request = Request::new(proto::SendMessageRequest { msg }); + /// Sends a message using the test contract and returns the message id. + async fn send_message( + &self, + src: Address, + dest_network: NetworkId, + dest: Address, + gas_limit: u128, + gas_cost: u128, + payload: Vec, + ) -> Result { + let request = Request::new(proto::SendMessageRequest { + src, + dest_network, + dest, + gas_limit, + gas_cost, + payload, + }); let response = self.client.lock().await.send_message(request).await?.into_inner(); Ok(response.message_id) } diff --git a/gmp/grpc/src/main.rs b/gmp/grpc/src/main.rs index ba1875122..dfa10e9c1 100644 --- a/gmp/grpc/src/main.rs +++ b/gmp/grpc/src/main.rs @@ -246,13 +246,25 @@ impl Gmp for ConnectorWrapper { Ok(Response::new(proto::DeployTestResponse { address, block })) } + async fn estimate_message_gas_limit( + &self, + request: Request, + ) -> GmpResult { + let (connector, msg) = self.connector(request)?; + let gas_limit = connector + .estimate_message_gas_limit(msg.contract, msg.src_network, msg.src, msg.payload) + .await + .map_err(|err| Status::unknown(err.to_string()))?; + Ok(Response::new(proto::EstimateMessageGasLimitResponse { gas_limit })) + } + async fn estimate_message_cost( &self, request: Request, ) -> GmpResult { let (connector, msg) = self.connector(request)?; let cost = connector - .estimate_message_cost(msg.gateway, &msg.msg) + .estimate_message_cost(msg.gateway, msg.dest_network, msg.gas_limit, msg.payload) .await .map_err(|err| Status::unknown(err.to_string()))?; Ok(Response::new(proto::EstimateMessageCostResponse { cost })) @@ -264,7 +276,14 @@ impl Gmp for ConnectorWrapper { ) -> GmpResult { let (connector, msg) = self.connector(request)?; let message_id = connector - .send_message(msg.msg) + .send_message( + msg.src, + msg.dest_network, + msg.dest, + msg.gas_limit, + msg.gas_cost, + msg.payload, + ) .await .map_err(|err| Status::unknown(err.to_string()))?; Ok(Response::new(proto::SendMessageResponse { message_id })) diff --git a/gmp/grpc/src/proto.rs b/gmp/grpc/src/proto.rs index 81d783b89..de32c9914 100644 --- a/gmp/grpc/src/proto.rs +++ b/gmp/grpc/src/proto.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use serde_big_array::Array; use time_primitives::{ - Address, BatchId, Gateway, GatewayMessage, GmpEvent, GmpMessage, MessageId, Route, + Address, BatchId, Gateway, GatewayMessage, GmpEvent, GmpMessage, MessageId, NetworkId, Route, TssPublicKey, TssSignature, }; @@ -164,10 +164,25 @@ pub struct DeployTestResponse { pub block: u64, } +#[derive(Serialize, Deserialize)] +pub struct EstimateMessageGasLimitRequest { + pub contract: Address, + pub src_network: NetworkId, + pub src: Address, + pub payload: Vec, +} + +#[derive(Serialize, Deserialize)] +pub struct EstimateMessageGasLimitResponse { + pub gas_limit: u128, +} + #[derive(Serialize, Deserialize)] pub struct EstimateMessageCostRequest { pub gateway: Address, - pub msg: GmpMessage, + pub dest_network: NetworkId, + pub gas_limit: u128, + pub payload: Vec, } #[derive(Serialize, Deserialize)] @@ -177,7 +192,12 @@ pub struct EstimateMessageCostResponse { #[derive(Serialize, Deserialize)] pub struct SendMessageRequest { - pub msg: GmpMessage, + pub src: Address, + pub dest_network: NetworkId, + pub dest: Address, + pub gas_limit: u128, + pub gas_cost: u128, + pub payload: Vec, } #[derive(Serialize, Deserialize)] diff --git a/gmp/rust/src/lib.rs b/gmp/rust/src/lib.rs index a5d9a33e2..e25dd8bc4 100644 --- a/gmp/rust/src/lib.rs +++ b/gmp/rust/src/lib.rs @@ -447,27 +447,57 @@ impl IConnectorAdmin for Connector { Ok((tester, block)) } - async fn estimate_message_cost(&self, _gateway: Address, msg: &GmpMessage) -> Result { - Ok(msg.bytes.len() as u128 * 100) + async fn estimate_message_gas_limit( + &self, + _contract: Address, + _src_network: NetworkId, + _src: Address, + _payload: Vec, + ) -> Result { + Ok(100_000) } - async fn send_message(&self, mut msg: GmpMessage) -> Result { - anyhow::ensure!(msg.src_network == self.network_id, "invalid source network id"); - let addr = msg.src; + async fn estimate_message_cost( + &self, + _gateway: Address, + _dest_network: NetworkId, + gas_limit: u128, + payload: Vec, + ) -> Result { + Ok(gas_limit + payload.len() as u128 * 100) + } + async fn send_message( + &self, + src: Address, + dest_network: NetworkId, + dest: Address, + gas_limit: u128, + gas_cost: u128, + payload: Vec, + ) -> Result { let tx = self.db.begin_write()?; let id = { // read nonce let mut t = tx.open_table(NONCE)?; - let nonce = t.get((msg.src, addr))?.map(|a| a.value()).unwrap_or_default(); - // set nonce - msg.nonce = nonce; + let nonce = t.get((src, dest))?.map(|a| a.value()).unwrap_or_default(); + // construct msg + let msg = GmpMessage { + src_network: self.network_id, + src, + dest_network, + dest, + nonce, + gas_limit, + gas_cost, + bytes: payload, + }; let id = msg.message_id(); // increment nonce - t.insert((msg.src, addr), nonce + 1)?; + t.insert((src, dest), nonce + 1)?; // read gateway address let t = tx.open_table(GATEWAY)?; - let gateway = t.get(addr)?.context("tester not deployed")?.value(); + let gateway = t.get(src)?.context("tester not deployed")?.value(); // insert gateway event let mut t = tx.open_multimap_table(EVENTS)?; @@ -589,8 +619,8 @@ mod tests { src, dest, nonce: 0, - gas_limit: 0, - gas_cost: 0, + gas_limit: 100_000, + gas_cost: 100_000, bytes: vec![], } } @@ -613,9 +643,14 @@ mod tests { assert_eq!(events, vec![GmpEvent::ShardRegistered(shard.public_key())]); let (src, _) = chain.deploy_test(gateway, "".as_ref()).await?; let (dest, _) = chain.deploy_test(gateway, "".as_ref()).await?; - let mut msg = gmp_msg(src, dest); - msg.gas_cost = chain.estimate_message_cost(gateway, &msg).await?; - chain.send_message(msg.clone()).await?; + let payload = vec![]; + let gas_limit = + chain.estimate_message_gas_limit(dest, network, src, payload.clone()).await?; + let gas_cost = chain + .estimate_message_cost(gateway, network, gas_limit, payload.clone()) + .await?; + chain.send_message(src, network, dest, gas_limit, gas_cost, payload).await?; + let msg = gmp_msg(src, dest); let current2 = chain.block_stream().next().await.unwrap(); let events = chain.read_events(gateway, current..current2).await?; assert_eq!(events, vec![GmpEvent::MessageReceived(msg.clone())]); diff --git a/primitives/src/gmp.rs b/primitives/src/gmp.rs index 768850d07..00581e1b2 100644 --- a/primitives/src/gmp.rs +++ b/primitives/src/gmp.rs @@ -412,10 +412,32 @@ pub trait IConnectorAdmin: IConnector { async fn set_route(&self, gateway: Address, route: Route) -> Result<()>; /// Deploys a test contract. async fn deploy_test(&self, gateway: Address, tester: &[u8]) -> Result<(Address, u64)>; + /// Estimates the message gas limit. + async fn estimate_message_gas_limit( + &self, + contract: Address, + src_network: NetworkId, + src: Address, + payload: Vec, + ) -> Result; /// Estimates the message cost. - async fn estimate_message_cost(&self, gateway: Address, msg: &GmpMessage) -> Result; + async fn estimate_message_cost( + &self, + gateway: Address, + dest_network: NetworkId, + gas_limit: u128, + payload: Vec, + ) -> Result; /// Sends a message using the test contract and returns the message id. - async fn send_message(&self, msg: GmpMessage) -> Result; + async fn send_message( + &self, + src: Address, + dest_network: NetworkId, + dest: Address, + gas_limit: u128, + gas_cost: u128, + payload: Vec, + ) -> Result; /// Receives messages from test contract. async fn recv_messages(&self, contract: Address, blocks: Range) -> Result>; diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 81921b211..c7bbc854c 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -945,16 +945,21 @@ impl Tc { connector.deploy_test(gateway, &contracts.tester).await } - pub async fn estimate_message_cost(&self, msg: &GmpMessage) -> Result { - let (connector, gateway) = self.gateway(msg.src_network).await?; - connector.estimate_message_cost(gateway, msg).await - } - - pub async fn send_message(&self, msg: GmpMessage) -> Result { - let connector = self.connector(msg.src_network)?; - let dest_network = msg.dest_network; - let dest = msg.dest; - let gas_cost = self.format_balance(Some(msg.src_network), msg.gas_cost)?; + pub async fn send_message( + &self, + src_network: NetworkId, + src_addr: Address, + dest_network: NetworkId, + dest_addr: Address, + payload: Vec, + ) -> Result { + let (src, src_gateway) = self.gateway(msg.src_network)?; + let dest = self.connector(msg.dest_network)?; + let gas_limit = + dest.estimate_message_gas_limit(src_network, src_addr, payload.clone()).await?; + let gas_cost = src + .estimate_message_cost(src_gateway, dest_network, gas_limit, payload.clone()) + .await?; let id = self .println( None, @@ -962,11 +967,13 @@ impl Tc { "send message to {} {} with {}", dest_network, self.format_address(Some(dest_network), dest)?, - &gas_cost, + self.format_balance(Some(src_network), gas_cost)?, ), ) .await?; - let msg_id = connector.send_message(msg).await?; + let msg_id = src + .send_message(src_addr, dest_network, dest, gas_limit, gas_cost, payload) + .await?; self.println( Some(id), format!( @@ -974,7 +981,7 @@ impl Tc { hex::encode(msg_id), dest_network, self.format_address(Some(dest_network), dest)?, - &gas_cost, + self.format_balance(Some(src_network), gas_cost)?, ), ) .await?; diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index ffc639910..723ad8fa2 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -150,6 +150,7 @@ enum Command { tester: String, dest: NetworkId, dest_addr: String, + payload: String, }, SmokeTest { src: NetworkId, @@ -347,21 +348,12 @@ async fn real_main() -> Result<()> { tester, dest, dest_addr, + payload, } => { let tester = tc.parse_address(Some(network), &tester)?; let dest_addr = tc.parse_address(Some(dest), &dest_addr)?; - let mut msg = GmpMessage { - src_network: network, - src: tester, - dest_network: dest, - dest: dest_addr, - nonce: 0, - gas_limit: 300_000, - gas_cost: 0, - bytes: vec![], - }; - msg.gas_cost = tc.estimate_message_cost(&msg).await?; - let msg_id = tc.send_message(msg).await?; + let payload = hex::decode(payload)?; + let msg_id = tc.send_message(network, tester, dest, dest_addr, payload).await?; tc.println(None, hex::encode(msg_id)).await?; }, Command::SmokeTest { src, dest } => { From 5e2917a5e1cf47d592782cba9f37c1444f575aa6 Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 18:54:51 +0100 Subject: [PATCH 19/26] Update tc-cli. --- tc-cli/src/lib.rs | 43 +++++++++++---- tc-cli/src/main.rs | 130 +++++++++++++++++++++++++++++++-------------- 2 files changed, 122 insertions(+), 51 deletions(-) diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index c7bbc854c..6204b4949 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -945,34 +945,55 @@ impl Tc { connector.deploy_test(gateway, &contracts.tester).await } + pub async fn estimate_message_gas_limit( + &self, + dest_network: NetworkId, + dest_addr: Address, + src_network: NetworkId, + src_addr: Address, + payload: Vec, + ) -> Result { + let connector = self.connector(dest_network)?; + connector + .estimate_message_gas_limit(dest_addr, src_network, src_addr, payload) + .await + } + + pub async fn estimate_message_cost( + &self, + src_network: NetworkId, + dest_network: NetworkId, + gas_limit: u128, + payload: Vec, + ) -> Result { + let (connector, gateway) = self.gateway(src_network).await?; + connector.estimate_message_cost(gateway, dest_network, gas_limit, payload).await + } + pub async fn send_message( &self, src_network: NetworkId, src_addr: Address, dest_network: NetworkId, dest_addr: Address, + gas_limit: u128, + gas_cost: u128, payload: Vec, ) -> Result { - let (src, src_gateway) = self.gateway(msg.src_network)?; - let dest = self.connector(msg.dest_network)?; - let gas_limit = - dest.estimate_message_gas_limit(src_network, src_addr, payload.clone()).await?; - let gas_cost = src - .estimate_message_cost(src_gateway, dest_network, gas_limit, payload.clone()) - .await?; + let connector = self.connector(src_network)?; let id = self .println( None, format!( "send message to {} {} with {}", dest_network, - self.format_address(Some(dest_network), dest)?, + self.format_address(Some(dest_network), dest_addr)?, self.format_balance(Some(src_network), gas_cost)?, ), ) .await?; - let msg_id = src - .send_message(src_addr, dest_network, dest, gas_limit, gas_cost, payload) + let msg_id = connector + .send_message(src_addr, dest_network, dest_addr, gas_limit, gas_cost, payload) .await?; self.println( Some(id), @@ -980,7 +1001,7 @@ impl Tc { "sent message {} to {} {} with {}", hex::encode(msg_id), dest_network, - self.format_address(Some(dest_network), dest)?, + self.format_address(Some(dest_network), dest_addr)?, self.format_balance(Some(src_network), gas_cost)?, ), ) diff --git a/tc-cli/src/main.rs b/tc-cli/src/main.rs index 723ad8fa2..bd761d309 100644 --- a/tc-cli/src/main.rs +++ b/tc-cli/src/main.rs @@ -5,7 +5,7 @@ use std::collections::HashSet; use std::path::PathBuf; use std::str::FromStr; use tc_cli::{Query, Sender, Tc}; -use time_primitives::{BatchId, GmpMessage, Hash, NetworkId, ShardId, TaskId}; +use time_primitives::{BatchId, Hash, NetworkId, ShardId, TaskId}; use tracing_subscriber::filter::EnvFilter; #[derive(Clone, Debug)] @@ -145,11 +145,26 @@ enum Command { network_id: NetworkId, batch_id: BatchId, }, + EstimateMessageGasLimit { + dest_network: NetworkId, + dest_addr: String, + src_network: NetworkId, + src_addr: String, + payload: String, + }, + EstimateMessageGasCost { + src_network: NetworkId, + dest_network: NetworkId, + gas_limit: u128, + payload: String, + }, SendMessage { - network: NetworkId, - tester: String, - dest: NetworkId, + src_network: NetworkId, + src_addr: String, + dest_network: NetworkId, dest_addr: String, + gas_limit: u128, + gas_cost: u128, payload: String, }, SmokeTest { @@ -343,35 +358,69 @@ async fn real_main() -> Result<()> { Command::CompleteBatch { network_id, batch_id } => { tc.complete_batch(network_id, batch_id).await? }, + Command::EstimateMessageGasLimit { + dest_network, + dest_addr, + src_network, + src_addr, + payload, + } => { + let src_addr = tc.parse_address(Some(src_network), &src_addr)?; + let dest_addr = tc.parse_address(Some(dest_network), &dest_addr)?; + let payload = hex::decode(payload)?; + let gas_limit = tc + .estimate_message_gas_limit(dest_network, dest_addr, src_network, src_addr, payload) + .await?; + tc.println(None, gas_limit.to_string()).await?; + }, + Command::EstimateMessageGasCost { + src_network, + dest_network, + gas_limit, + payload, + } => { + let payload = hex::decode(payload)?; + let gas_cost = + tc.estimate_message_cost(src_network, dest_network, gas_limit, payload).await?; + tc.println(None, gas_cost.to_string()).await?; + }, Command::SendMessage { - network, - tester, - dest, + src_network, + src_addr, + dest_network, dest_addr, + gas_limit, + gas_cost, payload, } => { - let tester = tc.parse_address(Some(network), &tester)?; - let dest_addr = tc.parse_address(Some(dest), &dest_addr)?; + let src_addr = tc.parse_address(Some(src_network), &src_addr)?; + let dest_addr = tc.parse_address(Some(dest_network), &dest_addr)?; let payload = hex::decode(payload)?; - let msg_id = tc.send_message(network, tester, dest, dest_addr, payload).await?; + let msg_id = tc + .send_message( + src_network, + src_addr, + dest_network, + dest_addr, + gas_limit, + gas_cost, + payload, + ) + .await?; tc.println(None, hex::encode(msg_id)).await?; }, Command::SmokeTest { src, dest } => { let (src_addr, dest_addr) = tc.setup_test(src, dest).await?; let mut blocks = tc.finality_notification_stream(); let (_, start) = blocks.next().await.context("expected block")?; - let mut msg = GmpMessage { - src_network: src, - src: src_addr, - dest_network: dest, - dest: dest_addr, - nonce: 0, - gas_limit: 300_000, - gas_cost: 0, - bytes: vec![], - }; - msg.gas_cost = tc.estimate_message_cost(&msg).await?; - let msg_id = tc.send_message(msg).await?; + let payload = vec![]; + let gas_limit = tc + .estimate_message_gas_limit(dest, dest_addr, src, src_addr, payload.clone()) + .await?; + let gas_cost = tc.estimate_message_cost(src, dest, gas_limit, payload.clone()).await?; + let msg_id = tc + .send_message(src, src_addr, dest, dest_addr, gas_limit, gas_cost, payload.clone()) + .await?; let mut id = None; let (exec, end) = loop { let (_, end) = blocks.next().await.context("expected block")?; @@ -400,22 +449,24 @@ async fn real_main() -> Result<()> { let mut blocks = tc.finality_notification_stream(); let (_, start) = blocks.next().await.context("expected block")?; let mut msgs = HashSet::new(); - let mut gas_cost = 0; + let payload = vec![]; + let gas_limit = tc + .estimate_message_gas_limit(dest, dest_addr, src, src_addr, payload.clone()) + .await?; + let gas_cost = tc.estimate_message_cost(src, dest, gas_limit, payload.clone()).await?; for _ in 0..num_messages { - let mut msg = GmpMessage { - src_network: src, - src: src_addr, - dest_network: dest, - dest: dest_addr, - nonce: 0, - gas_limit: 300_000, - gas_cost: 0, - bytes: vec![], - }; - msg.gas_cost = tc.estimate_message_cost(&msg).await?; - gas_cost += msg.gas_cost; - let msg = tc.send_message(msg).await?; - msgs.insert(msg); + let msg_id = tc + .send_message( + src, + src_addr, + dest, + dest_addr, + gas_limit, + gas_cost, + payload.clone(), + ) + .await?; + msgs.insert(msg_id); } let mut id = None; while let Some((_, block)) = blocks.next().await { @@ -432,15 +483,14 @@ async fn real_main() -> Result<()> { let num_received = num_messages - msgs.len() as u16; let blocks = block - start; let throughput = num_received as f64 / blocks as f64; - let avg_msg_cost = gas_cost / num_messages as u128; - let avg_msg_cost = tc.format_balance(Some(src), avg_msg_cost)?; id = Some( tc.println( id, format!( r#"{num_received} out of {num_messages} received in {blocks} blocks throughput {throughput:.3} msgs/block - avg msg cost {avg_msg_cost}"# + msg cost {}"#, + tc.format_balance(Some(src), gas_cost)?, ), ) .await?, From 17a8c4564d49b76ae22753b50f0358a13159b20c Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 19:00:52 +0100 Subject: [PATCH 20/26] Fix clippy. --- gmp/evm/src/lib.rs | 2 +- tc-cli/src/lib.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 0e648f2c2..79341b158 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -766,7 +766,7 @@ impl IConnectorAdmin for Connector { gasLimit: gas_limit as _, data: payload.into(), }; - let call = sol::GmpTester::sendMessageCall { msg: msg.into() }; + let call = sol::GmpTester::sendMessageCall { msg }; let result = self.evm_call(contract, call, gas_cost, None, None).await?; let id: MessageId = *result.0._0; Ok(id) diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 6204b4949..771c460a9 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -970,6 +970,7 @@ impl Tc { connector.estimate_message_cost(gateway, dest_network, gas_limit, payload).await } + #[allow(clippy::too_many_arguments)] pub async fn send_message( &self, src_network: NetworkId, From d54439f0c5812f90d2e4d1efbbc7d013670dad5f Mon Sep 17 00:00:00 2001 From: David Craven Date: Thu, 13 Feb 2025 19:16:58 +0100 Subject: [PATCH 21/26] Fix review comments. --- Cargo.lock | 34 +++++++++++++++++----------------- gmp/evm/Cargo.toml | 3 ++- gmp/evm/src/lib.rs | 26 ++++++++++++++------------ 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2d05df7b4..4e72542b2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5594,6 +5594,7 @@ dependencies = [ "async-trait", "futures", "hex", + "hex-literal", "reqwest", "rosetta-client", "serde", @@ -14154,7 +14155,7 @@ dependencies = [ [[package]] name = "rosetta-client" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14165,7 +14166,6 @@ dependencies = [ "futures-util", "getrandom 0.2.15", "hex", - "hex-literal", "js-sys", "log", "num-traits", @@ -14189,7 +14189,7 @@ dependencies = [ [[package]] name = "rosetta-config-astar" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "rosetta-core", @@ -14199,7 +14199,7 @@ dependencies = [ [[package]] name = "rosetta-config-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "const-hex", @@ -14219,7 +14219,7 @@ dependencies = [ [[package]] name = "rosetta-config-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "rosetta-core", @@ -14230,7 +14230,7 @@ dependencies = [ [[package]] name = "rosetta-core" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14247,7 +14247,7 @@ dependencies = [ [[package]] name = "rosetta-crypto" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "bech32", @@ -14273,7 +14273,7 @@ dependencies = [ [[package]] name = "rosetta-ethereum-backend" version = "0.1.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "async-trait", "auto_impl", @@ -14289,7 +14289,7 @@ dependencies = [ [[package]] name = "rosetta-ethereum-types" version = "0.2.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "bytes", "const-hex", @@ -14323,7 +14323,7 @@ dependencies = [ [[package]] name = "rosetta-server" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14346,7 +14346,7 @@ dependencies = [ [[package]] name = "rosetta-server-astar" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14370,7 +14370,7 @@ dependencies = [ [[package]] name = "rosetta-server-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14399,7 +14399,7 @@ dependencies = [ [[package]] name = "rosetta-server-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "async-trait", @@ -14420,7 +14420,7 @@ dependencies = [ [[package]] name = "rosetta-tx-ethereum" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "rosetta-config-ethereum", @@ -14431,7 +14431,7 @@ dependencies = [ [[package]] name = "rosetta-tx-polkadot" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "anyhow", "blake2-rfc", @@ -14445,7 +14445,7 @@ dependencies = [ [[package]] name = "rosetta-types" version = "0.6.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "serde", "serde_json", @@ -14454,7 +14454,7 @@ dependencies = [ [[package]] name = "rosetta-utils" version = "0.1.0" -source = "git+https://github.com/analog-labs/chain-connectors?rev=84df6f5#84df6f5522744d0614c80c01f62deded3a55af79" +source = "git+https://github.com/analog-labs/chain-connectors?rev=5bbe80d#5bbe80d8f257dc25c3cb842b42aae2aa74581cda" dependencies = [ "bytes", "futures-timer", diff --git a/gmp/evm/Cargo.toml b/gmp/evm/Cargo.toml index aeaa51eec..495e22c9e 100644 --- a/gmp/evm/Cargo.toml +++ b/gmp/evm/Cargo.toml @@ -16,7 +16,7 @@ async-trait.workspace = true futures.workspace = true hex.workspace = true reqwest = { version = "0.12.7", default-features = false, features = ["json", "rustls-tls-native-roots"] } -rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "84df6f5" } +rosetta-client = { git = "https://github.com/analog-labs/chain-connectors", rev = "5bbe80d" } sha3 = { version = "0.10", default-features = false } serde.workspace = true serde_json = "1.0.127" @@ -24,3 +24,4 @@ thiserror = "2.0.9" time-primitives = { workspace = true, default-features = true } tokio.workspace = true tracing.workspace = true +hex-literal = "0.4.1" diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 79341b158..89d8b27db 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -12,8 +12,8 @@ use rosetta_client::{ DefaultFeeEstimatorConfig, EthereumRpcExt, PolygonFeeEstimatorConfig, }, types::AccountIdentifier, - AtBlock, CallResult, FilterBlockOption, GetTransactionCount, SubmitResult, TransactionReceipt, - Wallet, + AtBlock, Blockchain, CallResult, FilterBlockOption, GetTransactionCount, SubmitResult, + TransactionReceipt, Wallet, }; use serde::Deserialize; use sha3::{Digest, Keccak256}; @@ -141,8 +141,8 @@ impl Connector { ) -> Result<(Address, u64)> { let mut contract = get_contract_from_slice(abi)?; contract.extend(constructor.abi_encode()); - let tx_hash = self.wallet.eth_deploy_contract(contract).await?.tx_hash().0; - let tx_receipt = self.wallet.eth_transaction_receipt(tx_hash).await?.unwrap(); + let tx_hash = self.wallet.eth_deploy_contract(contract).await?.tx_hash(); + let tx_receipt = self.wallet.eth_transaction_receipt(tx_hash.0).await?.unwrap(); let address = tx_receipt.contract_address.unwrap(); let block_number = tx_receipt.block_number.unwrap(); tracing::info!( @@ -393,15 +393,17 @@ impl IConnectorBuilder for Connector { where Self: Sized, { + let (blockchain, private_key) = if params.blockchain == "anvil" { + let private_key = hex_literal::hex![ + "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80" + ]; + (Blockchain::Ethereum, Some(private_key)) + } else { + (params.blockchain.parse()?, None) + }; let wallet = Arc::new( - Wallet::new( - params.blockchain.parse()?, - ¶ms.network, - ¶ms.url, - ¶ms.mnemonic, - None, - ) - .await?, + Wallet::new(blockchain, ¶ms.network, ¶ms.url, ¶ms.mnemonic, private_key) + .await?, ); let client = default_client(¶ms.url, None) .await From e64fdd73baeaf0f296d2a1ca8dfba17dc18d9096 Mon Sep 17 00:00:00 2001 From: David Craven Date: Fri, 14 Feb 2025 09:29:34 +0100 Subject: [PATCH 22/26] Add nonce to onGmpReceived. --- analog-gmp/src/Primitives.sol | 2 ++ analog-gmp/src/interfaces/IGmpReceiver.sol | 2 +- analog-gmp/test/Batching.t.sol | 1 + analog-gmp/test/Gateway.t.sol | 1 + analog-gmp/test/MockERC20.sol | 2 +- analog-gmp/test/utils/GasSpender.sol | 2 +- analog-gmp/test/utils/GasSpender.t.sol | 1 + analog-gmp/test/utils/GmpProxy.sol | 2 +- 8 files changed, 9 insertions(+), 4 deletions(-) diff --git a/analog-gmp/src/Primitives.sol b/analog-gmp/src/Primitives.sol index b279c95fa..b96c8cbbb 100644 --- a/analog-gmp/src/Primitives.sol +++ b/analog-gmp/src/Primitives.sol @@ -349,6 +349,7 @@ library PrimitiveUtils { callback.eip712hash, callback.srcNetwork, callback.source, + callback.nonce, data ); } else { @@ -364,6 +365,7 @@ library PrimitiveUtils { callback.eip712hash, callback.srcNetwork, callback.source, + callback.nonce, m.data ); } diff --git a/analog-gmp/src/interfaces/IGmpReceiver.sol b/analog-gmp/src/interfaces/IGmpReceiver.sol index 64fccd4a3..85c1a62a2 100644 --- a/analog-gmp/src/interfaces/IGmpReceiver.sol +++ b/analog-gmp/src/interfaces/IGmpReceiver.sol @@ -17,7 +17,7 @@ interface IGmpReceiver { * @param payload The message payload with no specified format * @return 32 byte result which will be stored together with GMP message */ - function onGmpReceived(bytes32 id, uint128 network, bytes32 source, bytes calldata payload) + function onGmpReceived(bytes32 id, uint128 network, bytes32 source, uint64 nonce, bytes calldata payload) external payable returns (bytes32); diff --git a/analog-gmp/test/Batching.t.sol b/analog-gmp/test/Batching.t.sol index 5de543620..4aa7878bf 100644 --- a/analog-gmp/test/Batching.t.sol +++ b/analog-gmp/test/Batching.t.sol @@ -161,6 +161,7 @@ contract Batching is BaseTest { 0x0000000000000000000000000000000000000000000000000000000000000000, 1, 0x0000000000000000000000000000000000000000000000000000000000000000, + 0, abi.encode(gasToWaste) ) ); diff --git a/analog-gmp/test/Gateway.t.sol b/analog-gmp/test/Gateway.t.sol index 4c94fb507..82c0933b9 100644 --- a/analog-gmp/test/Gateway.t.sol +++ b/analog-gmp/test/Gateway.t.sol @@ -328,6 +328,7 @@ contract GatewayTest is BaseTest { 0x0000000000000000000000000000000000000000000000000000000000000000, 1, 0x0000000000000000000000000000000000000000000000000000000000000000, + 0, abi.encode(uint256(1234)) ) ); diff --git a/analog-gmp/test/MockERC20.sol b/analog-gmp/test/MockERC20.sol index 22fad2006..524645cfc 100644 --- a/analog-gmp/test/MockERC20.sol +++ b/analog-gmp/test/MockERC20.sol @@ -73,7 +73,7 @@ contract MockERC20 is ERC20, IGmpReceiver { ); } - function onGmpReceived(bytes32 id, uint128 network, bytes32 sender, bytes calldata data) + function onGmpReceived(bytes32 id, uint128 network, bytes32 sender, uint64, bytes calldata data) external payable returns (bytes32) diff --git a/analog-gmp/test/utils/GasSpender.sol b/analog-gmp/test/utils/GasSpender.sol index 799d179fa..7dd8745e9 100644 --- a/analog-gmp/test/utils/GasSpender.sol +++ b/analog-gmp/test/utils/GasSpender.sol @@ -70,7 +70,7 @@ contract GasSpender is IGmpReceiver { } } - function onGmpReceived(bytes32, uint128, bytes32, bytes calldata payload) external payable returns (bytes32) { + function onGmpReceived(bytes32, uint128, bytes32, uint64, bytes calldata payload) external payable returns (bytes32) { unchecked { // OBS: This is just an example on how this contract works, the actual code is implemented directly in // low level EVM, as defined in the `BYTECODE` constant. diff --git a/analog-gmp/test/utils/GasSpender.t.sol b/analog-gmp/test/utils/GasSpender.t.sol index 4f284ffcb..a838caf2e 100644 --- a/analog-gmp/test/utils/GasSpender.t.sol +++ b/analog-gmp/test/utils/GasSpender.t.sol @@ -20,6 +20,7 @@ contract GasSpenderTest is BaseTest { 0x0000000000000000000000000000000000000000000000000000000000000000, 1, 0x0000000000000000000000000000000000000000000000000000000000000000, + 0, abi.encode(gasToWaste) ) ); diff --git a/analog-gmp/test/utils/GmpProxy.sol b/analog-gmp/test/utils/GmpProxy.sol index 4af245eb0..0d20a9422 100644 --- a/analog-gmp/test/utils/GmpProxy.sol +++ b/analog-gmp/test/utils/GmpProxy.sol @@ -36,7 +36,7 @@ contract GmpProxy is IGmpReceiver { return GATEWAY.submitMessage{value: value}(message.dest, message.destNetwork, message.gasLimit, message.data); } - function onGmpReceived(bytes32 id, uint128, bytes32, bytes calldata payload) external payable returns (bytes32) { + function onGmpReceived(bytes32 id, uint128, bytes32, uint64, bytes calldata payload) external payable returns (bytes32) { // For testing purpose // we keep the original struct in payload so we dont depend on OnGmpReceived call since it doesnt provide everything. (GmpMessage memory message) = abi.decode(payload, (GmpMessage)); From cb1d71989a6a84643b383832da6f5cdba2e16ba3 Mon Sep 17 00:00:00 2001 From: David Craven Date: Fri, 14 Feb 2025 09:48:27 +0100 Subject: [PATCH 23/26] Fix GmpProxy. --- analog-gmp/test/utils/GmpProxy.sol | 20 +++++++--- analog-gmp/test/utils/GmpProxy.t.sol | 57 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 analog-gmp/test/utils/GmpProxy.t.sol diff --git a/analog-gmp/test/utils/GmpProxy.sol b/analog-gmp/test/utils/GmpProxy.sol index 0d20a9422..290765312 100644 --- a/analog-gmp/test/utils/GmpProxy.sol +++ b/analog-gmp/test/utils/GmpProxy.sol @@ -7,6 +7,7 @@ import {ERC1967} from "../../src/utils/ERC1967.sol"; import {IGmpReceiver} from "../../src/interfaces/IGmpReceiver.sol"; import {IGateway} from "../../src/interfaces/IGateway.sol"; import {BranchlessMath} from "../../src/utils/BranchlessMath.sol"; +import {console} from "forge-std/console.sol"; contract GmpProxy is IGmpReceiver { using BranchlessMath for uint256; @@ -36,12 +37,19 @@ contract GmpProxy is IGmpReceiver { return GATEWAY.submitMessage{value: value}(message.dest, message.destNetwork, message.gasLimit, message.data); } - function onGmpReceived(bytes32 id, uint128, bytes32, uint64, bytes calldata payload) external payable returns (bytes32) { - // For testing purpose - // we keep the original struct in payload so we dont depend on OnGmpReceived call since it doesnt provide everything. - (GmpMessage memory message) = abi.decode(payload, (GmpMessage)); - message.data = payload; - + function onGmpReceived(bytes32 id, uint128 srcNetwork, bytes32 src, uint64 nonce, bytes calldata payload) external payable returns (bytes32) { + uint64 gasLimit = uint64(gasleft()); + // this is the constant added to gasLimit + console.log(300_000 - gasLimit); + GmpMessage memory message = GmpMessage({ + source: src, + srcNetwork: uint16(srcNetwork), + dest: address(this), + destNetwork: NETWORK_ID, + gasLimit: gasLimit + 579, + nonce: nonce, + data: payload + }); emit MessageReceived(message); return id; } diff --git a/analog-gmp/test/utils/GmpProxy.t.sol b/analog-gmp/test/utils/GmpProxy.t.sol new file mode 100644 index 000000000..813163c73 --- /dev/null +++ b/analog-gmp/test/utils/GmpProxy.t.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >=0.8.0; + +import {Test, console, Vm} from "forge-std/Test.sol"; +import {IGateway} from "../../src/interfaces/IGateway.sol"; +import {IGmpReceiver} from "../../src/interfaces/IGmpReceiver.sol"; +import {GmpProxy} from "./GmpProxy.sol"; + +contract MockGateway is IGateway { + uint16 _networkId; + + constructor(uint16 network) { + _networkId = network; + } + + function networkId() external view returns (uint16) { + return _networkId; + } + + function estimateMessageCost( + uint16, + uint256, + uint256 + ) external pure returns (uint256) { + return 0; + } + + function submitMessage( + address, + uint16, + uint256, + bytes calldata + ) external payable returns (bytes32) { + return 0x0; + } +} + +contract GmpProxyTest is Test { + MockGateway gateway; + GmpProxy proxy; + + function setUp() external { + gateway = new MockGateway(1); + proxy = new GmpProxy(address(gateway)); + } + + function test_onGmpReceived() external { + proxy.onGmpReceived{gas: 300000}( + 0x0, + 0, + 0x0, + 0, + abi.encode(0x0) + ); + } +} From 226910d0179facddd4e8cde41723165c81035938 Mon Sep 17 00:00:00 2001 From: David Craven Date: Fri, 14 Feb 2025 10:13:12 +0100 Subject: [PATCH 24/26] Update tc-cli. --- analog-gmp/test/utils/GmpProxy.sol | 9 ++++++--- gmp/evm/src/lib.rs | 1 + gmp/evm/src/sol.rs | 2 +- tc-cli/src/lib.rs | 6 ++++-- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/analog-gmp/test/utils/GmpProxy.sol b/analog-gmp/test/utils/GmpProxy.sol index 290765312..3fe0ebe34 100644 --- a/analog-gmp/test/utils/GmpProxy.sol +++ b/analog-gmp/test/utils/GmpProxy.sol @@ -38,15 +38,18 @@ contract GmpProxy is IGmpReceiver { } function onGmpReceived(bytes32 id, uint128 srcNetwork, bytes32 src, uint64 nonce, bytes calldata payload) external payable returns (bytes32) { - uint64 gasLimit = uint64(gasleft()); + // when estimating gas an insane amount of gas is provided + uint256 gasLimit = gasleft(); // this is the constant added to gasLimit - console.log(300_000 - gasLimit); + unchecked { console.log(300_000 - gasLimit); } + uint64 msgGasLimit; + unchecked { msgGasLimit = uint64(gasLimit + 579); } GmpMessage memory message = GmpMessage({ source: src, srcNetwork: uint16(srcNetwork), dest: address(this), destNetwork: NETWORK_ID, - gasLimit: gasLimit + 579, + gasLimit: msgGasLimit, nonce: nonce, data: payload }); diff --git a/gmp/evm/src/lib.rs b/gmp/evm/src/lib.rs index 89d8b27db..87762dbf6 100644 --- a/gmp/evm/src/lib.rs +++ b/gmp/evm/src/lib.rs @@ -709,6 +709,7 @@ impl IConnectorAdmin for Connector { id: [0; 32].into(), network: src_network.into(), source: src.into(), + nonce: 0, payload: payload.into(), }; let gas_limit = self diff --git a/gmp/evm/src/sol.rs b/gmp/evm/src/sol.rs index 1e0eb6067..9f73f1e06 100644 --- a/gmp/evm/src/sol.rs +++ b/gmp/evm/src/sol.rs @@ -186,7 +186,7 @@ alloy_sol_types::sol! { } interface IGmpReceiver { - function onGmpReceived(bytes32 id, uint128 network, bytes32 source, bytes calldata payload) + function onGmpReceived(bytes32 id, uint128 network, bytes32 source, uint64 nonce, bytes calldata payload) external payable returns (bytes32); diff --git a/tc-cli/src/lib.rs b/tc-cli/src/lib.rs index 771c460a9..cf13a8986 100644 --- a/tc-cli/src/lib.rs +++ b/tc-cli/src/lib.rs @@ -986,9 +986,10 @@ impl Tc { .println( None, format!( - "send message to {} {} with {}", + "send message to {} {} with {} gas for {}", dest_network, self.format_address(Some(dest_network), dest_addr)?, + gas_limit, self.format_balance(Some(src_network), gas_cost)?, ), ) @@ -999,10 +1000,11 @@ impl Tc { self.println( Some(id), format!( - "sent message {} to {} {} with {}", + "sent message {} to {} {} with {} gas for {}", hex::encode(msg_id), dest_network, self.format_address(Some(dest_network), dest_addr)?, + gas_limit, self.format_balance(Some(src_network), gas_cost)?, ), ) From 4c61d0c26010e341202ee8e787a459edabe58672 Mon Sep 17 00:00:00 2001 From: David Craven Date: Fri, 14 Feb 2025 11:06:50 +0100 Subject: [PATCH 25/26] Fix startup issue. --- docker-compose.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index fe8774dd2..b20baffa1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -78,7 +78,7 @@ services: chain-2-evm: image: 'ghcr.io/foundry-rs/foundry:latest' command: - - 'anvil -b 2 --steps-tracing' + - 'anvil -b 2 --steps-tracing --base-fee 0' environment: ANVIL_IP_ADDR: '0.0.0.0' profiles: @@ -104,7 +104,7 @@ services: chain-3-evm: image: 'ghcr.io/foundry-rs/foundry:latest' command: - - 'anvil -b 2 --steps-tracing' + - 'anvil -b 2 --steps-tracing --base-fee 0' environment: ANVIL_IP_ADDR: '0.0.0.0' profiles: From 70c2c7e46061843a2521e1e0dff2dcd6bc99758d Mon Sep 17 00:00:00 2001 From: David Craven Date: Fri, 14 Feb 2025 11:56:31 +0100 Subject: [PATCH 26/26] Fix some assembly. --- analog-gmp/src/Primitives.sol | 13 +++++++------ analog-gmp/test/utils/GasSpender.sol | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/analog-gmp/src/Primitives.sol b/analog-gmp/src/Primitives.sol index b96c8cbbb..b4e879335 100644 --- a/analog-gmp/src/Primitives.sol +++ b/analog-gmp/src/Primitives.sol @@ -281,7 +281,7 @@ library PrimitiveUtils { bytes memory onGmpReceived = callback.callback; bytes32 dataHash; assembly ("memory-safe") { - let offset := add(onGmpReceived, 0xa4) + let offset := add(onGmpReceived, 0xc4) dataHash := keccak256(add(offset, 0x20), mload(offset)) } callback.eip712hash = bytes32(GMP_VERSION); @@ -332,9 +332,10 @@ library PrimitiveUtils { // | 0x0124..0x0144 <- onGmpReceived.id // | 0x0144..0x0164 <- onGmpReceived.network // | 0x0164..0x0184 <- onGmpReceived.source - // | 0x0184..0x01a4 <- onGmpReceived.data.offset - // | 0x01a4..0x01c4 <- onGmpReceived.data.length - // | 0x01c4........ <- onGmpReceived.data + // | 0x0184..0x01a4 <- onGmpReceived.nonce + // | 0x01a4..0x01c4 <- onGmpReceived.data.offset + // | 0x01c4..0x01e4 <- onGmpReceived.data.length + // | 0x01e4........ <- onGmpReceived.data if (isCalldata) { GmpMessage calldata m = _intoCalldataPointer(message); callback.source = m.source; @@ -345,7 +346,7 @@ library PrimitiveUtils { callback.nonce = m.nonce; bytes calldata data = m.data; callback.callback = abi.encodeWithSignature( - "onGmpReceived(bytes32,uint128,bytes32,bytes)", + "onGmpReceived(bytes32,uint128,bytes32,uint64,bytes)", callback.eip712hash, callback.srcNetwork, callback.source, @@ -361,7 +362,7 @@ library PrimitiveUtils { callback.gasLimit = m.gasLimit; callback.nonce = m.nonce; callback.callback = abi.encodeWithSignature( - "onGmpReceived(bytes32,uint128,bytes32,bytes)", + "onGmpReceived(bytes32,uint128,bytes32,uint64,bytes)", callback.eip712hash, callback.srcNetwork, callback.source, diff --git a/analog-gmp/test/utils/GasSpender.sol b/analog-gmp/test/utils/GasSpender.sol index 7dd8745e9..265c74a6c 100644 --- a/analog-gmp/test/utils/GasSpender.sol +++ b/analog-gmp/test/utils/GasSpender.sol @@ -17,7 +17,7 @@ contract GasSpender is IGmpReceiver { // 0x07 0x3d RETURNDATASIZE // 0x08 0x6020 PUSH1 0x20 // 0x0a 0x91 SWAP2 - // 0x0b 0x6064 PUSH1 0x64 + // 0x0b 0x6084 PUSH1 0x84 // 0x0d 0x35 CALLDATALOAD -- Load the payload offset from the calldata // 0x0e 0x6024 PUSH1 0x24 // 0x10 0x01 ADD @@ -61,7 +61,7 @@ contract GasSpender is IGmpReceiver { // `=>0x3a 0x5b JUMPDEST // 0x3b 0xf3 RETURN bytes private constant BYTECODE = - hex"5a600201803d523d60209160643560240135146018575bfd5b60365a116018575a604903565b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5bf3"; + hex"5a600201803d523d60209160843560240135146018575bfd5b60365a116018575a604903565b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5b5bf3"; constructor() payable { bytes memory bytecode = BYTECODE;