diff --git a/CHANGELOG.md b/CHANGELOG.md index 31018a206d..21e8b20c71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to ### Added +- cosmwasm-std: Add `addr_make` and `with_prefix` for + `cosmwasm_std::testing::MockApi` ([#1905]). - cosmwasm-std: Add `abs` and `unsigned_abs` for `Int{64,128,256,512}` ([#1854]). - cosmwasm-std: Add `From` for `Int512`, @@ -25,6 +27,7 @@ and this project adheres to - cosmwasm-std: Add `SignedDecimal` and `SignedDecimal256` ([#1807]). - cosmwasm-vm: Allow float operations with NaN canonicalization ([#1864]). +[#1905]: https://github.com/CosmWasm/cosmwasm/pull/1905 [#1854]: https://github.com/CosmWasm/cosmwasm/pull/1854 [#1861]: https://github.com/CosmWasm/cosmwasm/pull/1861 [#1866]: https://github.com/CosmWasm/cosmwasm/pull/1866 diff --git a/Cargo.lock b/Cargo.lock index bb734ad74e..315dfca724 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -179,6 +179,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.3.2" @@ -488,6 +494,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "chrono", "cosmwasm-crypto", diff --git a/contracts/burner/Cargo.lock b/contracts/burner/Cargo.lock index 566e96cb44..02737f48b0 100644 --- a/contracts/burner/Cargo.lock +++ b/contracts/burner/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -235,6 +241,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/crypto-verify/Cargo.lock b/contracts/crypto-verify/Cargo.lock index a8008a6dff..304029844e 100644 --- a/contracts/crypto-verify/Cargo.lock +++ b/contracts/crypto-verify/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/cyberpunk/Cargo.lock b/contracts/cyberpunk/Cargo.lock index 21bffcd7f7..672322b137 100644 --- a/contracts/cyberpunk/Cargo.lock +++ b/contracts/cyberpunk/Cargo.lock @@ -91,6 +91,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -259,6 +265,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64 0.21.2", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/floaty/Cargo.lock b/contracts/floaty/Cargo.lock index fa69b7a4b4..4dbedc6f74 100644 --- a/contracts/floaty/Cargo.lock +++ b/contracts/floaty/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/hackatom/Cargo.lock b/contracts/hackatom/Cargo.lock index bf7fdc272d..ad372a0f9e 100644 --- a/contracts/hackatom/Cargo.lock +++ b/contracts/hackatom/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/ibc-reflect-send/Cargo.lock b/contracts/ibc-reflect-send/Cargo.lock index 60524cc905..68a66fdf78 100644 --- a/contracts/ibc-reflect-send/Cargo.lock +++ b/contracts/ibc-reflect-send/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/ibc-reflect/Cargo.lock b/contracts/ibc-reflect/Cargo.lock index 8aa6139a1b..342121c6eb 100644 --- a/contracts/ibc-reflect/Cargo.lock +++ b/contracts/ibc-reflect/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/queue/Cargo.lock b/contracts/queue/Cargo.lock index e2eaef6aa1..165eb6a32e 100644 --- a/contracts/queue/Cargo.lock +++ b/contracts/queue/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/reflect/Cargo.lock b/contracts/reflect/Cargo.lock index 52c5a727e8..25303ef1b9 100644 --- a/contracts/reflect/Cargo.lock +++ b/contracts/reflect/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/staking/Cargo.lock b/contracts/staking/Cargo.lock index 1a1373ef1e..e7e58ec944 100644 --- a/contracts/staking/Cargo.lock +++ b/contracts/staking/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/contracts/virus/Cargo.lock b/contracts/virus/Cargo.lock index f214963f0a..efc2cf15d1 100644 --- a/contracts/virus/Cargo.lock +++ b/contracts/virus/Cargo.lock @@ -73,6 +73,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dea908e7347a8c64e378c17e30ef880ad73e3b4498346b055c2c00ea342f3179" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.2.1" @@ -224,6 +230,7 @@ name = "cosmwasm-std" version = "1.4.0" dependencies = [ "base64", + "bech32", "bnum", "cosmwasm-crypto", "cosmwasm-derive", diff --git a/packages/std/Cargo.toml b/packages/std/Cargo.toml index 323b73b70c..6ab8a5ab44 100644 --- a/packages/std/Cargo.toml +++ b/packages/std/Cargo.toml @@ -64,6 +64,7 @@ bnum = "0.8.0" static_assertions = "1.1.0" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] +bech32 = "0.9.1" cosmwasm-crypto = { path = "../crypto", version = "1.4.0" } [dev-dependencies] diff --git a/packages/std/src/testing/mock.rs b/packages/std/src/testing/mock.rs index d2ca6d65f6..1c337e1ac1 100644 --- a/packages/std/src/testing/mock.rs +++ b/packages/std/src/testing/mock.rs @@ -1,10 +1,12 @@ use alloc::collections::BTreeMap; +use bech32::{encode, ToBase32, Variant}; use core::marker::PhantomData; #[cfg(feature = "cosmwasm_1_3")] use core::ops::Bound; use serde::de::DeserializeOwned; #[cfg(feature = "stargate")] use serde::Serialize; +use sha2::{Digest, Sha256}; #[cfg(feature = "cosmwasm_1_3")] use std::collections::BTreeSet; use std::collections::HashMap; @@ -106,6 +108,9 @@ const CANONICAL_LENGTH: usize = 90; // n = 45 const SHUFFLES_ENCODE: usize = 10; const SHUFFLES_DECODE: usize = 2; +/// Default prefix used when creating Bech32 encoded address. +const BECH32_PREFIX: &str = "cosmwasm"; + // MockApi zero pads all human addresses to make them fit the canonical_length // it trims off zeros for the reverse operation. // not really smart, but allows us to see a difference (and consistent length for canonical addresses) @@ -114,12 +119,15 @@ pub struct MockApi { /// Length of canonical addresses created with this API. Contracts should not make any assumptions /// what this value is. canonical_length: usize, + /// Prefix used for creating addresses in Bech32 encoding. + bech32_prefix: &'static str, } impl Default for MockApi { fn default() -> Self { MockApi { canonical_length: CANONICAL_LENGTH, + bech32_prefix: BECH32_PREFIX, } } } @@ -244,6 +252,55 @@ impl Api for MockApi { } } +impl MockApi { + /// Returns [MockApi] with Bech32 prefix set to provided value. + /// + /// Bech32 prefix must not be empty. + /// + /// # Example + /// + /// ``` + /// # use cosmwasm_std::Addr; + /// # use cosmwasm_std::testing::MockApi; + /// # + /// let mock_api = MockApi::default().with_prefix("juno"); + /// let addr = mock_api.addr_make("creator"); + /// + /// assert_eq!(addr.to_string(), "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp"); + /// ``` + pub fn with_prefix(mut self, prefix: &'static str) -> Self { + self.bech32_prefix = prefix; + self + } + + /// Returns an address built from provided input string. + /// + /// # Example + /// + /// ``` + /// # use cosmwasm_std::Addr; + /// # use cosmwasm_std::testing::MockApi; + /// # + /// let mock_api = MockApi::default(); + /// let addr = mock_api.addr_make("creator"); + /// + /// assert_eq!(addr.to_string(), "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp"); + /// ``` + /// + /// # Panics + /// + /// This function panics when generating a valid address is not possible, + /// especially when Bech32 prefix set in function [with_prefix](Self::with_prefix) is empty. + /// + pub fn addr_make(&self, input: &str) -> Addr { + let digest = Sha256::digest(input).to_vec(); + match encode(self.bech32_prefix, digest.to_base32(), Variant::Bech32) { + Ok(address) => Addr::unchecked(address), + Err(reason) => panic!("Generating address failed with reason: {reason}"), + } + } +} + /// Returns a default enviroment with height, time, chain_id, and contract address /// You can submit as is to most contracts, or modify height/time if you want to /// test for expiration. @@ -2264,4 +2321,31 @@ mod tests { assert_eq!(digit_sum(&[255, 1]), 256); } + + #[test] + fn making_an_address_works() { + let mock_api = MockApi::default(); + + assert_eq!( + mock_api.addr_make("creator").to_string(), + "cosmwasm1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqs8s7vcp", + ); + + assert_eq!( + mock_api.addr_make("").to_string(), + "cosmwasm1uwcvgs5clswpfxhm7nyfjmaeysn6us0yvjdexn9yjkv3k7zjhp2sly4xh9", + ); + + let mock_api = MockApi::default().with_prefix("juno"); + assert_eq!( + mock_api.addr_make("creator").to_string(), + "juno1h34lmpywh4upnjdg90cjf4j70aee6z8qqfspugamjp42e4q28kqsksmtyp", + ); + } + + #[test] + #[should_panic(expected = "Generating address failed with reason: invalid length")] + fn making_an_address_with_empty_prefix_should_panic() { + MockApi::default().with_prefix("").addr_make("creator"); + } }