diff --git a/eigentrust-cli/README.md b/eigentrust-cli/README.md index 2e70f991..8f75d506 100644 --- a/eigentrust-cli/README.md +++ b/eigentrust-cli/README.md @@ -105,6 +105,9 @@ The command-line interface was built using [clap.rs](http://clap.rs/). There is - `local-scores`: Uses locally stored attestation to calculate the global scores and stores them in the `scores.csv` file within the `assets` folder. - `scores`: Retrieve attestations and calculates the global scores and stores them in the `scores.csv` file within the `assets` folder. - `show`: Displays the `config.json` file. +- `th-proof`: Generates a threshold proof for the given ethereum address. +- `th-proving-key`: Generates the threshold circuit proving keys. +- `th-verify`: Verifies the generated threshold proof. - `update`: Updates the specified field in `config.json`. Takes the following options: - `--as-address`: Updates the address of the AttestationStation contract. @@ -135,6 +138,20 @@ The command-line interface was built using [clap.rs](http://clap.rs/). There is ./target/release/eigentrust-cli bandada --action add --ic 82918723982 --addr 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266 ``` +### Example of threshold proofs + +Threshold proofs are generated for a specific participant of the set, in this case we're assuming that you made an attestation with the examples given in this file. + +```bash +# Generate necessary files +./target/release/eigentrust-cli kzg-params --k 21 +./target/release/eigentrust-cli th-proving-key + +# Generate and verify proof +./target/release/eigentrust-cli th-proof --peer 0x70997970C51812dc3A010C7d01b50e0d17dc79C8 +./target/release/eigentrust-cli th-verify +``` + ## Configuration The configuration file is stored in `eigentrust-cli/assets/config.json`. You may need to update these parameters if, for example, the smart contracts are redeployed to new addresses or if you want to connect to a different Ethereum node. You can modify the following parameters: diff --git a/eigentrust-cli/src/cli.rs b/eigentrust-cli/src/cli.rs index 7533f89d..4df29de8 100644 --- a/eigentrust-cli/src/cli.rs +++ b/eigentrust-cli/src/cli.rs @@ -540,6 +540,16 @@ pub async fn handle_th_pk() -> Result<(), EigenError> { /// Handles threshold circuit proof generation. pub async fn handle_th_proof(data: ThProofData) -> Result<(), EigenError> { + // Validate peer argument + let peer_id = match data.peer { + Some(peer) => H160::from_str(&peer).map_err(|e| EigenError::ParsingError(e.to_string()))?, + None => { + return Err(EigenError::ValidationError( + "Missing argument 'peer': participant address.".to_string(), + )) + }, + }; + let config = load_config()?; let mnemonic = load_mnemonic(); let client = Client::new( @@ -557,23 +567,13 @@ pub async fn handle_th_proof(data: ThProofData) -> Result<(), EigenError> { let th_kzg_params = EigenFile::KzgParams(TH_PARAMS_K).load()?; let proving_key = EigenFile::ProvingKey(Circuit::Threshold).load()?; - // Parse peer id - let peer_id = match data.peer { - Some(peer) => peer.parse::().map_err(|e| EigenError::ParsingError(e.to_string()))?, - None => { - return Err(EigenError::ValidationError( - "Missing parameter 'peer': participant address.".to_string(), - )) - }, - }; - let report = client.generate_th_proof( attestations, et_kzg_params, th_kzg_params, proving_key, config.band_th.parse().unwrap(), - peer_id, + *peer_id.as_fixed_bytes(), )?; EigenFile::Proof(Circuit::Threshold).save(report.proof)?; diff --git a/eigentrust/src/lib.rs b/eigentrust/src/lib.rs index 402df994..804bf245 100644 --- a/eigentrust/src/lib.rs +++ b/eigentrust/src/lib.rs @@ -271,10 +271,11 @@ impl Client { /// Generates Threshold circuit proof for the selected participant. pub fn generate_th_proof( &self, att: Vec, raw_et_kzg_params: Vec, - raw_th_kzg_params: Vec, raw_proving_key: Vec, threshold: u32, participant_id: u32, + raw_th_kzg_params: Vec, raw_proving_key: Vec, threshold: u32, + participant: [u8; 20], ) -> Result { let rng = &mut thread_rng(); - let th_setup = self.th_circuit_setup(att, raw_et_kzg_params, threshold, participant_id)?; + let th_setup = self.th_circuit_setup(att, raw_et_kzg_params, threshold, participant)?; // Build kzg params and proving key let th_kzg_params = @@ -467,7 +468,7 @@ impl Client { /// Generates Threshold circuit proof for the selected participant pub fn th_circuit_setup( &self, att: Vec, raw_et_kzg_params: Vec, threshold: u32, - participant_id: u32, + participant: [u8; 20], ) -> Result { let rng = &mut thread_rng(); let et_setup = self.et_circuit_setup(att)?; @@ -478,8 +479,18 @@ impl Client { EigenError::ReadWriteError(format!("Failed to read ET KZG params: {}", e)) })?; + // Find participant in the set and get the id + let participant_address = Address::from(participant); + let id = et_setup.address_set.iter().position(|r| r == &participant_address).ok_or_else( + || { + EigenError::ValidationError(format!( + "Participant {} not found", + participant_address.to_string() + )) + }, + )?; + // Extract and prepare participant-specific data - let id = participant_id as usize; let p_address = et_setup.pub_inputs.participants[id]; let score = et_setup.pub_inputs.scores[id]; let rational_score = et_setup.rational_scores[id].clone(); @@ -546,7 +557,7 @@ impl Client { Ok(proving_key.to_bytes(SerdeFormat::Processed)) } - /// Generates new proving key for the Threshold circuit (not working) + /// Generates new proving key for the Threshold circuit pub fn generate_th_pk( &self, att: Vec, raw_et_kzg_params: Vec, raw_th_kzg_params: Vec, @@ -555,8 +566,9 @@ impl Client { ParamsKZG::::read(&mut raw_th_kzg_params.as_slice()).map_err(|e| { EigenError::ReadWriteError(format!("Failed to read TH KZG params: {}", e)) })?; + let participant = AttestationEth::from(att[0].clone().attestation).about.to_fixed_bytes(); let th_setup = - self.th_circuit_setup(att, raw_et_kzg_params, u32::default(), u32::default())?; + self.th_circuit_setup(att, raw_et_kzg_params, u32::default(), participant)?; info!("Generating proving key, this may take a while."); let start_time = Instant::now();