Skip to content
Open
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
d3018e2
Add super_swiper weight reduction and tests
arnab-roy Nov 19, 2025
3d75d13
Add weight-reduction solver repo
arnab-roy Nov 19, 2025
fb5251f
Add Sui validator stake/ticket scripts and test integration
arnab-roy Nov 20, 2025
3d7e72a
Add Sui validator stake data files
arnab-roy Nov 20, 2025
fab373f
Refactor super swiper reduced node creation API
arnab-roy Nov 20, 2025
348dc4a
Remove unused weight-reduction solvers and tests
arnab-roy Nov 22, 2025
39cccf2
Remove weight-reduction data and test files
arnab-roy Nov 22, 2025
75f11a5
Integrating Ratio types
arnab-roy Nov 22, 2025
9783482
Removing swiper folder
arnab-roy Nov 22, 2025
a57905b
More cleanup
arnab-roy Nov 22, 2025
3bcc9a8
More cleanups
arnab-roy Nov 22, 2025
cc46e32
More cleanups
arnab-roy Nov 22, 2025
f2e4f61
More cleanups
arnab-roy Nov 22, 2025
a621735
fixed nightly build req
arnab-roy Nov 22, 2025
a8251a3
Update super_swiper_test.rs
arnab-roy Nov 22, 2025
68163f6
Remove super-swiper feature gating and update dependencies
arnab-roy Nov 24, 2025
b498120
Clean up deps
arnab-roy Nov 24, 2025
ec66c87
Add weight reduction validation and enhance super_swiper
arnab-roy Dec 4, 2025
a81a218
Refactor super swiper reduction to use slack-based validation
arnab-roy Dec 6, 2025
937fb37
Cleanup
arnab-roy Dec 6, 2025
873d377
GH tests
arnab-roy Dec 8, 2025
e3948c7
lock
jonas-lj Dec 8, 2025
1cc63e0
Refactor
jonas-lj Dec 8, 2025
578d2a8
revert
jonas-lj Dec 8, 2025
40a8713
Refactor for GH tests
arnab-roy Dec 8, 2025
8327706
Edits for fmt check
arnab-roy Dec 8, 2025
01f4251
Edits for ubuntu GH actions
arnab-roy Dec 8, 2025
b2c0005
Edits for Ubuntu GH actions
arnab-roy Dec 8, 2025
6b06cb3
Refactor super_swiper_reduced to use threshold t
arnab-roy Dec 10, 2025
db15818
Refactor weight reduction to use delta constraint
arnab-roy Dec 11, 2025
896e427
Add test for new_reduced with delta constraint
arnab-roy Dec 11, 2025
0835717
Add Sui validator voting power data and test integration
arnab-roy Dec 12, 2025
3e6fe93
Add multi-epoch Sui voting power data and tests
arnab-roy Dec 12, 2025
de73353
Resolving comments from Jonas
arnab-roy Dec 19, 2025
6932854
fmt and clippy fixes
arnab-roy Dec 19, 2025
ffc61f6
Ensuring and clarifying loop bounds
arnab-roy Dec 19, 2025
e823b29
Misc clean up
jonas-lj Jan 23, 2026
5254229
Align names with paper
jonas-lj Jan 23, 2026
534e681
Simplify'ish + refactor
jonas-lj Jan 23, 2026
7e2b9cd
Simplify a bit in new_reduced function
jonas-lj Jan 23, 2026
b7b88e6
more simplifications
jonas-lj Jan 23, 2026
033ea41
New precision loss calculation and delta check
arnab-roy Jan 28, 2026
e6163ae
Document and refactor super_swiper weight reduction logic
arnab-roy Jan 28, 2026
1f62c57
Updated t', f' constraints
arnab-roy Feb 3, 2026
9d0ec5b
Update beta and f' calculations
arnab-roy Feb 8, 2026
2d59d35
Updated the analysis and modified node.rs
arnab-roy Feb 14, 2026
20c38ae
Simplify super_swiper reduction and update tests
arnab-roy Mar 25, 2026
467c81c
Refine super_swiper weight reduction search
arnab-roy Mar 25, 2026
e6facf5
Update weight_reduction PROOF: bounds & params
arnab-roy Apr 14, 2026
9755d23
Update PROOF.md
arnab-roy Apr 14, 2026
928c573
Merge branch 'main' into arnab/swiper
arnab-roy Apr 14, 2026
c243bc7
Refactor super-swiper and weight reduction
arnab-roy Apr 14, 2026
b536200
Add new_reduced_v2 weight-reduction and tests
arnab-roy Apr 14, 2026
aa9a648
Add W vs W' comparison chart test
arnab-roy Apr 15, 2026
7d57f76
SuperSwiper: bilateral analysis and tests
arnab-roy Apr 30, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 37 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions fastcrypto-tbls/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ repository = "https://github.com/MystenLabs/fastcrypto"

[dependencies]
fastcrypto = { path = "../fastcrypto", features = ["aes"] }
num-rational = { version = "0.4.2", features = ["std"] }

rand.workspace = true
serde.workspace = true
Expand All @@ -28,6 +29,7 @@ serde-big-array = "0.5.1"
[dev-dependencies]
criterion = "0.5.1"
generic-tests = "0.1.2"
test-case = "3.3.1"

[[bench]]
name = "polynomial"
Expand Down
5 changes: 5 additions & 0 deletions fastcrypto-tbls/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod random_oracle;
pub mod tbls;
pub mod threshold_schnorr;
pub mod types;
pub mod weight_reduction;

