From 9df462c8d1e2dd1ac5e06ea1e95f52aafe3db55b Mon Sep 17 00:00:00 2001 From: DragonMural Date: Wed, 21 Oct 2020 00:11:32 -0400 Subject: [PATCH 1/3] Firs commit --- Cargo.lock | 99 ++++++++++++++++- blockchain/message_pool/Cargo.toml | 2 + blockchain/message_pool/src/block_prob.rs | 128 ++++++++++++++++++++++ blockchain/message_pool/src/lib.rs | 1 + 4 files changed, 227 insertions(+), 3 deletions(-) create mode 100644 blockchain/message_pool/src/block_prob.rs diff --git a/Cargo.lock b/Cargo.lock index f324d537a432..433ad857181c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,6 +219,17 @@ dependencies = [ "memchr", ] +[[package]] +name = "alga" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f823d037a7ec6ea2197046bafd4ae150e6bc36f9ca347404f46a46823fa84f2" +dependencies = [ + "approx", + "num-complex 0.2.4", + "num-traits 0.2.12", +] + [[package]] name = "ansi_term" version = "0.11.0" @@ -234,6 +245,15 @@ version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" +[[package]] +name = "approx" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3" +dependencies = [ + "num-traits 0.2.12", +] + [[package]] name = "arrayref" version = "0.3.6" @@ -1901,7 +1921,7 @@ dependencies = [ "cl-sys", "enum_primitive", "failure", - "num-complex", + "num-complex 0.1.43", "num-traits 0.2.12", "ocl-core-vector", "rustc_version 0.1.7", @@ -3346,6 +3366,12 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "libm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d73b3f436185384286bd8098d17ec07c9a7d2388a6599f824d8502b529702a" + [[package]] name = "libnghttp2-sys" version = "0.1.4+1.41.0" @@ -3761,6 +3787,15 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +[[package]] +name = "matrixmultiply" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4f7ec66360130972f34830bfad9ef05c6610a43938a467bcc9ab9369ab3478f" +dependencies = [ + "rawpointer", +] + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -3838,9 +3873,11 @@ dependencies = [ "log", "lru", "num-traits 0.2.12", + "rand 0.7.3", "serde", "state_manager", "state_tree", + "statrs", "thiserror", ] @@ -3962,6 +3999,24 @@ dependencies = [ "unsigned-varint 0.4.0", ] +[[package]] +name = "nalgebra" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abb021006c01b126a936a8dd1351e0720d83995f4fc942d0d426c654f990745" +dependencies = [ + "alga", + "approx", + "generic-array 0.13.2", + "matrixmultiply", + "num-complex 0.2.4", + "num-rational 0.2.4", + "num-traits 0.2.12", + "rand 0.7.3", + "rand_distr", + "typenum", +] + [[package]] name = "native-tls" version = "0.2.4" @@ -4069,10 +4124,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" dependencies = [ "num-bigint 0.1.44", - "num-complex", + "num-complex 0.1.43", "num-integer", "num-iter", - "num-rational", + "num-rational 0.1.42", "num-traits 0.2.12", ] @@ -4120,6 +4175,16 @@ dependencies = [ "rustc-serialize", ] +[[package]] +name = "num-complex" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6b19411a9719e753aff12e5187b74d60d3dc449ec3f4dc21e3989c3f554bc95" +dependencies = [ + "autocfg", + "num-traits 0.2.12", +] + [[package]] name = "num-derive" version = "0.3.2" @@ -4164,6 +4229,17 @@ dependencies = [ "rustc-serialize", ] +[[package]] +name = "num-rational" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c000134b5dbf44adc5cb772486d335293351644b801551abe8f75c84cfa4aef" +dependencies = [ + "autocfg", + "num-integer", + "num-traits 0.2.12", +] + [[package]] name = "num-traits" version = "0.1.43" @@ -4180,6 +4256,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -4818,6 +4895,12 @@ dependencies = [ "rustc_version 0.2.3", ] +[[package]] +name = "rawpointer" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" + [[package]] name = "rayon" version = "1.4.1" @@ -5654,6 +5737,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "statrs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e34b58a8f9b7462b6922e0b4e3c83d1b3c2075f7f996a56d6c66afa81590064" +dependencies = [ + "nalgebra", + "rand 0.7.3", +] + [[package]] name = "stdweb" version = "0.4.20" diff --git a/blockchain/message_pool/Cargo.toml b/blockchain/message_pool/Cargo.toml index b6bfde003f06..d5b8c90226fb 100644 --- a/blockchain/message_pool/Cargo.toml +++ b/blockchain/message_pool/Cargo.toml @@ -31,6 +31,8 @@ async-trait = "0.1" interpreter = { path = "../../vm/interpreter/" } types = { package = "fil_types", path = "../../types" } num-traits = "0.2" +statrs = "0.13.0" +rand = "0.7.3" [dev-dependencies] interpreter = { path = "../../vm/interpreter/" } diff --git a/blockchain/message_pool/src/block_prob.rs b/blockchain/message_pool/src/block_prob.rs new file mode 100644 index 000000000000..81ea1fbfbf25 --- /dev/null +++ b/blockchain/message_pool/src/block_prob.rs @@ -0,0 +1,128 @@ + +use statrs::function::gamma::ln_gamma; +use rand::{Rng,thread_rng}; +use std::f64::consts::E; + +const MAX_BLOCKS : usize = 15; +const MU : f64 = 5.0; + + +fn poiss_pdf(x : f64, mu : f64, cond : f64 ) -> f64 { + let ln_gamma = ln_gamma( x + 1.0 ); + let log_mu = mu.log(E); + let exponent = log_mu * x - ln_gamma - cond; + E.powf(exponent) +} + + +fn no_winners_prob() -> Vec { + let mut out : Vec = vec![]; + for i in 0..MAX_BLOCKS { + out.push(poiss_pdf(i as f64, MU, MU)); + } + out +} + + +fn no_winners_prob_assuming_more_than_one() -> Vec { + let cond = (E.powf(5.0) - 1.0).log(E); + let mut out : Vec = vec![]; + for i in 0..MAX_BLOCKS { + out.push(poiss_pdf(i as f64 + 1.0, MU, cond)); + } + out +} + +fn binomial_coefficient(mut n : f64, k : f64) -> Result { + + if k > n { + return Err(()); + } + + let mut r = 1.0; + let mut d = 1.0; + while d <= k { + r *= n; + r /= d; + n -= 1.0; + d+= 1.0; + } + Ok(r) +} + +fn bino_pdf(x : f64, trials : f64, p : f64) -> f64 { + // based on https://github.com/atgjack/prob + if x > trials { + return 0.0 + } + if p == 0.0 { + if x == 0.0 { + return 1.0 + } + return 0.0 + } + if p == 1.0 { + if x == trials { + return 1.0 + } + return 0.0 + } + let coef = if let Ok(v) = binomial_coefficient(trials, x){ + v + } + else{ + return 0.0; + }; + + let pow = p.powf(x) * (1.0-p).powf( trials-x); + return coef * pow +} + + +pub fn block_probabilities(tq : f64) -> Vec { + let no_winners = no_winners_prob_assuming_more_than_one(); + let p = 1.0 - tq; + let mut out : Vec = vec![]; + + for place in 0..MAX_BLOCKS{ + let mut p_place = 0.0; + for (other_winner,p_case) in no_winners.iter().enumerate() { + p_place += p_case * bino_pdf(place as f64, other_winner as f64, p); + } + out.push(p_place); + } + out + +} + +#[test] +fn test_block_probability() { + let bp = block_probabilities(1.0 - 0.15); + for i in 0.. bp.len()-1 { + assert!(bp[i] >= bp[i+1]); + } +} + +#[test] +fn test_winner_probability() { + let n = 1_000_000; + let winner_prob = no_winners_prob(); + let mut sum = 0.0; + + // Generates a radnom number from 0 to not including 1 + let mut rng = thread_rng(); + + for _ in 0..n { + let mut miners_rand: f64 = rng.gen::() * f64::MAX; + for j in 0..MAX_BLOCKS{ + miners_rand -= winner_prob[j]; + if miners_rand < 0.0{ + break + } + sum +=1.0; + } + } + + let avg = sum/(n as f64); + assert!((avg-5.0).abs() > 0.01, "Average too far off "); +} diff --git a/blockchain/message_pool/src/lib.rs b/blockchain/message_pool/src/lib.rs index 270bc679ca78..7950e3e3d83f 100644 --- a/blockchain/message_pool/src/lib.rs +++ b/blockchain/message_pool/src/lib.rs @@ -4,6 +4,7 @@ mod config; mod errors; mod msgpool; +mod block_prob; pub use self::config::*; pub use self::errors::*; pub use self::msgpool::*; From 253ba0df31531cdbfaae55487dc68361984dd226 Mon Sep 17 00:00:00 2001 From: DragonMural Date: Wed, 21 Oct 2020 00:52:21 -0400 Subject: [PATCH 2/3] Lint fixes --- blockchain/message_pool/src/block_prob.rs | 92 +++++++++++------------ blockchain/message_pool/src/lib.rs | 2 +- 2 files changed, 45 insertions(+), 49 deletions(-) diff --git a/blockchain/message_pool/src/block_prob.rs b/blockchain/message_pool/src/block_prob.rs index 81ea1fbfbf25..41c7beaa0eb6 100644 --- a/blockchain/message_pool/src/block_prob.rs +++ b/blockchain/message_pool/src/block_prob.rs @@ -1,110 +1,106 @@ +// Copyright 2020 ChainSafe Systems +// SPDX-License-Identifier: Apache-2.0, MIT use statrs::function::gamma::ln_gamma; -use rand::{Rng,thread_rng}; use std::f64::consts::E; -const MAX_BLOCKS : usize = 15; -const MU : f64 = 5.0; +const MAX_BLOCKS: usize = 15; +const MU: f64 = 5.0; - -fn poiss_pdf(x : f64, mu : f64, cond : f64 ) -> f64 { - let ln_gamma = ln_gamma( x + 1.0 ); +fn poiss_pdf(x: f64, mu: f64, cond: f64) -> f64 { + let ln_gamma = ln_gamma(x + 1.0); let log_mu = mu.log(E); let exponent = log_mu * x - ln_gamma - cond; E.powf(exponent) } - -fn no_winners_prob() -> Vec { - let mut out : Vec = vec![]; +pub fn no_winners_prob() -> Vec { + let mut out: Vec = vec![]; for i in 0..MAX_BLOCKS { out.push(poiss_pdf(i as f64, MU, MU)); } out } - fn no_winners_prob_assuming_more_than_one() -> Vec { let cond = (E.powf(5.0) - 1.0).log(E); - let mut out : Vec = vec![]; + let mut out: Vec = vec![]; for i in 0..MAX_BLOCKS { out.push(poiss_pdf(i as f64 + 1.0, MU, cond)); } out } -fn binomial_coefficient(mut n : f64, k : f64) -> Result { - +fn binomial_coefficient(mut n: f64, k: f64) -> Result { if k > n { return Err(()); } let mut r = 1.0; let mut d = 1.0; - while d <= k { - r *= n; - r /= d; + while d <= k { + r *= n; + r /= d; n -= 1.0; - d+= 1.0; - } - Ok(r) + d += 1.0; + } + Ok(r) } -fn bino_pdf(x : f64, trials : f64, p : f64) -> f64 { +fn bino_pdf(x: f64, trials: f64, p: f64) -> f64 { // based on https://github.com/atgjack/prob if x > trials { - return 0.0 + return 0.0; } if p == 0.0 { if x == 0.0 { - return 1.0 + return 1.0; } - return 0.0 + return 0.0; } - if p == 1.0 { - if x == trials { - return 1.0 + if (p - 1.0).abs() < f64::EPSILON { + if (x - trials).abs() < f64::EPSILON { + return 1.0; } - return 0.0 + return 0.0; } - let coef = if let Ok(v) = binomial_coefficient(trials, x){ + let coef = if let Ok(v) = binomial_coefficient(trials, x) { v - } - else{ + } else { return 0.0; }; - let pow = p.powf(x) * (1.0-p).powf( trials-x); - return coef * pow + let pow = p.powf(x) * (1.0 - p).powf(trials - x); + coef * pow } - -pub fn block_probabilities(tq : f64) -> Vec { +pub fn block_probabilities(tq: f64) -> Vec { let no_winners = no_winners_prob_assuming_more_than_one(); let p = 1.0 - tq; - let mut out : Vec = vec![]; + let mut out: Vec = vec![]; - for place in 0..MAX_BLOCKS{ + for place in 0..MAX_BLOCKS { let mut p_place = 0.0; - for (other_winner,p_case) in no_winners.iter().enumerate() { + for (other_winner, p_case) in no_winners.iter().enumerate() { p_place += p_case * bino_pdf(place as f64, other_winner as f64, p); } out.push(p_place); } out - } #[test] fn test_block_probability() { - let bp = block_probabilities(1.0 - 0.15); - for i in 0.. bp.len()-1 { - assert!(bp[i] >= bp[i+1]); - } + let bp = block_probabilities(1.0 - 0.15); + for i in 0..bp.len() - 1 { + assert!(bp[i] >= bp[i + 1]); + } } #[test] fn test_winner_probability() { + use rand::thread_rng; + use rand::Rng; let n = 1_000_000; let winner_prob = no_winners_prob(); let mut sum = 0.0; @@ -114,15 +110,15 @@ fn test_winner_probability() { for _ in 0..n { let mut miners_rand: f64 = rng.gen::() * f64::MAX; - for j in 0..MAX_BLOCKS{ + for j in 0..MAX_BLOCKS { miners_rand -= winner_prob[j]; - if miners_rand < 0.0{ - break + if miners_rand < 0.0 { + break; } - sum +=1.0; + sum += 1.0; } } - let avg = sum/(n as f64); - assert!((avg-5.0).abs() > 0.01, "Average too far off "); + let avg = sum / (n as f64); + assert!((avg - 5.0).abs() > 0.01, "Average too far off "); } diff --git a/blockchain/message_pool/src/lib.rs b/blockchain/message_pool/src/lib.rs index 7950e3e3d83f..3134559e5a05 100644 --- a/blockchain/message_pool/src/lib.rs +++ b/blockchain/message_pool/src/lib.rs @@ -1,10 +1,10 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +pub mod block_prob; mod config; mod errors; mod msgpool; -mod block_prob; pub use self::config::*; pub use self::errors::*; pub use self::msgpool::*; From 296c6ab92ffe15c7bcad00dc05525597cd960a98 Mon Sep 17 00:00:00 2001 From: DragonMural Date: Wed, 21 Oct 2020 19:29:47 -0400 Subject: [PATCH 3/3] Adding requested updates --- blockchain/message_pool/Cargo.toml | 3 +- blockchain/message_pool/src/block_prob.rs | 40 +++++++++++------------ blockchain/message_pool/src/lib.rs | 1 + 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/blockchain/message_pool/Cargo.toml b/blockchain/message_pool/Cargo.toml index d5b8c90226fb..e4088f8256bb 100644 --- a/blockchain/message_pool/Cargo.toml +++ b/blockchain/message_pool/Cargo.toml @@ -32,8 +32,9 @@ interpreter = { path = "../../vm/interpreter/" } types = { package = "fil_types", path = "../../types" } num-traits = "0.2" statrs = "0.13.0" -rand = "0.7.3" + [dev-dependencies] interpreter = { path = "../../vm/interpreter/" } key_management = { path = "../../key_management" } +rand = "0.7.3" diff --git a/blockchain/message_pool/src/block_prob.rs b/blockchain/message_pool/src/block_prob.rs index 41c7beaa0eb6..b8c5d8ba3e8f 100644 --- a/blockchain/message_pool/src/block_prob.rs +++ b/blockchain/message_pool/src/block_prob.rs @@ -15,20 +15,18 @@ fn poiss_pdf(x: f64, mu: f64, cond: f64) -> f64 { } pub fn no_winners_prob() -> Vec { - let mut out: Vec = vec![]; - for i in 0..MAX_BLOCKS { - out.push(poiss_pdf(i as f64, MU, MU)); - } - out + (0..MAX_BLOCKS) + .into_iter() + .map(|i| poiss_pdf(i as f64, MU, MU)) + .collect() } fn no_winners_prob_assuming_more_than_one() -> Vec { let cond = (E.powf(5.0) - 1.0).log(E); - let mut out: Vec = vec![]; - for i in 0..MAX_BLOCKS { - out.push(poiss_pdf(i as f64 + 1.0, MU, cond)); - } - out + (0..MAX_BLOCKS) + .into_iter() + .map(|i| poiss_pdf(i as f64, MU, cond)) + .collect() } fn binomial_coefficient(mut n: f64, k: f64) -> Result { @@ -77,16 +75,18 @@ fn bino_pdf(x: f64, trials: f64, p: f64) -> f64 { pub fn block_probabilities(tq: f64) -> Vec { let no_winners = no_winners_prob_assuming_more_than_one(); let p = 1.0 - tq; - let mut out: Vec = vec![]; - - for place in 0..MAX_BLOCKS { - let mut p_place = 0.0; - for (other_winner, p_case) in no_winners.iter().enumerate() { - p_place += p_case * bino_pdf(place as f64, other_winner as f64, p); - } - out.push(p_place); - } - out + (0..MAX_BLOCKS) + .into_iter() + .map(|place| { + no_winners + .iter() + .enumerate() + .map(|(other_winner, p_case)| { + p_case * bino_pdf(place as f64, other_winner as f64, p) + }) + .sum() + }) + .collect() } #[test] diff --git a/blockchain/message_pool/src/lib.rs b/blockchain/message_pool/src/lib.rs index 3134559e5a05..907f4d51f311 100644 --- a/blockchain/message_pool/src/lib.rs +++ b/blockchain/message_pool/src/lib.rs @@ -1,6 +1,7 @@ // Copyright 2020 ChainSafe Systems // SPDX-License-Identifier: Apache-2.0, MIT +// TODO Remove public once Message Selection has been implemented pub mod block_prob; mod config; mod errors;