Skip to content

Commit

Permalink
Add total_weight_lower_bound to Nodes::reduce (#733)
Browse files Browse the repository at this point in the history
  • Loading branch information
benr-ml authored Feb 28, 2024
1 parent 41056bf commit a6ff7df
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 5 deletions.
21 changes: 18 additions & 3 deletions fastcrypto-tbls/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use fastcrypto::error::{FastCryptoError, FastCryptoResult};
use fastcrypto::groups::GroupElement;
use fastcrypto::hash::{Blake2b256, Digest, HashFunction};
use serde::{Deserialize, Serialize};
use tracing::debug;

pub type PartyId = u16;

Expand Down Expand Up @@ -145,14 +146,28 @@ impl<G: GroupElement + Serialize> Nodes<G> {
/// - The precision loss, counted as the sum of the remainders of the division by d, is at most
/// the allowed delta
/// In practice, allowed delta will be the extra liveness we would assume above 2f+1.
pub fn reduce(&self, t: u16, allowed_delta: u16) -> (Self, u16) {
/// total_weight_lower_bound allows limiting the level of reduction (e.g., in benchmarks). To get the best results,
/// set it to 1.
pub fn reduce(&self, t: u16, allowed_delta: u16, total_weight_lower_bound: u32) -> (Self, u16) {
assert!(total_weight_lower_bound <= self.total_weight && total_weight_lower_bound > 0);
let mut max_d = 1;
for d in 2..=40 {
let sum = self.nodes.iter().map(|n| n.weight % d).sum::<u16>();
if sum <= allowed_delta {
// Break if we reached the lower bound.
let new_total_weight = self.nodes.iter().map(|n| n.weight / d).sum::<u16>();
if new_total_weight < total_weight_lower_bound as u16 {
break;
}
// Compute the precision loss.
let delta = self.nodes.iter().map(|n| n.weight % d).sum::<u16>();
if delta <= allowed_delta {
max_d = d;
}
}
debug!(
"Nodes::reduce reducing from {} with max_d {}, allowed_delta {}, total_weight_lower_bound {}",
self.total_weight, max_d, allowed_delta, total_weight_lower_bound
);

let nodes = self
.nodes
.iter()
Expand Down
28 changes: 26 additions & 2 deletions fastcrypto-tbls/src/tests/nodes_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,40 @@ fn test_reduce() {
let t = (nodes.total_weight() / 3) as u16;

// No extra gap, should return the inputs
let (new_nodes, new_t) = nodes.reduce(t, 1);
let (new_nodes, new_t) = nodes.reduce(t, 1, 1);
assert_eq!(nodes, new_nodes);
assert_eq!(t, new_t);

// 10% gap
let (new_nodes, _new_t) = nodes.reduce(t, (nodes.total_weight() / 10) as u16);
let (new_nodes, _new_t) = nodes.reduce(t, (nodes.total_weight() / 10) as u16, 1);
// Estimate the real factor d
let d = nodes.iter().last().unwrap().weight / new_nodes.iter().last().unwrap().weight;
// The loss per node is on average (d - 1) / 2
// We use 9 instead of 10 to compensate wrong value of d
assert!((d - 1) / 2 * number_of_nodes < ((nodes.total_weight() / 9) as u16));
}
}

#[test]
fn test_reduce_with_lower_bounds() {
let number_of_nodes = 100;
let node_vec = get_nodes::<RistrettoPoint>(number_of_nodes);
let nodes = Nodes::new(node_vec).unwrap();
let t = (nodes.total_weight() / 3) as u16;

// No extra gap, should return the inputs
let (new_nodes, new_t) = nodes.reduce(t, 1, 1);
assert_eq!(nodes, new_nodes);
assert_eq!(t, new_t);

// 10% gap
let (new_nodes1, _new_t1) = nodes.reduce(t, (nodes.total_weight() / 20) as u16, 1);
let (new_nodes2, _new_t2) = nodes.reduce(
t,
(nodes.total_weight() / 20) as u16,
nodes.total_weight() / 3,
);
assert!(new_nodes1.total_weight() < new_nodes2.total_weight());
assert!(new_nodes2.total_weight() >= nodes.total_weight() / 3);
assert!(new_nodes2.total_weight() < nodes.total_weight());
}

0 comments on commit a6ff7df

Please sign in to comment.