diff --git a/eigentrust-cli/assets/attestations.csv b/eigentrust-cli/assets/attestations.csv index 5bef0d66..0c73a628 100644 --- a/eigentrust-cli/assets/attestations.csv +++ b/eigentrust-cli/assets/attestations.csv @@ -1,2 +1,2 @@ about,domain,value,message,sig_r,sig_s,rec_id -0x70997970c51812dc3a010c7d01b50e0d17dc7668,0x0000000000000000000000000000000000000000,8,0x0000000000000000000000000000000000000000000000000000000000000000,0x274c5c01d85bbc9bf69f498d08ecca54f692ba2111910c35fb68e89f6a6de2a1,0x06215a213b4bf6a5b9608a7ac23d7f01e0a6e29b088df7d5a50ebd8d2896d03a,0 +0x70997970c51812dc3a010c7d01b50e0d17dc79c8,0x0000000000000000000000000000000000000000,5,0x0000000000000000000000000000000000000000000000000000000000000000,0x1cc60bf64279111e233842283422f63cc34235adb4622a905aa325b6c8c44c4f,0xefa0e00156ab25f681075542d005f82e4b53ecdedee9d776268c0d7e7f325a21,1 diff --git a/eigentrust-cli/assets/scores.csv b/eigentrust-cli/assets/scores.csv index cbc527b4..391741dc 100644 --- a/eigentrust-cli/assets/scores.csv +++ b/eigentrust-cli/assets/scores.csv @@ -1,5 +1,3 @@ peer_address,score_fr,numerator,denominator,score -0x70997970c51812dc3a010c7d01b50e0d17dc7666,0x268ac16f8598e86f93c3c0323f9d890b116e644167ea4b476dcc06209c0f274a,55358500,59049,937 -0x70997970c51812dc3a010c7d01b50e0d17dc7667,0x28aef48fc67971ad01291f460e61d68e24b76dd4fe8a94b62dec5ac09d96966f,59787100,59049,1012 -0x70997970c51812dc3a010c7d01b50e0d17dc7668,0x118ee6e67650e636dbb3abf4b50351211a41fe7a8cfe0124ec0b8a46a65a4e01,62001400,59049,1049 +0x70997970c51812dc3a010c7d01b50e0d17dc79c8,0x00000000000000000000000000000000000000000000000000000000000003e8,1000,1,1000 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266,0x00000000000000000000000000000000000000000000000000000000000003e8,1000,1,1000 diff --git a/eigentrust-zk/src/circuits/dynamic_sets/native.rs b/eigentrust-zk/src/circuits/dynamic_sets/native.rs index 41a56b71..eccbbdfc 100644 --- a/eigentrust-zk/src/circuits/dynamic_sets/native.rs +++ b/eigentrust-zk/src/circuits/dynamic_sets/native.rs @@ -7,7 +7,6 @@ use crate::{ FieldExt, Hasher, SpongeHasher, }; use halo2::halo2curves::CurveAffine; -use itertools::Itertools; use num_bigint::{BigInt, ToBigInt}; use num_rational::BigRational; use num_traits::{FromPrimitive, One, Zero}; @@ -51,6 +50,14 @@ where Self { attestation, signature } } + + /// Constructs a new empty attestation with about + pub fn empty_with_about(about: N, domain: N) -> Self { + let attestation = Attestation:: { about, domain, ..Default::default() }; + let signature = Signature { r: Integer::one(), s: Integer::one(), ..Default::default() }; + + Self { attestation, signature } + } } impl Default @@ -195,13 +202,28 @@ impl< &mut self, from: PublicKey, op: Vec>>, ) -> N { - let empty_att = SignedAttestation::empty(self.domain); - let op_unwrapped = op.iter().map(|x| x.clone().unwrap_or(empty_att.clone())).collect_vec(); - let op = Opinion::::new( - from, op_unwrapped, self.domain, + // Get participant set addresses + let set: Vec = self.set.iter().map(|&(addr, _)| addr).collect(); + + // Build the opinion group by unwrapping attestations and filling the empty ones with default values. + // Enumerating to keep track of the participant this opinion is about. + let opinion_group = op + .into_iter() + .enumerate() + .map(|(index, attestation)| { + attestation.unwrap_or_else(|| { + SignedAttestation::::empty_with_about( + set[index], self.domain, + ) + }) + }) + .collect(); + + // Build opinion from the opinion group and validate + let opinion = Opinion::::new( + from, opinion_group, self.domain, ); - let set = self.set.iter().map(|&(addr, _)| addr).collect(); - let (addr, scores, op_hash) = op.validate(set); + let (addr, scores, op_hash) = opinion.validate(set); self.ops.insert(addr, scores); diff --git a/eigentrust-zk/src/ecdsa/native.rs b/eigentrust-zk/src/ecdsa/native.rs index 54aedcda..54d5b5ec 100644 --- a/eigentrust-zk/src/ecdsa/native.rs +++ b/eigentrust-zk/src/ecdsa/native.rs @@ -96,18 +96,18 @@ where let rev_y: Vec = y.iter().rev().cloned().collect(); let pub_key = [rev_x, rev_y].concat(); - // Hash and get first 20 bytes. - let hashed_public_key = Keccak256::digest(&pub_key); - let address_slice = &Keccak256::digest(&pub_key)[hashed_public_key.len() - 20..]; + // Hash and get the last 20 bytes. + let pub_key_hash = Keccak256::digest(pub_key); + let address: &[u8] = &pub_key_hash[pub_key_hash.len() - 20..]; - // Build fixed-size array. - let mut address = [0u8; 32]; - address[..20].copy_from_slice(address_slice); + // Get little endian address + let le_address: Vec = address.iter().rev().cloned().collect(); - let mut address_bytes = ::Repr::default(); - address.as_ref().read_exact(address_bytes.as_mut()).unwrap(); + // Build fixed-size array. + let mut address = [0u8; 64]; + address[..20].copy_from_slice(&le_address); - N::from_repr(address_bytes).unwrap() + N::from_uniform_bytes(&address) } } diff --git a/eigentrust/src/attestation.rs b/eigentrust/src/attestation.rs index 280aa5f9..a58ee528 100644 --- a/eigentrust/src/attestation.rs +++ b/eigentrust/src/attestation.rs @@ -646,9 +646,13 @@ mod tests { let signed_attestation = SignedAttestationEth::new(attestation_eth, signature_eth); - // Replace with expected address - let expected_address_bytes = keypair.public_key.to_address().to_bytes(); - let expected_address = Address::from_slice(&expected_address_bytes[..20]); + // Create expected address + let le_address = keypair.public_key.to_address().to_bytes(); + let mut expected_address_bytes: [u8; 20] = [0; 20]; + expected_address_bytes.copy_from_slice(&le_address[0..20]); + expected_address_bytes.reverse(); + + let expected_address = Address::from(expected_address_bytes); let public_key = signed_attestation.recover_public_key().unwrap(); let address = address_from_ecdsa_key(&public_key); diff --git a/eigentrust/src/eth.rs b/eigentrust/src/eth.rs index 15c73516..037ab469 100644 --- a/eigentrust/src/eth.rs +++ b/eigentrust/src/eth.rs @@ -68,12 +68,9 @@ pub fn ecdsa_keypairs_from_mnemonic( /// Constructs an Ethereum address for the given ECDSA public key. pub fn address_from_ecdsa_key(pub_key: &ECDSAPublicKey) -> Address { - let address: Vec = pub_key.to_address().to_bytes().to_vec(); - - let mut address_array = [0; 20]; - address_array.copy_from_slice(&address[0..20]); - - Address::from(address_array) + let mut address_bytes = pub_key.to_address().to_bytes(); + address_bytes[..20].reverse(); + Address::from_slice(&address_bytes[0..20]) } /// Constructs a Scalar from the given Ethereum address. @@ -134,12 +131,16 @@ mod tests { hex::decode(address_str).expect("Decoding failed").try_into().expect("Wrong length"); let keypairs = ecdsa_keypairs_from_mnemonic(TEST_MNEMONIC, 1).unwrap(); - let recovered_address = keypairs[0].public_key.to_address().to_bytes().to_vec(); - let mut recovered_address_bytes: [u8; 20] = [0; 20]; - recovered_address_bytes.copy_from_slice(&recovered_address[0..20]); + // Get the little-endian address from the public key. + let le_address = keypairs[0].public_key.to_address().to_bytes(); + + // Convert the first 20 bytes of the little-endian address back to the original format. + let mut rec_address_bytes: [u8; 20] = [0; 20]; + rec_address_bytes.copy_from_slice(&le_address[0..20]); + rec_address_bytes.reverse(); - assert_eq!(recovered_address_bytes, expected_address_bytes); + assert_eq!(rec_address_bytes, expected_address_bytes); } #[test] diff --git a/eigentrust/src/lib.rs b/eigentrust/src/lib.rs index d335a1ab..22daa7ae 100644 --- a/eigentrust/src/lib.rs +++ b/eigentrust/src/lib.rs @@ -68,7 +68,6 @@ use eigentrust_zk::{ ecdsa::native::{EcdsaKeypair, PublicKey, Signature}, halo2::halo2curves::{ bn256, - ff::PrimeField, secp256k1::{Fq, Secp256k1Affine}, }, params::{ @@ -86,13 +85,14 @@ use ethers::{ prelude::EthDisplay, providers::{Http, Middleware, Provider}, signers::{coins_bip39::English, LocalWallet, MnemonicBuilder, Signer}, - types::{Filter, Log, H256}, + types::{Filter, Log, H160, H256}, }; use log::{info, warn}; use num_rational::BigRational; use serde::{Deserialize, Serialize}; use std::{ collections::{BTreeSet, HashMap}, + str::FromStr, sync::Arc, }; @@ -106,8 +106,6 @@ const INITIAL_SCORE: u128 = 1000; const NUM_DECIMAL_LIMBS: usize = 2; /// Number of digits of each limbs for threshold checking. const POWER_OF_TEN: usize = 72; -/// Attestation domain value -const DOMAIN: u128 = 42; /// Client Signer. pub type ClientSigner = SignerMiddleware, LocalWallet>; @@ -290,7 +288,11 @@ impl Client { attestation_matrix[attester_pos][attested_pos] = Some(signed_attestation_fr); } - let domain = Scalar::from_u128(DOMAIN); + // Build domain + let domain_bytes: H160 = H160::from_str(&self.config.domain) + .map_err(|e| EigenError::ParsingError(format!("Error parsing domain: {}", e)))?; + let domain = Scalar::from_bytes(H256::from(domain_bytes).as_fixed_bytes()).unwrap(); + // Initialize EigenTrustSet let mut eigen_trust_set = EigenTrustSet::< MAX_NEIGHBOURS, @@ -349,14 +351,18 @@ impl Client { let mut scalar = score_fr.to_bytes(); scalar.reverse(); + let num_bytes = score_rat.numer().to_bytes_be().1; + let den_bytes = score_rat.denom().to_bytes_be().1; + let score_bytes = score_rat.to_integer().to_bytes_be().1; + let mut numerator: [u8; 32] = [0; 32]; - numerator.copy_from_slice(score_rat.numer().to_bytes_be().1.as_slice()); + numerator[32 - num_bytes.len()..].copy_from_slice(&num_bytes); let mut denominator: [u8; 32] = [0; 32]; - denominator.copy_from_slice(score_rat.denom().to_bytes_be().1.as_slice()); + denominator[32 - den_bytes.len()..].copy_from_slice(&den_bytes); let mut score_hex: [u8; 32] = [0; 32]; - score_hex.copy_from_slice(score_rat.to_integer().to_bytes_be().1.as_slice()); + score_hex[32 - score_bytes.len()..].copy_from_slice(&score_bytes); Score { address, score_fr: scalar, score_rat: (numerator, denominator), score_hex } }) diff --git a/eigentrust/src/storage.rs b/eigentrust/src/storage.rs index b5f78c51..686d5e60 100644 --- a/eigentrust/src/storage.rs +++ b/eigentrust/src/storage.rs @@ -9,7 +9,7 @@ use crate::{ }; use csv::{ReaderBuilder, WriterBuilder}; use ethers::{ - types::{H160, H256}, + types::{H160, H256, U256}, utils::hex, }; use serde::Deserialize; @@ -132,11 +132,11 @@ impl ScoreRecord { /// Creates a new score record from a score. pub fn from_score(score: Score) -> Self { - let peer_address = Self::to_hex_string(&score.address, true); - let score_fr_hex = Self::to_hex_string(&score.score_fr, true); - let numerator = Self::to_hex_string(&score.score_rat.0, false); - let denominator = Self::to_hex_string(&score.score_rat.1, false); - let score_hex = Self::to_hex_string(&score.score_hex, true); + let peer_address = format!("0x{}", hex::encode(score.address)); + let score_fr_hex = format!("0x{}", hex::encode(score.score_fr)); + let numerator = U256::from_big_endian(&score.score_rat.0).to_string(); + let denominator = U256::from_big_endian(&score.score_rat.1).to_string(); + let score_hex = U256::from_big_endian(&score.score_hex).to_string(); Self::new( peer_address, score_fr_hex, numerator, denominator, score_hex, @@ -167,16 +167,6 @@ impl ScoreRecord { pub fn score(&self) -> &String { &self.score } - - /// Converts bytes to a hexadecimal string. - fn to_hex_string(bytes: &[u8], prefix: bool) -> String { - let hex_string = bytes.iter().map(|byte| format!("{:02x}", byte)).collect::(); - if prefix { - format!("0x{}", hex_string) - } else { - hex_string - } - } } /// Attestation record.