From 66155e3b7c88a8400dda6858f6d005fc23aa0699 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Wed, 16 Oct 2024 21:34:00 +0800 Subject: [PATCH 1/3] feat(minor-axelarnet-gateway): route messages from nexus to router --- contracts/axelarnet-gateway/src/contract.rs | 15 ++++++++++++--- .../axelarnet-gateway/src/contract/execute.rs | 17 +++++++++++++++++ contracts/axelarnet-gateway/src/msg.rs | 5 +++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/contracts/axelarnet-gateway/src/contract.rs b/contracts/axelarnet-gateway/src/contract.rs index c85fbdbdd..bc9662d99 100644 --- a/contracts/axelarnet-gateway/src/contract.rs +++ b/contracts/axelarnet-gateway/src/contract.rs @@ -3,8 +3,10 @@ use axelar_wasm_std::error::ContractError; use axelar_wasm_std::{address, FnExt, IntoContractError}; #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{to_json_binary, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response}; -use error_stack::ResultExt; +use cosmwasm_std::{ + to_json_binary, Addr, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, Storage, +}; +use error_stack::{Report, ResultExt}; use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg}; use crate::state::{self, Config}; @@ -70,7 +72,7 @@ pub fn execute( info: MessageInfo, msg: ExecuteMsg, ) -> Result, ContractError> { - match msg.ensure_permissions(deps.storage, &info.sender)? { + match msg.ensure_permissions(deps.storage, &info.sender, match_nexus)? { ExecuteMsg::CallContract { destination_chain, destination_address, @@ -91,6 +93,9 @@ pub fn execute( ExecuteMsg::Execute { cc_id, payload } => { execute::execute(deps, cc_id, payload).change_context(Error::Execute) } + ExecuteMsg::RouteMessagesFromNexus(msgs) => { + Ok(execute::route_messages_from_nexus(deps.storage, msgs)?) + } }? .then(Ok) } @@ -111,6 +116,10 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result Result> { + Ok(state::load_config(storage).nexus) +} + #[cfg(test)] mod tests { use assert_ok::assert_ok; diff --git a/contracts/axelarnet-gateway/src/contract/execute.rs b/contracts/axelarnet-gateway/src/contract/execute.rs index 8047eff37..e800cef44 100644 --- a/contracts/axelarnet-gateway/src/contract/execute.rs +++ b/contracts/axelarnet-gateway/src/contract/execute.rs @@ -55,6 +55,8 @@ pub enum Error { InvalidToken, #[error("invalid routing destination")] InvalidRoutingDestination, + #[error("failed converting the nexus message for the router")] + InvalidNexusMessageForRouter, } #[cw_serde] @@ -173,6 +175,21 @@ pub fn execute( .then(Ok) } +pub fn route_messages_from_nexus( + storage: &dyn Storage, + msgs: Vec, +) -> Result> { + let msgs: Vec<_> = msgs + .into_iter() + .map(router_api::Message::try_from) + .collect::, _>>() + .change_context(Error::InvalidNexusMessageForRouter)?; + + let router = Router::new(state::load_config(storage).router); + + Ok(Response::new().add_messages(router.route(msgs))) +} + fn ensure_same_payload_hash( payload_hash: &[u8; 32], ) -> impl FnOnce(&Message) -> core::result::Result<(), state::Error> + '_ { diff --git a/contracts/axelarnet-gateway/src/msg.rs b/contracts/axelarnet-gateway/src/msg.rs index 85d6f674f..8f40a74a4 100644 --- a/contracts/axelarnet-gateway/src/msg.rs +++ b/contracts/axelarnet-gateway/src/msg.rs @@ -1,3 +1,4 @@ +use axelar_core_std::nexus; use cosmwasm_schema::{cw_serde, QueryResponses}; use cosmwasm_std::HexBinary; use msgs_derive::EnsurePermissions; @@ -41,6 +42,10 @@ pub enum ExecuteMsg { destination_address: Address, payload: HexBinary, }, + + /// Forward the given nexus messages to the next step of the routing layer. + #[permission(Specific(nexus))] + RouteMessagesFromNexus(Vec), } #[cw_serde] From c79f4b0bf5b090eb79922c172bde250d5acd1828 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Thu, 17 Oct 2024 22:21:59 +0800 Subject: [PATCH 2/3] add test --- .../axelarnet-gateway/src/contract/execute.rs | 2 +- contracts/axelarnet-gateway/tests/execute.rs | 17 +++++++++++++++++ .../testdata/route_from_nexus_to_router.golden | 16 ++++++++++++++++ .../axelarnet-gateway/tests/utils/execute.rs | 12 ++++++++++++ .../axelarnet-gateway/tests/utils/messages.rs | 16 ++++++++++++++++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden diff --git a/contracts/axelarnet-gateway/src/contract/execute.rs b/contracts/axelarnet-gateway/src/contract/execute.rs index e800cef44..ce9969e78 100644 --- a/contracts/axelarnet-gateway/src/contract/execute.rs +++ b/contracts/axelarnet-gateway/src/contract/execute.rs @@ -55,7 +55,7 @@ pub enum Error { InvalidToken, #[error("invalid routing destination")] InvalidRoutingDestination, - #[error("failed converting the nexus message for the router")] + #[error("failed to convert the nexus message for the router")] InvalidNexusMessageForRouter, } diff --git a/contracts/axelarnet-gateway/tests/execute.rs b/contracts/axelarnet-gateway/tests/execute.rs index fe8cc957b..d7fec84a9 100644 --- a/contracts/axelarnet-gateway/tests/execute.rs +++ b/contracts/axelarnet-gateway/tests/execute.rs @@ -394,3 +394,20 @@ fn contract_call_with_token_to_amplifier_chains_fails() { ExecuteError::InvalidRoutingDestination, ); } + +#[test] +fn route_from_nexus_to_router() { + let mut deps = mock_dependencies(); + + utils::instantiate_contract(deps.as_mut()).unwrap(); + + let response = assert_ok!(utils::route_from_nexus( + deps.as_mut(), + vec![ + messages::dummy_from_nexus(&vec![1, 2, 3]), + messages::dummy_from_nexus(&vec![4, 5, 6]), + ] + )); + + goldie::assert_json!(response.messages) +} diff --git a/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden b/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden new file mode 100644 index 000000000..88e9bc6b5 --- /dev/null +++ b/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden @@ -0,0 +1,16 @@ +[ + { + "id": 0, + "msg": { + "wasm": { + "execute": { + "contract_addr": "router", + "msg": "eyJyb3V0ZV9tZXNzYWdlcyI6W3siY2NfaWQiOnsic291cmNlX2NoYWluIjoiRXRoZXJldW0iLCJtZXNzYWdlX2lkIjoic291cmNlLWNoYWluLTAifSwic291cmNlX2FkZHJlc3MiOiJzb3VyY2UtYWRkcmVzcyIsImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdGluYXRpb24tY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdGluYXRpb24tYWRkcmVzcyIsInBheWxvYWRfaGFzaCI6ImYxODg1ZWRhNTRiN2EwNTMzMThjZDQxZTIwOTMyMjBkYWIxNWQ2NTM4MWIxMTU3YTM2MzNhODNiZmQ1YzkyMzkifSx7ImNjX2lkIjp7InNvdXJjZV9jaGFpbiI6IkV0aGVyZXVtIiwibWVzc2FnZV9pZCI6InNvdXJjZS1jaGFpbi0wIn0sInNvdXJjZV9hZGRyZXNzIjoic291cmNlLWFkZHJlc3MiLCJkZXN0aW5hdGlvbl9jaGFpbiI6ImRlc3RpbmF0aW9uLWNoYWluIiwiZGVzdGluYXRpb25fYWRkcmVzcyI6ImRlc3RpbmF0aW9uLWFkZHJlc3MiLCJwYXlsb2FkX2hhc2giOiIyZTZhNWViY2NjODgxMGZlZTMzMjRjMGQ0NDUwMDExODg3ODdkMGQzYWM4YWJhMmNkODliNzc1MjdkMTk4YmIwIn1dfQ==", + "funds": [] + } + } + }, + "gas_limit": null, + "reply_on": "never" + } +] \ No newline at end of file diff --git a/contracts/axelarnet-gateway/tests/utils/execute.rs b/contracts/axelarnet-gateway/tests/utils/execute.rs index cb544c3c9..dbc9dd833 100644 --- a/contracts/axelarnet-gateway/tests/utils/execute.rs +++ b/contracts/axelarnet-gateway/tests/utils/execute.rs @@ -70,3 +70,15 @@ pub fn route_to_router( GatewayExecuteMsg::RouteMessages(msgs), ) } + +pub fn route_from_nexus( + deps: DepsMut, + msgs: Vec, +) -> Result, ContractError> { + contract::execute( + deps, + mock_env(), + mock_info("nexus", &[]), + GatewayExecuteMsg::RouteMessagesFromNexus(msgs), + ) +} diff --git a/contracts/axelarnet-gateway/tests/utils/messages.rs b/contracts/axelarnet-gateway/tests/utils/messages.rs index 386ff094f..7de5a4699 100644 --- a/contracts/axelarnet-gateway/tests/utils/messages.rs +++ b/contracts/axelarnet-gateway/tests/utils/messages.rs @@ -1,3 +1,5 @@ +use axelar_core_std::nexus; +use cw_storage_plus::Prefixer; use router_api::{CrossChainId, Message}; use sha3::Digest; @@ -22,3 +24,17 @@ pub fn dummy_to_router(payload: &impl AsRef<[u8]>) -> Message { payload_hash: sha3::Keccak256::digest(payload).into(), } } + +pub fn dummy_from_nexus(payload: &impl AsRef<[u8]>) -> nexus::execute::Message { + nexus::execute::Message { + source_chain: "Ethereum".parse().unwrap(), + source_address: "source-address".parse().unwrap(), + destination_chain: "destination-chain".parse().unwrap(), + destination_address: "destination-address".parse().unwrap(), + payload_hash: sha3::Keccak256::digest(payload).into(), + source_tx_id: "source-chain".as_bytes().to_vec().try_into().unwrap(), + source_tx_index: 0, + id: "source-chain-0".to_string(), + token: None, + } +} From 48c2ea3ea065b96fffee3452e00fc135bcc744f0 Mon Sep 17 00:00:00 2001 From: Haiyi Zhong Date: Thu, 17 Oct 2024 22:31:26 +0800 Subject: [PATCH 3/3] update test --- contracts/axelarnet-gateway/tests/execute.rs | 3 +- .../route_from_nexus_to_router.golden | 38 +++++++++++-------- .../axelarnet-gateway/tests/utils/messages.rs | 1 - 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/contracts/axelarnet-gateway/tests/execute.rs b/contracts/axelarnet-gateway/tests/execute.rs index d7fec84a9..60ade8cfe 100644 --- a/contracts/axelarnet-gateway/tests/execute.rs +++ b/contracts/axelarnet-gateway/tests/execute.rs @@ -409,5 +409,6 @@ fn route_from_nexus_to_router() { ] )); - goldie::assert_json!(response.messages) + let msg: RouterExecuteMsg = assert_ok!(inspect_response_msg(response)); + goldie::assert_json!(msg) } diff --git a/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden b/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden index 88e9bc6b5..61c5cd092 100644 --- a/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden +++ b/contracts/axelarnet-gateway/tests/testdata/route_from_nexus_to_router.golden @@ -1,16 +1,24 @@ -[ - { - "id": 0, - "msg": { - "wasm": { - "execute": { - "contract_addr": "router", - "msg": "eyJyb3V0ZV9tZXNzYWdlcyI6W3siY2NfaWQiOnsic291cmNlX2NoYWluIjoiRXRoZXJldW0iLCJtZXNzYWdlX2lkIjoic291cmNlLWNoYWluLTAifSwic291cmNlX2FkZHJlc3MiOiJzb3VyY2UtYWRkcmVzcyIsImRlc3RpbmF0aW9uX2NoYWluIjoiZGVzdGluYXRpb24tY2hhaW4iLCJkZXN0aW5hdGlvbl9hZGRyZXNzIjoiZGVzdGluYXRpb24tYWRkcmVzcyIsInBheWxvYWRfaGFzaCI6ImYxODg1ZWRhNTRiN2EwNTMzMThjZDQxZTIwOTMyMjBkYWIxNWQ2NTM4MWIxMTU3YTM2MzNhODNiZmQ1YzkyMzkifSx7ImNjX2lkIjp7InNvdXJjZV9jaGFpbiI6IkV0aGVyZXVtIiwibWVzc2FnZV9pZCI6InNvdXJjZS1jaGFpbi0wIn0sInNvdXJjZV9hZGRyZXNzIjoic291cmNlLWFkZHJlc3MiLCJkZXN0aW5hdGlvbl9jaGFpbiI6ImRlc3RpbmF0aW9uLWNoYWluIiwiZGVzdGluYXRpb25fYWRkcmVzcyI6ImRlc3RpbmF0aW9uLWFkZHJlc3MiLCJwYXlsb2FkX2hhc2giOiIyZTZhNWViY2NjODgxMGZlZTMzMjRjMGQ0NDUwMDExODg3ODdkMGQzYWM4YWJhMmNkODliNzc1MjdkMTk4YmIwIn1dfQ==", - "funds": [] - } - } +{ + "route_messages": [ + { + "cc_id": { + "source_chain": "Ethereum", + "message_id": "source-chain-0" + }, + "source_address": "source-address", + "destination_chain": "destination-chain", + "destination_address": "destination-address", + "payload_hash": "f1885eda54b7a053318cd41e2093220dab15d65381b1157a3633a83bfd5c9239" }, - "gas_limit": null, - "reply_on": "never" - } -] \ No newline at end of file + { + "cc_id": { + "source_chain": "Ethereum", + "message_id": "source-chain-0" + }, + "source_address": "source-address", + "destination_chain": "destination-chain", + "destination_address": "destination-address", + "payload_hash": "2e6a5ebccc8810fee3324c0d445001188787d0d3ac8aba2cd89b77527d198bb0" + } + ] +} \ No newline at end of file diff --git a/contracts/axelarnet-gateway/tests/utils/messages.rs b/contracts/axelarnet-gateway/tests/utils/messages.rs index 7de5a4699..613d28ba8 100644 --- a/contracts/axelarnet-gateway/tests/utils/messages.rs +++ b/contracts/axelarnet-gateway/tests/utils/messages.rs @@ -1,5 +1,4 @@ use axelar_core_std::nexus; -use cw_storage_plus::Prefixer; use router_api::{CrossChainId, Message}; use sha3::Digest;