From 2b4965f54b75fa45e5378b979d8f9b4a65ccb0ca Mon Sep 17 00:00:00 2001 From: cong-or Date: Wed, 15 Jan 2025 10:23:10 +0000 Subject: [PATCH 01/10] feat(quadratic voting): alternative --- Cargo.lock | 40 +++++++++---------- .../chain-impl-mockchain/Cargo.toml | 2 + .../chain-impl-mockchain/src/vote/tally.rs | 7 +++- src/chain-libs/chain-vote/Cargo.toml | 3 ++ src/chain-libs/chain-vote/src/tally.rs | 11 ++++- 5 files changed, 40 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f1eec6842..58756bf061 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1216,6 +1216,7 @@ dependencies = [ "hex", "imhamt", "lazy_static", + "num-integer", "proptest", "quickcheck", "quickcheck_macros", @@ -1303,12 +1304,14 @@ dependencies = [ "const_format", "criterion", "cryptoxide 0.4.4", + "num-integer", "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", "rayon", "smoke", "thiserror", + "tracing", ] [[package]] @@ -4023,9 +4026,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "lazycell" @@ -4739,25 +4742,24 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", - "num-rational 0.4.1", + "num-rational 0.4.2", "num-traits", ] [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", "serde", @@ -4765,9 +4767,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", "serde", @@ -4786,19 +4788,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -4818,11 +4819,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -4831,9 +4831,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", diff --git a/src/chain-libs/chain-impl-mockchain/Cargo.toml b/src/chain-libs/chain-impl-mockchain/Cargo.toml index 83f4b2b74d..4523268cf1 100644 --- a/src/chain-libs/chain-impl-mockchain/Cargo.toml +++ b/src/chain-libs/chain-impl-mockchain/Cargo.toml @@ -32,6 +32,8 @@ criterion = { version = "0.3.0", optional = true } rand = "0.8" cryptoxide = "0.4" tracing.workspace = true +num-integer = "0.1" + [features] property-test-api = [ diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index 7d6a1c2f24..32c601ee5e 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -4,6 +4,7 @@ use crate::{ vote::{Choice, Options}, }; use chain_vote::EncryptedTally; +use num_integer::Roots; use std::fmt; use thiserror::Error; @@ -166,7 +167,11 @@ impl TallyResult { } else { let index = choice.as_byte() as usize; - self.results[index] = self.results[index].saturating_add(weight); + // Returns the truncated principal square root of an integer – ⌊√x⌋ + // This is solving for r in r² = x, rounding toward zero. The result will satisfy r² ≤ x < (r+1)² + let weight_gammad = weight.0.sqrt(); + + self.results[index] = self.results[index].saturating_add(Weight(weight_gammad)); Ok(()) } diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 6d31e20b84..17b6628f4e 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -14,6 +14,9 @@ thiserror = "1.0" cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" +tracing = "0.1" +num-integer = "0.1" + [dev-dependencies] rand_chacha = "0.3" diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index d28543be17..644342266d 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -11,6 +11,8 @@ use crate::{ use base64::{engine::general_purpose, Engine as _}; use cryptoxide::blake2b::Blake2b; use cryptoxide::digest::Digest; +use num_integer::Roots; + use rand_core::{CryptoRng, RngCore}; /// Secret key for opening vote @@ -155,10 +157,15 @@ impl EncryptedTally { pub fn add(&mut self, ballot: &Ballot, weight: u64) { assert_eq!(ballot.vote().len(), self.r.len()); assert_eq!(ballot.fingerprint(), &self.fingerprint); + + // Returns the truncated principal square root of an integer – ⌊√x⌋ + // This is solving for r in r² = x, rounding toward zero. The result will satisfy r² ≤ x < (r+1)² + let weight_gammad = weight.sqrt(); + for (ri, ci) in self.r.iter_mut().zip(ballot.vote().iter()) { - *ri = &*ri + &(ci * weight); + *ri = &*ri + &(ci * weight_gammad); } - self.max_stake += weight; + self.max_stake += weight_gammad; } /// Given a single committee member's `secret_key`, returns a partial decryption of From a13cc3e291d29c27d525f6366d8ed82d3fdf63ef Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 13:44:52 +0000 Subject: [PATCH 02/10] refactor(gamma): big decimal --- Cargo.lock | 54 ++++++++++++------- src/audit/README.md | 11 ++++ src/audit/src/offline/bin/main.rs | 17 ++++++ .../chain-impl-mockchain/Cargo.toml | 2 +- .../chain-impl-mockchain/src/vote/tally.rs | 27 ++++++++-- src/chain-libs/chain-vote/Cargo.toml | 3 +- src/chain-libs/chain-vote/src/tally.rs | 26 ++++++--- 7 files changed, 108 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58756bf061..b09ccbd898 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -691,6 +691,19 @@ dependencies = [ "serde", ] +[[package]] +name = "bigdecimal" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" +dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "bincode" version = "1.3.3" @@ -1203,6 +1216,7 @@ dependencies = [ name = "chain-impl-mockchain" version = "0.1.0" dependencies = [ + "bigdecimal", "cardano-legacy-address", "chain-addr", "chain-core", @@ -1216,7 +1230,6 @@ dependencies = [ "hex", "imhamt", "lazy_static", - "num-integer", "proptest", "quickcheck", "quickcheck_macros", @@ -1298,13 +1311,13 @@ name = "chain-vote" version = "0.1.0" dependencies = [ "base64 0.21.5", + "bigdecimal", "cfg-if 1.0.0", "chain-core", "chain-crypto", "const_format", "criterion", "cryptoxide 0.4.4", - "num-integer", "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", @@ -4026,9 +4039,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" @@ -4742,24 +4755,25 @@ dependencies = [ [[package]] name = "num" -version = "0.4.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", - "num-rational 0.4.2", + "num-rational 0.4.1", "num-traits", ] [[package]] name = "num-bigint" -version = "0.4.6" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" dependencies = [ + "autocfg", "num-integer", "num-traits", "serde", @@ -4767,9 +4781,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.6" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" dependencies = [ "num-traits", "serde", @@ -4788,18 +4802,19 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" dependencies = [ + "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.45" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" dependencies = [ "autocfg", "num-integer", @@ -4819,10 +4834,11 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" dependencies = [ + "autocfg", "num-bigint", "num-integer", "num-traits", @@ -4831,9 +4847,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.19" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", "libm", diff --git a/src/audit/README.md b/src/audit/README.md index f7f3629579..ef1457f384 100644 --- a/src/audit/README.md +++ b/src/audit/README.md @@ -31,6 +31,17 @@ FRAGMENTS_STORAGE=/tmp/fund9-leader-1/persist/leader-1 ``` +```bash + +OFFICIAL_RESULTS=/tmp/activevoteplans.json +BLOCK0=/tmp/fund9-leader-1/artifacts/block0.bin +FRAGMENTS_STORAGE=/tmp/fund9-leader-1/persist/leader-1 +QUADRATIC_SCALE=0.1 + +./target/release/offline --fragments $FRAGMENTS_STORAGE --block0 $BLOCK0 --official-results $OFFICIAL_RESULTS --quadratic_scaling $QUADRATIC_SCALE + +``` + This will create three files: - *ledger_after_tally.json* **(decrypted ledger state after tally)** *should match official results!* - *ledger_before_tally.json* **(encrypted ledger state before tally)** diff --git a/src/audit/src/offline/bin/main.rs b/src/audit/src/offline/bin/main.rs index 39402585d7..ff4401faf5 100644 --- a/src/audit/src/offline/bin/main.rs +++ b/src/audit/src/offline/bin/main.rs @@ -19,6 +19,7 @@ use lib::offline::{ use chain_core::packer::Codec; use color_eyre::{eyre::Context, Report}; +use std::env; use std::{error::Error, path::PathBuf}; /// @@ -36,6 +37,12 @@ pub struct Args { /// cross reference official results #[clap(short, long)] official_results: Option, + /// Quadratic scaling + #[clap(short, long)] + gamma: Option, + /// Quadratic scaling + #[clap(short, long)] + precision: Option, } fn main() -> Result<(), Box> { @@ -95,6 +102,16 @@ fn main() -> Result<(), Box> { // use tally tool to validate decrypted results let shares_and_results = extract_decryption_shares_and_results(all_fragments); + if let Some(gamma) = args.gamma { + const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; + std::env::set_var(SCALE_FACTOR, gamma); + } + + if let Some(precision) = args.precision { + const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + std::env::set_var(PRECISION, precision); + } + // Compare decrypted tallies with official results if provided if let Some(official_results) = args.official_results { // official catalyst results in json format diff --git a/src/chain-libs/chain-impl-mockchain/Cargo.toml b/src/chain-libs/chain-impl-mockchain/Cargo.toml index 4523268cf1..b5acfb01b5 100644 --- a/src/chain-libs/chain-impl-mockchain/Cargo.toml +++ b/src/chain-libs/chain-impl-mockchain/Cargo.toml @@ -32,7 +32,7 @@ criterion = { version = "0.3.0", optional = true } rand = "0.8" cryptoxide = "0.4" tracing.workspace = true -num-integer = "0.1" +bigdecimal = "0.4.7" [features] diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index 32c601ee5e..b703797272 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -3,8 +3,14 @@ use crate::{ value::Value, vote::{Choice, Options}, }; +use bigdecimal::BigDecimal; +use bigdecimal::ToPrimitive; use chain_vote::EncryptedTally; -use num_integer::Roots; +use std::num::NonZeroI64; + +use std::str::FromStr; + +use std::env; use std::fmt; use thiserror::Error; @@ -167,11 +173,22 @@ impl TallyResult { } else { let index = choice.as_byte() as usize; - // Returns the truncated principal square root of an integer – ⌊√x⌋ - // This is solving for r in r² = x, rounding toward zero. The result will satisfy r² ≤ x < (r+1)² - let weight_gammad = weight.0.sqrt(); + const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; + const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + + let scaling_factor = env::var(SCALE_FACTOR).unwrap_or(1.to_string()); + let precision = + i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); + + let gamma = BigDecimal::from_str(&scaling_factor).unwrap_or(BigDecimal::from(1)); + let stake = BigDecimal::from(weight.0); + + let weight = (gamma * stake) + .round(precision) + .to_u64() + .unwrap_or(weight.0); - self.results[index] = self.results[index].saturating_add(Weight(weight_gammad)); + self.results[index] = self.results[index].saturating_add(Weight(weight)); Ok(()) } diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 17b6628f4e..4dfbba1836 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -15,7 +15,8 @@ cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" tracing = "0.1" -num-integer = "0.1" +bigdecimal = "0.4.7" + [dev-dependencies] diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index 644342266d..f6e254e8cc 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -1,5 +1,8 @@ +use std::num::NonZeroI64; use std::num::NonZeroU64; +use std::str::FromStr; + use crate::GroupElement; use crate::{ committee::*, @@ -9,9 +12,13 @@ use crate::{ TallyOptimizationTable, }; use base64::{engine::general_purpose, Engine as _}; + +use bigdecimal::BigDecimal; +use bigdecimal::ToPrimitive; use cryptoxide::blake2b::Blake2b; use cryptoxide::digest::Digest; -use num_integer::Roots; + +use std::env; use rand_core::{CryptoRng, RngCore}; @@ -158,14 +165,21 @@ impl EncryptedTally { assert_eq!(ballot.vote().len(), self.r.len()); assert_eq!(ballot.fingerprint(), &self.fingerprint); - // Returns the truncated principal square root of an integer – ⌊√x⌋ - // This is solving for r in r² = x, rounding toward zero. The result will satisfy r² ≤ x < (r+1)² - let weight_gammad = weight.sqrt(); + const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; + const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + + let scaling_factor = env::var(SCALE_FACTOR).unwrap_or(1.to_string()); + let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); + + let gamma = BigDecimal::from_str(&scaling_factor).unwrap_or(BigDecimal::from(1)); + let stake = BigDecimal::from(weight); + + let weight = (gamma * stake).round(precision).to_u64().unwrap_or(weight); for (ri, ci) in self.r.iter_mut().zip(ballot.vote().iter()) { - *ri = &*ri + &(ci * weight_gammad); + *ri = &*ri + &(ci * weight); } - self.max_stake += weight_gammad; + self.max_stake += weight; } /// Given a single committee member's `secret_key`, returns a partial decryption of From 038fdb8839711210177e5e2726ad31d92d4c33f1 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 13:51:41 +0000 Subject: [PATCH 03/10] refactor(gamma): big decimal --- src/audit/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/audit/README.md b/src/audit/README.md index ef1457f384..8746e9421c 100644 --- a/src/audit/README.md +++ b/src/audit/README.md @@ -31,14 +31,18 @@ FRAGMENTS_STORAGE=/tmp/fund9-leader-1/persist/leader-1 ``` + +*Generate encrypted tally with gamma scaling* + + ```bash -OFFICIAL_RESULTS=/tmp/activevoteplans.json BLOCK0=/tmp/fund9-leader-1/artifacts/block0.bin FRAGMENTS_STORAGE=/tmp/fund9-leader-1/persist/leader-1 -QUADRATIC_SCALE=0.1 +GAMMA=0.1 +PRECISION=5 -./target/release/offline --fragments $FRAGMENTS_STORAGE --block0 $BLOCK0 --official-results $OFFICIAL_RESULTS --quadratic_scaling $QUADRATIC_SCALE +./target/release/offline --fragments $FRAGMENTS_STORAGE --block0 $BLOCK0 --gamma $GAMMA --precision $PRECISION ``` From eabf187ebb1e74c23eedc0af4ba98452e687e773 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 13:52:53 +0000 Subject: [PATCH 04/10] refactor(gamma): big decimal --- Cargo.lock | 1 - src/chain-libs/chain-vote/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b09ccbd898..4c85dc6f23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1324,7 +1324,6 @@ dependencies = [ "rayon", "smoke", "thiserror", - "tracing", ] [[package]] diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 4dfbba1836..7e94af1184 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -14,7 +14,6 @@ thiserror = "1.0" cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" -tracing = "0.1" bigdecimal = "0.4.7" From 72e6c8f0da52d6d09f3606d3fbaa12499e5192ab Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 18:45:41 +0000 Subject: [PATCH 05/10] refactor(gamma): big decimal --- src/audit/src/offline/bin/main.rs | 8 ++++---- src/chain-libs/chain-impl-mockchain/src/vote/tally.rs | 6 +++--- src/chain-libs/chain-vote/src/tally.rs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/audit/src/offline/bin/main.rs b/src/audit/src/offline/bin/main.rs index ff4401faf5..97fdec1cc5 100644 --- a/src/audit/src/offline/bin/main.rs +++ b/src/audit/src/offline/bin/main.rs @@ -37,10 +37,10 @@ pub struct Args { /// cross reference official results #[clap(short, long)] official_results: Option, - /// Quadratic scaling + /// Gamma value for Quadratic scaling #[clap(short, long)] gamma: Option, - /// Quadratic scaling + /// Rounding precision for arithmetic #[clap(short, long)] precision: Option, } @@ -103,8 +103,8 @@ fn main() -> Result<(), Box> { let shares_and_results = extract_decryption_shares_and_results(all_fragments); if let Some(gamma) = args.gamma { - const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; - std::env::set_var(SCALE_FACTOR, gamma); + const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; + std::env::set_var(GAMMA, gamma); } if let Some(precision) = args.precision { diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index b703797272..bf9bcb60f0 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -173,14 +173,14 @@ impl TallyResult { } else { let index = choice.as_byte() as usize; - const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; + const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; - let scaling_factor = env::var(SCALE_FACTOR).unwrap_or(1.to_string()); + let gamma = env::var(GAMMA).unwrap_or(1.to_string()); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let gamma = BigDecimal::from_str(&scaling_factor).unwrap_or(BigDecimal::from(1)); + let gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); let stake = BigDecimal::from(weight.0); let weight = (gamma * stake) diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index f6e254e8cc..3fd8265145 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -165,13 +165,13 @@ impl EncryptedTally { assert_eq!(ballot.vote().len(), self.r.len()); assert_eq!(ballot.fingerprint(), &self.fingerprint); - const SCALE_FACTOR: &str = "QUADRATIC_VOTING_SCALING_FACTOR"; + const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; - let scaling_factor = env::var(SCALE_FACTOR).unwrap_or(1.to_string()); + let gamma = env::var(GAMMA).unwrap_or(1.to_string()); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let gamma = BigDecimal::from_str(&scaling_factor).unwrap_or(BigDecimal::from(1)); + let gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); let stake = BigDecimal::from(weight); let weight = (gamma * stake).round(precision).to_u64().unwrap_or(weight); From 12163056d309f0fb00359eaff9124e89dc572b56 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 18:51:57 +0000 Subject: [PATCH 06/10] refactor(gamma): big decimal --- src/chain-libs/chain-impl-mockchain/src/vote/tally.rs | 1 + src/chain-libs/chain-vote/src/tally.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index bf9bcb60f0..9a0b4c99c2 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -176,6 +176,7 @@ impl TallyResult { const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + // Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect. let gamma = env::var(GAMMA).unwrap_or(1.to_string()); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index 3fd8265145..ae6ed35c5a 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -168,6 +168,7 @@ impl EncryptedTally { const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + // Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect. let gamma = env::var(GAMMA).unwrap_or(1.to_string()); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); From 39aee7d0fbb12808694b78a7016f982d174b02c4 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 20:28:40 +0000 Subject: [PATCH 07/10] refactor(gamma): big decimal --- Cargo.lock | 13 ++++++------ src/audit/src/offline/bin/main.rs | 20 +++++++++---------- .../chain-impl-mockchain/src/vote/tally.rs | 7 ++++++- src/chain-libs/chain-vote/Cargo.toml | 2 +- src/chain-libs/chain-vote/src/tally.rs | 7 ++++++- 5 files changed, 30 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c85dc6f23..6755eda571 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1324,6 +1324,7 @@ dependencies = [ "rayon", "smoke", "thiserror", + "tracing", ] [[package]] @@ -7880,9 +7881,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -7904,9 +7905,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -7915,9 +7916,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", diff --git a/src/audit/src/offline/bin/main.rs b/src/audit/src/offline/bin/main.rs index 97fdec1cc5..9e98b0a9df 100644 --- a/src/audit/src/offline/bin/main.rs +++ b/src/audit/src/offline/bin/main.rs @@ -68,6 +68,16 @@ fn main() -> Result<(), Box> { info!("Audit Tool."); info!("Starting Offline Tally"); + if let Some(gamma) = args.gamma { + const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; + std::env::set_var(GAMMA, gamma); + } + + if let Some(precision) = args.precision { + const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; + std::env::set_var(PRECISION, precision); + } + // Load and replay fund fragments from storage let storage_path = PathBuf::from(args.fragments); @@ -102,16 +112,6 @@ fn main() -> Result<(), Box> { // use tally tool to validate decrypted results let shares_and_results = extract_decryption_shares_and_results(all_fragments); - if let Some(gamma) = args.gamma { - const GAMMA: &str = "QUADRATIC_VOTING_GAMMA"; - std::env::set_var(GAMMA, gamma); - } - - if let Some(precision) = args.precision { - const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; - std::env::set_var(PRECISION, precision); - } - // Compare decrypted tallies with official results if provided if let Some(official_results) = args.official_results { // official catalyst results in json format diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index 9a0b4c99c2..62f1bbab56 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -178,10 +178,15 @@ impl TallyResult { // Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect. let gamma = env::var(GAMMA).unwrap_or(1.to_string()); + let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); + let mut gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); + // Gamma must be between 0 and 1, anything else is treated as bad input; defaulting gamma to 1. + if gamma < BigDecimal::from(0) || gamma > BigDecimal::from(1) { + gamma = BigDecimal::from(1); + } let stake = BigDecimal::from(weight.0); let weight = (gamma * stake) diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 7e94af1184..06e5e01fc3 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -15,7 +15,7 @@ cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" bigdecimal = "0.4.7" - +tracing = "0.1.41" [dev-dependencies] diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index ae6ed35c5a..b5d13ad817 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -2,6 +2,7 @@ use std::num::NonZeroI64; use std::num::NonZeroU64; use std::str::FromStr; +use tracing::info; use crate::GroupElement; use crate::{ @@ -172,7 +173,11 @@ impl EncryptedTally { let gamma = env::var(GAMMA).unwrap_or(1.to_string()); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); + let mut gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); + // Gamma must be between 0 and 1, anything else is treated as bad input; defaulting gamma to 1. + if gamma < BigDecimal::from(0) || gamma > BigDecimal::from(1) { + gamma = BigDecimal::from(1); + } let stake = BigDecimal::from(weight); let weight = (gamma * stake).round(precision).to_u64().unwrap_or(weight); From 7dac2e114377e899074decd9a903b345e5d5bcf7 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 20:29:30 +0000 Subject: [PATCH 08/10] refactor(gamma): big decimal --- Cargo.lock | 1 - src/chain-libs/chain-vote/Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6755eda571..353917502b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1324,7 +1324,6 @@ dependencies = [ "rayon", "smoke", "thiserror", - "tracing", ] [[package]] diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 06e5e01fc3..1e2f57be62 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -15,7 +15,6 @@ cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" bigdecimal = "0.4.7" -tracing = "0.1.41" [dev-dependencies] From 375e6c1da1b58989a8869acf3a62dcbe70c86454 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 20:31:30 +0000 Subject: [PATCH 09/10] refactor(gamma): big decimal --- src/chain-libs/chain-vote/src/tally.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index b5d13ad817..666b9a7c1c 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -2,7 +2,6 @@ use std::num::NonZeroI64; use std::num::NonZeroU64; use std::str::FromStr; -use tracing::info; use crate::GroupElement; use crate::{ From d3c221a3b694f745897582c3e48efc03cae758c3 Mon Sep 17 00:00:00 2001 From: cong-or Date: Mon, 20 Jan 2025 21:54:00 +0000 Subject: [PATCH 10/10] refactor(big rational): fraction to denom and numer --- Cargo.lock | 36 +++++++++---------- .../chain-impl-mockchain/Cargo.toml | 1 + .../chain-impl-mockchain/src/vote/tally.rs | 16 +++++---- src/chain-libs/chain-vote/Cargo.toml | 2 ++ src/chain-libs/chain-vote/src/tally.rs | 23 ++++++++---- 5 files changed, 46 insertions(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 353917502b..cc4bb5a9e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1230,6 +1230,7 @@ dependencies = [ "hex", "imhamt", "lazy_static", + "num", "proptest", "quickcheck", "quickcheck_macros", @@ -1318,12 +1319,14 @@ dependencies = [ "const_format", "criterion", "cryptoxide 0.4.4", + "num", "rand 0.8.5", "rand_chacha 0.3.1", "rand_core 0.6.4", "rayon", "smoke", "thiserror", + "tracing", ] [[package]] @@ -4754,25 +4757,24 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", "num-integer", "num-iter", - "num-rational 0.4.1", + "num-rational 0.4.2", "num-traits", ] [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ - "autocfg", "num-integer", "num-traits", "serde", @@ -4780,9 +4782,9 @@ dependencies = [ [[package]] name = "num-complex" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ba157ca0885411de85d6ca030ba7e2a83a28636056c7c699b07c8b6f7383214" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", "serde", @@ -4801,19 +4803,18 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -4833,11 +4834,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -4846,9 +4846,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", diff --git a/src/chain-libs/chain-impl-mockchain/Cargo.toml b/src/chain-libs/chain-impl-mockchain/Cargo.toml index b5acfb01b5..c75ceaaa80 100644 --- a/src/chain-libs/chain-impl-mockchain/Cargo.toml +++ b/src/chain-libs/chain-impl-mockchain/Cargo.toml @@ -33,6 +33,7 @@ rand = "0.8" cryptoxide = "0.4" tracing.workspace = true bigdecimal = "0.4.7" +num = "0.4.3" [features] diff --git a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs index 62f1bbab56..60288505aa 100644 --- a/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs +++ b/src/chain-libs/chain-impl-mockchain/src/vote/tally.rs @@ -6,6 +6,8 @@ use crate::{ use bigdecimal::BigDecimal; use bigdecimal::ToPrimitive; use chain_vote::EncryptedTally; +use num::BigRational; +use num::{BigInt, FromPrimitive}; use std::num::NonZeroI64; use std::str::FromStr; @@ -177,19 +179,19 @@ impl TallyResult { const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; // Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect. - let gamma = env::var(GAMMA).unwrap_or(1.to_string()); + let gamma = f64::from_str(&env::var(GAMMA).unwrap_or(1.0.to_string())).unwrap(); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let mut gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); - // Gamma must be between 0 and 1, anything else is treated as bad input; defaulting gamma to 1. - if gamma < BigDecimal::from(0) || gamma > BigDecimal::from(1) { - gamma = BigDecimal::from(1); - } + let gamma = + BigRational::from_f64(gamma).unwrap_or(BigRational::from_integer(BigInt::from(1))); + let denom = BigDecimal::from_bigint(gamma.denom().clone(), precision); + let numer = BigDecimal::from_bigint(gamma.numer().clone(), precision); + let stake = BigDecimal::from(weight.0); - let weight = (gamma * stake) + let weight = ((stake.clone() * numer.clone()) / denom) .round(precision) .to_u64() .unwrap_or(weight.0); diff --git a/src/chain-libs/chain-vote/Cargo.toml b/src/chain-libs/chain-vote/Cargo.toml index 1e2f57be62..d5baca7013 100644 --- a/src/chain-libs/chain-vote/Cargo.toml +++ b/src/chain-libs/chain-vote/Cargo.toml @@ -15,6 +15,8 @@ cryptoxide = "^0.4.2" const_format = "0.2" base64 = "0.21.0" bigdecimal = "0.4.7" +num = "0.4.3" +tracing = "*" [dev-dependencies] diff --git a/src/chain-libs/chain-vote/src/tally.rs b/src/chain-libs/chain-vote/src/tally.rs index 666b9a7c1c..ec146b10ce 100644 --- a/src/chain-libs/chain-vote/src/tally.rs +++ b/src/chain-libs/chain-vote/src/tally.rs @@ -12,6 +12,10 @@ use crate::{ TallyOptimizationTable, }; use base64::{engine::general_purpose, Engine as _}; +use num::BigInt; +use num::BigRational; +use num::FromPrimitive; +use tracing::info; use bigdecimal::BigDecimal; use bigdecimal::ToPrimitive; @@ -169,17 +173,22 @@ impl EncryptedTally { const PRECISION: &str = "QUADRATIC_VOTING_PRECISION"; // Apply quadratic scaling if gamma value specified in env var. Else gamma is 1 and has no effect. - let gamma = env::var(GAMMA).unwrap_or(1.to_string()); + let gamma = f64::from_str(&env::var(GAMMA).unwrap_or(1.0.to_string())).unwrap(); let precision = i64::from_str(&env::var(PRECISION).unwrap_or(1.to_string())).unwrap_or(1); - let mut gamma = BigDecimal::from_str(&gamma).unwrap_or(BigDecimal::from(1)); - // Gamma must be between 0 and 1, anything else is treated as bad input; defaulting gamma to 1. - if gamma < BigDecimal::from(0) || gamma > BigDecimal::from(1) { - gamma = BigDecimal::from(1); - } + let gamma = + BigRational::from_f64(gamma).unwrap_or(BigRational::from_integer(BigInt::from(1))); + let denom = BigDecimal::from_bigint(gamma.denom().clone(), precision); + let numer = BigDecimal::from_bigint(gamma.numer().clone(), precision); + let stake = BigDecimal::from(weight); - let weight = (gamma * stake).round(precision).to_u64().unwrap_or(weight); + let weight = ((stake.clone() * numer.clone()) / denom) + .round(precision) + .to_u64() + .unwrap_or(weight); + + info!("stake before {:?} stake after {:?}", stake.to_u64(), weight); for (ri, ci) in self.r.iter_mut().zip(ballot.vote().iter()) { *ri = &*ri + &(ci * weight);