From a26d695acea147adaa01317607494f98967f89e8 Mon Sep 17 00:00:00 2001 From: haiyizxx Date: Mon, 9 Sep 2024 15:18:31 -0400 Subject: [PATCH] feat(minor-voting-verifier): stellar source address validation (#611) --- Cargo.lock | 17 +++- Cargo.toml | 1 + external-gateways/stellar/Cargo.toml | 4 +- packages/axelar-wasm-std/Cargo.toml | 2 + packages/axelar-wasm-std/src/address.rs | 111 +++++++++++++++++++++--- 5 files changed, 117 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b3a638f69..f27eeacb5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,6 +809,7 @@ name = "axelar-wasm-std" version = "1.0.0" dependencies = [ "alloy-primitives", + "assert_ok", "axelar-wasm-std-derive", "bs58 0.5.1", "cosmwasm-schema", @@ -830,6 +831,7 @@ dependencies = [ "serde", "serde_json", "sha3", + "stellar-xdr", "strum 0.25.0", "sui-types 1.0.0", "thiserror", @@ -7846,7 +7848,7 @@ dependencies = [ "serde", "serde_json", "sha3", - "stellar-strkey", + "stellar-strkey 0.0.10", "stellar-xdr", "thiserror", ] @@ -7862,6 +7864,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "stellar-strkey" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecda1f64c0a1427563b0b35aa771b66c6ce508f02b18effcae1d0ab1261d014" +dependencies = [ + "crate-git-revision", + "data-encoding", + "thiserror", +] + [[package]] name = "stellar-xdr" version = "21.2.0" @@ -7871,7 +7884,7 @@ dependencies = [ "crate-git-revision", "escape-bytes", "hex", - "stellar-strkey", + "stellar-strkey 0.0.8", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index b878fba67..13d37e340 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ service-registry = { version = "^1.0.0", path = "contracts/service-registry" } sha3 = { version = "0.10.8", default-features = false, features = [] } signature-verifier-api = { version = "^1.0.0", path = "packages/signature-verifier-api" } stellar = { version = "^1.0.0", path = "external-gateways/stellar" } +stellar-xdr = { version = "21.2.0" } strum = { version = "0.25", default-features = false, features = ["derive"] } sui-gateway = { version = "^1.0.0", path = "packages/sui-gateway" } sui-types = { version = "^1.0.0", path = "packages/sui-types" } diff --git a/external-gateways/stellar/Cargo.toml b/external-gateways/stellar/Cargo.toml index 7b4819ab5..9d438462b 100644 --- a/external-gateways/stellar/Cargo.toml +++ b/external-gateways/stellar/Cargo.toml @@ -14,8 +14,8 @@ router-api = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } sha3 = { workspace = true } -stellar-strkey = { version = "0.0.8" } -stellar-xdr = { version = "21.2.0" } +stellar-strkey = { version = "0.0.10" } +stellar-xdr = { workspace = true } thiserror = { workspace = true } [lints] diff --git a/packages/axelar-wasm-std/Cargo.toml b/packages/axelar-wasm-std/Cargo.toml index 699bdd425..e7f8105df 100644 --- a/packages/axelar-wasm-std/Cargo.toml +++ b/packages/axelar-wasm-std/Cargo.toml @@ -46,12 +46,14 @@ schemars = "0.8.10" serde = { version = "1.0.145", default-features = false, features = ["derive"] } serde_json = "1.0.89" sha3 = { workspace = true } +stellar-xdr = { workspace = true } strum = { workspace = true } sui-types = { workspace = true } thiserror = { workspace = true } valuable = { version = "0.1.0", features = ["derive"] } [dev-dependencies] +assert_ok = { workspace = true } cw-multi-test = "0.15.1" hex = { version = "0.4.3", default-features = false } rand = "0.8.5" diff --git a/packages/axelar-wasm-std/src/address.rs b/packages/axelar-wasm-std/src/address.rs index 69162ca30..ea1544c44 100644 --- a/packages/axelar-wasm-std/src/address.rs +++ b/packages/axelar-wasm-std/src/address.rs @@ -3,7 +3,8 @@ use std::str::FromStr; use alloy_primitives::Address; use cosmwasm_schema::cw_serde; use cosmwasm_std::{Addr, Api}; -use error_stack::{Result, ResultExt}; +use error_stack::{bail, Result, ResultExt}; +use stellar_xdr::curr::ScAddress; use sui_types::SuiAddress; #[derive(thiserror::Error)] @@ -17,6 +18,7 @@ pub enum Error { pub enum AddressFormat { Eip55, Sui, + Stellar, } pub fn validate_address(address: &str, format: &AddressFormat) -> Result<(), Error> { @@ -29,6 +31,13 @@ pub fn validate_address(address: &str, format: &AddressFormat) -> Result<(), Err SuiAddress::from_str(address) .change_context(Error::InvalidAddress(address.to_string()))?; } + AddressFormat::Stellar => { + if address != address.to_uppercase() { + bail!(Error::InvalidAddress(address.to_string())) + } + ScAddress::from_str(address) + .change_context(Error::InvalidAddress(address.to_string()))?; + } } Ok(()) @@ -41,37 +50,64 @@ pub fn validate_cosmwasm_address(api: &dyn Api, addr: &str) -> Result(); - assert!(address::validate_address(&mixed_case, &address::AddressFormat::Sui).is_err()); + assert_err_contains!( + address::validate_address(&mixed_case, &address::AddressFormat::Sui), + address::Error, + address::Error::InvalidAddress(..) + ); let invalid_length = format!("{}5f", addr); - assert!(address::validate_address(&invalid_length, &address::AddressFormat::Sui).is_err()); + assert_err_contains!( + address::validate_address(&invalid_length, &address::AddressFormat::Sui), + address::Error, + address::Error::InvalidAddress(..) + ); } #[test] fn validate_cosmwasm_address() { let api = MockApi::default(); let addr = "axelar1x46rqay4d3cssq8gxxvqz8xt6nwlz4td20k38v"; - assert!(address::validate_cosmwasm_address(&api, addr).is_ok()); + assert_ok!(address::validate_cosmwasm_address(&api, addr)); let upper_case = addr.to_uppercase(); - assert!(err_contains!( - address::validate_cosmwasm_address(&api, &upper_case).unwrap_err(), + assert_err_contains!( + address::validate_cosmwasm_address(&api, &upper_case), address::Error, address::Error::InvalidAddress(..) + ); + } + + #[test] + fn validate_stellar_address() { + // account id + let addr = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; + assert_ok!(address::validate_address( + addr, + &address::AddressFormat::Stellar )); + + let lower_case = addr.to_lowercase(); + assert_err_contains!( + address::validate_address(&lower_case, &address::AddressFormat::Stellar), + address::Error, + address::Error::InvalidAddress(..) + ); + + // contract + let addr = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; + assert_ok!(address::validate_address( + addr, + &address::AddressFormat::Stellar + )); + + let lower_case = addr.to_lowercase(); + assert_err_contains!( + address::validate_address(&lower_case, &address::AddressFormat::Stellar), + address::Error, + address::Error::InvalidAddress(..) + ); + + // invalid + let invalid = "MA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVAAAAAAAAAAAAAJLK"; + assert_err_contains!( + address::validate_address(invalid, &address::AddressFormat::Stellar), + address::Error, + address::Error::InvalidAddress(..) + ); } }