From fc399a583eea3b76ce8bdfa66e8a3c5bdd54cdb8 Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Fri, 1 Apr 2022 15:05:55 +0200 Subject: [PATCH 1/3] Decimal/256: Add 'new' and 'raw' const constructors --- CHANGELOG.md | 2 ++ packages/std/src/math/decimal.rs | 30 +++++++++++++++++++++++++---- packages/std/src/math/decimal256.rs | 23 ++++++++++++++++++++++ packages/std/src/math/uint256.rs | 25 ++++++++++++++++++++++++ 4 files changed, 76 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2ac32424eb..f22c6c9b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ and this project adheres to - cosmwasm-std: Implement `MulAssign` for `Decimal`/`Decimal256`. - cosmwasm-std: Implement `is_zero`/`atomics`/`decimal_places` as const for Uint and Decimal types. +- cosmwasm-std: Implement `new` and `raw` const constructors for + `Decimal`/`Decimal256`. - cosmwasm-crypto: Upgrade ed25519-zebra to version 3. ### Changed diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index d5522db999..4c591cc056 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -33,24 +33,34 @@ impl Decimal { pub const MAX: Self = Self(Uint128::MAX); + /// Creates a Decimal(value) + pub const fn new(value: Uint128) -> Self { + Self(value) + } + + /// Creates a Decimal(Uint128(value)) + pub const fn raw(value: u128) -> Self { + Self(Uint128::new(value)) + } + /// Create a 1.0 Decimal pub const fn one() -> Self { - Decimal(Self::DECIMAL_FRACTIONAL) + Self(Self::DECIMAL_FRACTIONAL) } /// Create a 0.0 Decimal pub const fn zero() -> Self { - Decimal(Uint128::zero()) + Self(Uint128::zero()) } /// Convert x% into Decimal pub fn percent(x: u64) -> Self { - Decimal(((x as u128) * 10_000_000_000_000_000).into()) + Self(((x as u128) * 10_000_000_000_000_000).into()) } /// Convert permille (x/1000) into Decimal pub fn permille(x: u64) -> Self { - Decimal(((x as u128) * 1_000_000_000_000_000).into()) + Self(((x as u128) * 1_000_000_000_000_000).into()) } /// Creates a decimal from a number of atomic units and the number @@ -478,6 +488,18 @@ mod tests { use super::*; use crate::{from_slice, to_vec}; + #[test] + fn decimal_new() { + let expected = Uint128::from(300u128); + assert_eq!(expected, Decimal::new(expected).0); + } + + #[test] + fn decimal_raw() { + let value = 300u128; + assert_eq!(value, Decimal::raw(value).0.u128()); + } + #[test] fn decimal_one() { let value = Decimal::one(); diff --git a/packages/std/src/math/decimal256.rs b/packages/std/src/math/decimal256.rs index a71d29fdd8..d0775bcef4 100644 --- a/packages/std/src/math/decimal256.rs +++ b/packages/std/src/math/decimal256.rs @@ -42,6 +42,16 @@ impl Decimal256 { pub const MAX: Self = Self(Uint256::MAX); + /// Creates a Decimal from Uint256 + pub const fn new(value: Uint256) -> Self { + Self(value) + } + + /// Creates a Decimal from u128 + pub const fn raw(value: u128) -> Self { + Self(Uint256::from_u128(value)) + } + /// Create a 1.0 Decimal256 pub const fn one() -> Self { Self(Self::DECIMAL_FRACTIONAL) @@ -491,6 +501,19 @@ mod tests { use crate::errors::StdError; use crate::{from_slice, to_vec}; + #[test] + fn decimal256_new() { + let expected = Uint256::from(300u128); + assert_eq!(expected, Decimal256::new(expected).0); + } + + #[test] + fn decimal256_raw() { + let value = 300u128; + let expected = Uint256::from(value); + assert_eq!(expected, Decimal256::raw(value).0); + } + #[test] fn decimal256_one() { let value = Decimal256::one(); diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index 5eb8e48e4f..c9dd72638a 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -102,6 +102,18 @@ impl Uint256 { Uint256(U256(words)) } + /// A conversion from `u128` that, unlike the one provided by the `From` trait, + /// can be used in a `const` context. + pub const fn from_u128(num: u128) -> Self { + let bytes = num.to_le_bytes(); + + Self::from_le_bytes([ + bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], + bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]) + } + /// A conversion from `Uint128` that, unlike the one provided by the `From` trait, /// can be used in a `const` context. pub const fn from_uint128(num: Uint128) -> Self { @@ -945,6 +957,19 @@ mod tests { ); } + #[test] + fn uint256_from_u128() { + assert_eq!( + Uint256::from_u128(123u128), + Uint256::from_str("123").unwrap() + ); + + assert_eq!( + Uint256::from_u128(9785746283745u128), + Uint256::from_str("9785746283745").unwrap() + ); + } + #[test] fn uint256_from_uint128() { assert_eq!( From 47f92864521a45428eda109ba294e4bd31d3d430 Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Mon, 4 Apr 2022 11:05:00 +0200 Subject: [PATCH 2/3] Fix changelog so not modify old entries --- CHANGELOG.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f22c6c9b09..6b20f92a69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,9 +6,21 @@ and this project adheres to ## [Unreleased] +### Added + +- cosmwasm-std: Implement `MulAssign` for `Decimal`/`Decimal256`. +- cosmwasm-std: Implement `is_zero`/`atomics`/`decimal_places` as const for Uint + and Decimal types. +- cosmwasm-std: Implement `new` and `raw` const constructors for + `Decimal`/`Decimal256`. + ### Changed - all: Drop support for Rust versions lower than 1.56.1. +- cosmwasm-std: `MockQuerier` now supports adding custom behaviour for handling + Wasm queries via `MockQuerier::update_wasm` ([#1050]). + +[#1050]: https://github.com/CosmWasm/cosmwasm/pull/1050 ## [1.0.0-beta7] - 2022-03-22 @@ -22,20 +34,11 @@ and this project adheres to `Uint64`/`Uint128`/`Uint256`/`Uint512`. - cosmwasm-std: Implement `pow`/`checked_pow` for `Uint64`/`Uint128`/`Uint512`. - cosmwasm-std: Implement `SubAssign`/`AddAssign` for `Decimal`/`Decimal256`. -- cosmwasm-std: Implement `MulAssign` for `Decimal`/`Decimal256`. -- cosmwasm-std: Implement `is_zero`/`atomics`/`decimal_places` as const for Uint - and Decimal types. -- cosmwasm-std: Implement `new` and `raw` const constructors for - `Decimal`/`Decimal256`. - cosmwasm-crypto: Upgrade ed25519-zebra to version 3. ### Changed - cosmwasm-vm: Upgrade Wasmer to 2.2.1. -- cosmwasm-std: `MockQuerier` now supports adding custom behaviour for handling - Wasm queries via `MockQuerier::update_wasm` ([#1050]). - -[#1050]: https://github.com/CosmWasm/cosmwasm/pull/1050 ## [1.0.0-beta6] - 2022-03-07 From e08b5c579dc84d008f4a7df3df970c2626bf0c73 Mon Sep 17 00:00:00 2001 From: Jakub Bogucki Date: Mon, 4 Apr 2022 11:42:58 +0200 Subject: [PATCH 3/3] Uint256: dedup implementation from_u128 in from_uint128; Fix review comments --- packages/std/src/math/decimal.rs | 6 ++++-- packages/std/src/math/decimal256.rs | 10 ++++++---- packages/std/src/math/uint256.rs | 8 +------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/packages/std/src/math/decimal.rs b/packages/std/src/math/decimal.rs index 4c591cc056..c71792e371 100644 --- a/packages/std/src/math/decimal.rs +++ b/packages/std/src/math/decimal.rs @@ -34,11 +34,13 @@ impl Decimal { pub const MAX: Self = Self(Uint128::MAX); /// Creates a Decimal(value) + /// This is equivalent to `Decimal::from_atomics(value, 18)` but usable in a const context. pub const fn new(value: Uint128) -> Self { Self(value) } /// Creates a Decimal(Uint128(value)) + /// This is equivalent to `Decimal::from_atomics(value, 18)` but usable in a const context. pub const fn raw(value: u128) -> Self { Self(Uint128::new(value)) } @@ -491,13 +493,13 @@ mod tests { #[test] fn decimal_new() { let expected = Uint128::from(300u128); - assert_eq!(expected, Decimal::new(expected).0); + assert_eq!(Decimal::new(expected).0, expected); } #[test] fn decimal_raw() { let value = 300u128; - assert_eq!(value, Decimal::raw(value).0.u128()); + assert_eq!(Decimal::raw(value).0.u128(), value); } #[test] diff --git a/packages/std/src/math/decimal256.rs b/packages/std/src/math/decimal256.rs index d0775bcef4..fe55ce71d6 100644 --- a/packages/std/src/math/decimal256.rs +++ b/packages/std/src/math/decimal256.rs @@ -42,12 +42,14 @@ impl Decimal256 { pub const MAX: Self = Self(Uint256::MAX); - /// Creates a Decimal from Uint256 + /// Creates a Decimal256 from Uint256 + /// This is equivalent to `Decimal256::from_atomics(value, 18)` but usable in a const context. pub const fn new(value: Uint256) -> Self { Self(value) } - /// Creates a Decimal from u128 + /// Creates a Decimal256 from u128 + /// This is equivalent to `Decimal256::from_atomics(value, 18)` but usable in a const context. pub const fn raw(value: u128) -> Self { Self(Uint256::from_u128(value)) } @@ -504,14 +506,14 @@ mod tests { #[test] fn decimal256_new() { let expected = Uint256::from(300u128); - assert_eq!(expected, Decimal256::new(expected).0); + assert_eq!(Decimal256::new(expected).0, expected); } #[test] fn decimal256_raw() { let value = 300u128; let expected = Uint256::from(value); - assert_eq!(expected, Decimal256::raw(value).0); + assert_eq!(Decimal256::raw(value).0, expected); } #[test] diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index c9dd72638a..2df305cdec 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -117,13 +117,7 @@ impl Uint256 { /// A conversion from `Uint128` that, unlike the one provided by the `From` trait, /// can be used in a `const` context. pub const fn from_uint128(num: Uint128) -> Self { - let bytes = num.to_le_bytes(); - - Self::from_le_bytes([ - bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], - bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15], - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - ]) + Self::from_u128(num.u128()) } /// Returns a copy of the number as big endian bytes.