From 4de9312272db1f4725cc74204b996aee66fc6c62 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 22 Aug 2023 10:52:30 +0100 Subject: [PATCH 1/6] Use E-1 to authenticate a valset upd proof for some epoch E --- shared/src/ledger/eth_bridge/validator_set.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/shared/src/ledger/eth_bridge/validator_set.rs b/shared/src/ledger/eth_bridge/validator_set.rs index 6814fae8ec..53e910a6e6 100644 --- a/shared/src/ledger/eth_bridge/validator_set.rs +++ b/shared/src/ledger/eth_bridge/validator_set.rs @@ -557,11 +557,18 @@ where .map_err(|e| Error::critical(e.to_string()))? .next() }; + + if hints::unlikely(epoch_to_relay == Epoch(0)) { + return Err(Error::critical( + "There is no validator set update proof for epoch 0", + )); + } + let shell = RPC.shell().eth_bridge(); let encoded_proof_fut = shell.read_valset_upd_proof(nam_client, &epoch_to_relay); - let bridge_current_epoch = Epoch(epoch_to_relay.0.saturating_sub(2)); + let bridge_current_epoch = epoch_to_relay - 1; let shell = RPC.shell().eth_bridge(); let encoded_validator_set_args_fut = shell.read_consensus_valset(nam_client, &bridge_current_epoch); From 651b72af75c50d2e8ca31010e40f3da299b36b09 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 22 Aug 2023 11:53:20 +0100 Subject: [PATCH 2/6] Print error msgs when a proof is not available, in the relayer --- shared/src/ledger/eth_bridge/validator_set.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/shared/src/ledger/eth_bridge/validator_set.rs b/shared/src/ledger/eth_bridge/validator_set.rs index 53e910a6e6..619bbc4a5e 100644 --- a/shared/src/ledger/eth_bridge/validator_set.rs +++ b/shared/src/ledger/eth_bridge/validator_set.rs @@ -165,6 +165,9 @@ trait ShouldRelay { where E: Middleware, E::Error: std::fmt::Display; + + /// Try to recover from an error that has happened. + fn try_recover(err: String) -> Error; } impl ShouldRelay for DoNotCheckNonce { @@ -179,6 +182,11 @@ impl ShouldRelay for DoNotCheckNonce { { std::future::ready(Ok(())) } + + #[inline] + fn try_recover(err: String) -> Error { + Error::recoverable(err) + } } impl ShouldRelay for CheckNonce { @@ -216,6 +224,11 @@ impl ShouldRelay for CheckNonce { } }) } + + #[inline] + fn try_recover(err: String) -> Error { + Error::critical(err) + } } /// Relay result for [`CheckNonce`]. @@ -582,7 +595,7 @@ where encoded_validator_set_args_fut, governance_address_fut ) - .map_err(|err| Error::recoverable(err.to_string()))?; + .map_err(|err| R::try_recover(err.to_string()))?; let (bridge_hash, gov_hash, signatures): ( [u8; 32], From a002028b5b3e0a8dd068848bc04479a65fedae22 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 22 Aug 2023 13:47:20 +0100 Subject: [PATCH 3/6] Fix validator set update relayer daemon nonce logic --- shared/src/ledger/eth_bridge/validator_set.rs | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/shared/src/ledger/eth_bridge/validator_set.rs b/shared/src/ledger/eth_bridge/validator_set.rs index 619bbc4a5e..434d455065 100644 --- a/shared/src/ledger/eth_bridge/validator_set.rs +++ b/shared/src/ledger/eth_bridge/validator_set.rs @@ -460,16 +460,18 @@ where "Failed to fetch latest validator set nonce: {err}" ); }) - .map(|e| Epoch(e.as_u64())) + .map(|e| e.as_u64() as i128) }); let shell = RPC.shell(); let nam_current_epoch_fut = shell.epoch(nam_client).map(|result| { - result.map_err(|err| { - tracing::error!( - "Failed to fetch the latest epoch in Namada: {err}" - ); - }) + result + .map_err(|err| { + tracing::error!( + "Failed to fetch the latest epoch in Namada: {err}" + ); + }) + .map(|Epoch(e)| e as i128) }); let (nam_current_epoch, gov_current_epoch) = @@ -482,8 +484,11 @@ where "Fetched the latest epochs" ); - match nam_current_epoch.cmp(&gov_current_epoch) { - Ordering::Equal => { + let new_epoch = match nam_current_epoch - gov_current_epoch { + // NB: a namada epoch should always be one behind the nonce + // in the governance contract, for the latter to be considered + // up to date + -1 => { tracing::debug!( "Nothing to do, since the validator set in the Governance \ contract is up to date", @@ -491,16 +496,21 @@ where last_call_succeeded = false; continue; } - Ordering::Less => { + 0.. => { + let e = gov_current_epoch + 1; + // consider only the lower 64-bits + Epoch((e & (u64::MAX as i128)) as u64) + } + // NB: if the nonce difference is lower than 0, somehow the state + // of namada managed to fall behind the state of the smart contract + _ => { tracing::error!("The Governance contract is ahead of Namada!"); last_call_succeeded = false; continue; } - Ordering::Greater => {} - } + }; // update epoch in the contract - let new_epoch = gov_current_epoch + 1u64; args.epoch = Some(new_epoch); let result = relay_validator_set_update_once::( From 052ae9126d74cd63c1c73be70446941b0d0e2a38 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 22 Aug 2023 13:56:58 +0100 Subject: [PATCH 4/6] Fix spelling in valset upd relayer log msg --- shared/src/ledger/eth_bridge/validator_set.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shared/src/ledger/eth_bridge/validator_set.rs b/shared/src/ledger/eth_bridge/validator_set.rs index 434d455065..7ff30ef07c 100644 --- a/shared/src/ledger/eth_bridge/validator_set.rs +++ b/shared/src/ledger/eth_bridge/validator_set.rs @@ -373,7 +373,7 @@ where } RelayResult::Receipt { receipt } => { if receipt.is_successful() { - tracing::info!(?receipt, "Ethereum transfer succeded"); + tracing::info!(?receipt, "Ethereum transfer succeeded"); } else { tracing::error!(?receipt, "Ethereum transfer failed"); } @@ -525,7 +525,7 @@ where }; last_call_succeeded = receipt.is_successful(); if last_call_succeeded { - tracing::info!(?receipt, "Ethereum transfer succeded"); + tracing::info!(?receipt, "Ethereum transfer succeeded"); tracing::info!(?new_epoch, "Updated the validator set"); } else { tracing::error!(?receipt, "Ethereum transfer failed"); From ecc1b0492860738ae59e1b02e863090c977e03dd Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Fri, 25 Aug 2023 10:01:05 +0100 Subject: [PATCH 5/6] Switch to a big-endian encoding on Ethereum uints --- core/src/types/ethereum_events.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/core/src/types/ethereum_events.rs b/core/src/types/ethereum_events.rs index f7097e9749..57c8047fdd 100644 --- a/core/src/types/ethereum_events.rs +++ b/core/src/types/ethereum_events.rs @@ -51,11 +51,14 @@ impl Ord for Uint { } impl Uint { - /// Convert to a little endian byte representation of - /// a uint256. + /// Convert to an Ethereum-compatible byte representation. + /// + /// The Ethereum virtual machine employs big-endian integers + /// (Wood, 2014), therefore the returned byte array has the + /// same endianness. pub fn to_bytes(self) -> [u8; 32] { let mut bytes = [0; 32]; - ethUint(self.0).to_little_endian(&mut bytes); + ethUint(self.0).to_big_endian(&mut bytes); bytes } From 80bc32fbbf07b07f8ce60447969ac61b0d11f40b Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Tue, 29 Aug 2023 13:54:39 +0100 Subject: [PATCH 6/6] Changelog for #1856 --- .../unreleased/bug-fixes/1856-eth-contract-nonce-fixes.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changelog/unreleased/bug-fixes/1856-eth-contract-nonce-fixes.md diff --git a/.changelog/unreleased/bug-fixes/1856-eth-contract-nonce-fixes.md b/.changelog/unreleased/bug-fixes/1856-eth-contract-nonce-fixes.md new file mode 100644 index 0000000000..0e11191cd3 --- /dev/null +++ b/.changelog/unreleased/bug-fixes/1856-eth-contract-nonce-fixes.md @@ -0,0 +1,2 @@ +- Miscellaneous Ethereum smart contract nonce fixes + ([\#1856](https://github.com/anoma/namada/pull/1856)) \ No newline at end of file