Skip to content

Commit

Permalink
Merge branch 'tiago/eth-contract-nonce-fixes' (#1856)
Browse files Browse the repository at this point in the history
  • Loading branch information
sug0 committed Aug 30, 2023
2 parents aadb22b + 80bc32f commit 7f2bce9
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Miscellaneous Ethereum smart contract nonce fixes
([\#1856](https://github.com/anoma/namada/pull/1856))
9 changes: 6 additions & 3 deletions core/src/types/ethereum_events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down
62 changes: 46 additions & 16 deletions shared/src/ledger/eth_bridge/validator_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -216,6 +224,11 @@ impl ShouldRelay for CheckNonce {
}
})
}

#[inline]
fn try_recover(err: String) -> Error {
Error::critical(err)
}
}

/// Relay result for [`CheckNonce`].
Expand Down Expand Up @@ -360,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");
}
Expand Down Expand Up @@ -447,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) =
Expand All @@ -469,25 +484,33 @@ 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",
);
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::<DoNotCheckNonce, _, _, _>(
Expand All @@ -502,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");
Expand Down Expand Up @@ -557,11 +580,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);
Expand All @@ -575,7 +605,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],
Expand Down

0 comments on commit 7f2bce9

Please sign in to comment.