// TODO: needs to use ecies_v1
// #[cfg(any(test, feature = "experimental"))]
Expand Down Expand Up @@ -59,3 +60,7 @@ pub mod nodes_tests;
#[cfg(test)]
#[path = "tests/nizk_tests.rs"]
pub mod nizk_tests;

#[cfg(test)]
#[path = "tests/super_swiper_test.rs"]
pub mod super_swiper_test;
132 changes: 132 additions & 0 deletions fastcrypto-tbls/src/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,13 @@

use crate::ecies_v1;
use crate::types::ShareIndex;
use crate::weight_reduction::solve;
use crate::weight_reduction::weight_reduction_checks::compute_precision_loss;
use fastcrypto::error::{FastCryptoError, FastCryptoResult};
use fastcrypto::groups::GroupElement;
use fastcrypto::hash::{Blake2b256, Digest, HashFunction};
use itertools::Itertools;
use num_rational::Ratio;
use serde::{Deserialize, Serialize};
use tracing::debug;

Expand Down Expand Up @@ -221,4 +225,132 @@ impl<G: GroupElement + Serialize> Nodes<G> {
new_t,
))
}

/// Create a new set of nodes using the super_swiper algorithm for weight reduction.
/// This uses the swiper algorithms from the `weight_reduction` directory.
///
/// # Parameters
/// - `nodes_vec`: Input nodes with weights
/// - `t`: Threshold (adversarial weight threshold in absolute terms)
/// - `allowed_delta`: Maximum allowed delta value
/// - `total_weight_lower_bound`: Minimum allowed total weight after reduction
///
/// # Returns
/// A tuple of (reduced Nodes, new threshold, beta numerator, beta denominator)
pub fn new_super_swiper_reduced(
nodes_vec: Vec<Node<G>>,
t: u16,
allowed_delta: u16,
total_weight_lower_bound: u16,
) -> FastCryptoResult<(Self, u16, Ratio<u64>)> {
let n = Self::new(nodes_vec)?;
let original_total_weight = n.total_weight() as u64;

// Validate total_weight_lower_bound (similar to new_reduced)
if total_weight_lower_bound > n.total_weight
|| total_weight_lower_bound == 0
|| original_total_weight == 0
{
return Err(FastCryptoError::InvalidInput);
}

let alpha = Ratio::new(t as u64, original_total_weight);

// Extract weights from nodes, sorted in descending order (required by super_swiper)
let weights_sorted = n
.nodes
.iter()
.map(|node| node.weight as u64)
.sorted()
.rev()
.collect_vec();

// Original weights for delta calculation (in original order)
let original_weights: Vec<u64> = n.nodes.iter().map(|node| node.weight as u64).collect();

// Map from sorted index back to original index (computed once, used in loop)
let indexed_weights: Vec<(usize, u16)> = n
.nodes
.iter()
.enumerate()
.map(|(i, node)| (i, node.weight))
.sorted_by_key(|(_, w)| *w)
.rev()
.collect_vec();

// Find the highest beta such that delta < allowed_delta
// Start high and decrease until constraint is met
let step = Ratio::new(1u64, 100u64);
let beta_min = alpha + step; // Minimum beta is alpha + 1/100
let beta_max = Ratio::new(1u64, 2u64); // Maximum beta is 1/2
let mut beta = beta_max;

loop {
if beta < beta_min {
return Err(FastCryptoError::InvalidInput);
}

let reduced_weights_sorted = solve(alpha, beta, &weights_sorted);
let new_total_weight: u64 = reduced_weights_sorted.iter().sum();

// Map reduced weights back to original order
let mut new_weights = vec![0u16; n.nodes.len()];
for (idx_in_sorted, (original_idx, _)) in indexed_weights.iter().enumerate() {
if idx_in_sorted < reduced_weights_sorted.len() {
new_weights[*original_idx] = reduced_weights_sorted[idx_in_sorted] as u16;
}
}

let reduced_weights: Vec<u64> = new_weights.iter().copied().map(u64::from).collect();

// Compute delta = sum(max(original[i] - reduced[i] * d, 0))
// where d = total_original / total_reduced (exact ratio)
let (delta, d) = compute_precision_loss(&original_weights, &reduced_weights);

// Check condition: (2*n+1)/3 + allowed_delta - delta >= 2 * beta * n - d
// where n = original_total_weight
let n_ratio = Ratio::from_integer(original_total_weight);
let two_n_plus_one = Ratio::from_integer(2 * original_total_weight + 1);
let left_side = two_n_plus_one / Ratio::from_integer(3)
+ Ratio::from_integer(allowed_delta as u64)
- delta;
let right_side = Ratio::from_integer(2u64) * beta * n_ratio - d;
let condition_met = left_side >= right_side;

let lower_bound_ok = new_total_weight >= total_weight_lower_bound as u64;

// If condition not met or lower bound not met, decrease beta
if !condition_met || !lower_bound_ok {
beta -= step;
continue;
}

// Success - build and return the result
let nodes = n
.nodes
.into_iter()
.zip(new_weights)
.map(|(Node { id, pk, weight: _ }, new_weight)| Node {
id,
pk,
weight: new_weight,
})
.collect_vec();

let accumulated_weights = Self::get_accumulated_weights(&nodes);
let nodes_with_nonzero_weight = Self::filter_nonzero_weights(&nodes);
let new_t = (beta * new_total_weight).to_integer() as u16;

return Ok((
Self {
nodes,
total_weight: new_total_weight as u16,
accumulated_weights,
nodes_with_nonzero_weight,
},
new_t,
beta,
));
}
}
}
Loading
Loading