diff --git a/.changelog/unreleased/miscellaneous/1885-migrate-new-contracts.md b/.changelog/unreleased/miscellaneous/1885-migrate-new-contracts.md new file mode 100644 index 0000000000..42e75fb5a3 --- /dev/null +++ b/.changelog/unreleased/miscellaneous/1885-migrate-new-contracts.md @@ -0,0 +1,2 @@ +- Migrate to the new Ethereum contracts + ([\#1885](https://github.com/anoma/namada/pull/1885)) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e100cceb45..2e205d26fc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2106,8 +2106,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethbridge-bridge-events", "ethbridge-structs", @@ -2117,8 +2117,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethbridge-structs", @@ -2128,40 +2128,17 @@ dependencies = [ [[package]] name = "ethbridge-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethbridge-bridge-events", - "ethbridge-governance-events", "ethers", ] -[[package]] -name = "ethbridge-governance-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethbridge-governance-events", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - -[[package]] -name = "ethbridge-governance-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethabi", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - [[package]] name = "ethbridge-structs" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethers", @@ -4088,7 +4065,6 @@ dependencies = [ "derivation-path", "derivative", "ethbridge-bridge-contract", - "ethbridge-governance-contract", "ethers", "eyre", "futures", @@ -4167,7 +4143,6 @@ dependencies = [ "ethabi", "ethbridge-bridge-events", "ethbridge-events", - "ethbridge-governance-events", "eyre", "fd-lock", "ferveo", diff --git a/Cargo.toml b/Cargo.toml index 48141a0f77..e1f3124fbf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -67,12 +67,10 @@ directories = "4.0.1" ed25519-consensus = "1.2.0" escargot = "0.5.7" ethabi = "18.0.0" -ethbridge-bridge-contract = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0"} -ethbridge-bridge-events = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0"} -ethbridge-events = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0"} -ethbridge-governance-contract = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0"} -ethbridge-governance-events = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0"} -ethbridge-structs = { git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.23.0" } +ethbridge-bridge-contract = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.24.0"} +ethbridge-bridge-events = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.24.0"} +ethbridge-events = {git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.24.0"} +ethbridge-structs = { git = "https://github.com/heliaxdev/ethbridge-rs", tag = "v0.24.0" } ethers = "2.0.0" expectrl = "0.7.0" eyre = "0.6.5" diff --git a/apps/Cargo.toml b/apps/Cargo.toml index 16fe028be3..1d33f55df7 100644 --- a/apps/Cargo.toml +++ b/apps/Cargo.toml @@ -89,7 +89,6 @@ ed25519-consensus.workspace = true ethabi.workspace = true ethbridge-bridge-events.workspace = true ethbridge-events.workspace = true -ethbridge-governance-events.workspace = true eyre.workspace = true fd-lock.workspace = true ferveo-common.workspace = true diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index 70cba50687..657379b1e4 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -2292,10 +2292,12 @@ pub mod cmds { /// Used as sub-commands (`SubCmd` instance) in `namadar` binary. #[derive(Clone, Debug)] pub enum ValidatorSet { - /// Query an Ethereum ABI encoding of the consensus validator - /// set in Namada, at the given epoch, or the latest - /// one, if none is provided. - ConsensusValidatorSet(ConsensusValidatorSet), + /// Query the Bridge validator set in Namada, at the given epoch, + /// or the latest one, if none is provided. + BridgeValidatorSet(BridgeValidatorSet), + /// Query the Governance validator set in Namada, at the given epoch, + /// or the latest one, if none is provided. + GovernanceValidatorSet(GovernanceValidatorSet), /// Query an Ethereum ABI encoding of a proof of the consensus /// validator set in Namada, at the given epoch, or the next /// one, if none is provided. @@ -2310,14 +2312,19 @@ pub mod cmds { fn parse(matches: &ArgMatches) -> Option { matches.subcommand_matches(Self::CMD).and_then(|matches| { - let consensus_validator_set = - ConsensusValidatorSet::parse(matches) - .map(Self::ConsensusValidatorSet); + let bridge_validator_set = BridgeValidatorSet::parse(matches) + .map(Self::BridgeValidatorSet); + let governance_validator_set = + GovernanceValidatorSet::parse(matches) + .map(Self::GovernanceValidatorSet); let validator_set_proof = ValidatorSetProof::parse(matches) .map(Self::ValidatorSetProof); let relay = ValidatorSetUpdateRelay::parse(matches) .map(Self::ValidatorSetUpdateRelay); - consensus_validator_set.or(validator_set_proof).or(relay) + bridge_validator_set + .or(governance_validator_set) + .or(validator_set_proof) + .or(relay) }) } @@ -2329,34 +2336,56 @@ pub mod cmds { contracts.", ) .subcommand_required(true) - .subcommand(ConsensusValidatorSet::def().display_order(1)) + .subcommand(BridgeValidatorSet::def().display_order(1)) + .subcommand(GovernanceValidatorSet::def().display_order(1)) .subcommand(ValidatorSetProof::def().display_order(1)) .subcommand(ValidatorSetUpdateRelay::def().display_order(1)) } } #[derive(Clone, Debug)] - pub struct ConsensusValidatorSet( - pub args::ConsensusValidatorSet, + pub struct BridgeValidatorSet(pub args::BridgeValidatorSet); + + impl SubCmd for BridgeValidatorSet { + const CMD: &'static str = "bridge"; + + fn parse(matches: &ArgMatches) -> Option { + matches + .subcommand_matches(Self::CMD) + .map(|matches| Self(args::BridgeValidatorSet::parse(matches))) + } + + fn def() -> App { + App::new(Self::CMD) + .about( + "Query the Bridge validator set in Namada, at the given \ + epoch, or the latest one, if none is provided.", + ) + .add_args::>() + } + } + + #[derive(Clone, Debug)] + pub struct GovernanceValidatorSet( + pub args::GovernanceValidatorSet, ); - impl SubCmd for ConsensusValidatorSet { - const CMD: &'static str = "consensus"; + impl SubCmd for GovernanceValidatorSet { + const CMD: &'static str = "governance"; fn parse(matches: &ArgMatches) -> Option { matches.subcommand_matches(Self::CMD).map(|matches| { - Self(args::ConsensusValidatorSet::parse(matches)) + Self(args::GovernanceValidatorSet::parse(matches)) }) } fn def() -> App { App::new(Self::CMD) .about( - "Query an Ethereum ABI encoding of the consensus \ - validator set in Namada, at the requested epoch, or the \ - current one, if no epoch is provided.", + "Query the Governance validator set in Namada, at the \ + given epoch, or the latest one, if none is provided.", ) - .add_args::>() + .add_args::>() } } @@ -3193,18 +3222,18 @@ pub mod args { } } - impl CliToSdkCtxless> - for ConsensusValidatorSet + impl CliToSdkCtxless> + for BridgeValidatorSet { - fn to_sdk_ctxless(self) -> ConsensusValidatorSet { - ConsensusValidatorSet:: { + fn to_sdk_ctxless(self) -> BridgeValidatorSet { + BridgeValidatorSet:: { query: self.query.to_sdk_ctxless(), epoch: self.epoch, } } } - impl Args for ConsensusValidatorSet { + impl Args for BridgeValidatorSet { fn parse(matches: &ArgMatches) -> Self { let query = Query::parse(matches); let epoch = EPOCH.parse(matches); @@ -3214,12 +3243,37 @@ pub mod args { fn def(app: App) -> App { app.add_args::>().arg( EPOCH.def().help( - "The epoch of the consensus set of validators to query.", + "The epoch of the Bridge set of validators to query.", ), ) } } + impl CliToSdkCtxless> + for GovernanceValidatorSet + { + fn to_sdk_ctxless(self) -> GovernanceValidatorSet { + GovernanceValidatorSet:: { + query: self.query.to_sdk_ctxless(), + epoch: self.epoch, + } + } + } + + impl Args for GovernanceValidatorSet { + fn parse(matches: &ArgMatches) -> Self { + let query = Query::parse(matches); + let epoch = EPOCH.parse(matches); + Self { query, epoch } + } + + fn def(app: App) -> App { + app.add_args::>().arg(EPOCH.def().help( + "The epoch of the Governance set of validators to query.", + )) + } + } + impl CliToSdkCtxless> for ValidatorSetProof { diff --git a/apps/src/lib/cli/relayer.rs b/apps/src/lib/cli/relayer.rs index f0d38cce77..3322e84e2f 100644 --- a/apps/src/lib/cli/relayer.rs +++ b/apps/src/lib/cli/relayer.rs @@ -125,7 +125,7 @@ impl CliApi { } }, cli::NamadaRelayer::ValidatorSet(sub) => match sub { - ValidatorSet::ConsensusValidatorSet(ConsensusValidatorSet( + ValidatorSet::BridgeValidatorSet(BridgeValidatorSet( mut args, )) => { let client = client.unwrap_or_else(|| { @@ -138,7 +138,25 @@ impl CliApi { .await .proceed_or_else(error)?; let args = args.to_sdk_ctxless(); - validator_set::query_validator_set_args::<_, IO>( + validator_set::query_bridge_validator_set::<_, IO>( + &client, args, + ) + .await; + } + ValidatorSet::GovernanceValidatorSet( + GovernanceValidatorSet(mut args), + ) => { + let client = client.unwrap_or_else(|| { + C::from_tendermint_address( + &mut args.query.ledger_address, + ) + }); + client + .wait_until_node_is_synced::() + .await + .proceed_or_else(error)?; + let args = args.to_sdk_ctxless(); + validator_set::query_governnace_validator_set::<_, IO>( &client, args, ) .await; diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index eced8e1047..ac3738a9bc 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -1126,10 +1126,6 @@ pub fn genesis(num_validators: u64) -> Genesis { address: EthAddress([0; 20]), version: Default::default(), }, - governance: UpgradeableContract { - address: EthAddress([1; 20]), - version: Default::default(), - }, }, }), native_token: address::nam(), diff --git a/apps/src/lib/node/ledger/ethereum_oracle/events.rs b/apps/src/lib/node/ledger/ethereum_oracle/events.rs index bd11cf09e8..4baae5e19f 100644 --- a/apps/src/lib/node/ledger/ethereum_oracle/events.rs +++ b/apps/src/lib/node/ledger/ethereum_oracle/events.rs @@ -3,15 +3,11 @@ pub mod eth_events { use std::str::FromStr; use ethbridge_bridge_events::{ - BridgeEvents, TransferToErcFilter, TransferToNamadaFilter, - }; - use ethbridge_events::{DynEventCodec, Events as RawEvents}; - use ethbridge_governance_events::{ - GovernanceEvents, NewContractFilter, UpgradedContractFilter, + BridgeEvents, TransferToChainFilter, TransferToErcFilter, ValidatorSetUpdateFilter, }; + use ethbridge_events::{DynEventCodec, Events as RawEvents}; use namada::core::types::ethereum_structs; - use namada::eth_bridge::ethers::contract::EthEvent; use namada::types::address::Address; use namada::types::ethereum_events::{ EthAddress, EthereumEvent, TransferToEthereum, TransferToNamada, Uint, @@ -70,20 +66,17 @@ pub mod eth_events { TransferToErcFilter { nonce, transfers, - valid_map, relayer_address, }, )) => EthereumEvent::TransfersToEthereum { nonce: nonce.parse_uint256()?, transfers: transfers.parse_transfer_to_eth_array()?, - valid_transfers_map: valid_map, relayer: relayer_address.parse_address()?, }, - RawEvents::Bridge(BridgeEvents::TransferToNamadaFilter( - TransferToNamadaFilter { + RawEvents::Bridge(BridgeEvents::TransferToChainFilter( + TransferToChainFilter { nonce, transfers, - valid_map, confirmations: requested_confirmations, }, )) => { @@ -96,34 +89,15 @@ pub mod eth_events { nonce: nonce.parse_uint256()?, transfers: transfers .parse_transfer_to_namada_array()?, - valid_transfers_map: valid_map, } } - RawEvents::Governance(GovernanceEvents::NewContractFilter( - NewContractFilter { name: _, addr: _ }, - )) => { - return Err(Error::NotInUse( - NewContractFilter::name().into(), - )); - } - RawEvents::Governance( - GovernanceEvents::UpgradedContractFilter( - UpgradedContractFilter { name: _, addr: _ }, - ), - ) => { - return Err(Error::NotInUse( - UpgradedContractFilter::name().into(), - )); - } - RawEvents::Governance( - GovernanceEvents::ValidatorSetUpdateFilter( - ValidatorSetUpdateFilter { - validator_set_nonce, - bridge_validator_set_hash, - governance_validator_set_hash, - }, - ), - ) => EthereumEvent::ValidatorSetUpdate { + RawEvents::Bridge(BridgeEvents::ValidatorSetUpdateFilter( + ValidatorSetUpdateFilter { + validator_set_nonce, + bridge_validator_set_hash, + governance_validator_set_hash, + }, + )) => EthereumEvent::ValidatorSetUpdate { nonce: validator_set_nonce.into(), bridge_validator_hash: bridge_validator_set_hash .parse_keccak()?, @@ -253,7 +227,7 @@ pub mod eth_events { } } - impl Parse for Vec { + impl Parse for Vec { fn parse_transfer_to_namada_array( self, ) -> Result> { @@ -264,7 +238,7 @@ pub mod eth_events { } } - impl Parse for ethereum_structs::NamadaTransfer { + impl Parse for ethereum_structs::ChainTransfer { fn parse_transfer_to_namada(self) -> Result { let asset = self.from.parse_eth_address()?; let amount = self.amount.parse_amount()?; @@ -293,7 +267,7 @@ pub mod eth_events { let asset = self.from.parse_eth_address()?; let receiver = self.to.parse_eth_address()?; let amount = self.amount.parse_amount()?; - let checksum = self.namada_data_digest.parse_hash()?; + let checksum = self.data_digest.parse_hash()?; Ok(TransferToEthereum { asset, amount, @@ -321,9 +295,10 @@ pub mod eth_events { use assert_matches::assert_matches; use ethabi::ethereum_types::{H160, U256}; use ethbridge_events::{ - TRANSFER_TO_ERC_CODEC, TRANSFER_TO_NAMADA_CODEC, + TRANSFER_TO_CHAIN_CODEC, TRANSFER_TO_ERC_CODEC, VALIDATOR_SET_UPDATE_CODEC, }; + use namada::eth_bridge::ethers::contract::EthEvent; use super::*; use crate::node::ledger::ethereum_oracle::test_tools::event_log::GetLog; @@ -339,10 +314,9 @@ pub mod eth_events { let lower_than_min_confirmations = 5u64; let (codec, event) = ( - TRANSFER_TO_NAMADA_CODEC, - TransferToNamadaFilter { + TRANSFER_TO_CHAIN_CODEC, + TransferToChainFilter { transfers: vec![], - valid_map: vec![], nonce: 0.into(), confirmations: lower_than_min_confirmations.into(), }, @@ -363,42 +337,38 @@ pub mod eth_events { Ok(()) } - /// Test decoding a [`TransferToNamadaFilter`] Ethereum event. + /// Test decoding a "Transfer to Namada" Ethereum event. #[test] fn test_transfer_to_namada_decode() { let data = vec![ + 170, 156, 23, 249, 166, 216, 156, 37, 67, 204, 150, 161, 103, + 163, 161, 122, 243, 66, 109, 149, 141, 194, 27, 80, 238, 109, + 40, 128, 254, 233, 54, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 160, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 189, - 178, 49, 86, 120, 175, 236, 179, 103, 240, 50, 217, 63, 100, - 47, 100, 24, 10, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 84, - 97, 116, 101, 115, 116, 49, 118, 52, 101, 104, 103, 119, 51, - 54, 120, 117, 117, 110, 119, 100, 54, 57, 56, 57, 112, 114, - 119, 100, 102, 107, 120, 113, 109, 110, 118, 115, 102, 106, - 120, 115, 54, 110, 118, 118, 54, 120, 120, 117, 99, 114, 115, - 51, 102, 51, 120, 99, 109, 110, 115, 51, 102, 99, 120, 100, - 122, 114, 118, 118, 122, 57, 120, 118, 101, 114, 122, 118, 122, - 114, 53, 54, 108, 101, 56, 102, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 189, 178, 49, 86, + 120, 175, 236, 179, 103, 240, 50, 217, 63, 100, 47, 100, 24, + 10, 163, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1, + 0, 0, 0, 84, 97, 116, 101, 115, 116, 49, 118, 52, 101, 104, + 103, 119, 51, 54, 120, 117, 117, 110, 119, 100, 54, 57, 56, 57, + 112, 114, 119, 100, 102, 107, 120, 113, 109, 110, 118, 115, + 102, 106, 120, 115, 54, 110, 118, 118, 54, 120, 120, 117, 99, + 114, 115, 51, 102, 51, 120, 99, 109, 110, 115, 51, 102, 99, + 120, 100, 122, 114, 118, 118, 122, 57, 120, 118, 101, 114, 122, + 118, 122, 114, 53, 54, 108, 101, 56, 102, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, ]; - let raw: TransferToNamadaFilter = TRANSFER_TO_NAMADA_CODEC + let raw: TransferToChainFilter = TRANSFER_TO_CHAIN_CODEC .decode(ðabi::RawLog { - topics: vec![TransferToNamadaFilter::signature()], + topics: vec![TransferToChainFilter::signature()], data, }) .expect("Test failed") @@ -407,7 +377,7 @@ pub mod eth_events { assert_eq!( raw.transfers, - vec![ethereum_structs::NamadaTransfer { + vec![ethereum_structs::ChainTransfer { amount: 100u64.into(), from: ethabi::Address::from_str("0x5FbDB2315678afecb367f032d93F642f64180aa3").unwrap(), to: "atest1v4ehgw36xuunwd6989prwdfkxqmnvsfjxs6nvv6xxucrs3f3xcmns3fcxdzrvvz9xverzvzr56le8f".into(), @@ -425,10 +395,9 @@ pub mod eth_events { let higher_than_min_confirmations = 200u64; let (codec, event) = ( - TRANSFER_TO_NAMADA_CODEC, - TransferToNamadaFilter { + TRANSFER_TO_CHAIN_CODEC, + TransferToChainFilter { transfers: vec![], - valid_map: vec![], nonce: 0u64.into(), confirmations: higher_than_min_confirmations.into(), }, @@ -501,16 +470,15 @@ pub mod eth_events { let address: String = "atest1v4ehgw36gep5ysecxq6nyv3jg3zygv3e89qn2vp48pryxsf4xpznvve5gvmy23fs89pryvf5a6ht90" .into(); - let nam_transfers = TransferToNamadaFilter { + let nam_transfers = TransferToChainFilter { transfers: vec![ - ethereum_structs::NamadaTransfer { + ethereum_structs::ChainTransfer { amount: 0u64.into(), from: H160([0; 20]), to: address.clone(), }; 2 ], - valid_map: vec![true; 2], nonce: 0u64.into(), confirmations: 0u64.into(), }; @@ -520,11 +488,10 @@ pub mod eth_events { from: H160([1; 20]), to: H160([2; 20]), amount: 0u64.into(), - namada_data_digest: [0; 32], + data_digest: [0; 32], }; 2 ], - valid_map: vec![true; 2], nonce: 0u64.into(), relayer_address: address, }; @@ -535,8 +502,8 @@ pub mod eth_events { }; assert_eq!( { - let decoded: TransferToNamadaFilter = - TRANSFER_TO_NAMADA_CODEC + let decoded: TransferToChainFilter = + TRANSFER_TO_CHAIN_CODEC .decode(&nam_transfers.clone().get_log()) .expect("Test failed") .try_into() diff --git a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs index a8db91831c..6980778c07 100644 --- a/apps/src/lib/node/ledger/ethereum_oracle/mod.rs +++ b/apps/src/lib/node/ledger/ethereum_oracle/mod.rs @@ -444,7 +444,6 @@ async fn process( let sig = codec.event_signature(); let addr: Address = match codec.kind() { EventKind::Bridge => config.bridge_contract.into(), - EventKind::Governance => config.governance_contract.into(), }; tracing::debug!( ?block_to_process, @@ -562,9 +561,7 @@ pub mod last_processed_block { mod test_oracle { use std::num::NonZeroU64; - use ethbridge_bridge_events::{ - TransferToErcFilter, TransferToNamadaFilter, - }; + use ethbridge_bridge_events::{TransferToChainFilter, TransferToErcFilter}; use namada::eth_bridge::ethers::types::H160; use namada::eth_bridge::structs::Erc20Transfer; use namada::types::address::testing::gen_established_address; @@ -710,16 +707,15 @@ mod test_oracle { // Increase height above the configured minimum confirmations controller.apply_cmd(TestCmd::NewHeight(min_confirmations.into())); - let new_event = TransferToNamadaFilter { + let new_event = TransferToChainFilter { nonce: 0.into(), transfers: vec![], - valid_map: vec![], confirmations: 100.into(), } .get_log(); let (sender, _) = channel(); controller.apply_cmd(TestCmd::NewEvent { - event_type: event_signature::(), + event_type: event_signature::(), log: new_event, height: 101, seen: sender, @@ -760,16 +756,15 @@ mod test_oracle { // set the oracle to be unresponsive controller.apply_cmd(TestCmd::Unresponsive); // send a new event to the oracle - let new_event = TransferToNamadaFilter { + let new_event = TransferToChainFilter { nonce: 0.into(), transfers: vec![], - valid_map: vec![], confirmations: 100.into(), } .get_log(); let (sender, mut seen) = channel(); controller.apply_cmd(TestCmd::NewEvent { - event_type: event_signature::(), + event_type: event_signature::(), log: new_event, height: 150, seen: sender, @@ -815,10 +810,9 @@ mod test_oracle { controller.apply_cmd(TestCmd::NewHeight(min_confirmations.into())); // confirmed after 100 blocks - let first_event = TransferToNamadaFilter { + let first_event = TransferToChainFilter { nonce: 0.into(), transfers: vec![], - valid_map: vec![], confirmations: 100.into(), } .get_log(); @@ -830,9 +824,8 @@ mod test_oracle { amount: 0.into(), from: H160([0; 20]), to: H160([1; 20]), - namada_data_digest: [0; 32], + data_digest: [0; 32], }], - valid_map: vec![true], relayer_address: gas_payer.to_string(), nonce: 0.into(), } @@ -848,7 +841,7 @@ mod test_oracle { }); let (sender, _recv) = channel(); controller.apply_cmd(TestCmd::NewEvent { - event_type: event_signature::(), + event_type: event_signature::(), log: first_event, height: 100, seen: sender, @@ -859,15 +852,9 @@ mod test_oracle { controller.apply_cmd(TestCmd::NewHeight(Uint256::from(200u32))); // check the correct event is received let event = eth_recv.recv().await.expect("Test failed"); - if let EthereumEvent::TransfersToNamada { - nonce, - transfers, - valid_transfers_map: valid_map, - } = event - { + if let EthereumEvent::TransfersToNamada { nonce, transfers } = event { assert_eq!(nonce, 0.into()); assert!(transfers.is_empty()); - assert!(valid_map.is_empty()); } else { panic!("Test failed, {:?}", event); } diff --git a/apps/src/lib/node/ledger/ethereum_oracle/test_tools/mod.rs b/apps/src/lib/node/ledger/ethereum_oracle/test_tools/mod.rs index 672a1546f8..9a2454be17 100644 --- a/apps/src/lib/node/ledger/ethereum_oracle/test_tools/mod.rs +++ b/apps/src/lib/node/ledger/ethereum_oracle/test_tools/mod.rs @@ -6,9 +6,8 @@ pub mod event_log { // p.s.: https://medium.com/mycrypto/understanding-event-logs-on-the-ethereum-blockchain-f4ae7ba50378 use ethbridge_bridge_events::{ - TransferToErcFilter, TransferToNamadaFilter, + TransferToChainFilter, TransferToErcFilter, ValidatorSetUpdateFilter, }; - use ethbridge_governance_events::ValidatorSetUpdateFilter; use namada::eth_bridge::ethers::abi::AbiEncode; use namada::eth_bridge::ethers::contract::EthEvent; @@ -18,7 +17,7 @@ pub mod event_log { fn get_log(self) -> ethabi::RawLog; } - impl GetLog for TransferToNamadaFilter { + impl GetLog for TransferToChainFilter { fn get_log(self) -> ethabi::RawLog { ethabi::RawLog { topics: vec![Self::signature()], @@ -35,8 +34,7 @@ pub mod event_log { self.nonce.to_big_endian(&mut buf); ethabi::ethereum_types::H256(buf) }], - data: (self.transfers, self.valid_map, self.relayer_address) - .encode(), + data: (self.transfers, self.relayer_address).encode(), } } } diff --git a/apps/src/lib/node/ledger/shell/finalize_block.rs b/apps/src/lib/node/ledger/shell/finalize_block.rs index b08e3ce770..53252065f1 100644 --- a/apps/src/lib/node/ledger/shell/finalize_block.rs +++ b/apps/src/lib/node/ledger/shell/finalize_block.rs @@ -1497,9 +1497,9 @@ mod test_finalize_block { .clone(); // ---- the ledger receives a new Ethereum event - let event = EthereumEvent::NewContract { - name: "Test".to_string(), - address: EthAddress([0; 20]), + let event = EthereumEvent::TransfersToNamada { + nonce: 0u64.into(), + transfers: vec![], }; tokio_test::block_on(oracle.send(event.clone())).expect("Test failed"); let [queued_event]: [EthereumEvent; 1] = @@ -1575,9 +1575,9 @@ mod test_finalize_block { .clone(); // ---- the ledger receives a new Ethereum event - let event = EthereumEvent::NewContract { - name: "Test".to_string(), - address: EthAddress([0; 20]), + let event = EthereumEvent::TransfersToNamada { + nonce: 0u64.into(), + transfers: vec![], }; tokio_test::block_on(oracle.send(event.clone())).expect("Test failed"); let [queued_event]: [EthereumEvent; 1] = @@ -1695,17 +1695,8 @@ mod test_finalize_block { #[test] /// Test that adding a new erc20 transfer to the bridge pool - /// increments the pool's nonce, whether only invalid transfers - /// were relayed or not. + /// increments the pool's nonce. fn test_bp_nonce_is_incremented() { - test_bp_nonce_is_incremented_aux(false); - test_bp_nonce_is_incremented_aux(true); - } - - /// Helper function to [`test_bp_nonce_is_incremented`]. - /// - /// Sets the validity of the transfer on Ethereum's side. - fn test_bp_nonce_is_incremented_aux(valid_transfer: bool) { use crate::node::ledger::shell::address::nam; test_bp(|shell: &mut TestShell| { let asset = EthAddress([0xff; 20]); @@ -1771,7 +1762,6 @@ mod test_finalize_block { let ethereum_event = EthereumEvent::TransfersToEthereum { nonce: 0u64.into(), transfers: vec![transfer], - valid_transfers_map: vec![valid_transfer], relayer: bertha, }; let (protocol_key, _, _) = diff --git a/apps/src/lib/node/ledger/shell/mod.rs b/apps/src/lib/node/ledger/shell/mod.rs index 019c022c5f..778ceffd01 100644 --- a/apps/src/lib/node/ledger/shell/mod.rs +++ b/apps/src/lib/node/ledger/shell/mod.rs @@ -1034,7 +1034,6 @@ where let config = namada::eth_bridge::oracle::config::Config { min_confirmations: config.min_confirmations.into(), bridge_contract: config.contracts.bridge.address, - governance_contract: config.contracts.governance.address, start_block, }; tracing::info!( @@ -2153,12 +2152,10 @@ mod abciplus_mempool_tests { let ethereum_event_0 = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ethereum_event_1 = EthereumEvent::TransfersToNamada { nonce: 1u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; shell .wl_storage @@ -2204,7 +2201,6 @@ mod abciplus_mempool_tests { let ethereum_event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let eth_vext = EthereumTxData::EthEventsVext( ethereum_events::Vext { @@ -2257,7 +2253,6 @@ mod abciplus_mempool_tests { let ethereum_event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = { let ext = ethereum_events::Vext { @@ -2291,7 +2286,6 @@ mod abciplus_mempool_tests { let ethereum_event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = { let ext = ethereum_events::Vext { diff --git a/apps/src/lib/node/ledger/shell/prepare_proposal.rs b/apps/src/lib/node/ledger/shell/prepare_proposal.rs index 840bab3892..3687a6d39b 100644 --- a/apps/src/lib/node/ledger/shell/prepare_proposal.rs +++ b/apps/src/lib/node/ledger/shell/prepare_proposal.rs @@ -786,7 +786,6 @@ mod test_prepare_proposal { let ethereum_event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let signed_vote_extension = { let ev = ethereum_event; @@ -987,7 +986,6 @@ mod test_prepare_proposal { let ethereum_event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let signed_eth_ev_vote_extension = { let ext = ethereum_events::Vext { diff --git a/apps/src/lib/node/ledger/shell/process_proposal.rs b/apps/src/lib/node/ledger/shell/process_proposal.rs index e77ec1d3aa..ab544de3f8 100644 --- a/apps/src/lib/node/ledger/shell/process_proposal.rs +++ b/apps/src/lib/node/ledger/shell/process_proposal.rs @@ -1170,7 +1170,6 @@ mod test_process_proposal { let event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = ethereum_events::Vext { validator_addr: addr.clone(), @@ -1297,7 +1296,6 @@ mod test_process_proposal { let event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = ethereum_events::Vext { validator_addr: addr.clone(), @@ -1402,7 +1400,6 @@ mod test_process_proposal { let event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = { // generate a valid signature @@ -1472,7 +1469,6 @@ mod test_process_proposal { let event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = { #[allow(clippy::redundant_clone)] @@ -1528,7 +1524,6 @@ mod test_process_proposal { let event = EthereumEvent::TransfersToNamada { nonce: 0u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ext = { #[allow(clippy::redundant_clone)] diff --git a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs index 1ee2331f23..0dd85bfd70 100644 --- a/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs +++ b/apps/src/lib/node/ledger/shell/vote_extensions/eth_events.rs @@ -192,24 +192,11 @@ where /// thus the inclusion of its container Ethereum events vote /// extension. /// - /// Additionally, the length of the transfers array and their - /// respective validity map must match, for the event to be - /// considered valid. - /// /// ## Transfers to Namada /// /// For a transfers to Namada event to be considered valid, /// the nonce of this kind of event must not be lower than /// the one stored in Namada. - /// - /// In this case, the length of the transfers array and their - /// respective validity map must also match. - /// - /// ## Whitelist updates - /// - /// For any of these events to be considered valid, the - /// whitelist update nonce in storage must be greater - /// than or equal to the nonce in the event. fn validate_eth_event( &self, event: &EthereumEvent, @@ -222,20 +209,8 @@ where // out such events, which will time out in storage match event { EthereumEvent::TransfersToEthereum { - nonce: ext_nonce, - transfers, - valid_transfers_map, - .. + nonce: ext_nonce, .. } => { - if transfers.len() != valid_transfers_map.len() { - tracing::debug!( - transfers_len = transfers.len(), - valid_transfers_map_len = valid_transfers_map.len(), - "{}", - VoteExtensionError::TransfersLenMismatch - ); - return Err(VoteExtensionError::TransfersLenMismatch); - } let current_bp_nonce = self.wl_storage.ethbridge_queries().get_bridge_pool_nonce(); if ¤t_bp_nonce != ext_nonce { @@ -249,20 +224,8 @@ where } } EthereumEvent::TransfersToNamada { - nonce: ext_nonce, - transfers, - valid_transfers_map, - .. + nonce: ext_nonce, .. } => { - if transfers.len() != valid_transfers_map.len() { - tracing::debug!( - transfers_len = transfers.len(), - valid_transfers_map_len = valid_transfers_map.len(), - "{}", - VoteExtensionError::TransfersLenMismatch - ); - return Err(VoteExtensionError::TransfersLenMismatch); - } let next_nam_transfers_nonce = self .wl_storage .ethbridge_queries() @@ -514,7 +477,6 @@ mod test_vote_extensions { .validate_eth_event(&EthereumEvent::TransfersToEthereum { nonce, transfers: vec![], - valid_transfers_map: vec![], relayer: gen_established_address(), }) .expect("Test failed"); @@ -524,7 +486,6 @@ mod test_vote_extensions { .validate_eth_event(&EthereumEvent::TransfersToEthereum { nonce: nonce + 1, transfers: vec![], - valid_transfers_map: vec![], relayer: gen_established_address(), }) .expect_err("Test failed"); @@ -532,7 +493,6 @@ mod test_vote_extensions { .validate_eth_event(&EthereumEvent::TransfersToEthereum { nonce: nonce - 1, transfers: vec![], - valid_transfers_map: vec![], relayer: gen_established_address(), }) .expect_err("Test failed"); @@ -542,14 +502,12 @@ mod test_vote_extensions { .validate_eth_event(&EthereumEvent::TransfersToNamada { nonce, transfers: vec![], - valid_transfers_map: vec![], }) .expect("Test failed"); shell .validate_eth_event(&EthereumEvent::TransfersToNamada { nonce: nonce + 5, transfers: vec![], - valid_transfers_map: vec![], }) .expect("Test failed"); @@ -558,32 +516,12 @@ mod test_vote_extensions { .validate_eth_event(&EthereumEvent::TransfersToNamada { nonce: nonce - 1, transfers: vec![], - valid_transfers_map: vec![], }) .expect_err("Test failed"); shell .validate_eth_event(&EthereumEvent::TransfersToNamada { nonce: nonce - 2, transfers: vec![], - valid_transfers_map: vec![], - }) - .expect_err("Test failed"); - - // either kind of transfer with different validity map and transfer - // array length are invalid - shell - .validate_eth_event(&EthereumEvent::TransfersToEthereum { - nonce, - transfers: vec![], - valid_transfers_map: vec![true, true], - relayer: gen_established_address(), - }) - .expect_err("Test failed"); - shell - .validate_eth_event(&EthereumEvent::TransfersToNamada { - nonce, - transfers: vec![], - valid_transfers_map: vec![true, true], }) .expect_err("Test failed"); } @@ -605,7 +543,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }; let event_2 = EthereumEvent::TransfersToEthereum { @@ -616,34 +553,41 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }; - let event_3 = EthereumEvent::NewContract { - name: "Test".to_string(), - address: EthAddress([0; 20]), + let event_3 = EthereumEvent::TransfersToNamada { + nonce: 0.into(), + transfers: vec![], }; tokio_test::block_on(oracle.send(event_1.clone())) .expect("Test failed"); tokio_test::block_on(oracle.send(event_3.clone())) .expect("Test failed"); - let [event_first, event_second]: [EthereumEvent; 2] = + + let got_events: [EthereumEvent; 2] = shell.new_ethereum_events().try_into().expect("Test failed"); + let expected_events: Vec<_> = std::collections::BTreeSet::from([ + event_1.clone(), + event_3.clone(), + ]) + .into_iter() + .collect(); + assert_eq!(expected_events, got_events); - assert_eq!(event_first, event_1); - assert_eq!(event_second, event_3); // check that we queue and de-duplicate events tokio_test::block_on(oracle.send(event_2.clone())) .expect("Test failed"); tokio_test::block_on(oracle.send(event_3.clone())) .expect("Test failed"); - let [event_first, event_second, event_third]: [EthereumEvent; 3] = - shell.new_ethereum_events().try_into().expect("Test failed"); - assert_eq!(event_first, event_1); - assert_eq!(event_second, event_2); - assert_eq!(event_third, event_3); + let got_events: [EthereumEvent; 3] = + shell.new_ethereum_events().try_into().expect("Test failed"); + let expected_events: Vec<_> = + std::collections::BTreeSet::from([event_1, event_2, event_3]) + .into_iter() + .collect(); + assert_eq!(expected_events, got_events); } /// Test that ethereum events are added to vote extensions. @@ -665,7 +609,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }; let event_2 = EthereumEvent::NewContract { @@ -725,7 +668,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }], block_height: shell @@ -817,7 +759,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }], block_height: signed_height, @@ -922,7 +863,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }], block_height: shell.wl_storage.storage.get_last_block_height(), @@ -1002,7 +942,6 @@ mod test_vote_extensions { receiver: EthAddress([2; 20]), checksum: Hash::default(), }], - valid_transfers_map: vec![true], relayer: gen_established_address(), }], block_height: shell.wl_storage.storage.get_last_block_height(), diff --git a/core/src/ledger/eth_bridge/storage/bridge_pool.rs b/core/src/ledger/eth_bridge/storage/bridge_pool.rs index 167e23e779..78e15b5d38 100644 --- a/core/src/ledger/eth_bridge/storage/bridge_pool.rs +++ b/core/src/ledger/eth_bridge/storage/bridge_pool.rs @@ -15,6 +15,14 @@ use crate::types::hash::Hash; use crate::types::keccak::{keccak_hash, KeccakHash}; use crate::types::storage::{BlockHeight, DbKeySeg, Key, KeySeg}; +/// Prefix to be used in Bridge pool tree root computations. +/// This value corresponds to leaf nodes. +const POOL_ROOT_PREFIX_LEAF: u8 = 0x00; + +/// Prefix to be used in Bridge pool tree root computations. +/// This value corresponds to non-leaf nodes. +const POOL_ROOT_PREFIX_NON_LEAF: u8 = 0xff; + /// The main address of the Ethereum bridge pool pub const BRIDGE_POOL_ADDRESS: Address = Address::Internal(InternalAddress::EthBridgePool); @@ -156,14 +164,16 @@ impl BridgePoolTree { /// Compute the root of the merkle tree fn compute_root(&self) -> KeccakHash { let mut hashes: Vec = self.leaves.keys().cloned().collect(); + let mut prefix = POOL_ROOT_PREFIX_LEAF; while hashes.len() > 1 { let mut next_hashes = vec![]; for pair in hashes.chunks(2) { let left = pair[0].clone(); let right = pair.get(1).cloned().unwrap_or_default(); - next_hashes.push(hash_pair(left, right)); + next_hashes.push(hash_pair(left, right, prefix)); } hashes = next_hashes; + prefix = POOL_ROOT_PREFIX_NON_LEAF; } if hashes.is_empty() { @@ -215,6 +225,8 @@ impl BridgePoolTree { }) .collect(); + let mut prefix = POOL_ROOT_PREFIX_LEAF; + while hashes.len() > 1 { let mut next_hashes = vec![]; @@ -224,30 +236,41 @@ impl BridgePoolTree { match (left, right) { (Node::OnPath(left), Node::OnPath(right)) => { flags.push(true); - next_hashes - .push(Node::OnPath(hash_pair(left.clone(), right))); + next_hashes.push(Node::OnPath(hash_pair( + left.clone(), + right, + prefix, + ))); } (Node::OnPath(hash), Node::OffPath(sib)) => { flags.push(false); proof_hashes.push(sib.clone()); - next_hashes - .push(Node::OnPath(hash_pair(hash.clone(), sib))); + next_hashes.push(Node::OnPath(hash_pair( + hash.clone(), + sib, + prefix, + ))); } (Node::OffPath(sib), Node::OnPath(hash)) => { flags.push(false); proof_hashes.push(sib.clone()); - next_hashes - .push(Node::OnPath(hash_pair(hash, sib.clone()))); + next_hashes.push(Node::OnPath(hash_pair( + hash, + sib.clone(), + prefix, + ))); } (Node::OffPath(left), Node::OffPath(right)) => { next_hashes.push(Node::OffPath(hash_pair( left.clone(), right, + prefix, ))); } } } hashes = next_hashes; + prefix = POOL_ROOT_PREFIX_NON_LEAF; } // add the root to the proof if flags.is_empty() && proof_hashes.is_empty() && leaves.is_empty() { @@ -285,14 +308,21 @@ impl BridgePoolTree { } } -/// Concatenate two keccak hashes and hash the result +/// Concatenate a byte prefix and two keccak hashes, +/// then compute the keccak hash of the resulting +/// byte array. #[inline] -fn hash_pair(left: KeccakHash, right: KeccakHash) -> KeccakHash { +fn hash_pair(left: KeccakHash, right: KeccakHash, prefix: u8) -> KeccakHash { + let mut buf = [0u8; 32 + 32 + 1]; + buf[0] = prefix; if left.0 < right.0 { - keccak_hash([left.0, right.0].concat().as_slice()) + buf[1..33].copy_from_slice(&left.0); + buf[33..].copy_from_slice(&right.0); } else { - keccak_hash([right.0, left.0].concat().as_slice()) + buf[1..33].copy_from_slice(&right.0); + buf[33..].copy_from_slice(&left.0); } + keccak_hash(buf) } /// Keeps track if a node is on a path from the @@ -348,14 +378,14 @@ impl BridgePoolProof { let mut proof_pos = 0usize; for i in 0..total_hashes { - let left = if leaf_pos < leaf_len { + let (left, prefix) = if leaf_pos < leaf_len { let next = self.leaves[leaf_pos].keccak256(); leaf_pos += 1; - next + (next, POOL_ROOT_PREFIX_LEAF) } else { let next = hashes[hash_pos].clone(); hash_pos += 1; - next + (next, POOL_ROOT_PREFIX_NON_LEAF) }; let right = if self.flags[i] { if leaf_pos < leaf_len { @@ -372,7 +402,7 @@ impl BridgePoolProof { proof_pos += 1; next }; - hashes[i] = hash_pair(left, right); + hashes[i] = hash_pair(left, right, prefix); } if let Some(computed) = hashes.last() { @@ -479,8 +509,11 @@ mod test_bridge_pool_tree { transfers.push(transfer); let _ = tree.insert_key(&key, BlockHeight(1)).expect("Test failed"); } - let expected = - hash_pair(transfers[0].keccak256(), transfers[1].keccak256()); + let expected = hash_pair( + transfers[0].keccak256(), + transfers[1].keccak256(), + POOL_ROOT_PREFIX_LEAF, + ); assert_eq!(tree.root(), expected); } @@ -516,11 +549,18 @@ mod test_bridge_pool_tree { tree.leaves.keys().cloned().collect::>() ); - let left_hash = - hash_pair(transfers[0].keccak256(), transfers[1].keccak256()); - let right_hash = - hash_pair(transfers[2].keccak256(), Default::default()); - let expected = hash_pair(left_hash, right_hash); + let left_hash = hash_pair( + transfers[0].keccak256(), + transfers[1].keccak256(), + POOL_ROOT_PREFIX_LEAF, + ); + let right_hash = hash_pair( + transfers[2].keccak256(), + Default::default(), + POOL_ROOT_PREFIX_LEAF, + ); + let expected = + hash_pair(left_hash, right_hash, POOL_ROOT_PREFIX_NON_LEAF); assert_eq!(tree.root(), expected); } @@ -581,8 +621,11 @@ mod test_bridge_pool_tree { let deleted_key = Key::from(&transfers[1]); tree.delete_key(&deleted_key).expect("Test failed"); - let expected = - hash_pair(transfers[0].keccak256(), transfers[2].keccak256()); + let expected = hash_pair( + transfers[0].keccak256(), + transfers[2].keccak256(), + POOL_ROOT_PREFIX_LEAF, + ); assert_eq!(tree.root(), expected); assert_matches!(tree.get(&deleted_key), Err(_)); } diff --git a/core/src/ledger/eth_bridge/storage/mod.rs b/core/src/ledger/eth_bridge/storage/mod.rs index e728603fb7..5e11db64ef 100644 --- a/core/src/ledger/eth_bridge/storage/mod.rs +++ b/core/src/ledger/eth_bridge/storage/mod.rs @@ -63,11 +63,6 @@ pub fn bridge_contract_key() -> Key { get_bridge_contract_address_key_at_addr(PARAM_ADDRESS) } -/// Storage key for the Ethereum address of the governance contract. -pub fn governance_contract_key() -> Key { - get_governance_contract_address_key_at_addr(PARAM_ADDRESS) -} - #[cfg(test)] mod test { use super::*; diff --git a/core/src/ledger/parameters/storage.rs b/core/src/ledger/parameters/storage.rs index c31a6e59da..4b4b85822f 100644 --- a/core/src/ledger/parameters/storage.rs +++ b/core/src/ledger/parameters/storage.rs @@ -23,8 +23,6 @@ struct Keys { native_erc20: &'static str, /// Sub-lkey for storing the Ethereum address of the bridge contract. bridge_contract_address: &'static str, - /// Sub-key for storing the Ethereum address of the governance contract. - governance_contract_address: &'static str, // ======================================== // PoS parameters // ======================================== diff --git a/core/src/types/eth_abi.rs b/core/src/types/eth_abi.rs index adda87e6c9..27d2b93db1 100644 --- a/core/src/types/eth_abi.rs +++ b/core/src/types/eth_abi.rs @@ -198,17 +198,17 @@ mod tests { ) .expect("Test failed"), ], - voting_powers: vec![8828299.try_into().unwrap()], + voting_powers: vec![8828299u64.into()], epoch: 0.into(), }; let encoded = valset_update.encode().into_inner(); let encoded = HEXLOWER.encode(&encoded); - let expected = "00000000000000000000000000000000000000000000000000000000000000200000\ - 00000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000\ - 000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000\ - 00000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000\ - 241d37b7cf5233b3b0b204321420a86e8f7bfdb50000000000000000000000000000000000000000000000000000\ - 000000000001000000000000000000000000000000000000000000000000000000000086b58b"; + let expected = "000000000000000000000000000000000000000000000000000000000000002\ + 000000000000000000000000000000000000000000000000000000000000000\ + 400000000000000000000000000000000000000000000000000000000000000\ + 000000000000000000000000000000000000000000000000000000000000000\ + 0001241d37b7cf5233b3b0b204321420a86e8f7bfdb50000000000000000008\ + 6b58b"; assert_eq!(expected, encoded); } } diff --git a/core/src/types/eth_bridge_pool.rs b/core/src/types/eth_bridge_pool.rs index 86b0815509..0f1a887345 100644 --- a/core/src/types/eth_bridge_pool.rs +++ b/core/src/types/eth_bridge_pool.rs @@ -210,12 +210,12 @@ impl PendingTransfer { impl From<&PendingTransfer> for ethbridge_structs::Erc20Transfer { fn from(pending: &PendingTransfer) -> Self { - let HashDigest(namada_data_digest) = pending.appendix().checksum(); + let HashDigest(data_digest) = pending.appendix().checksum(); Self { from: pending.transfer.asset.0.into(), to: pending.transfer.recipient.0.into(), amount: pending.transfer.amount.into(), - namada_data_digest, + data_digest, } } } diff --git a/core/src/types/ethereum_events.rs b/core/src/types/ethereum_events.rs index 57c8047fdd..8dce0a39a4 100644 --- a/core/src/types/ethereum_events.rs +++ b/core/src/types/ethereum_events.rs @@ -235,8 +235,6 @@ pub struct TransfersToNamada { pub nonce: Uint, /// The batch of transfers pub transfers: Vec, - /// The indices of the transfers which succeeded or failed - pub valid_transfers_map: Vec, } impl GetEventNonce for TransfersToNamada { @@ -249,16 +247,8 @@ impl GetEventNonce for TransfersToNamada { impl From for EthereumEvent { #[inline] fn from(event: TransfersToNamada) -> Self { - let TransfersToNamada { - nonce, - transfers, - valid_transfers_map, - } = event; - Self::TransfersToNamada { - nonce, - transfers, - valid_transfers_map, - } + let TransfersToNamada { nonce, transfers } = event; + Self::TransfersToNamada { nonce, transfers } } } @@ -285,9 +275,6 @@ pub enum EthereumEvent { /// The batch of transfers #[allow(dead_code)] transfers: Vec, - /// The indices of the transfers which succeeded or failed - #[allow(dead_code)] - valid_transfers_map: Vec, }, /// A confirmation event that a batch of transfers have been made /// from Namada to Ethereum @@ -298,9 +285,6 @@ pub enum EthereumEvent { /// The batch of transfers #[allow(dead_code)] transfers: Vec, - /// The indices of the transfers which succeeded or failed - #[allow(dead_code)] - valid_transfers_map: Vec, /// The Namada address that receives the gas fees /// for relaying a batch of transfers #[allow(dead_code)] @@ -319,25 +303,6 @@ pub enum EthereumEvent { #[allow(dead_code)] governance_validator_hash: KeccakHash, }, - /// Event indication that a new smart contract has been - /// deployed - NewContract { - /// Name of the contract - #[allow(dead_code)] - name: String, - /// Address of the contract on Ethereum - #[allow(dead_code)] - address: EthAddress, - }, - /// Event indicating that a smart contract has been updated - UpgradedContract { - /// Name of the contract - #[allow(dead_code)] - name: String, - /// Address of the contract on Ethereum - #[allow(dead_code)] - address: EthAddress, - }, } impl EthereumEvent { @@ -417,7 +382,7 @@ impl From for TransferToEthereum { }, asset: EthAddress(transfer.from.0), receiver: EthAddress(transfer.to.0), - checksum: Hash(transfer.namada_data_digest), + checksum: Hash(transfer.data_digest), } } } @@ -530,7 +495,6 @@ pub mod testing { asset: arbitrary_eth_address(), receiver, }], - valid_transfers_map: vec![true], } } } diff --git a/core/src/types/storage.rs b/core/src/types/storage.rs index a4fd16977a..4aae00b42e 100644 --- a/core/src/types/storage.rs +++ b/core/src/types/storage.rs @@ -1490,7 +1490,6 @@ mod tests { let mut queue = EthEventsQueue::default(); queue.transfers_to_namada.next_nonce_to_process = 2u64.into(); let new_event = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 2u64.into(), }; @@ -1510,7 +1509,6 @@ mod tests { let mut queue = EthEventsQueue::default(); queue.transfers_to_namada.next_nonce_to_process = 3u64.into(); let new_event = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 2u64.into(), }; @@ -1525,27 +1523,22 @@ mod tests { queue.transfers_to_namada.next_nonce_to_process = 1u64.into(); let new_event_1 = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 1u64.into(), }; let new_event_2 = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 2u64.into(), }; let new_event_3 = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 3u64.into(), }; let new_event_4 = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 4u64.into(), }; let new_event_7 = TransfersToNamada { - valid_transfers_map: vec![], transfers: vec![], nonce: 7u64.into(), }; diff --git a/core/src/types/vote_extensions/ethereum_events.rs b/core/src/types/vote_extensions/ethereum_events.rs index 863211a18d..efd019c76b 100644 --- a/core/src/types/vote_extensions/ethereum_events.rs +++ b/core/src/types/vote_extensions/ethereum_events.rs @@ -155,16 +155,15 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce, transfers: vec![], - valid_transfers_map: vec![], }; let hash = event.hash().unwrap(); assert_eq!( hash, Hash([ - 237, 76, 45, 220, 228, 238, 146, 153, 170, 10, 70, 130, 32, 16, - 67, 66, 231, 34, 223, 166, 173, 203, 204, 195, 54, 19, 165, - 119, 63, 252, 187, 132 + 94, 131, 116, 129, 41, 204, 178, 144, 24, 8, 185, 16, 103, 236, + 209, 191, 20, 89, 145, 17, 41, 233, 31, 98, 185, 6, 217, 204, + 80, 38, 224, 23 ]) ); } @@ -181,12 +180,10 @@ mod tests { let ev_1 = EthereumEvent::TransfersToNamada { nonce: 1u64.into(), transfers: vec![], - valid_transfers_map: vec![], }; let ev_2 = EthereumEvent::TransfersToEthereum { nonce: 2u64.into(), transfers: vec![], - valid_transfers_map: vec![], relayer: address::testing::established_address_1(), }; diff --git a/core/src/types/vote_extensions/validator_set_update.rs b/core/src/types/vote_extensions/validator_set_update.rs index 5a9324fec6..bf3d749ff5 100644 --- a/core/src/types/vote_extensions/validator_set_update.rs +++ b/core/src/types/vote_extensions/validator_set_update.rs @@ -4,7 +4,6 @@ use std::cmp::Ordering; use std::collections::HashMap; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; -use ethabi::ethereum_types as ethereum; use crate::proto::Signed; use crate::types::address::Address; @@ -165,16 +164,16 @@ pub trait VotingPowersMapExt { /// sorted in descending order by voting power, as this is more efficient to /// deal with on the Ethereum side when working out if there is enough /// voting power for a given validator set update. - fn get_abi_encoded(&self) -> (Vec, Vec, Vec) { + fn get_abi_encoded(&self) -> (Vec, Vec) { let sorted = self.get_sorted(); let total_voting_power: token::Amount = sorted.iter().map(|&(_, &voting_power)| voting_power).sum(); - // split the vec into three portions - sorted.into_iter().fold( - Default::default(), - |accum, (addr_book, &voting_power)| { + // split the vec into two portions + sorted + .into_iter() + .map(|(addr_book, &voting_power)| { let voting_power: EthBridgeVotingPower = FractionalVotingPower::new( voting_power.into(), @@ -186,22 +185,23 @@ pub trait VotingPowersMapExt { ) .into(); - let (mut hot_key_addrs, mut cold_key_addrs, mut voting_powers) = - accum; let &EthAddrBook { - hot_key_addr: EthAddress(hot_key_addr), - cold_key_addr: EthAddress(cold_key_addr), + hot_key_addr, + cold_key_addr, } = addr_book; - hot_key_addrs - .push(Token::Address(ethereum::H160(hot_key_addr))); - cold_key_addrs - .push(Token::Address(ethereum::H160(cold_key_addr))); - voting_powers.push(Token::Uint(voting_power.into())); - - (hot_key_addrs, cold_key_addrs, voting_powers) - }, - ) + ( + Token::FixedBytes( + encode_validator_data(hot_key_addr, voting_power) + .into(), + ), + Token::FixedBytes( + encode_validator_data(cold_key_addr, voting_power) + .into(), + ), + ) + }) + .unzip() } /// Returns the bridge and governance keccak hashes of @@ -211,13 +211,11 @@ pub trait VotingPowersMapExt { &self, next_epoch: Epoch, ) -> (KeccakHash, KeccakHash) { - let (hot_key_addrs, cold_key_addrs, voting_powers) = - self.get_abi_encoded(); + let (bridge_validators, governance_validators) = self.get_abi_encoded(); valset_upd_toks_to_hashes( next_epoch, - hot_key_addrs, - cold_key_addrs, - voting_powers, + bridge_validators, + governance_validators, ) } } @@ -227,23 +225,20 @@ pub trait VotingPowersMapExt { /// voting powers, normalized to `2^32`. pub fn valset_upd_toks_to_hashes( next_epoch: Epoch, - hot_key_addrs: Vec, - cold_key_addrs: Vec, - voting_powers: Vec, + bridge_validators: Vec, + governance_validators: Vec, ) -> (KeccakHash, KeccakHash) { let bridge_hash = compute_hash( next_epoch, BRIDGE_CONTRACT_VERSION, BRIDGE_CONTRACT_NAMESPACE, - hot_key_addrs, - voting_powers.clone(), + bridge_validators, ); let governance_hash = compute_hash( next_epoch, GOVERNANCE_CONTRACT_VERSION, GOVERNANCE_CONTRACT_NAMESPACE, - cold_key_addrs, - voting_powers, + governance_validators, ); (bridge_hash, governance_hash) } @@ -286,21 +281,46 @@ fn compute_hash( contract_version: u8, contract_namespace: &str, validators: Vec, - voting_powers: Vec, ) -> KeccakHash { AbiEncode::keccak256(&[ Token::Uint(contract_version.into()), Token::String(contract_namespace.into()), Token::Array(validators), - Token::Array(voting_powers), epoch_to_token(next_epoch), ]) } +/// Given a validator's [`EthAddress`] and its respective +/// [`EthBridgeVotingPower`], return an encoded representation +/// of this data, understood by the smart contract. +#[inline] +fn encode_validator_data( + address: EthAddress, + voting_power: EthBridgeVotingPower, +) -> [u8; 32] { + let address = address.0; + let voting_power = u128::from(voting_power).to_be_bytes(); + + let mut buffer = [0u8; 32]; + buffer[..20].copy_from_slice(&address); + buffer[20..].copy_from_slice(&voting_power[4..]); + + buffer +} + /// Struct for serializing validator set /// arguments with ABI for Ethereum smart /// contracts. -#[derive(Debug, Clone, Default, Eq, PartialEq)] +#[derive( + Debug, + Clone, + Default, + Eq, + PartialEq, + BorshSerialize, + BorshDeserialize, + BorshSchema, +)] // TODO: find a new home for this type pub struct ValidatorSetArgs { /// Ethereum addresses of the validators. @@ -322,13 +342,10 @@ impl From for ethbridge_structs::ValidatorSetArgs { epoch, } = valset; ethbridge_structs::ValidatorSetArgs { - validators: validators - .into_iter() - .map(|addr| addr.0.into()) - .collect(), - powers: voting_powers + validator_set: validators .into_iter() - .map(|power| u64::from(power).into()) + .zip(voting_powers.into_iter()) + .map(|(addr, power)| encode_validator_data(addr, power)) .collect(), nonce: epoch.0.into(), } @@ -337,20 +354,17 @@ impl From for ethbridge_structs::ValidatorSetArgs { impl Encode<1> for ValidatorSetArgs { fn tokenize(&self) -> [Token; 1] { - let addrs = Token::Array( + let validator_set = Token::Array( self.validators .iter() - .map(|addr| Token::Address(addr.0.into())) - .collect(), - ); - let powers = Token::Array( - self.voting_powers - .iter() - .map(|&power| Token::Uint(power.into())) + .zip(self.voting_powers.iter()) + .map(|(&addr, &power)| { + Token::FixedBytes(encode_validator_data(addr, power).into()) + }) .collect(), ); let nonce = Token::Uint(self.epoch.0.into()); - [Token::Tuple(vec![addrs, powers, nonce])] + [Token::Tuple(vec![validator_set, nonce])] } } @@ -384,7 +398,7 @@ mod tag { ext.voting_powers.get_bridge_and_gov_hashes(next_epoch); AbiEncode::signable_keccak256(&[ Token::Uint(GOVERNANCE_CONTRACT_VERSION.into()), - Token::String("updateValidatorsSet".into()), + Token::String("updateValidatorSet".into()), Token::FixedBytes(bridge_hash.to_vec()), Token::FixedBytes(gov_hash.to_vec()), epoch_to_token(next_epoch), @@ -409,11 +423,11 @@ mod tests { // const ethers = require('ethers'); // const keccak256 = require('keccak256') // - // const abiEncoder = new ethers.utils.AbiCoder(); + // const abiEncoder = new ethers.AbiCoder(); // // const output = abiEncoder.encode( - // ['uint256', 'string', 'address[]', 'uint256[]', 'uint256'], - // [1, 'bridge', [], [], 1], + // ['uint256', 'string', 'bytes32[]', 'uint256'], + // [1, 'bridge', [], 1], // ); // // const hash = keccak256(output).toString('hex'); @@ -421,14 +435,13 @@ mod tests { // console.log(hash); // ``` const EXPECTED: &str = - "b8da710845ad3b9e8a9dec6639a0b1a60c90441037cc0845c4b45d5aed19ec59"; + "b97454f4c266c0d223651a52a705d76f3be337ace04be4590d9aedab9818dabc"; let KeccakHash(got) = compute_hash( 1u64.into(), BRIDGE_CONTRACT_VERSION, BRIDGE_CONTRACT_NAMESPACE, vec![], - vec![], ); assert_eq!(&HEXLOWER.encode(&got[..]), EXPECTED); diff --git a/core/src/types/voting_power.rs b/core/src/types/voting_power.rs index ab1358358c..a28eedc1a4 100644 --- a/core/src/types/voting_power.rs +++ b/core/src/types/voting_power.rs @@ -30,19 +30,28 @@ use crate::types::uint::Uint; Hash, Debug, )] -pub struct EthBridgeVotingPower(u64); +pub struct EthBridgeVotingPower(u128); impl EthBridgeVotingPower { /// Maximum value that can be represented for the voting power /// stored in an Ethereum bridge smart contract. - pub const MAX: Self = Self(1 << 32); + /// + /// The smart contract uses 12-byte integers. + pub const MAX: Self = Self((1 << 96) - 1); } -impl TryFrom for EthBridgeVotingPower { +impl From for EthBridgeVotingPower { + #[inline] + fn from(val: u64) -> Self { + Self(val as u128) + } +} + +impl TryFrom for EthBridgeVotingPower { type Error = (); #[inline] - fn try_from(val: u64) -> Result { + fn try_from(val: u128) -> Result { if val <= Self::MAX.0 { Ok(Self(val)) } else { @@ -52,14 +61,11 @@ impl TryFrom for EthBridgeVotingPower { } impl From<&FractionalVotingPower> for EthBridgeVotingPower { - fn from(ratio: &FractionalVotingPower) -> Self { - // normalize the voting power - // https://github.com/anoma/ethereum-bridge/blob/fe93d2e95ddb193a759811a79c8464ad4d709c12/test/utils/utilities.js#L29 - const NORMALIZED_VOTING_POWER: Uint = - Uint::from_u64(EthBridgeVotingPower::MAX.0); + fn from(FractionalVotingPower(ratio): &FractionalVotingPower) -> Self { + let max_bridge_voting_power = Uint::from(EthBridgeVotingPower::MAX.0); - let voting_power = ratio.0 * NORMALIZED_VOTING_POWER; - let voting_power = voting_power.round().to_integer().low_u64(); + let voting_power = ratio * max_bridge_voting_power; + let voting_power = voting_power.round().to_integer().low_u128(); Self(voting_power) } @@ -79,9 +85,9 @@ impl From for ethereum::U256 { } } -impl From for u64 { +impl From for u128 { #[inline] - fn from(EthBridgeVotingPower(voting_power): EthBridgeVotingPower) -> u64 { + fn from(EthBridgeVotingPower(voting_power): EthBridgeVotingPower) -> u128 { voting_power } } diff --git a/ethereum_bridge/src/oracle/config.rs b/ethereum_bridge/src/oracle/config.rs index 4ddb3ede1d..b0718e81d9 100644 --- a/ethereum_bridge/src/oracle/config.rs +++ b/ethereum_bridge/src/oracle/config.rs @@ -12,8 +12,6 @@ pub struct Config { pub min_confirmations: NonZeroU64, /// The Ethereum address of the current bridge contract. pub bridge_contract: EthAddress, - /// The Ethereum address of the current governance contract. - pub governance_contract: EthAddress, /// The earliest Ethereum block from which events may be processed. pub start_block: ethereum_structs::BlockHeight, } @@ -27,7 +25,6 @@ impl std::default::Default for Config { // value that is >= 1 min_confirmations: unsafe { NonZeroU64::new_unchecked(100) }, bridge_contract: EthAddress([0; 20]), - governance_contract: EthAddress([1; 20]), start_block: 0.into(), } } diff --git a/ethereum_bridge/src/parameters.rs b/ethereum_bridge/src/parameters.rs index 6395dd6cab..c86ef1e6ed 100644 --- a/ethereum_bridge/src/parameters.rs +++ b/ethereum_bridge/src/parameters.rs @@ -137,8 +137,6 @@ pub struct Contracts { pub native_erc20: EthAddress, /// The Ethereum address of the bridge contract. pub bridge: UpgradeableContract, - /// The Ethereum address of the governance contract. - pub governance: UpgradeableContract, } /// Represents chain parameters for the Ethereum bridge. @@ -183,14 +181,12 @@ impl EthereumBridgeConfig { Contracts { native_erc20, bridge, - governance, }, } = self; let active_key = bridge_storage::active_key(); let min_confirmations_key = bridge_storage::min_confirmations_key(); let native_erc20_key = bridge_storage::native_erc20_key(); let bridge_contract_key = bridge_storage::bridge_contract_key(); - let governance_contract_key = bridge_storage::governance_contract_key(); let eth_start_height_key = bridge_storage::eth_start_height_key(); wl_storage .write_bytes( @@ -207,9 +203,6 @@ impl EthereumBridgeConfig { wl_storage .write_bytes(&bridge_contract_key, encode(bridge)) .unwrap(); - wl_storage - .write_bytes(&governance_contract_key, encode(governance)) - .unwrap(); wl_storage .write_bytes(ð_start_height_key, encode(eth_start_height)) .unwrap(); @@ -309,7 +302,6 @@ impl EthereumOracleConfig { let min_confirmations_key = bridge_storage::min_confirmations_key(); let native_erc20_key = bridge_storage::native_erc20_key(); let bridge_contract_key = bridge_storage::bridge_contract_key(); - let governance_contract_key = bridge_storage::governance_contract_key(); let eth_start_height_key = bridge_storage::eth_start_height_key(); // These reads must succeed otherwise the storage is corrupt or a @@ -318,8 +310,6 @@ impl EthereumOracleConfig { must_read_key(wl_storage, &min_confirmations_key); let native_erc20 = must_read_key(wl_storage, &native_erc20_key); let bridge_contract = must_read_key(wl_storage, &bridge_contract_key); - let governance_contract = - must_read_key(wl_storage, &governance_contract_key); let eth_start_height = must_read_key(wl_storage, ð_start_height_key); Some(Self { @@ -328,7 +318,6 @@ impl EthereumOracleConfig { contracts: Contracts { native_erc20, bridge: bridge_contract, - governance: governance_contract, }, }) } @@ -403,10 +392,6 @@ mod tests { address: EthAddress([23; 20]), version: ContractVersion::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: ContractVersion::default(), - }, }, }; let serialized = toml::to_string(&config)?; @@ -429,10 +414,6 @@ mod tests { address: EthAddress([23; 20]), version: ContractVersion::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: ContractVersion::default(), - }, }, }; config.init_storage(&mut wl_storage); @@ -465,10 +446,6 @@ mod tests { address: EthAddress([23; 20]), version: ContractVersion::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: ContractVersion::default(), - }, }, }; config.init_storage(&mut wl_storage); diff --git a/ethereum_bridge/src/protocol/transactions/ethereum_events/events.rs b/ethereum_bridge/src/protocol/transactions/ethereum_events/events.rs index 48aac0b8de..d878a56d11 100644 --- a/ethereum_bridge/src/protocol/transactions/ethereum_events/events.rs +++ b/ethereum_bridge/src/protocol/transactions/ethereum_events/events.rs @@ -45,29 +45,17 @@ where H: 'static + StorageHasher + Sync, { match event { - EthereumEvent::TransfersToNamada { - transfers, - valid_transfers_map, - nonce, - } => act_on_transfers_to_namada( - wl_storage, - TransfersToNamada { - transfers, - valid_transfers_map, - nonce, - }, - ), + EthereumEvent::TransfersToNamada { transfers, nonce } => { + act_on_transfers_to_namada( + wl_storage, + TransfersToNamada { transfers, nonce }, + ) + } EthereumEvent::TransfersToEthereum { ref transfers, ref relayer, - ref valid_transfers_map, .. - } => act_on_transfers_to_eth( - wl_storage, - transfers, - valid_transfers_map, - relayer, - ), + } => act_on_transfers_to_eth(wl_storage, transfers, relayer), _ => { tracing::debug!(?event, "No actions taken for Ethereum event"); Ok(BTreeSet::default()) @@ -93,28 +81,11 @@ where .transfers_to_namada .push_and_iter(transfer_event) .collect(); - for TransfersToNamada { - transfers, - valid_transfers_map, - .. - } in confirmed_events - { + for TransfersToNamada { transfers, .. } in confirmed_events { update_transfers_to_namada_state( wl_storage, &mut changed_keys, - transfers.iter().zip(valid_transfers_map.iter()).filter_map( - |(transfer, &valid)| { - if valid { - Some(transfer) - } else { - tracing::debug!( - ?transfer, - "Ignoring invalid transfer to Namada event" - ); - None - } - }, - ), + transfers.iter(), )?; } Ok(changed_keys) @@ -329,18 +300,13 @@ where fn act_on_transfers_to_eth( wl_storage: &mut WlStorage, transfers: &[TransferToEthereum], - valid_transfers: &[bool], relayer: &Address, ) -> Result> where D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, { - tracing::debug!( - ?transfers, - ?valid_transfers, - "Acting on transfers to Ethereum" - ); + tracing::debug!(?transfers, "Acting on transfers to Ethereum"); let mut changed_keys = BTreeSet::default(); // the BP nonce should always be incremented, even if no valid @@ -362,9 +328,7 @@ where .filter(is_pending_transfer_key) .collect(); // Remove the completed transfers from the bridge pool - for (event, is_valid) in - transfers.iter().zip(valid_transfers.iter().copied()) - { + for event in transfers { let (pending_transfer, key) = if let Some((pending, key)) = wl_storage.ethbridge_queries().lookup_transfer_to_eth(event) { @@ -373,27 +337,15 @@ where hints::cold(); unreachable!("The transfer should exist in the bridge pool"); }; - if hints::likely(is_valid) { - tracing::debug!( - ?pending_transfer, - "Valid transfer to Ethereum detected, compensating the \ - relayer and burning any Ethereum assets in Namada" - ); - changed_keys.append(&mut update_transferred_asset_balances( - wl_storage, - &pending_transfer, - )?); - } else { - tracing::debug!( - ?pending_transfer, - "Invalid transfer to Ethereum detected, compensating the \ - relayer and refunding assets in Namada" - ); - changed_keys.append(&mut refund_transferred_assets( - wl_storage, - &pending_transfer, - )?); - } + tracing::debug!( + ?pending_transfer, + "Valid transfer to Ethereum detected, compensating the relayer \ + and burning any Ethereum assets in Namada" + ); + changed_keys.append(&mut update_transferred_asset_balances( + wl_storage, + &pending_transfer, + )?); let pool_balance_key = balance_key(&pending_transfer.gas_fee.token, &BRIDGE_POOL_ADDRESS); let relayer_rewards_key = @@ -625,8 +577,7 @@ mod tests { use namada_core::types::address::{gen_established_address, nam, wnam}; use namada_core::types::eth_bridge_pool::GasFee; use namada_core::types::ethereum_events::testing::{ - arbitrary_eth_address, arbitrary_keccak_hash, arbitrary_nonce, - DAI_ERC20_ETH_ADDRESS, + arbitrary_keccak_hash, arbitrary_nonce, DAI_ERC20_ETH_ADDRESS, }; use namada_core::types::time::DurationSecs; use namada_core::types::token::Amount; @@ -860,21 +811,11 @@ mod tests { let mut wl_storage = TestWlStorage::default(); test_utils::bootstrap_ethereum_bridge(&mut wl_storage); let initial_stored_keys_count = stored_keys_count(&wl_storage); - let events = vec![ - EthereumEvent::NewContract { - name: "bridge".to_string(), - address: arbitrary_eth_address(), - }, - EthereumEvent::UpgradedContract { - name: "bridge".to_string(), - address: arbitrary_eth_address(), - }, - EthereumEvent::ValidatorSetUpdate { - nonce: arbitrary_nonce(), - bridge_validator_hash: arbitrary_keccak_hash(), - governance_validator_hash: arbitrary_keccak_hash(), - }, - ]; + let events = vec![EthereumEvent::ValidatorSetUpdate { + nonce: arbitrary_nonce(), + bridge_validator_hash: arbitrary_keccak_hash(), + governance_validator_hash: arbitrary_keccak_hash(), + }]; for event in events { act_on(&mut wl_storage, event.clone()).unwrap(); @@ -904,7 +845,6 @@ mod tests { }]; let event = EthereumEvent::TransfersToNamada { nonce: arbitrary_nonce(), - valid_transfers_map: transfers.iter().map(|_| true).collect(), transfers, }; @@ -1084,7 +1024,6 @@ mod tests { .collect(); let event = EthereumEvent::TransfersToEthereum { nonce: arbitrary_nonce(), - valid_transfers_map: transfers.iter().map(|_| true).collect(), transfers, relayer: relayer.clone(), }; @@ -1235,7 +1174,6 @@ mod tests { let event = EthereumEvent::TransfersToEthereum { nonce: arbitrary_nonce(), transfers: vec![], - valid_transfers_map: vec![], relayer: gen_implicit_address(), }; let _ = act_on(&mut wl_storage, event).unwrap(); @@ -1428,17 +1366,16 @@ mod tests { ], ); init_balance(&mut wl_storage, &pending_transfers); - let (transfers, valid_transfers_map) = pending_transfers + let transfers = pending_transfers .into_iter() .map(|ref transfer| { let transfer_to_eth: TransferToEthereum = transfer.into(); - (transfer_to_eth, true) + transfer_to_eth }) - .unzip(); + .collect(); let relayer = gen_established_address("random"); let event = EthereumEvent::TransfersToEthereum { nonce: arbitrary_nonce(), - valid_transfers_map, transfers, relayer, }; diff --git a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs index a95790ab51..8b71bb26c4 100644 --- a/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs +++ b/ethereum_bridge/src/protocol/transactions/ethereum_events/mod.rs @@ -329,7 +329,6 @@ mod tests { let asset = arbitrary_eth_address(); let body = EthereumEvent::TransfersToNamada { nonce: arbitrary_nonce(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount, asset, @@ -444,7 +443,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, @@ -507,7 +505,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, @@ -559,7 +556,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, @@ -682,7 +678,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, @@ -713,7 +708,6 @@ mod tests { let new_event = EthereumEvent::TransfersToNamada { nonce: 1.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, @@ -810,7 +804,6 @@ mod tests { let receiver = address::testing::established_address_1(); let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), - valid_transfers_map: vec![true], transfers: vec![TransferToNamada { amount: Amount::from(100), asset: DAI_ERC20_ETH_ADDRESS, diff --git a/ethereum_bridge/src/protocol/transactions/votes/storage.rs b/ethereum_bridge/src/protocol/transactions/votes/storage.rs index e9262ff08e..832797ae1b 100644 --- a/ethereum_bridge/src/protocol/transactions/votes/storage.rs +++ b/ethereum_bridge/src/protocol/transactions/votes/storage.rs @@ -151,7 +151,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), transfers: vec![], - valid_transfers_map: vec![], }; let keys = vote_tallies::Keys::from(&event); @@ -191,7 +190,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), transfers: vec![], - valid_transfers_map: vec![], }; let keys = vote_tallies::Keys::from(&event); let tally = Tally { @@ -240,7 +238,6 @@ mod tests { let event = EthereumEvent::TransfersToNamada { nonce: 0.into(), transfers: vec![], - valid_transfers_map: vec![], }; let keys = vote_tallies::Keys::from(&event); let tally = Tally { diff --git a/ethereum_bridge/src/protocol/transactions/votes/update.rs b/ethereum_bridge/src/protocol/transactions/votes/update.rs index 9b20be92ea..c1173bdf12 100644 --- a/ethereum_bridge/src/protocol/transactions/votes/update.rs +++ b/ethereum_bridge/src/protocol/transactions/votes/update.rs @@ -236,7 +236,6 @@ mod tests { EthereumEvent::TransfersToNamada { nonce: 0.into(), transfers: vec![], - valid_transfers_map: vec![], } } diff --git a/ethereum_bridge/src/storage/eth_bridge_queries.rs b/ethereum_bridge/src/storage/eth_bridge_queries.rs index 5d068d2e38..5e2f7b6399 100644 --- a/ethereum_bridge/src/storage/eth_bridge_queries.rs +++ b/ethereum_bridge/src/storage/eth_bridge_queries.rs @@ -354,12 +354,16 @@ where } } - /// Query the consensus [`ValidatorSetArgs`] at the given [`Epoch`]. + /// Query a chosen [`ValidatorSetArgs`] at the given [`Epoch`]. /// Also returns a map of each validator's voting power. - pub fn get_validator_set_args( + fn get_validator_set_args( self, epoch: Option, - ) -> (ValidatorSetArgs, VotingPowersMap) { + mut select_validator: F, + ) -> (ValidatorSetArgs, VotingPowersMap) + where + F: FnMut(&EthAddrBook) -> EthAddress, + { let epoch = epoch .unwrap_or_else(|| self.wl_storage.storage.get_current_epoch().0); @@ -377,12 +381,12 @@ where let (validators, voting_powers) = voting_powers_map .get_sorted() .into_iter() - .map(|(&EthAddrBook { hot_key_addr, .. }, &power)| { + .map(|(addr_book, &power)| { let voting_power: EthBridgeVotingPower = FractionalVotingPower::new(power.into(), total_power) .expect("Fractional voting power should be >1") .into(); - (hot_key_addr, voting_power) + (select_validator(addr_book), voting_power) }) .unzip(); @@ -396,6 +400,32 @@ where ) } + /// Query the Bridge [`ValidatorSetArgs`] at the given [`Epoch`]. + /// Also returns a map of each validator's voting power. + #[inline] + pub fn get_bridge_validator_set( + self, + epoch: Option, + ) -> (ValidatorSetArgs, VotingPowersMap) { + self.get_validator_set_args( + epoch, + |&EthAddrBook { hot_key_addr, .. }| hot_key_addr, + ) + } + + /// Query the Governance [`ValidatorSetArgs`] at the given [`Epoch`]. + /// Also returns a map of each validator's voting power. + #[inline] + pub fn get_governance_validator_set( + self, + epoch: Option, + ) -> (ValidatorSetArgs, VotingPowersMap) { + self.get_validator_set_args( + epoch, + |&EthAddrBook { cold_key_addr, .. }| cold_key_addr, + ) + } + /// Check if the token at the given [`EthAddress`] is whitelisted. pub fn is_token_whitelisted(self, &token: &EthAddress) -> bool { let key = whitelist::Key { diff --git a/ethereum_bridge/src/storage/proof.rs b/ethereum_bridge/src/storage/proof.rs index c25033bb9f..a028725883 100644 --- a/ethereum_bridge/src/storage/proof.rs +++ b/ethereum_bridge/src/storage/proof.rs @@ -102,14 +102,13 @@ pub fn sort_sigs( impl Encode<1> for EthereumProof<(Epoch, VotingPowersMap)> { fn tokenize(&self) -> [eth_abi::Token; 1] { let signatures = sort_sigs(&self.data.1, &self.signatures); - let (hot_key_addrs, cold_key_addrs, voting_powers) = + let (bridge_validators, governance_validators) = self.data.1.get_abi_encoded(); let (KeccakHash(bridge_hash), KeccakHash(gov_hash)) = valset_upd_toks_to_hashes( self.data.0, - hot_key_addrs, - cold_key_addrs, - voting_powers, + bridge_validators, + governance_validators, ); [eth_abi::Token::Tuple(vec![ eth_abi::Token::FixedBytes(bridge_hash.to_vec()), diff --git a/ethereum_bridge/src/storage/vote_tallies.rs b/ethereum_bridge/src/storage/vote_tallies.rs index 09c9278d43..ec03c498d6 100644 --- a/ethereum_bridge/src/storage/vote_tallies.rs +++ b/ethereum_bridge/src/storage/vote_tallies.rs @@ -265,9 +265,8 @@ mod test { EthereumEvent::TransfersToNamada { nonce: 0.into(), transfers: vec![], - valid_transfers_map: vec![], }, - "9E1736C43D19118E6CE4302118AF337109491ECC52757DFB949BAD6A7940B0C2" + "AB24A95F44CECA5D2AED4B6D056ADDDD8539F44C6CD6CA506534E830C82EA8A8" .to_owned(), ) } diff --git a/ethereum_bridge/src/test_utils.rs b/ethereum_bridge/src/test_utils.rs index 3b7b80febe..9c24e9edfa 100644 --- a/ethereum_bridge/src/test_utils.rs +++ b/ethereum_bridge/src/test_utils.rs @@ -117,10 +117,6 @@ pub fn bootstrap_ethereum_bridge( address: EthAddress([2; 20]), version: ContractVersion::default(), }, - governance: UpgradeableContract { - address: EthAddress([3; 20]), - version: ContractVersion::default(), - }, }, }; config.init_storage(wl_storage); diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 783a349883..47023ab9da 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -101,7 +101,6 @@ data-encoding.workspace = true derivation-path.workspace = true derivative.workspace = true ethbridge-bridge-contract.workspace = true -ethbridge-governance-contract.workspace = true ethers.workspace = true eyre.workspace = true futures.workspace = true diff --git a/shared/src/ledger/eth_bridge/bridge_pool.rs b/shared/src/ledger/eth_bridge/bridge_pool.rs index 3c428738c5..b9573cab97 100644 --- a/shared/src/ledger/eth_bridge/bridge_pool.rs +++ b/shared/src/ledger/eth_bridge/bridge_pool.rs @@ -16,9 +16,9 @@ use serde::{Deserialize, Serialize}; use super::{block_on_eth_sync, eth_sync_or_exit, BlockOnEthSync}; use crate::eth_bridge::ethers::abi::AbiDecode; -use crate::eth_bridge::structs::RelayProof; use crate::ledger::queries::{ - Client, GenBridgePoolProofReq, GenBridgePoolProofRsp, RPC, + Client, GenBridgePoolProofReq, GenBridgePoolProofRsp, TransferToErcArgs, + RPC, }; use crate::proto::Tx; use crate::sdk::args; @@ -288,7 +288,7 @@ struct BridgePoolProofResponse { hashes: Vec, relayer_address: Address, total_fees: HashMap, - abi_encoded_proof: Vec, + abi_encoded_args: Vec, } /// Construct a merkle proof of a batch of transfers in @@ -302,7 +302,7 @@ where C: Client + Sync, { let GenBridgePoolProofRsp { - abi_encoded_proof: bp_proof_bytes, + abi_encoded_args, appendices, } = construct_bridge_pool_proof::<_, IO>( client, @@ -332,7 +332,7 @@ where ) }) .unwrap_or_default(), - abi_encoded_proof: bp_proof_bytes, + abi_encoded_args, }; display_line!(IO, "{}", serde_json::to_string(&resp).unwrap()); control_flow::proceed(()) @@ -365,8 +365,7 @@ where } let GenBridgePoolProofRsp { - abi_encoded_proof: bp_proof, - .. + abi_encoded_args, .. } = construct_bridge_pool_proof::<_, IO>( nam_client, GenBridgePoolProofReq { @@ -398,8 +397,8 @@ where } }; - let bp_proof: RelayProof = - AbiDecode::decode(&bp_proof).try_halt(|error| { + let (validator_set, signatures, bp_proof): TransferToErcArgs = + AbiDecode::decode(&abi_encoded_args).try_halt(|error| { display_line!( IO, "Unable to decode the generated proof: {:?}", @@ -442,7 +441,8 @@ where } } - let mut relay_op = bridge.transfer_to_erc(bp_proof); + let mut relay_op = + bridge.transfer_to_erc(validator_set, signatures, bp_proof); if let Some(gas) = args.gas { relay_op.tx.set_gas(gas); } diff --git a/shared/src/ledger/eth_bridge/validator_set.rs b/shared/src/ledger/eth_bridge/validator_set.rs index 899d297d34..4ae08dd598 100644 --- a/shared/src/ledger/eth_bridge/validator_set.rs +++ b/shared/src/ledger/eth_bridge/validator_set.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use std::task::Poll; use data_encoding::HEXLOWER; -use ethbridge_governance_contract::Governance; +use ethbridge_bridge_contract::Bridge; use ethers::providers::Middleware; use futures::future::{self, FutureExt}; use namada_core::hints; @@ -17,7 +17,7 @@ use namada_core::types::storage::Epoch; use super::{block_on_eth_sync, eth_sync_or, eth_sync_or_exit, BlockOnEthSync}; use crate::eth_bridge::ethers::abi::{AbiDecode, AbiType, Tokenizable}; use crate::eth_bridge::ethers::core::types::TransactionReceipt; -use crate::eth_bridge::structs::{Signature, ValidatorSetArgs}; +use crate::eth_bridge::structs::Signature; use crate::ledger::queries::RPC; use crate::sdk::args; use crate::sdk::queries::Client; @@ -25,7 +25,9 @@ use crate::types::control_flow::time::{self, Duration, Instant}; use crate::types::control_flow::{ self, install_shutdown_signal, Halt, TryHalt, }; +use crate::types::ethereum_events::EthAddress; use crate::types::io::{DefaultIo, Io}; +use crate::types::vote_extensions::validator_set_update::ValidatorSetArgs; use crate::{display_line, edisplay_line}; /// Relayer related errors. @@ -142,7 +144,7 @@ impl GetStatus for RelayResult { fn is_successful(&self) -> bool { use RelayResult::*; match self { - GovernanceCallError(_) | NonceError { .. } | NoReceipt => false, + BridgeCallError(_) | NonceError { .. } | NoReceipt => false, Receipt { receipt } => receipt.is_successful(), } } @@ -154,7 +156,7 @@ enum CheckNonce {} /// Do not check the nonce of a relay. enum DoNotCheckNonce {} -/// Determine if the nonce in the Governance smart contract prompts +/// Determine if the nonce in the Bridge smart contract prompts /// a relay operation or not. trait ShouldRelay { /// The result of a relay operation. @@ -164,7 +166,7 @@ trait ShouldRelay { type Future<'gov>: Future> + 'gov; /// Returns [`Ok`] if the relay should happen. - fn should_relay(_: Epoch, _: &Governance) -> Self::Future<'_> + fn should_relay(_: Epoch, _: &Bridge) -> Self::Future<'_> where E: Middleware, E::Error: std::fmt::Display; @@ -178,7 +180,7 @@ impl ShouldRelay for DoNotCheckNonce { type RelayResult = Option; #[inline] - fn should_relay(_: Epoch, _: &Governance) -> Self::Future<'_> + fn should_relay(_: Epoch, _: &Bridge) -> Self::Future<'_> where E: Middleware, E::Error: std::fmt::Display, @@ -197,26 +199,23 @@ impl ShouldRelay for CheckNonce { Pin> + 'gov>>; type RelayResult = RelayResult; - fn should_relay( - epoch: Epoch, - governance: &Governance, - ) -> Self::Future<'_> + fn should_relay(epoch: Epoch, bridge: &Bridge) -> Self::Future<'_> where E: Middleware, E::Error: std::fmt::Display, { Box::pin(async move { - let governance_epoch_prep_call = governance.validator_set_nonce(); - let governance_epoch_fut = - governance_epoch_prep_call.call().map(|result| { + let bridge_epoch_prep_call = bridge.validator_set_nonce(); + let bridge_epoch_fut = + bridge_epoch_prep_call.call().map(|result| { result .map_err(|err| { - RelayResult::GovernanceCallError(err.to_string()) + RelayResult::BridgeCallError(err.to_string()) }) .map(|e| Epoch(e.as_u64())) }); - let gov_current_epoch = governance_epoch_fut.await?; + let gov_current_epoch = bridge_epoch_fut.await?; if epoch == gov_current_epoch + 1u64 { Ok(()) } else { @@ -236,15 +235,15 @@ impl ShouldRelay for CheckNonce { /// Relay result for [`CheckNonce`]. enum RelayResult { - /// The call to Governance failed. - GovernanceCallError(String), + /// The call to Bridge failed. + BridgeCallError(String), /// Some nonce related error occurred. /// /// The following comparison must hold: `contract + 1 = argument`. NonceError { /// The value of the [`Epoch`] argument passed via CLI. argument: Epoch, - /// The value of the [`Epoch`] in the Governance contract. + /// The value of the [`Epoch`] in the bridge contract. contract: Epoch, }, /// No receipt was returned from the relay operation. @@ -291,11 +290,12 @@ pub async fn query_validator_set_update_proof( display_line!(IO, "0x{}", HEXLOWER.encode(encoded_proof.as_ref())); } -/// Query an ABI encoding of the validator set at a given epoch. -pub async fn query_validator_set_args( +/// Query an ABI encoding of the Bridge validator set at a given epoch. +pub async fn query_bridge_validator_set( client: &C, - args: args::ConsensusValidatorSet, -) where + args: args::BridgeValidatorSet, +) -> Halt<()> +where C: Client + Sync, { let epoch = if let Some(epoch) = args.epoch { @@ -304,17 +304,78 @@ pub async fn query_validator_set_args( RPC.shell().epoch(client).await.unwrap() }; - let encoded_validator_set_args = RPC + let args = RPC .shell() .eth_bridge() - .read_consensus_valset(client, &epoch) + .read_bridge_valset(client, &epoch) .await - .unwrap(); + .try_halt(|err| { + tracing::error!(%err, "Failed to fetch Bridge validator set"); + })?; + + display_validator_set::(args); + control_flow::proceed(()) +} + +/// Query an ABI encoding of the Governance validator set at a given epoch. +pub async fn query_governnace_validator_set( + client: &C, + args: args::GovernanceValidatorSet, +) -> Halt<()> +where + C: Client + Sync, +{ + let epoch = if let Some(epoch) = args.epoch { + epoch + } else { + RPC.shell().epoch(client).await.unwrap() + }; + + let args = RPC + .shell() + .eth_bridge() + .read_governance_valset(client, &epoch) + .await + .try_halt(|err| { + tracing::error!(%err, "Failed to fetch Governance validator set"); + })?; + + display_validator_set::(args); + control_flow::proceed(()) +} + +/// Display the given [`ValidatorSetArgs`]. +fn display_validator_set(args: ValidatorSetArgs) { + use serde::Serialize; + + #[derive(Serialize)] + struct Validator { + addr: EthAddress, + voting_power: u128, + } + + #[derive(Serialize)] + struct ValidatorSet { + set: Vec, + } + + let ValidatorSetArgs { + validators, + voting_powers, + .. + } = args; + let validator_set = ValidatorSet { + set: validators + .into_iter() + .zip(voting_powers.into_iter().map(u128::from)) + .map(|(addr, voting_power)| Validator { addr, voting_power }) + .collect(), + }; display_line!( IO, - "0x{}", - HEXLOWER.encode(encoded_validator_set_args.as_ref()) + "{}", + serde_json::to_string_pretty(&validator_set).unwrap() ); } @@ -358,10 +419,10 @@ where eth_client, nam_client, |relay_result| match relay_result { - RelayResult::GovernanceCallError(reason) => { + RelayResult::BridgeCallError(reason) => { edisplay_line!( IO, - "Calling Governance failed due to: {reason}" + "Calling Bridge failed due to: {reason}" ); } RelayResult::NonceError { argument, contract } => { @@ -462,27 +523,25 @@ where } // we could be racing against governance updates, - // so it is best to always fetch the latest governance + // so it is best to always fetch the latest Bridge // contract address - let governance = - get_governance_contract(nam_client, Arc::clone(ð_client)) - .await - .try_halt(|err| { - // only care about displaying errors, - // exit on all circumstances - _ = err.handle(); - })?; - let governance_epoch_prep_call = governance.validator_set_nonce(); - let governance_epoch_fut = - governance_epoch_prep_call.call().map(|result| { - result - .map_err(|err| { - tracing::error!( - "Failed to fetch latest validator set nonce: {err}" - ); - }) - .map(|e| e.as_u64() as i128) - }); + let bridge = get_bridge_contract(nam_client, Arc::clone(ð_client)) + .await + .try_halt(|err| { + // only care about displaying errors, + // exit on all circumstances + _ = err.handle(); + })?; + let bridge_epoch_prep_call = bridge.validator_set_nonce(); + let bridge_epoch_fut = bridge_epoch_prep_call.call().map(|result| { + result + .map_err(|err| { + tracing::error!( + "Failed to fetch latest validator set nonce: {err}" + ); + }) + .map(|e| e.as_u64() as i128) + }); let shell = RPC.shell(); let nam_current_epoch_fut = shell.epoch(nam_client).map(|result| { @@ -496,7 +555,7 @@ where }); let (nam_current_epoch, gov_current_epoch) = - futures::try_join!(nam_current_epoch_fut, governance_epoch_fut) + futures::try_join!(nam_current_epoch_fut, bridge_epoch_fut) .try_halt(|()| ())?; tracing::debug!( @@ -507,11 +566,11 @@ where 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 + // in the bridge contract, for the latter to be considered // up to date -1 => { tracing::debug!( - "Nothing to do, since the validator set in the Governance \ + "Nothing to do, since the validator set in the Bridge \ contract is up to date", ); last_call_succeeded = false; @@ -525,7 +584,7 @@ where // 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!"); + tracing::error!("The Bridge contract is ahead of Namada!"); last_call_succeeded = false; continue; } @@ -562,21 +621,21 @@ where } } -async fn get_governance_contract( +async fn get_bridge_contract( nam_client: &C, eth_client: Arc, -) -> Result, Error> +) -> Result, Error> where C: Client + Sync, E: Middleware, { - let governance_contract = RPC + let bridge_contract = RPC .shell() .eth_bridge() - .read_governance_contract(nam_client) + .read_bridge_contract(nam_client) .await .map_err(|err| Error::critical(err.to_string()))?; - Ok(Governance::new(governance_contract.address, eth_client)) + Ok(Bridge::new(bridge_contract.address, eth_client)) } async fn relay_validator_set_update_once( @@ -614,17 +673,17 @@ where 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); + let validator_set_args_fut = + shell.read_bridge_valset(nam_client, &bridge_current_epoch); let shell = RPC.shell().eth_bridge(); - let governance_address_fut = shell.read_governance_contract(nam_client); + let bridge_address_fut = shell.read_bridge_contract(nam_client); - let (encoded_proof, encoded_validator_set_args, governance_contract) = + let (encoded_proof, validator_set_args, bridge_contract) = futures::try_join!( encoded_proof_fut, - encoded_validator_set_args_fut, - governance_address_fut + validator_set_args_fut, + bridge_address_fut ) .map_err(|err| R::try_recover(err.to_string()))?; @@ -633,22 +692,19 @@ where [u8; 32], Vec, ) = abi_decode_struct(encoded_proof); - let consensus_set: ValidatorSetArgs = - abi_decode_struct(encoded_validator_set_args); - let governance = Governance::new(governance_contract.address, eth_client); + let bridge = Bridge::new(bridge_contract.address, eth_client); - if let Err(result) = R::should_relay(epoch_to_relay, &governance).await { + if let Err(result) = R::should_relay(epoch_to_relay, &bridge).await { action(result); return Err(Error::NoContext); } - let mut relay_op = governance.update_validators_set( - consensus_set, + let mut relay_op = bridge.update_validator_set( + validator_set_args.into(), bridge_hash, gov_hash, signatures, - epoch_to_relay.0.into(), ); if let Some(gas) = args.gas { relay_op.tx.set_gas(gas); @@ -709,7 +765,7 @@ mod tests { }) .is_successful() ); - assert!(!RelayResult::GovernanceCallError("".into()).is_successful()); + assert!(!RelayResult::BridgeCallError("".into()).is_successful()); assert!( !RelayResult::NonceError { contract: 0.into(), diff --git a/shared/src/ledger/native_vp/ethereum_bridge/bridge_pool_vp.rs b/shared/src/ledger/native_vp/ethereum_bridge/bridge_pool_vp.rs index 9853a1daca..5efea15ac5 100644 --- a/shared/src/ledger/native_vp/ethereum_bridge/bridge_pool_vp.rs +++ b/shared/src/ledger/native_vp/ethereum_bridge/bridge_pool_vp.rs @@ -913,10 +913,6 @@ mod test_bridge_pool_vp { address: EthAddress([42; 20]), version: Default::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: Default::default(), - }, }, }; let mut wl_storage = WlStorage { diff --git a/shared/src/ledger/native_vp/ethereum_bridge/vp.rs b/shared/src/ledger/native_vp/ethereum_bridge/vp.rs index 650c065ab7..4d006229a1 100644 --- a/shared/src/ledger/native_vp/ethereum_bridge/vp.rs +++ b/shared/src/ledger/native_vp/ethereum_bridge/vp.rs @@ -236,10 +236,6 @@ mod tests { address: EthAddress([42; 20]), version: Default::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: Default::default(), - }, }, }; config.init_storage(&mut wl_storage); diff --git a/shared/src/ledger/protocol/mod.rs b/shared/src/ledger/protocol/mod.rs index b3eb247530..ceb41a36af 100644 --- a/shared/src/ledger/protocol/mod.rs +++ b/shared/src/ledger/protocol/mod.rs @@ -1079,7 +1079,6 @@ mod tests { asset: DAI_ERC20_ETH_ADDRESS, receiver: address::testing::established_address_4(), }], - valid_transfers_map: vec![true], }; let vext = EthereumEventsVext { block_height: BlockHeight(100), diff --git a/shared/src/ledger/queries/mod.rs b/shared/src/ledger/queries/mod.rs index 0d0764490b..dd42680a2e 100644 --- a/shared/src/ledger/queries/mod.rs +++ b/shared/src/ledger/queries/mod.rs @@ -12,6 +12,7 @@ use vp::{Vp, VP}; pub use self::shell::eth_bridge::{ Erc20FlowControl, GenBridgePoolProofReq, GenBridgePoolProofRsp, + TransferToErcArgs, }; use super::storage::traits::StorageHasher; use super::storage::{DBIter, DB}; diff --git a/shared/src/ledger/queries/shell/eth_bridge.rs b/shared/src/ledger/queries/shell/eth_bridge.rs index 237a9bf795..0bbc0aa679 100644 --- a/shared/src/ledger/queries/shell/eth_bridge.rs +++ b/shared/src/ledger/queries/shell/eth_bridge.rs @@ -16,7 +16,7 @@ use namada_core::types::eth_bridge_pool::PendingTransferAppendix; use namada_core::types::ethereum_events::{ EthAddress, EthereumEvent, TransferToEthereum, }; -use namada_core::types::ethereum_structs::RelayProof; +use namada_core::types::ethereum_structs; use namada_core::types::storage::{BlockHeight, DbKeySeg, Key}; use namada_core::types::token::Amount; use namada_core::types::vote_extensions::validator_set_update::{ @@ -31,8 +31,7 @@ use namada_ethereum_bridge::storage::eth_bridge_queries::EthBridgeQueries; use namada_ethereum_bridge::storage::proof::{sort_sigs, EthereumProof}; use namada_ethereum_bridge::storage::vote_tallies::{eth_msgs_prefix, Keys}; use namada_ethereum_bridge::storage::{ - bridge_contract_key, governance_contract_key, native_erc20_key, - vote_tallies, + bridge_contract_key, native_erc20_key, vote_tallies, }; use namada_proof_of_stake::pos_queries::PosQueries; @@ -69,11 +68,18 @@ pub struct GenBridgePoolProofReq<'transfers, 'relayer> { pub with_appendix: bool, } +/// Arguments to pass to `transfer_to_erc`. +pub type TransferToErcArgs = ( + ethereum_structs::ValidatorSetArgs, + Vec, + ethereum_structs::RelayProof, +); + /// Response data returned by `generate_bridge_pool_proof`. #[derive(Debug, Clone, Eq, PartialEq, BorshSerialize, BorshDeserialize)] pub struct GenBridgePoolProofRsp { - /// Ethereum ABI encoded [`RelayProof`]. - pub abi_encoded_proof: Vec, + /// Ethereum ABI encoded arguments to pass to `transfer_to_erc`. + pub abi_encoded_args: Vec, /// Appendix data of all requested pending transfers. pub appendices: Option>>, } @@ -81,9 +87,9 @@ pub struct GenBridgePoolProofRsp { impl GenBridgePoolProofRsp { /// Retrieve all [`PendingTransfer`] instances returned from the RPC server. pub fn pending_transfers(self) -> impl Iterator { - RelayProof::decode(&self.abi_encoded_proof) + TransferToErcArgs::decode(&self.abi_encoded_args) .into_iter() - .flat_map(|proof| proof.transfers) + .flat_map(|(_, _, proof)| proof.transfers) .zip(self.appendices.into_iter().flatten()) .map(|(event, appendix)| { let event: TransferToEthereum = event.into(); @@ -121,16 +127,17 @@ router! {ETH_BRIDGE, -> EncodeCell> = read_valset_upd_proof, - // Request the set of consensus validator at the given epoch. + // Request the set of bridge validators at the given epoch. // // The request may fail if no validator set exists at that epoch. - ( "validator_set" / "consensus" / [epoch: Epoch] ) - -> EncodeCell = read_consensus_valset, + ( "validator_set" / "bridge" / [epoch: Epoch] ) + -> ValidatorSetArgs = read_bridge_valset, - // Read the address and version of the Ethereum bridge's Governance - // smart contract. - ( "contracts" / "governance" ) - -> UpgradeableContract = read_governance_contract, + // Request the set of governance validators at the given epoch. + // + // The request may fail if no validator set exists at that epoch. + ( "validator_set" / "governance" / [epoch: Epoch] ) + -> ValidatorSetArgs = read_governance_valset, // Read the address and version of the Ethereum bridge's Bridge // smart contract. @@ -202,19 +209,6 @@ where Ok(contract) } -/// Read the address and version of the Ethereum bridge's Governance -/// smart contract. -#[inline] -fn read_governance_contract( - ctx: RequestCtx<'_, D, H>, -) -> storage_api::Result -where - D: 'static + DB + for<'iter> DBIter<'iter> + Sync, - H: 'static + StorageHasher + Sync, -{ - read_contract(&governance_contract_key(), ctx) -} - /// Read the address and version of the Ethereum bridge's Bridge /// smart contract. #[inline] @@ -410,13 +404,8 @@ where let (validator_args, voting_powers) = ctx .wl_storage .ethbridge_queries() - .get_validator_set_args(None); - let relay_proof = RelayProof { - validator_set_args: validator_args.into(), - signatures: sort_sigs( - &voting_powers, - &signed_root.signatures, - ), + .get_bridge_validator_set(None); + let relay_proof = ethereum_structs::RelayProof { transfers, pool_root: signed_root.data.0.0, proof: proof.proof.into_iter().map(|hash| hash.0).collect(), @@ -424,10 +413,16 @@ where batch_nonce: signed_root.data.1.into(), relayer_address: relayer.to_string(), }; + let validator_set: ethereum_structs::ValidatorSetArgs = + validator_args.into(); + let signatures = + sort_sigs(&voting_powers, &signed_root.signatures); let rsp = GenBridgePoolProofRsp { - abi_encoded_proof: ethers::abi::AbiEncode::encode( + abi_encoded_args: ethers::abi::AbiEncode::encode(( + validator_set, + signatures, relay_proof, - ), + )), appendices: with_appendix.then_some(appendices), }; let data = rsp.try_to_vec().into_storage_result()?; @@ -569,14 +564,44 @@ where Ok(proof.map(|set| (epoch, set)).encode()) } -/// Read the consensus set of validators at the given [`Epoch`]. +/// Request the set of bridge validators at the given epoch. +/// +/// This method may fail if no set of validators exists yet, +/// at that [`Epoch`]. +fn read_bridge_valset( + ctx: RequestCtx<'_, D, H>, + epoch: Epoch, +) -> storage_api::Result +where + D: 'static + DB + for<'iter> DBIter<'iter> + Sync, + H: 'static + StorageHasher + Sync, +{ + let current_epoch = ctx.wl_storage.storage.last_epoch; + if epoch > current_epoch.next() { + Err(storage_api::Error::Custom(CustomError( + format!( + "Requesting Bridge validator set at {epoch:?}, but the last \ + installed epoch is still {current_epoch:?}" + ) + .into(), + ))) + } else { + Ok(ctx + .wl_storage + .ethbridge_queries() + .get_bridge_validator_set(Some(epoch)) + .0) + } +} + +/// Request the set of governance validators at the given epoch. /// /// This method may fail if no set of validators exists yet, /// at that [`Epoch`]. -fn read_consensus_valset( +fn read_governance_valset( ctx: RequestCtx<'_, D, H>, epoch: Epoch, -) -> storage_api::Result> +) -> storage_api::Result where D: 'static + DB + for<'iter> DBIter<'iter> + Sync, H: 'static + StorageHasher + Sync, @@ -585,7 +610,7 @@ where if epoch > current_epoch.next() { Err(storage_api::Error::Custom(CustomError( format!( - "Requesting consensus validator set at {epoch:?}, but the \ + "Requesting Governance validator set at {epoch:?}, but the \ last installed epoch is still {current_epoch:?}" ) .into(), @@ -594,9 +619,8 @@ where Ok(ctx .wl_storage .ethbridge_queries() - .get_validator_set_args(Some(epoch)) - .0 - .encode()) + .get_governance_validator_set(Some(epoch)) + .0) } } @@ -638,7 +662,7 @@ where let (_, voting_powers) = ctx .wl_storage .ethbridge_queries() - .get_validator_set_args(Some(epoch)); + .get_bridge_validator_set(Some(epoch)); Ok(voting_powers) } @@ -678,7 +702,7 @@ mod test_ethbridge_router { }; use crate::types::ethereum_events::EthAddress; - /// Test that reading the consensus validator set works. + /// Test that reading the bridge validator set works. #[tokio::test] async fn test_read_consensus_valset() { let mut client = TestClient::new(RPC); @@ -699,7 +723,7 @@ mod test_ethbridge_router { let validator_set = RPC .shell() .eth_bridge() - .read_consensus_valset(&client, &epoch) + .read_bridge_valset(&client, &epoch) .await .unwrap(); let expected = { @@ -733,7 +757,6 @@ mod test_ethbridge_router { validators, voting_powers, } - .encode() }; assert_eq!(validator_set, expected); @@ -760,7 +783,7 @@ mod test_ethbridge_router { let result = RPC .shell() .eth_bridge() - .read_consensus_valset(&client, &Epoch(999_999)) + .read_bridge_valset(&client, &Epoch(999_999)) .await; let Err(err) = result else { panic!("Test failed"); @@ -1071,10 +1094,8 @@ mod test_ethbridge_router { let (validator_args, voting_powers) = client .wl_storage .ethbridge_queries() - .get_validator_set_args(None); - let data = RelayProof { - validator_set_args: validator_args.into(), - signatures: sort_sigs(&voting_powers, &signed_root.signatures), + .get_bridge_validator_set(None); + let relay_proof = ethereum_structs::RelayProof { transfers: vec![(&transfer).into()], pool_root: signed_root.data.0.0, proof: proof.proof.into_iter().map(|hash| hash.0).collect(), @@ -1082,8 +1103,15 @@ mod test_ethbridge_router { batch_nonce: Default::default(), relayer_address: bertha_address().to_string(), }; - let proof = ethers::abi::AbiEncode::encode(data); - assert_eq!(proof, resp.data.abi_encoded_proof); + let signatures = sort_sigs(&voting_powers, &signed_root.signatures); + let validator_set: ethereum_structs::ValidatorSetArgs = + validator_args.into(); + let encoded = ethers::abi::AbiEncode::encode(( + validator_set, + signatures, + relay_proof, + )); + assert_eq!(encoded, resp.data.abi_encoded_args); } /// Test if the merkle tree including a transfer has not had its @@ -1292,7 +1320,6 @@ mod test_ethbridge_router { let eth_event = EthereumEvent::TransfersToEthereum { nonce: Default::default(), transfers: vec![event_transfer.clone()], - valid_transfers_map: vec![true], relayer: bertha_address(), }; let eth_msg_key = vote_tallies::Keys::from(ð_event); diff --git a/shared/src/sdk/args.rs b/shared/src/sdk/args.rs index d3413c588b..b765dece5a 100644 --- a/shared/src/sdk/args.rs +++ b/shared/src/sdk/args.rs @@ -822,9 +822,18 @@ pub struct RelayBridgePoolProof { pub safe_mode: bool, } -/// Consensus validator set arguments. +/// Bridge validator set arguments. #[derive(Debug, Clone)] -pub struct ConsensusValidatorSet { +pub struct BridgeValidatorSet { + /// The query parameters. + pub query: Query, + /// The epoch to query. + pub epoch: Option, +} + +/// Governance validator set arguments. +#[derive(Debug, Clone)] +pub struct GovernanceValidatorSet { /// The query parameters. pub query: Query, /// The epoch to query. diff --git a/tests/src/native_vp/eth_bridge_pool.rs b/tests/src/native_vp/eth_bridge_pool.rs index 22584e1464..364dcd074c 100644 --- a/tests/src/native_vp/eth_bridge_pool.rs +++ b/tests/src/native_vp/eth_bridge_pool.rs @@ -77,10 +77,6 @@ mod test_bridge_pool_vp { address: EthAddress([42; 20]), version: Default::default(), }, - governance: UpgradeableContract { - address: EthAddress([18; 20]), - version: Default::default(), - }, }, }; // initialize Ethereum bridge storage diff --git a/wasm/Cargo.lock b/wasm/Cargo.lock index 4edaef87c4..d547e7dc8b 100644 --- a/wasm/Cargo.lock +++ b/wasm/Cargo.lock @@ -1677,8 +1677,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethbridge-bridge-events", "ethbridge-structs", @@ -1688,30 +1688,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethabi", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - -[[package]] -name = "ethbridge-governance-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethbridge-governance-events", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - -[[package]] -name = "ethbridge-governance-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethbridge-structs", @@ -1721,8 +1699,8 @@ dependencies = [ [[package]] name = "ethbridge-structs" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethers", @@ -3344,7 +3322,6 @@ dependencies = [ "derivation-path", "derivative", "ethbridge-bridge-contract", - "ethbridge-governance-contract", "ethers", "eyre", "futures", diff --git a/wasm_for_tests/wasm_source/Cargo.lock b/wasm_for_tests/wasm_source/Cargo.lock index 2c4f12d24c..7269fdb27e 100644 --- a/wasm_for_tests/wasm_source/Cargo.lock +++ b/wasm_for_tests/wasm_source/Cargo.lock @@ -1677,8 +1677,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethbridge-bridge-events", "ethbridge-structs", @@ -1688,30 +1688,8 @@ dependencies = [ [[package]] name = "ethbridge-bridge-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethabi", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - -[[package]] -name = "ethbridge-governance-contract" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" -dependencies = [ - "ethbridge-governance-events", - "ethbridge-structs", - "ethers", - "ethers-contract", -] - -[[package]] -name = "ethbridge-governance-events" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethbridge-structs", @@ -1721,8 +1699,8 @@ dependencies = [ [[package]] name = "ethbridge-structs" -version = "0.23.0" -source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.23.0#1bb96e06cbc3889aa46a01e3768bf25f0c78168a" +version = "0.24.0" +source = "git+https://github.com/heliaxdev/ethbridge-rs?tag=v0.24.0#d66708bb8a734111988b9eaf08c7473bd7020c00" dependencies = [ "ethabi", "ethers", @@ -3344,7 +3322,6 @@ dependencies = [ "derivation-path", "derivative", "ethbridge-bridge-contract", - "ethbridge-governance-contract", "ethers", "eyre", "futures",