From c539acd4dc8c0116fc9abd024bdad5e114e771b0 Mon Sep 17 00:00:00 2001 From: Eric Bolten Date: Tue, 12 Jul 2022 15:44:47 -0700 Subject: [PATCH 1/3] Specify gas limit multiplier for relaying This adds a CLI option for specifying an Ethereum gas limit multiplier, and converts relay contract calls into legacy versions to account for a bug in ethers that does not respect manually set gas limits in EIP1559 transactions. --- orchestrator/ethereum_gravity/src/logic_call.rs | 3 ++- orchestrator/ethereum_gravity/src/submit_batch.rs | 3 ++- orchestrator/ethereum_gravity/src/valset_update.rs | 3 ++- orchestrator/gorc/src/commands/orchestrator/start.rs | 1 + orchestrator/gorc/src/config.rs | 2 ++ orchestrator/orchestrator/src/main_loop.rs | 2 ++ orchestrator/relayer/src/batch_relaying.rs | 5 +++++ orchestrator/relayer/src/logic_call_relaying.rs | 3 +++ orchestrator/relayer/src/main.rs | 1 + orchestrator/relayer/src/main_loop.rs | 5 +++++ orchestrator/relayer/src/valset_relaying.rs | 9 ++++++++- 11 files changed, 33 insertions(+), 4 deletions(-) diff --git a/orchestrator/ethereum_gravity/src/logic_call.rs b/orchestrator/ethereum_gravity/src/logic_call.rs index 49281274e..82d99320c 100644 --- a/orchestrator/ethereum_gravity/src/logic_call.rs +++ b/orchestrator/ethereum_gravity/src/logic_call.rs @@ -72,7 +72,8 @@ pub async fn send_eth_logic_call( let contract_call = contract_call .gas(gas_cost.gas) - .gas_price(gas_cost.gas_price); + .gas_price(gas_cost.gas_price) + .legacy(); // must submit transactions as legacy due to bug in manually-specified EIP1559 gas limits let pending_tx = contract_call.send().await?; let tx_hash = *pending_tx; diff --git a/orchestrator/ethereum_gravity/src/submit_batch.rs b/orchestrator/ethereum_gravity/src/submit_batch.rs index 1eda0f9c0..cf8136c27 100644 --- a/orchestrator/ethereum_gravity/src/submit_batch.rs +++ b/orchestrator/ethereum_gravity/src/submit_batch.rs @@ -64,7 +64,8 @@ pub async fn send_eth_transaction_batch( let contract_call = contract_call .gas(gas_cost.gas) - .gas_price(gas_cost.gas_price); + .gas_price(gas_cost.gas_price) + .legacy(); // must submit transactions as legacy due to bug in manually-specified EIP1559 gas limits let pending_tx = contract_call.send().await?; let tx_hash = *pending_tx; diff --git a/orchestrator/ethereum_gravity/src/valset_update.rs b/orchestrator/ethereum_gravity/src/valset_update.rs index 3b8b44c92..7cd90ffec 100644 --- a/orchestrator/ethereum_gravity/src/valset_update.rs +++ b/orchestrator/ethereum_gravity/src/valset_update.rs @@ -50,7 +50,8 @@ pub async fn send_eth_valset_update( )?; let contract_call = contract_call .gas(gas_cost.gas) - .gas_price(gas_cost.gas_price); + .gas_price(gas_cost.gas_price) + .legacy(); // must submit transactions as legacy due to bug in manually-specified EIP1559 gas limits let pending_tx = contract_call.send().await?; let tx_hash = *pending_tx; diff --git a/orchestrator/gorc/src/commands/orchestrator/start.rs b/orchestrator/gorc/src/commands/orchestrator/start.rs index ed11027f3..740282c2c 100644 --- a/orchestrator/gorc/src/commands/orchestrator/start.rs +++ b/orchestrator/gorc/src/commands/orchestrator/start.rs @@ -108,6 +108,7 @@ impl Runnable for StartCommand { gas_price, &config.metrics.listen_addr, config.ethereum.gas_price_multiplier, + config.ethereum.gas_multiplier, config.ethereum.blocks_to_search, config.cosmos.gas_adjustment, self.orchestrator_only, diff --git a/orchestrator/gorc/src/config.rs b/orchestrator/gorc/src/config.rs index 96fbc919c..076980071 100644 --- a/orchestrator/gorc/src/config.rs +++ b/orchestrator/gorc/src/config.rs @@ -74,6 +74,7 @@ pub struct EthereumSection { pub key_derivation_path: String, pub rpc: String, pub gas_price_multiplier: f32, + pub gas_multiplier: f32, pub blocks_to_search: u64, } @@ -83,6 +84,7 @@ impl Default for EthereumSection { key_derivation_path: "m/44'/60'/0'/0/0".to_owned(), rpc: "http://localhost:8545".to_owned(), gas_price_multiplier: 1.0f32, + gas_multiplier: 1.0f32, blocks_to_search: 5000, } } diff --git a/orchestrator/orchestrator/src/main_loop.rs b/orchestrator/orchestrator/src/main_loop.rs index a3fae0dbb..619436b84 100644 --- a/orchestrator/orchestrator/src/main_loop.rs +++ b/orchestrator/orchestrator/src/main_loop.rs @@ -55,6 +55,7 @@ pub async fn orchestrator_main_loop( gas_price: (f64, String), metrics_listen: &net::SocketAddr, eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, blocks_to_search: u64, gas_adjustment: f64, relayer_opt_out: bool, @@ -98,6 +99,7 @@ pub async fn orchestrator_main_loop( grpc_client.clone(), gravity_contract_address, eth_gas_price_multiplier, + eth_gas_multiplier, ); futures::future::join5(a, b, c, d, e).await; } else { diff --git a/orchestrator/relayer/src/batch_relaying.rs b/orchestrator/relayer/src/batch_relaying.rs index 5087657ab..94f3848de 100644 --- a/orchestrator/relayer/src/batch_relaying.rs +++ b/orchestrator/relayer/src/batch_relaying.rs @@ -37,6 +37,7 @@ pub async fn relay_batches( gravity_id: String, timeout: Duration, eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, ) { let possible_batches = get_batches_and_signatures(current_valset.clone(), grpc_client, gravity_id.clone()).await; @@ -50,6 +51,7 @@ pub async fn relay_batches( gravity_id, timeout, eth_gas_price_multiplier, + eth_gas_multiplier, possible_batches, ) .await; @@ -132,6 +134,7 @@ async fn submit_batches( gravity_id: String, timeout: Duration, eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, possible_batches: HashMap>, ) { let ethereum_block_height = if let Ok(bn) = eth_client.get_block_number().await { @@ -198,6 +201,7 @@ async fn submit_batches( } let total_cost = total_cost.unwrap(); let gas_price_as_f32 = downcast_to_f32(cost.gas_price).unwrap(); // if the total cost isn't greater, this isn't + let gas_as_f32 = downcast_to_f32(cost.gas).unwrap(); // same as above re: total cost info!( "We have detected latest batch {} but latest on Ethereum is {} This batch is estimated to cost {} Gas / {:.4} ETH to submit", @@ -208,6 +212,7 @@ async fn submit_batches( ); cost.gas_price = ((gas_price_as_f32 * eth_gas_price_multiplier) as u128).into(); + cost.gas = ((gas_as_f32 * eth_gas_multiplier) as u128).into(); let res = send_eth_transaction_batch( current_valset.clone(), diff --git a/orchestrator/relayer/src/logic_call_relaying.rs b/orchestrator/relayer/src/logic_call_relaying.rs index 174ceaf15..d3ec492e1 100644 --- a/orchestrator/relayer/src/logic_call_relaying.rs +++ b/orchestrator/relayer/src/logic_call_relaying.rs @@ -24,6 +24,7 @@ pub async fn relay_logic_calls( gravity_id: String, timeout: Duration, eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, logic_call_skips: &mut LogicCallSkips, ) { let latest_calls = match get_latest_logic_calls(grpc_client).await { @@ -141,6 +142,7 @@ pub async fn relay_logic_calls( } let total_cost = total_cost.unwrap(); let gas_price_as_f32 = downcast_to_f32(cost.gas_price).unwrap(); // if the total cost isn't greater, this isn't + let gas_as_f32 = downcast_to_f32(cost.gas).unwrap(); // same as above re: total cost info!( "We have detected latest LogicCall {} but latest on Ethereum is {} This LogicCall is estimated to cost {} Gas / {:.4} ETH to submit", @@ -151,6 +153,7 @@ pub async fn relay_logic_calls( ); cost.gas_price = ((gas_price_as_f32 * eth_gas_price_multiplier) as u128).into(); + cost.gas = ((gas_as_f32 * eth_gas_multiplier) as u128).into(); let res = send_eth_logic_call( current_valset, diff --git a/orchestrator/relayer/src/main.rs b/orchestrator/relayer/src/main.rs index fbf05ae1d..97c982393 100644 --- a/orchestrator/relayer/src/main.rs +++ b/orchestrator/relayer/src/main.rs @@ -110,6 +110,7 @@ async fn main() { connections.grpc.unwrap(), gravity_contract_address, 1f32, + 1f32, ) .await } diff --git a/orchestrator/relayer/src/main_loop.rs b/orchestrator/relayer/src/main_loop.rs index 7ea85976c..8d8b15c46 100644 --- a/orchestrator/relayer/src/main_loop.rs +++ b/orchestrator/relayer/src/main_loop.rs @@ -18,6 +18,7 @@ pub async fn relayer_main_loop( grpc_client: GravityQueryClient, gravity_contract_address: EthAddress, eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, ) { let mut grpc_client = grpc_client; let gravity_id = get_gravity_id(gravity_contract_address, eth_client.clone()).await; @@ -50,6 +51,8 @@ pub async fn relayer_main_loop( gravity_contract_address, gravity_id.clone(), LOOP_SPEED, + eth_gas_price_multiplier, + eth_gas_multiplier, ) .await; @@ -61,6 +64,7 @@ pub async fn relayer_main_loop( gravity_id.clone(), LOOP_SPEED, eth_gas_price_multiplier, + eth_gas_multiplier, ) .await; @@ -72,6 +76,7 @@ pub async fn relayer_main_loop( gravity_id.clone(), LOOP_SPEED, eth_gas_price_multiplier, + eth_gas_multiplier, &mut logic_call_skips, ) .await; diff --git a/orchestrator/relayer/src/valset_relaying.rs b/orchestrator/relayer/src/valset_relaying.rs index 0043b5873..ad47fa548 100644 --- a/orchestrator/relayer/src/valset_relaying.rs +++ b/orchestrator/relayer/src/valset_relaying.rs @@ -24,6 +24,8 @@ pub async fn relay_valsets( gravity_contract_address: EthAddress, gravity_id: String, timeout: Duration, + eth_gas_price_multiplier: f32, + eth_gas_multiplier: f32, ) { // we have to start with the current ethereum valset, we need to know what's currently // in the contract in order to determine if a new validator set is valid. @@ -162,7 +164,7 @@ pub async fn relay_valsets( ); return; } - let cost = cost.unwrap(); + let mut cost = cost.unwrap(); let total_cost = downcast_to_f32(cost.get_total()); if total_cost.is_none() { error!( @@ -172,6 +174,8 @@ pub async fn relay_valsets( return; } let total_cost = total_cost.unwrap(); + let gas_price_as_f32 = downcast_to_f32(cost.gas_price).unwrap(); // if the total cost isn't greater, this isn't + let gas_as_f32 = downcast_to_f32(cost.gas).unwrap(); // same as above re: total cost info!( "We have detected latest valset {} but latest on Ethereum is {} This valset is estimated to cost {} Gas / {:.4} ETH to submit", @@ -180,6 +184,9 @@ pub async fn relay_valsets( total_cost / one_eth_f32() ); + cost.gas_price = ((gas_price_as_f32 * eth_gas_price_multiplier) as u128).into(); + cost.gas = ((gas_as_f32 * eth_gas_multiplier) as u128).into(); + let relay_response = send_eth_valset_update( latest_cosmos_valset.clone(), current_eth_valset.clone(), From 000d998118b1687d74e0ed4a7ab34b7949dbd87d Mon Sep 17 00:00:00 2001 From: Eric Bolten Date: Tue, 12 Jul 2022 17:12:52 -0700 Subject: [PATCH 2/3] Standalone relayer using 1.1 as default multiplier --- orchestrator/relayer/src/main.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/orchestrator/relayer/src/main.rs b/orchestrator/relayer/src/main.rs index 97c982393..8f2d05290 100644 --- a/orchestrator/relayer/src/main.rs +++ b/orchestrator/relayer/src/main.rs @@ -109,8 +109,8 @@ async fn main() { eth_client, connections.grpc.unwrap(), gravity_contract_address, - 1f32, - 1f32, + 1.1f32, + 1.1f32, ) .await } From 95b0eb6c199e6cd1bcbf13dc416afa9df3e65bc9 Mon Sep 17 00:00:00 2001 From: Eric Bolten Date: Tue, 12 Jul 2022 17:13:10 -0700 Subject: [PATCH 3/3] 120 second pending TX timeout for relays --- orchestrator/relayer/src/main_loop.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/orchestrator/relayer/src/main_loop.rs b/orchestrator/relayer/src/main_loop.rs index 8d8b15c46..5f02de878 100644 --- a/orchestrator/relayer/src/main_loop.rs +++ b/orchestrator/relayer/src/main_loop.rs @@ -9,6 +9,7 @@ use std::{time::Duration}; use tonic::transport::Channel; pub const LOOP_SPEED: Duration = Duration::from_secs(17); +pub const PENDING_TX_TIMEOUT: Duration = Duration::from_secs(120); /// This function contains the orchestrator primary loop, it is broken out of the main loop so that /// it can be called in the test runner for easier orchestration of multi-node tests @@ -50,7 +51,7 @@ pub async fn relayer_main_loop( &mut grpc_client, gravity_contract_address, gravity_id.clone(), - LOOP_SPEED, + PENDING_TX_TIMEOUT, eth_gas_price_multiplier, eth_gas_multiplier, ) @@ -62,7 +63,7 @@ pub async fn relayer_main_loop( &mut grpc_client, gravity_contract_address, gravity_id.clone(), - LOOP_SPEED, + PENDING_TX_TIMEOUT, eth_gas_price_multiplier, eth_gas_multiplier, ) @@ -74,7 +75,7 @@ pub async fn relayer_main_loop( &mut grpc_client, gravity_contract_address, gravity_id.clone(), - LOOP_SPEED, + PENDING_TX_TIMEOUT, eth_gas_price_multiplier, eth_gas_multiplier, &mut logic_call_skips,