Skip to content
This repository has been archived by the owner on Nov 23, 2023. It is now read-only.

Commit

Permalink
feat: native threshold circuit (#347)
Browse files Browse the repository at this point in the history
  • Loading branch information
brech1 authored Sep 6, 2023
1 parent 9048c3c commit 1cab80b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 19 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

44 changes: 29 additions & 15 deletions eigentrust-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,35 +209,49 @@ pub async fn handle_bandada(config: &ClientConfig, data: BandadaData) -> Result<

match action {
Action::Add => {
// Create a CSVFileStorage for scores
let scores_storage = CSVFileStorage::<ScoreRecord>::new("scores.csv".into());

// Read scores from the CSV file using load method from the Storage trait
let scores = scores_storage.load()?;
// Load scores
let scores = CSVFileStorage::<ScoreRecord>::new("scores.csv".into()).load()?;

// Find the participant record
let participant_record = scores
.iter()
.find(|record| *record.peer_address().as_str() == *address)
.find(|record| record.peer_address().as_str() == address)
.ok_or(EigenError::ValidationError(
"Participant not found in score records.".to_string(),
))?;

let participant_score: u32 = participant_record.score_fr().parse().map_err(|_| {
EigenError::ParsingError("Failed to parse participant score.".to_string())
// Parse participant values with error handling
let participant_score = participant_record
.score_fr()
.parse()
.map_err(|_| EigenError::ParsingError("Failed to parse score.".to_string()))?;

let score_num = participant_record
.numerator()
.parse()
.map_err(|_| EigenError::ParsingError("Failed to parse numerator.".to_string()))?;

let score_den = participant_record.denominator().parse().map_err(|_| {
EigenError::ParsingError("Failed to parse denominator.".to_string())
})?;

let threshold: u32 = config
let threshold = config
.band_th
.parse()
.map_err(|_| EigenError::ParsingError("Failed to parse threshold.".to_string()))?;

if participant_score < threshold {
return Err(EigenError::ValidationError(
"Participant score is below the group threshold.".to_string(),
));
// Verify threshold
let pass_threshold =
Client::verify_threshold(participant_score, score_num, score_den, threshold);

if pass_threshold {
bandada_api.add_member(&config.band_id, identity_commitment).await?;
} else {
return Err(EigenError::ValidationError(format!(
"Participant score below threshold. Score {} < Threshold {}.",
participant_score, threshold
)));
}

bandada_api.add_member(&config.band_id, identity_commitment).await?;
},
Action::Remove => {
bandada_api.remove_member(&config.band_id, identity_commitment).await?;
Expand Down
1 change: 1 addition & 0 deletions eigentrust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ csv = "1.1"
ethers = "2.0.8"
log = "0.4.19"
rand = "0.8"
num-rational = "0.4.1"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
thiserror = "1.0.43"
Expand Down
26 changes: 22 additions & 4 deletions eigentrust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,8 @@ use att_station::{
use attestation::{AttestationEth, AttestationRaw, SignedAttestationRaw};
use eigentrust_zk::{
circuits::{
dynamic_sets::native::EigenTrustSet, PoseidonNativeHasher, PoseidonNativeSponge,
HASHER_WIDTH, MIN_PEER_COUNT, NUM_BITS, NUM_LIMBS,
dynamic_sets::native::EigenTrustSet, threshold::native::Threshold, PoseidonNativeHasher,
PoseidonNativeSponge, HASHER_WIDTH, MIN_PEER_COUNT, NUM_BITS, NUM_LIMBS,
},
ecdsa::native::{EcdsaKeypair, PublicKey, Signature},
halo2::halo2curves::{
Expand All @@ -89,6 +89,7 @@ use ethers::{
types::{Filter, Log, H256},
};
use log::{info, warn};
use num_rational::BigRational;
use serde::{Deserialize, Serialize};
use std::{
collections::{BTreeSet, HashMap},
Expand All @@ -102,9 +103,9 @@ const NUM_ITERATIONS: usize = 20;
/// Initial score for each participant before the algorithms is run.
const INITIAL_SCORE: u128 = 1000;
/// Number of limbs for representing big numbers in threshold checking.
const _NUM_DECIMAL_LIMBS: usize = 2;
const NUM_DECIMAL_LIMBS: usize = 2;
/// Number of digits of each limbs for threshold checking.
const _POWER_OF_TEN: usize = 72;
const POWER_OF_TEN: usize = 72;
/// Attestation domain value
const DOMAIN: u128 = 42;

Expand Down Expand Up @@ -417,6 +418,23 @@ impl Client {
pub fn get_signer(&self) -> Arc<ClientSigner> {
self.signer.clone()
}

/// Verifies if a participant's score surpasses the score threshold.
pub fn verify_threshold(score: u64, score_num: u64, score_den: u64, threshold: u64) -> bool {
let score_fr = Scalar::from(score);
let threshold_fr = Scalar::from(threshold);
let score_ratio = BigRational::new(score_num.into(), score_den.into());

let th_circuit: Threshold<
Scalar,
NUM_DECIMAL_LIMBS,
POWER_OF_TEN,
MAX_NEIGHBOURS,
INITIAL_SCORE,
> = Threshold::new(score_fr, score_ratio, threshold_fr);

th_circuit.check_threshold()
}
}

#[cfg(test)]
Expand Down

0 comments on commit 1cab80b

Please sign in to comment.