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

Commit

Permalink
feat: generate-proofs command & verify from file
Browse files Browse the repository at this point in the history
  • Loading branch information
brech1 committed Apr 19, 2023
1 parent 71b9635 commit f451aac
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 80 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
.DS_Store
/data/*-proof.json
/target
.DS_Store
50 changes: 29 additions & 21 deletions client/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,52 +16,58 @@ cargo install --path ./anvil --bins --locked --force

## Getting Started

If running the project locally, the first step is to spin up our local EVM blockchain with Anvil. This is achieved by running the `anvil` command:
If you want to use a local EVM blockchain, the first step is to spin up Anvil by running the `anvil` command:

```bash
anvil
```

This implementation has two main components, a client and a server. The first thing we want to run is the server, so we can calculate the global reputation scores from the attestations.
Otherwise you should configure the `node_url` data field of the `client-config.json` file in the `data` directory to point to the correct Ethereum node. There's more about this in the configuration section.

```bash
cd ./server
cargo run --release
```

The last step is running the client. The client has a command line interface implemented with [clap.rs](http://clap.rs/) that allows us to, among other things, deploy contracts and submit attestations.
Open a new terminal to start interacting with the client through the CLI. The first step is to compile and deploy the contracts. This is done by running the following commands:

```bash
cd ../client
cargo run --release -- compile-contracts
cargo run --release -- deploy-contracts
```

We can now submit attestations. The attestation data is stored in the `client-config.json` file in the `data` directory. We will explore more about this in the Configuration section.
The next step is submitting attestations. The attestation data is also stored in the `client-config.json`

```bash
cargo run --release -- attest
```

And we’re running! If everything went well, our server should be calculating the global scores for our reputation system.
It's now possible to calculate the global scores and generate a proof. This is done by running the `generate-proofs` command:

```bash
cargo run --release -- generate-proofs
```

This command will generate a proof and store it in the `data` directory. The final step is to verify it running the `verify` command:

```bash
cargo run --release -- verify
```

## CLI

The client's command-line interface was built using [clap.rs](http://clap.rs/). It provides the following functions:
The client's command-line interface was built using [clap.rs](http://clap.rs/). It provides the following command options:

- `attest`: Takes `ops` from the `client-config.json` file, signs it using `secret_key`, and submits it to the AttestationStation smart contract.
- `compile-contracts`: Compiles all the `.sol` and `.yul` contracts available in the `data` folder. For `.sol` contracts, it generates an ABI JSON file and a Rust binding file. For `.yul` smart contracts, it compiles Yul code into binary.
- `deploy-contracts`: Deploys all the contracts.
- `generate-proofs`: Calculates the global scores, generates the zk proof and stores it in `et-proof.json` at the `data` directory.
- `show`: Displays the `client-config.json` file.
- `update`: Updates the specified field in `client-config.json`. The argument must be passed as `[subcommand] "[new_value]"`. The available subcommands are:
- `as_address`: Updates the address of the AttestationStation contract.
- `mnemonic`: Updates the mnemonic for the Ethereum wallet.
- `mnemonic`: Updates the Ethereum wallet mnemonic phrase.
- `score`: Updates a selected peer score. e.g. `score "Alice 100"`.
- `node_url`: Updates the URL for the Ethereum node.
- `node_url`: Updates the Ethereum node URL.
- `sk`: Updates the secret_key. Both strings should be separated by a comma.
- `verify`: Fetches the proof from the server on `server_url` and submits the proof to ET Verifier on `et_verifier_wrapper_address`.
- `verify`: Verifies the latest zk proof generated by the `generate-proofs` command.

An example of the `update` command is:
### Example of `update` command

```bash
cargo run --release -- update score "Alice 100"
Expand All @@ -71,11 +77,13 @@ cargo run --release -- update score "Alice 100"

### Client

The client configuration is stored in `data/client-config.json`, which specifies the following parameters:
The client configuration is stored in `data/client-config.json` and specifies the following parameters:

- `ops`: Contains the peer scores for the entire group, currently fixed at five members.
- `secret_key`: An EdDSA secret key, is used to manage the EigenTrust sets.
- `as_address`: Address of the AttestationStation smart contract from which events are being fetched.
- `et_verifier_wrapper_address`: A verifier smart contract for the EigenTrust global scores proof.
- `mnemonic`: Mnemonic for an Ethereum wallet.
- `ethereum_node_url`: URL of the Ethereum node we are connecting to. This defaults to `127.0.0.1:8545` to run with a local `anvil` EVM blockchain.
- `secret_key`: EdDSA secret key, is used to manage the EigenTrust sets.
- `as_address`: AttestationStation smart contract address. This is the contract that will receive the attestations.
- `et_verifier_wrapper_address`: Verifier smart contract for the EigenTrust global scores zk proof.
- `mnemonic`: Ethereum wallet mnemonic phrase.
- `node_url`: URL of the Ethereum node we are connecting to. The default is `127.0.0.1:8545` to work with a local `anvil` EVM blockchain.

It's possible to configure these parameters manually or using the `update` subcommand of the client CLI.
8 changes: 4 additions & 4 deletions client/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ pub struct ClientConfig {
pub as_address: String,
pub et_verifier_wrapper_address: String,
pub mnemonic: String,
pub ethereum_node_url: String,
pub node_url: String,
}

pub struct Client {
Expand All @@ -68,7 +68,7 @@ pub struct Client {

impl Client {
pub fn new(config: ClientConfig, user_secrets_raw: Vec<[String; 3]>) -> Self {
let client = setup_client(&config.mnemonic, &config.ethereum_node_url);
let client = setup_client(&config.mnemonic, &config.node_url);
Self { client, config, user_secrets_raw }
}

Expand Down Expand Up @@ -210,7 +210,7 @@ mod test {
as_address: as_address_string,
et_verifier_wrapper_address: et_verifier_address_string,
mnemonic,
ethereum_node_url: node_url,
node_url,
};

let et_client = Client::new(config, user_secrets_raw);
Expand Down Expand Up @@ -247,7 +247,7 @@ mod test {
as_address: format!("{:?}", Address::default()),
et_verifier_wrapper_address: et_verifier_address_string,
mnemonic,
ethereum_node_url: node_url,
node_url,
};

let et_client = Client::new(config, user_secrets_raw);
Expand Down
53 changes: 15 additions & 38 deletions client/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use clap::{Args, Parser, Subcommand};
use eigen_trust_circuit::{
utils::{read_bytes_data, read_json_data, write_json_data},
Proof, ProofRaw,
ProofRaw,
};
use eigen_trust_client::{
manager::MANAGER_STORE,
manager::{Manager, MANAGER_STORE},
utils::{
compile_sol_contract, compile_yul_contracts, deploy_as, deploy_et_wrapper, deploy_verifier,
get_attestations, read_csv_data,
Expand Down Expand Up @@ -88,7 +88,7 @@ async fn main() {
println!("Finished compiling!");
},
Mode::DeployContracts => {
let deploy_res = deploy_as(&config.mnemonic, &config.ethereum_node_url).await;
let deploy_res = deploy_as(&config.mnemonic, &config.node_url).await;
if let Err(e) = deploy_res {
eprintln!("Failed to deploy the AttestationStation contract: {:?}", e);
return;
Expand All @@ -97,56 +97,33 @@ async fn main() {
println!("AttestationStation contract deployed. Address: {}", address);

let et_contract = read_bytes_data("et_verifier");
let deploy_res =
deploy_verifier(&config.mnemonic, &config.ethereum_node_url, et_contract).await;
let deploy_res = deploy_verifier(&config.mnemonic, &config.node_url, et_contract).await;
if let Err(e) = deploy_res {
eprintln!("Failed to deploy the EigenTrustVerifier contract: {:?}", e);
return;
}
let address = deploy_res.unwrap();
let wrapper_res =
deploy_et_wrapper(&config.mnemonic, &config.ethereum_node_url, address).await;
let wrapper_res = deploy_et_wrapper(&config.mnemonic, &config.node_url, address).await;
let w_addr = wrapper_res.unwrap();
println!("EtVerifierWrapper contract deployed. Address: {}", w_addr);
},
Mode::GenerateProof => {
let mut _proof: Proof =
Proof::from(ProofRaw { pub_ins: vec![[0; 32]], proof: vec![0] });
let attestations = get_attestations(&config).await.unwrap();

match mng_store.lock() {
Ok(mut manager) => {
manager.generate_initial_attestations();

for att in attestations {
manager.add_attestation(att).unwrap();
}

_proof = manager.calculate_proofs().unwrap();
},
Err(e) => {
println!("error: {:?}", e);
},
if let Ok(mut manager) = mng_store.lock() {
manager.generate_initial_attestations();
manager.add_attestations(attestations).unwrap();
manager.calculate_proofs().unwrap();
}

// TODO: Save proof to file
},
Mode::Show => {
println!("Client config:\n{:#?}", config);
},
Mode::Update(data) => {
if let Err(e) = config_update(&mut config, data, user_secrets_raw) {
eprintln!("Failed to update client configuration.\n{}", e);
} else {
println!("Client configuration updated.");
}
Mode::Show => println!("Client config:\n{:#?}", config),
Mode::Update(data) => match config_update(&mut config, data, user_secrets_raw) {
Ok(_) => println!("Client configuration updated."),
Err(e) => eprintln!("Failed to update client configuration.\n{}", e),
},
Mode::Verify => {
// TODO: Read proof from file
let proof: Proof = Proof::from(ProofRaw { pub_ins: vec![[0; 32]], proof: vec![0] });

let client = Client::new(config, user_secrets_raw);
client.verify(ProofRaw::from(proof)).await.unwrap();
client.verify(ProofRaw::from(Manager::get_last_proof().unwrap())).await.unwrap();
println!("Proof verified");
},
}
Expand Down Expand Up @@ -181,7 +158,7 @@ fn config_update(
Err(_) => return Err("Failed to parse mnemonic.".to_string()),
},
Config::NodeUrl => match Http::from_str(&data) {
Ok(_) => config.ethereum_node_url = data,
Ok(_) => config.node_url = data,
Err(_) => return Err("Failed to parse node url.".to_string()),
},
Config::Score => {
Expand Down
34 changes: 20 additions & 14 deletions client/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ use eigen_trust_circuit::{
plonk::ProvingKey,
poly::kzg::commitment::ParamsKZG,
},
utils::{keygen, read_params, to_short},
utils::{keygen, read_json_data, read_params, to_short, write_json_data},
verifier::gen_proof,
Proof,
Proof, ProofRaw,
};
use once_cell::sync::Lazy;
use rand::thread_rng;
Expand Down Expand Up @@ -72,15 +72,14 @@ pub const PUBLIC_KEYS: [&str; NUM_NEIGHBOURS] = [
/// The peer struct.
pub struct Manager {
attestations: HashMap<Scalar, Attestation>,
cached_proofs: Vec<Proof>,
params: ParamsKZG<Bn256>,
proving_key: ProvingKey<G1Affine>,
}

impl Manager {
/// Creates a new peer.
pub fn new(params: ParamsKZG<Bn256>, pk: ProvingKey<G1Affine>) -> Self {
Self { attestations: HashMap::new(), cached_proofs: Vec::new(), params, proving_key: pk }
Self { attestations: HashMap::new(), params, proving_key: pk }
}

/// Add a new attestation into the cache, by first calculating the hash of
Expand Down Expand Up @@ -130,6 +129,15 @@ impl Manager {
Ok(())
}

/// Adds multiple attestations
pub fn add_attestations(&mut self, atts: Vec<Attestation>) -> Result<(), EigenError> {
for att in atts {
self.add_attestation(att)?;
}

Ok(())
}

/// Get the attestation cached under the hash of the public key
pub fn get_attestation(&self, pk: &PublicKey) -> Result<&Attestation, EigenError> {
let pk_hash_inp = [pk.0.x, pk.0.y, Scalar::zero(), Scalar::zero(), Scalar::zero()];
Expand Down Expand Up @@ -192,19 +200,17 @@ impl Manager {

let proof = Proof { pub_ins, proof: proof_bytes };

self.cached_proofs.push(proof.clone());
write_json_data(ProofRaw::from(proof.clone()), "et-proof").unwrap();

Ok(proof)
}

/// Query the proof at the given index
pub fn get_proof(&self, index: usize) -> Result<Proof, EigenError> {
self.cached_proofs.get(index).ok_or(EigenError::ProofNotFound).cloned()
}

/// Query the last generated proof
pub fn get_last_proof(&self) -> Result<Proof, EigenError> {
self.get_proof(self.cached_proofs.len() - 1)
/// Get the last generated proof
pub fn get_last_proof() -> Result<Proof, EigenError> {
match read_json_data::<ProofRaw>("et-proof") {
Ok(proof_raw) => Ok(Proof::from(proof_raw)),
Err(_) => Err(EigenError::ProofNotFound),
}
}
}

Expand Down Expand Up @@ -242,7 +248,7 @@ mod test {
manager.generate_initial_attestations();
manager.calculate_proofs().unwrap();

let proof = manager.get_proof(0).unwrap();
let proof = Manager::get_last_proof().unwrap();
let scores = [Scalar::from_u128(INITIAL_SCORE); NUM_NEIGHBOURS];
assert_eq!(proof.pub_ins, scores);

Expand Down
2 changes: 1 addition & 1 deletion client/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ pub fn keyset_from_raw<const N: usize>(

/// Get the attestations from the contract
pub async fn get_attestations(config: &ClientConfig) -> Result<Vec<Attestation>, EigenError> {
let client = setup_client(&config.mnemonic, &config.ethereum_node_url);
let client = setup_client(&config.mnemonic, &config.node_url);
let filter = Filter::new()
.address(config.as_address.parse::<Address>().unwrap())
.event("AttestationCreated(address,address,bytes32,bytes)")
Expand Down
2 changes: 1 addition & 1 deletion data/client-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@
"as_address": "0x5fbdb2315678afecb367f032d93f642f64180aa3",
"et_verifier_wrapper_address": "0x9fe46736679d2d9a65f0992f2272de9f3c7fa6e0",
"mnemonic": "test test test test test test test test test test test junk",
"ethereum_node_url": "http://localhost:8545"
"node_url": "http://localhost:8545"
}

0 comments on commit f451aac

Please sign in to comment.