diff --git a/substrate/bin/node/runtime/src/lib.rs b/substrate/bin/node/runtime/src/lib.rs index 169768243b5a47435e0a2157a8999dafcf9d6609..4ec0fa275b4feb7288f227cf584760c39067c0b1 100644 --- a/substrate/bin/node/runtime/src/lib.rs +++ b/substrate/bin/node/runtime/src/lib.rs @@ -83,7 +83,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // implementation changes and behavior does not, then leave spec_version as // is and increment impl_version. spec_version: 244, - impl_version: 1, + impl_version: 2, apis: RUNTIME_API_VERSIONS, transaction_version: 1, }; diff --git a/substrate/primitives/arithmetic/src/fixed64.rs b/substrate/primitives/arithmetic/src/fixed64.rs index af4dbf34e293b3d47e23760c2de87cbe5be18a28..63a69e66e7c9d6363e1c9eeba7b6c9e4c31b3164 100644 --- a/substrate/primitives/arithmetic/src/fixed64.rs +++ b/substrate/primitives/arithmetic/src/fixed64.rs @@ -113,7 +113,10 @@ impl Saturating for Fixed64 { } fn saturating_mul(self, rhs: Self) -> Self { - Self(self.0.saturating_mul(rhs.0) / DIV) + let a = self.0 as i128; + let b = rhs.0 as i128; + let res = a * b / DIV as i128; + Self(res.saturated_into()) } fn saturating_sub(self, rhs: Self) -> Self { @@ -121,7 +124,22 @@ impl Saturating for Fixed64 { } fn saturating_pow(self, exp: usize) -> Self { - Self(self.0.saturating_pow(exp as u32)) + if exp == 0 { + return Self::from_natural(1); + } + + let exp = exp as u64; + let msb_pos = 64 - exp.leading_zeros(); + + let mut result = Self::from_natural(1); + let mut pow_val = self; + for i in 0..msb_pos { + if ((1 << i) & exp) > 0 { + result = result.saturating_mul(pow_val); + } + pow_val = pow_val.saturating_mul(pow_val); + } + result } } @@ -333,4 +351,32 @@ mod tests { let b = Fixed64::from_rational(1, 100); assert_eq!(a.checked_div(&b), Some(Fixed64::from_rational(120, 1))); } + + #[test] + fn saturating_mul_should_work() { + assert_eq!(Fixed64::from_natural(100).saturating_mul(Fixed64::from_natural(100)), Fixed64::from_natural(10000)); + } + + #[test] + fn saturating_pow_should_work() { + assert_eq!(Fixed64::from_natural(2).saturating_pow(0), Fixed64::from_natural(1)); + assert_eq!(Fixed64::from_natural(2).saturating_pow(1), Fixed64::from_natural(2)); + assert_eq!(Fixed64::from_natural(2).saturating_pow(2), Fixed64::from_natural(4)); + assert_eq!(Fixed64::from_natural(2).saturating_pow(3), Fixed64::from_natural(8)); + assert_eq!(Fixed64::from_natural(2).saturating_pow(20), Fixed64::from_natural(1048576)); + + assert_eq!(Fixed64::from_natural(1).saturating_pow(1000), Fixed64::from_natural(1)); + assert_eq!(Fixed64::from_natural(-1).saturating_pow(1000), Fixed64::from_natural(1)); + assert_eq!(Fixed64::from_natural(-1).saturating_pow(1001), Fixed64::from_natural(-1)); + assert_eq!(Fixed64::from_natural(1).saturating_pow(usize::max_value()), Fixed64::from_natural(1)); + assert_eq!(Fixed64::from_natural(-1).saturating_pow(usize::max_value()), Fixed64::from_natural(-1)); + assert_eq!(Fixed64::from_natural(-1).saturating_pow(usize::max_value() - 1), Fixed64::from_natural(1)); + + assert_eq!(Fixed64::from_natural(309).saturating_pow(4), Fixed64::from_natural(9_116_621_361)); + assert_eq!(Fixed64::from_natural(309).saturating_pow(5), Fixed64::from_parts(i64::max_value())); + + assert_eq!(Fixed64::from_natural(1).saturating_pow(usize::max_value()), Fixed64::from_natural(1)); + assert_eq!(Fixed64::from_natural(0).saturating_pow(usize::max_value()), Fixed64::from_natural(0)); + assert_eq!(Fixed64::from_natural(2).saturating_pow(usize::max_value()), Fixed64::from_parts(i64::max_value())); + } }