From 5050c24e9b0be38255312c310f61ee916da7dd83 Mon Sep 17 00:00:00 2001 From: brentstone Date: Tue, 30 Aug 2022 20:29:47 +0300 Subject: [PATCH 1/2] replace floating point arithm from token module with rust_decimal --- proof_of_stake/src/parameters.rs | 5 ++++- shared/src/types/token.rs | 29 ++++++++++++----------------- tests/src/native_vp/pos.rs | 18 +++++++++++------- 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/proof_of_stake/src/parameters.rs b/proof_of_stake/src/parameters.rs index 7ee0abdf986..1c265bf1a84 100644 --- a/proof_of_stake/src/parameters.rs +++ b/proof_of_stake/src/parameters.rs @@ -71,11 +71,14 @@ pub enum ValidationError { UnbondingLenTooShort(u64, u64), } +/// The number of fundamental units per whole token of the native staking token +pub const TOKENS_PER_NAM: u64 = 1_000_000; + /// From Tendermint: const MAX_TOTAL_VOTING_POWER: i64 = i64::MAX / 8; /// Assuming token amount is `u64` in micro units. -const TOKEN_MAX_AMOUNT: u64 = u64::MAX / 1_000_000; +const TOKEN_MAX_AMOUNT: u64 = u64::MAX / TOKENS_PER_NAM; impl PosParams { /// Validate PoS parameters values. Returns an empty list if the values are diff --git a/shared/src/types/token.rs b/shared/src/types/token.rs index 787a8855dc5..b19642b85af 100644 --- a/shared/src/types/token.rs +++ b/shared/src/types/token.rs @@ -6,6 +6,7 @@ use std::ops::{Add, AddAssign, Mul, Sub, SubAssign}; use std::str::FromStr; use borsh::{BorshDeserialize, BorshSchema, BorshSerialize}; +use rust_decimal::prelude::{Decimal, ToPrimitive}; use serde::{Deserialize, Serialize}; use thiserror::Error; @@ -37,7 +38,6 @@ pub struct Amount { pub const MAX_DECIMAL_PLACES: u32 = 6; /// Decimal scale of token [`Amount`] and [`Change`]. pub const SCALE: u64 = 1_000_000; -const SCALE_F64: f64 = SCALE as f64; /// A change in tokens amount pub type Change = i128; @@ -109,21 +109,16 @@ impl<'de> serde::Deserialize<'de> for Amount { } } -impl From for f64 { - /// Warning: `f64` loses precision and it should not be used when exact - /// values are required. +impl From for Decimal { fn from(amount: Amount) -> Self { - amount.micro as f64 / SCALE_F64 + Into::::into(amount.micro) / Into::::into(SCALE) } } -impl From for Amount { - /// Warning: `f64` loses precision and it should not be used when exact - /// values are required. - fn from(micro: f64) -> Self { - Self { - micro: (micro * SCALE_F64).round() as u64, - } +impl From for Amount { + fn from(micro: Decimal) -> Self { + let res = (micro * Into::::into(SCALE)).to_u64().unwrap(); + Self { micro: res } } } @@ -205,7 +200,7 @@ impl FromStr for Amount { match rust_decimal::Decimal::from_str(s) { Ok(decimal) => { let scale = decimal.scale(); - if scale > 6 { + if scale > MAX_DECIMAL_PLACES { return Err(AmountParseError::ScaleTooLarge(scale)); } let whole = @@ -440,11 +435,11 @@ mod tests { /// The upper limit is set to `2^51`, because then the float is /// starting to lose precision. #[test] - fn test_token_amount_f64_conversion(raw_amount in 0..2_u64.pow(51)) { + fn test_token_amount_decimal_conversion(raw_amount in 0..2_u64.pow(51)) { let amount = Amount::from(raw_amount); - // A round-trip conversion to and from f64 should be an identity - let float = f64::from(amount); - let identity = Amount::from(float); + // A round-trip conversion to and from Decimal should be an identity + let decimal = Decimal::from(amount); + let identity = Amount::from(decimal); assert_eq!(amount, identity); } } diff --git a/tests/src/native_vp/pos.rs b/tests/src/native_vp/pos.rs index ec6f75a15f0..61b859a7d67 100644 --- a/tests/src/native_vp/pos.rs +++ b/tests/src/native_vp/pos.rs @@ -594,6 +594,10 @@ pub mod testing { use crate::tx::{self, tx_host_env}; + const TOKENS_PER_NAM: i128 = + namada::ledger::pos::namada_proof_of_stake::parameters::TOKENS_PER_NAM + as i128; + #[derive(Clone, Debug, Default)] pub struct TestValidator { pub address: Option
, @@ -940,9 +944,9 @@ pub mod testing { // We convert the tokens from micro units to whole tokens // with division by 10^6 let vp_before = - params.votes_per_token * ((total_delta) / 1_000_000); + params.votes_per_token * (total_delta / TOKENS_PER_NAM); let vp_after = params.votes_per_token - * ((total_delta + token_delta) / 1_000_000); + * ((total_delta + token_delta) / TOKENS_PER_NAM); // voting power delta let vp_delta = vp_after - vp_before; @@ -1001,12 +1005,12 @@ pub mod testing { let total_delta = validator_total_deltas .get(epoch) .unwrap_or_default(); - // We convert the tokens from micro units to whole + // We convert the tokens from micro units to whole // tokens with division by 10^6 let vp_before = params.votes_per_token - * ((total_delta) / 1_000_000); + * (total_delta / TOKENS_PER_NAM); let vp_after = params.votes_per_token - * ((total_delta + token_delta) / 1_000_000); + * ((total_delta + token_delta) / TOKENS_PER_NAM); // voting power delta let vp_delta_at_unbonding = vp_after - vp_before - vp_delta - total_vp_delta; @@ -1080,9 +1084,9 @@ pub mod testing { // We convert the tokens from micro units to whole tokens // with division by 10^6 let vp_before = params.votes_per_token - * ((total_delta_cur) / 1_000_000); + * (total_delta_cur / TOKENS_PER_NAM); let vp_after = params.votes_per_token - * ((total_delta_cur + token_delta) / 1_000_000); + * ((total_delta_cur + token_delta) / TOKENS_PER_NAM); // voting power delta let vp_delta = vp_after - vp_before; From 3f5581457e99e02a3e25bb0c07fb8abf5918e8ea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 26 Oct 2022 09:22:00 +0000 Subject: [PATCH 2/2] [ci] wasm checksums update --- wasm/checksums.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/wasm/checksums.json b/wasm/checksums.json index 01140354ba3..5dfd713ff79 100644 --- a/wasm/checksums.json +++ b/wasm/checksums.json @@ -1,18 +1,18 @@ { - "tx_bond.wasm": "tx_bond.38c037a51f9215c2be9c1b01f647251ffdc96a02a0c958c5d3db4ee36ccde43b.wasm", - "tx_ibc.wasm": "tx_ibc.5f86477029d987073ebfec66019dc991b0bb8b80717d4885b860f910916cbcdd.wasm", - "tx_init_account.wasm": "tx_init_account.8d901bce15d1ab63a591def00421183a651d4d5e09ace4291bf0a9044692741d.wasm", - "tx_init_nft.wasm": "tx_init_nft.1991808f44c1c24d4376a3d46b602bed27575f6c0359095c53f37b9225050ffc.wasm", - "tx_init_proposal.wasm": "tx_init_proposal.716cd08d59b26bd75815511f03e141e6ac27bc0b7d7be10a71b04559244722c2.wasm", - "tx_init_validator.wasm": "tx_init_validator.611edff2746f71cdaa7547a84a96676b555821f00af8375a28f8dab7ae9fc9fa.wasm", - "tx_mint_nft.wasm": "tx_mint_nft.3f20f1a86da43cc475ccc127428944bd177d40fbe2d2d1588c6fadd069cbe4b2.wasm", - "tx_transfer.wasm": "tx_transfer.5653340103a32e6685f9668ec24855f65ae17bcc43035c2559a13f5c47bb67af.wasm", - "tx_unbond.wasm": "tx_unbond.71e66ac6f792123a2aaafd60b3892d74a7d0e7a03c3ea34f15fea9089010b810.wasm", + "tx_bond.wasm": "tx_bond.059b1256240d15a64cf419f3a2d24af1496211c386d85acc3733095bc2e5da9b.wasm", + "tx_ibc.wasm": "tx_ibc.4eeb30bc1e6a32b8efe8958eab568082a238db01eb98340f28a9fa41371a3753.wasm", + "tx_init_account.wasm": "tx_init_account.85d017ac76e51f359fa07e753c0e6fcbd3341e7661492cbf2801cf3c41480dd4.wasm", + "tx_init_nft.wasm": "tx_init_nft.fbeb1687a364b2c249c9fd69588ff0985bd9c1f8f4c93e5328de1e9ba527d991.wasm", + "tx_init_proposal.wasm": "tx_init_proposal.43b52414649bb0fec86dfb35d001656c1825bc5906e450e8b0c3a60aaa5f3d45.wasm", + "tx_init_validator.wasm": "tx_init_validator.6ccb7fcf246cb7a2f97a5dfdcefe16ee1add72a832081c2572adc2d7a355cf56.wasm", + "tx_mint_nft.wasm": "tx_mint_nft.f2ed21521c676f04be4c6278cc60bec83265c3750437c87d9ea681b830767d71.wasm", + "tx_transfer.wasm": "tx_transfer.b6fc342f4a76918874e6d037a3864e4369dbba7cd7d558622e7a723e3d854da3.wasm", + "tx_unbond.wasm": "tx_unbond.6e7316d08bf8ab9a6fb1889f64a5a2265ee0399661dbb48e33555170545d1c7c.wasm", "tx_update_vp.wasm": "tx_update_vp.6d291dadb43545a809ba33fe26582b7984c67c65f05e363a93dbc62e06a33484.wasm", - "tx_vote_proposal.wasm": "tx_vote_proposal.ff3def7b4bb0c46635bd6d544ac1745362757ce063feb8142d2ed9ab207f2a12.wasm", - "tx_withdraw.wasm": "tx_withdraw.ba1a743cf8914a353d7706777e0b1a37e20cd271b16e022fd3b50ad28971291f.wasm", - "vp_nft.wasm": "vp_nft.4471284b5c5f3e28c973f0a2ad2dde52ebe4a1dcd5dc15e93b380706fd0e35ea.wasm", - "vp_testnet_faucet.wasm": "vp_testnet_faucet.7d7eb09cddc7ae348417da623e21ec4a4f8c78f15ae12de5abe7087eeab1e0db.wasm", - "vp_token.wasm": "vp_token.4a5436f7519de15c80103557add57e8d06e766e1ec1f7a642ffca252be01c5d0.wasm", - "vp_user.wasm": "vp_user.729b18aab60e8ae09b75b5f067658f30459a5ccfcd34f909b88da96523681019.wasm" + "tx_vote_proposal.wasm": "tx_vote_proposal.d0a87d58f64f46586ae3d83852deee269e22520f4780875c05aaf1731044c356.wasm", + "tx_withdraw.wasm": "tx_withdraw.e5dcc5ef2362018c1fa5ea02912528ee929aa7b6fefcf06f4ccf7509bfa52283.wasm", + "vp_nft.wasm": "vp_nft.9be5a821bc7b3075b917e8ead45893502d82cc7417e6af50dfd3f6baf36243e0.wasm", + "vp_testnet_faucet.wasm": "vp_testnet_faucet.8e2e45ff165d40dc8249188aca108e5cba86ac5dd1cd989b0237cadd4b66bfdf.wasm", + "vp_token.wasm": "vp_token.4a0446f20e7436de1e889c640a11644d1a1295c4d29e45b24582df2b9ed3176e.wasm", + "vp_user.wasm": "vp_user.eb1d6f1f524c28571ad0f21f75371aa635257313cea2702b9a70e5022fe6c3ef.wasm" } \ No newline at end of file