From 56b2b53014874d8320b64e73fa9a2996396038c2 Mon Sep 17 00:00:00 2001 From: ryardley Date: Fri, 27 Sep 2024 15:01:46 +1000 Subject: [PATCH 01/12] wip: contract rejecting params --- packages/ciphernode/core/src/events.rs | 66 +++++++++++++++++++ packages/ciphernode/core/src/evm_enclave.rs | 53 ++++++--------- packages/ciphernode/core/src/evm_listener.rs | 12 +++- packages/ciphernode/core/src/evm_utils.rs | 58 ++++++++++++++++ packages/ciphernode/core/src/lib.rs | 2 + .../ciphernode/enclave_node/src/bin/bfvgen.rs | 60 +++++++++++++++++ .../{test_encryptor.rs => fake_encrypt.rs} | 0 tests/basic_integration/lib/bfvgen.sh | 3 + tests/basic_integration/lib/fake_encrypt.sh | 2 +- tests/basic_integration/lib/prebuild.sh | 2 +- tests/basic_integration/test.sh | 4 +- 11 files changed, 225 insertions(+), 37 deletions(-) create mode 100644 packages/ciphernode/core/src/evm_utils.rs create mode 100644 packages/ciphernode/enclave_node/src/bin/bfvgen.rs rename packages/ciphernode/enclave_node/src/bin/{test_encryptor.rs => fake_encrypt.rs} (100%) create mode 100755 tests/basic_integration/lib/bfvgen.sh diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index 01dcbd95..684939b9 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -98,6 +98,10 @@ pub enum EnclaveEvent { id: EventId, data: CiphernodeRemoved, }, + EnclaveError { + id: EventId, + data: EnclaveError, + }, // CommitteeSelected, // OutputDecrypted, // CiphernodeRegistered, @@ -141,6 +145,7 @@ impl From for EventId { EnclaveEvent::CiphernodeSelected { id, .. } => id, EnclaveEvent::CiphernodeAdded { id, .. } => id, EnclaveEvent::CiphernodeRemoved { id, .. } => id, + EnclaveEvent::EnclaveError { id, .. } => id, } } } @@ -160,6 +165,13 @@ impl EnclaveEvent { } } +pub trait FromError +where + E: ToString, +{ + fn from_error(err_type: EnclaveErrorType, error: E) -> Self; +} + impl From for EnclaveEvent { fn from(data: KeyshareCreated) -> Self { EnclaveEvent::KeyshareCreated { @@ -240,6 +252,23 @@ impl From for EnclaveEvent { } } } + +impl From for EnclaveEvent { + fn from(data: EnclaveError) -> Self { + EnclaveEvent::EnclaveError { + id: EventId::from(data.clone()), + data: data.clone(), + } + } +} + +impl FromError for EnclaveEvent { + fn from_error(err_type: EnclaveErrorType, error: anyhow::Error) -> Self { + let error_event = EnclaveError::from_error(err_type, &error); + EnclaveEvent::from(error_event) + } +} + impl fmt::Display for EnclaveEvent { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str(&format!("{}({})", self.event_type(), self.get_id())) @@ -325,6 +354,43 @@ pub struct CiphernodeRemoved { pub num_nodes: usize, } + + +#[derive(Message, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +#[rtype(result = "()")] +pub struct EnclaveError { + pub err_type: EnclaveErrorType, + pub message: String, +} + +#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub enum EnclaveErrorType { + Evm, + KeyGeneration, + PublickeyAggregation, + IO, + PlaintextAggregation, + Decryption +} + +impl EnclaveError { + pub fn new(err_type: EnclaveErrorType, message: &str) -> Self { + Self { + err_type, + message: message.to_string(), + } + } +} + +impl FromError for EnclaveError { + fn from_error(err_type: EnclaveErrorType, error: E) -> Self { + Self { + err_type, + message: error.to_string(), + } + } +} + fn extract_enclave_event_name(s: &str) -> &str { let bytes = s.as_bytes(); for (i, &item) in bytes.iter().enumerate() { diff --git a/packages/ciphernode/core/src/evm_enclave.rs b/packages/ciphernode/core/src/evm_enclave.rs index 976b6acf..8ff0362d 100644 --- a/packages/ciphernode/core/src/evm_enclave.rs +++ b/packages/ciphernode/core/src/evm_enclave.rs @@ -1,16 +1,9 @@ -use std::sync::Arc; - use crate::{ - events, - evm_listener::{AddEventHandler, ContractEvent, StartListening}, - evm_manager::{AddListener, EvmContractManager}, - setup_crp_params, EnclaveEvent, EventBus, ParamsWithCrp, + decode_params, events, evm_listener::{AddEventHandler, ContractEvent, StartListening}, evm_manager::{AddListener, EvmContractManager}, DecodedParams, EnclaveEvent, EncodedBfvParamsWithCrp, EventBus }; use actix::Addr; use alloy::{primitives::Address, sol}; -use anyhow::Result; -use rand::SeedableRng; -use rand_chacha::ChaCha20Rng; +use anyhow::{anyhow, Context, Result}; sol! { #[derive(Debug)] @@ -45,37 +38,30 @@ sol! { ); } -impl From for events::E3Requested { - fn from(value: E3Requested) -> Self { - let _params_bytes = value.e3.e3ProgramParams; - // TODO: decode params bytes - // HACK: temp supply canned params: - // this is temporary parse this from params_bytes above - // We will parse the ABI encoded bytes and extract params - let ParamsWithCrp { +impl TryFrom<&E3Requested> for events::E3Requested { + type Error = anyhow::Error; + fn try_from(value: &E3Requested) -> Result { + let encoded_params = value.e3.e3ProgramParams.clone(); + let EncodedBfvParamsWithCrp { moduli, degree, plaintext_modulus, - crp_bytes, - .. - } = setup_crp_params( - &[0x3FFFFFFF000001], - 2048, - 1032193, - // HACK: This is required to be fixed in order to have the same CRP bytes which will be - // resolved once we are decrypting params from the contract - Arc::new(std::sync::Mutex::new(ChaCha20Rng::seed_from_u64(42))), - ); - events::E3Requested { + crp, + } = match decode_params(&encoded_params)? { + DecodedParams::WithCrp(data) => Ok(data), + DecodedParams::WithoutCrp(_) => Err(anyhow!("Params did not include a CRP")), + }?; + + Ok(events::E3Requested { moduli, plaintext_modulus, - degree, + degree: degree.try_into().unwrap(), threshold_m: value.e3.threshold[0] as usize, - crp: crp_bytes, + crp: crp.into(), // HACK: Following should be [u8;32] and not converted to u64 seed: value.e3.seed.try_into().unwrap_or_default(), // converting to u64 e3_id: value.e3Id.to_string().into(), - } + }) } } @@ -90,7 +76,10 @@ impl From for events::CiphertextOutputPublished { impl ContractEvent for E3Requested { fn process(&self, bus: Addr) -> Result<()> { - let data: events::E3Requested = self.clone().into(); + let data: events::E3Requested = self + .try_into() + .context("Could not parse E3Requested event")?; + bus.do_send(EnclaveEvent::from(data)); Ok(()) } diff --git a/packages/ciphernode/core/src/evm_listener.rs b/packages/ciphernode/core/src/evm_listener.rs index 7a631ebc..7e6b47b1 100644 --- a/packages/ciphernode/core/src/evm_listener.rs +++ b/packages/ciphernode/core/src/evm_listener.rs @@ -12,7 +12,7 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::sync::Arc; -use crate::EventBus; +use crate::{EnclaveError, EnclaveErrorType, EnclaveEvent, EventBus, FromError}; pub trait ContractEvent: Send + Sync + 'static { fn process(&self, bus: Addr) -> Result<()>; @@ -61,7 +61,15 @@ impl EvmEventListener { if let Some(topic0) = log.topic0() { if let Some(decoder) = self.handlers.get(topic0) { if let Ok(event) = decoder(log.clone()) { - event.process(self.bus.clone())?; + if let Err(err) = event.process(self.bus.clone()) { + // Send enclave error to bus + self.bus + .clone() + .do_send(EnclaveEvent::from_error( + EnclaveErrorType::Evm, + err, + )); + } } } } diff --git a/packages/ciphernode/core/src/evm_utils.rs b/packages/ciphernode/core/src/evm_utils.rs new file mode 100644 index 00000000..c2bfa9c1 --- /dev/null +++ b/packages/ciphernode/core/src/evm_utils.rs @@ -0,0 +1,58 @@ +use std::sync::{Arc, Mutex}; + +use alloy::{sol, sol_types::SolValue}; +use rand::SeedableRng; +use rand_chacha::ChaCha20Rng; +use anyhow::Result; +use crate::{setup_crp_params, ParamsWithCrp}; + +sol! { + struct EncodedBfvParams { + uint64[] moduli; + uint64 degree; + uint64 plaintext_modulus; + } + struct EncodedBfvParamsWithCrp { + uint64[] moduli; + uint64 degree; + uint64 plaintext_modulus; + bytes crp; + } +} + +pub fn abi_encode_params(moduli: Vec, degree: u64, plaintext_modulus: u64) -> Vec { + EncodedBfvParams::abi_encode(&EncodedBfvParams { + moduli, + degree, + plaintext_modulus, + }) +} + +pub fn abi_encode_params_crpgen(moduli: Vec, degree: u64, plaintext_modulus: u64) -> Vec { + let ParamsWithCrp { crp_bytes, .. } = setup_crp_params( + &moduli, + degree as usize, + plaintext_modulus, + Arc::new(Mutex::new(ChaCha20Rng::from_entropy())), + ); + + EncodedBfvParamsWithCrp::abi_encode(&EncodedBfvParamsWithCrp { + moduli: moduli.clone(), + degree, + plaintext_modulus, + crp: crp_bytes.into(), + }) +} +pub enum DecodedParams { + WithoutCrp(EncodedBfvParams), + WithCrp(EncodedBfvParamsWithCrp), +} + +pub fn decode_params(data: &[u8]) -> Result { + if let Ok(decoded) = EncodedBfvParamsWithCrp::abi_decode(data, false) { + Ok(DecodedParams::WithCrp(decoded)) + } else { + let decoded = EncodedBfvParams::abi_decode(data, false)?; + Ok(DecodedParams::WithoutCrp(decoded)) + } +} diff --git a/packages/ciphernode/core/src/lib.rs b/packages/ciphernode/core/src/lib.rs index e2d4ac42..3ffd3efc 100644 --- a/packages/ciphernode/core/src/lib.rs +++ b/packages/ciphernode/core/src/lib.rs @@ -25,6 +25,7 @@ mod public_key_writer; mod publickey_aggregator; mod sortition; mod utils; +mod evm_utils; // TODO: this is too permissive pub use actix::prelude::*; @@ -34,6 +35,7 @@ pub use data::*; pub use e3_request::*; pub use eventbus::*; pub use events::*; +pub use evm_utils::*; pub use fhe::*; pub use keyshare::*; pub use logger::*; diff --git a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs new file mode 100644 index 00000000..901f5d3e --- /dev/null +++ b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs @@ -0,0 +1,60 @@ +use std::{error::Error, num::ParseIntError, process}; +use alloy::sol; +use clap::{command, Parser}; +use enclave_core::{abi_encode_params, abi_encode_params_crpgen}; + +fn parse_hex(arg: &str) -> Result { + let without_prefix = arg.trim_start_matches("0x"); + u64::from_str_radix(without_prefix, 16) +} + +#[derive(Parser, Debug)] +#[command(author, version, about="Encodes BFV parameters whilst generating a random CRP", long_about = None)] +struct Args { + #[arg(short, long, required = true, value_parser = parse_hex,value_delimiter = ',')] + moduli: Vec, + + #[arg(short, long)] + degree: u64, + + #[arg(short, long = "plaintext-modulus")] + plaintext_modulus: u64, + + #[arg(short, long = "no-crp", help = "Skip the CRP generation")] + no_crp: bool, +} + +sol! { + struct EncodedBfvParams { + uint64[] moduli; + uint64 degree; + uint64 plaintext_modulus; + } + struct EncodedBfvParamsWithCrp { + uint64[] moduli; + uint64 degree; + uint64 plaintext_modulus; + bytes crp; + } +} + +fn main() -> Result<(), Box> { + let args = Args::parse(); + + if args.moduli.len() == 0 { + println!("Parameter `--moduli` must include at least one value"); + process::exit(1); + } + + let encoded = if args.no_crp { + abi_encode_params(args.moduli, args.degree, args.plaintext_modulus) + } else { + abi_encode_params_crpgen(args.moduli, args.degree, args.plaintext_modulus) + }; + + for byte in encoded { + print!("{:02x}", byte); + } + + Ok(()) +} diff --git a/packages/ciphernode/enclave_node/src/bin/test_encryptor.rs b/packages/ciphernode/enclave_node/src/bin/fake_encrypt.rs similarity index 100% rename from packages/ciphernode/enclave_node/src/bin/test_encryptor.rs rename to packages/ciphernode/enclave_node/src/bin/fake_encrypt.rs diff --git a/tests/basic_integration/lib/bfvgen.sh b/tests/basic_integration/lib/bfvgen.sh new file mode 100755 index 00000000..ff62f9e9 --- /dev/null +++ b/tests/basic_integration/lib/bfvgen.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo run --bin bfvgen -- "$@" diff --git a/tests/basic_integration/lib/fake_encrypt.sh b/tests/basic_integration/lib/fake_encrypt.sh index 416d868c..512a99ad 100755 --- a/tests/basic_integration/lib/fake_encrypt.sh +++ b/tests/basic_integration/lib/fake_encrypt.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo run --bin test_encryptor -- "$@" +cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo run --bin fake_encrypt -- "$@" diff --git a/tests/basic_integration/lib/prebuild.sh b/tests/basic_integration/lib/prebuild.sh index 26bd3b77..6a765c9c 100755 --- a/tests/basic_integration/lib/prebuild.sh +++ b/tests/basic_integration/lib/prebuild.sh @@ -1,3 +1,3 @@ #!/usr/bin/env sh -cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo build --bin test_encryptor --bin node --bin aggregator; +cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo build --bin fake_encrypt --bin node --bin aggregator; diff --git a/tests/basic_integration/test.sh b/tests/basic_integration/test.sh index 8080e6e0..a0cf35ec 100755 --- a/tests/basic_integration/test.sh +++ b/tests/basic_integration/test.sh @@ -120,7 +120,9 @@ yarn ciphernode:add --ciphernode-address $CIPHERNODE_ADDRESS_4 --network localho heading "Request Committee" -yarn committee:new --network localhost --duration 4 +PARAMS=0x$($SCRIPT_DIR/lib/bfvgen.sh --moduli 0x3FFFFFFF000001 --degree 2048 --plaintext-modulus 1032193) + +yarn committee:new --network localhost --duration 4 --e3-params "$PARAMS" waiton "$SCRIPT_DIR/output/pubkey.bin" From a602df62c8741300b1e84c38f4a0f9900fe39cc7 Mon Sep 17 00:00:00 2001 From: ryardley Date: Sat, 28 Sep 2024 09:55:34 +1000 Subject: [PATCH 02/12] params parsed in Fhe module --- packages/ciphernode/core/src/events.rs | 9 ++----- packages/ciphernode/core/src/evm_enclave.rs | 24 ++++++----------- packages/ciphernode/core/src/evm_utils.rs | 13 +-------- packages/ciphernode/core/src/fhe.rs | 27 ++++++++++++------- packages/ciphernode/core/src/utils.rs | 13 ++++++++- .../ciphernode/enclave_node/src/bin/bfvgen.rs | 24 +++-------------- 6 files changed, 43 insertions(+), 67 deletions(-) diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index 684939b9..cc051b2f 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -304,13 +304,8 @@ pub struct E3Requested { pub e3_id: E3id, pub threshold_m: usize, pub seed: u64, // Should actually be much larger eg [u8;32] - - // fhe params - pub moduli: Vec, - pub degree: usize, - pub plaintext_modulus: u64, - pub crp: Vec, - // threshold: usize, // TODO: + pub params: Vec, + // threshold: usize, // TODO: // computation_type: ??, // TODO: // execution_model_type: ??, // TODO: // input_deadline: ??, // TODO: diff --git a/packages/ciphernode/core/src/evm_enclave.rs b/packages/ciphernode/core/src/evm_enclave.rs index 8ff0362d..8d310a57 100644 --- a/packages/ciphernode/core/src/evm_enclave.rs +++ b/packages/ciphernode/core/src/evm_enclave.rs @@ -1,9 +1,12 @@ use crate::{ - decode_params, events, evm_listener::{AddEventHandler, ContractEvent, StartListening}, evm_manager::{AddListener, EvmContractManager}, DecodedParams, EnclaveEvent, EncodedBfvParamsWithCrp, EventBus + events, + evm_listener::{AddEventHandler, ContractEvent, StartListening}, + evm_manager::{AddListener, EvmContractManager}, + EnclaveEvent, EventBus, }; use actix::Addr; use alloy::{primitives::Address, sol}; -use anyhow::{anyhow, Context, Result}; +use anyhow::{Context, Result}; sol! { #[derive(Debug)] @@ -41,23 +44,12 @@ sol! { impl TryFrom<&E3Requested> for events::E3Requested { type Error = anyhow::Error; fn try_from(value: &E3Requested) -> Result { - let encoded_params = value.e3.e3ProgramParams.clone(); - let EncodedBfvParamsWithCrp { - moduli, - degree, - plaintext_modulus, - crp, - } = match decode_params(&encoded_params)? { - DecodedParams::WithCrp(data) => Ok(data), - DecodedParams::WithoutCrp(_) => Err(anyhow!("Params did not include a CRP")), - }?; + let params = value.e3.e3ProgramParams.to_vec(); + // let params = decode_params(&encoded_params)?; Ok(events::E3Requested { - moduli, - plaintext_modulus, - degree: degree.try_into().unwrap(), + params, threshold_m: value.e3.threshold[0] as usize, - crp: crp.into(), // HACK: Following should be [u8;32] and not converted to u64 seed: value.e3.seed.try_into().unwrap_or_default(), // converting to u64 e3_id: value.e3Id.to_string().into(), diff --git a/packages/ciphernode/core/src/evm_utils.rs b/packages/ciphernode/core/src/evm_utils.rs index c2bfa9c1..1dbdf37b 100644 --- a/packages/ciphernode/core/src/evm_utils.rs +++ b/packages/ciphernode/core/src/evm_utils.rs @@ -43,16 +43,5 @@ pub fn abi_encode_params_crpgen(moduli: Vec, degree: u64, plaintext_modulus crp: crp_bytes.into(), }) } -pub enum DecodedParams { - WithoutCrp(EncodedBfvParams), - WithCrp(EncodedBfvParamsWithCrp), -} -pub fn decode_params(data: &[u8]) -> Result { - if let Ok(decoded) = EncodedBfvParamsWithCrp::abi_decode(data, false) { - Ok(DecodedParams::WithCrp(decoded)) - } else { - let decoded = EncodedBfvParams::abi_decode(data, false)?; - Ok(DecodedParams::WithoutCrp(decoded)) - } -} + diff --git a/packages/ciphernode/core/src/fhe.rs b/packages/ciphernode/core/src/fhe.rs index be3189b7..75fbb7c3 100644 --- a/packages/ciphernode/core/src/fhe.rs +++ b/packages/ciphernode/core/src/fhe.rs @@ -1,4 +1,4 @@ -use crate::{ordered_set::OrderedSet, ActorFactory, E3Requested, EnclaveEvent}; +use crate::{ordered_set::OrderedSet, set_up_crp, ActorFactory, E3Requested, EnclaveEvent}; use anyhow::*; use fhe::{ bfv::{ @@ -6,7 +6,8 @@ use fhe::{ }, mbfv::{AggregateIter, CommonRandomPoly, DecryptionShare, PublicKeyShare}, }; -use fhe_traits::{DeserializeParametrized, FheDecoder, Serialize}; +use fhe_traits::{Deserialize, DeserializeParametrized, FheDecoder, Serialize}; +use rand::SeedableRng; use rand_chacha::ChaCha20Rng; use std::sync::{Arc, Mutex}; @@ -39,6 +40,13 @@ impl Fhe { Self { params, crp, rng } } + pub fn from_encoded(bytes: &[u8], seed: u64) -> Result { + let params = Arc::new(BfvParameters::try_deserialize(bytes)?); + let rng = Arc::new(Mutex::new(ChaCha20Rng::seed_from_u64(seed))); + let crp = set_up_crp(params.clone(), rng.clone()); + Ok(Fhe::new(params.clone(), crp, rng.clone())) + } + pub fn from_raw_params( moduli: &[u64], degree: usize, @@ -122,17 +130,16 @@ impl FheFactory { return; }; let E3Requested { - degree, - moduli, - plaintext_modulus, - crp, + // degree, + // moduli, + // plaintext_modulus, + // crp, + params, + seed, .. } = data; - ctx.fhe = Some(Arc::new( - Fhe::from_raw_params(&moduli, degree, plaintext_modulus, &crp, rng.clone()) - .unwrap(), - )); + ctx.fhe = Some(Arc::new(Fhe::from_encoded(¶ms, seed).unwrap())); }) } } diff --git a/packages/ciphernode/core/src/utils.rs b/packages/ciphernode/core/src/utils.rs index d56c1362..73b37191 100644 --- a/packages/ciphernode/core/src/utils.rs +++ b/packages/ciphernode/core/src/utils.rs @@ -1,9 +1,10 @@ use crate::SharedRng; +use anyhow::{Context, Result}; use fhe::{ bfv::{BfvParameters, BfvParametersBuilder}, mbfv::CommonRandomPoly, }; -use fhe_traits::Serialize; +use fhe_traits::{Deserialize, Serialize}; use std::{fs, io::Write, path::Path, sync::Arc}; pub struct ParamsWithCrp { @@ -44,6 +45,16 @@ pub fn setup_bfv_params( .unwrap() } +pub fn encode_bfv_params(moduli: Vec, degree: u64, plaintext_modulus: u64) -> Vec { + setup_bfv_params(&moduli, degree as usize, plaintext_modulus).to_bytes() +} + +pub fn decode_params(bytes: &[u8]) -> Result> { + Ok(Arc::new( + BfvParameters::try_deserialize(bytes).context("Could not decode Bfv Params")?, + )) +} + pub fn set_up_crp(params: Arc, rng: SharedRng) -> CommonRandomPoly { CommonRandomPoly::new(¶ms, &mut *rng.lock().unwrap()).unwrap() } diff --git a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs index 901f5d3e..74f7b518 100644 --- a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs +++ b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs @@ -1,7 +1,7 @@ -use std::{error::Error, num::ParseIntError, process}; use alloy::sol; use clap::{command, Parser}; -use enclave_core::{abi_encode_params, abi_encode_params_crpgen}; +use enclave_core::{abi_encode_params, abi_encode_params_crpgen, encode_bfv_params}; +use std::{error::Error, num::ParseIntError, process}; fn parse_hex(arg: &str) -> Result { let without_prefix = arg.trim_start_matches("0x"); @@ -24,20 +24,6 @@ struct Args { no_crp: bool, } -sol! { - struct EncodedBfvParams { - uint64[] moduli; - uint64 degree; - uint64 plaintext_modulus; - } - struct EncodedBfvParamsWithCrp { - uint64[] moduli; - uint64 degree; - uint64 plaintext_modulus; - bytes crp; - } -} - fn main() -> Result<(), Box> { let args = Args::parse(); @@ -46,11 +32,7 @@ fn main() -> Result<(), Box> { process::exit(1); } - let encoded = if args.no_crp { - abi_encode_params(args.moduli, args.degree, args.plaintext_modulus) - } else { - abi_encode_params_crpgen(args.moduli, args.degree, args.plaintext_modulus) - }; + let encoded = encode_bfv_params(args.moduli, args.degree, args.plaintext_modulus); for byte in encoded { print!("{:02x}", byte); From 9593d0dec635d378cd92bdbd372c487a671ab515 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 13:08:29 +1000 Subject: [PATCH 03/12] Use Seed for CRP --- .../ciphernode/core/src/committee_meta.rs | 4 +- packages/ciphernode/core/src/events.rs | 25 +++++- packages/ciphernode/core/src/evm_enclave.rs | 6 +- packages/ciphernode/core/src/fhe.rs | 28 +++--- packages/ciphernode/core/src/keyshare.rs | 88 ++++++++----------- packages/ciphernode/core/src/lib.rs | 51 ++++------- packages/ciphernode/core/src/logger.rs | 2 +- .../ciphernode/core/src/main_aggregator.rs | 7 +- .../ciphernode/core/src/main_ciphernode.rs | 8 +- .../core/src/plaintext_aggregator.rs | 7 +- .../core/src/publickey_aggregator.rs | 8 +- packages/ciphernode/core/src/sortition.rs | 10 +-- packages/evm/contracts/test/MockE3Program.sol | 4 +- 13 files changed, 118 insertions(+), 130 deletions(-) diff --git a/packages/ciphernode/core/src/committee_meta.rs b/packages/ciphernode/core/src/committee_meta.rs index 5cd42b57..603c6baa 100644 --- a/packages/ciphernode/core/src/committee_meta.rs +++ b/packages/ciphernode/core/src/committee_meta.rs @@ -1,9 +1,9 @@ -use crate::{ActorFactory, E3Requested, EnclaveEvent}; +use crate::{ActorFactory, E3Requested, EnclaveEvent, Seed}; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CommitteeMeta { pub threshold_m: usize, - pub seed: u64, + pub seed: Seed, } pub struct CommitteeMetaFactory; diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index cc051b2f..225bc568 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -2,9 +2,10 @@ use actix::Message; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{ - fmt, + fmt::{self, Display}, hash::{DefaultHasher, Hash, Hasher}, }; +use alloy::primitives::Uint; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct E3id(pub String); @@ -303,7 +304,7 @@ pub struct PublicKeyAggregated { pub struct E3Requested { pub e3_id: E3id, pub threshold_m: usize, - pub seed: u64, // Should actually be much larger eg [u8;32] + pub seed: Seed, // Should actually be much larger eg [u8;32] pub params: Vec, // threshold: usize, // TODO: // computation_type: ??, // TODO: @@ -358,6 +359,26 @@ pub struct EnclaveError { pub message: String, } +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct Seed(pub [u8;32]); +impl From for u64 { + fn from(value: Seed) -> Self { + u64::from_le_bytes(value.0[..8].try_into().unwrap()) + } +} + +impl From for [u8;32] { + fn from(value: Seed) -> Self { + value.0 + } +} + +impl From> for Seed { + fn from(value: Uint<256,4>) -> Self { + Seed(value.to_le_bytes()) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum EnclaveErrorType { Evm, diff --git a/packages/ciphernode/core/src/evm_enclave.rs b/packages/ciphernode/core/src/evm_enclave.rs index 8d310a57..ca1a3562 100644 --- a/packages/ciphernode/core/src/evm_enclave.rs +++ b/packages/ciphernode/core/src/evm_enclave.rs @@ -2,7 +2,7 @@ use crate::{ events, evm_listener::{AddEventHandler, ContractEvent, StartListening}, evm_manager::{AddListener, EvmContractManager}, - EnclaveEvent, EventBus, + EnclaveEvent, EventBus, Seed, }; use actix::Addr; use alloy::{primitives::Address, sol}; @@ -45,13 +45,11 @@ impl TryFrom<&E3Requested> for events::E3Requested { type Error = anyhow::Error; fn try_from(value: &E3Requested) -> Result { let params = value.e3.e3ProgramParams.to_vec(); - // let params = decode_params(&encoded_params)?; Ok(events::E3Requested { params, threshold_m: value.e3.threshold[0] as usize, - // HACK: Following should be [u8;32] and not converted to u64 - seed: value.e3.seed.try_into().unwrap_or_default(), // converting to u64 + seed: value.e3.seed.into(), e3_id: value.e3Id.to_string().into(), }) } diff --git a/packages/ciphernode/core/src/fhe.rs b/packages/ciphernode/core/src/fhe.rs index 75fbb7c3..2dee23d0 100644 --- a/packages/ciphernode/core/src/fhe.rs +++ b/packages/ciphernode/core/src/fhe.rs @@ -1,4 +1,4 @@ -use crate::{ordered_set::OrderedSet, set_up_crp, ActorFactory, E3Requested, EnclaveEvent}; +use crate::{ordered_set::OrderedSet, set_up_crp, ActorFactory, E3Requested, EnclaveEvent, Seed}; use anyhow::*; use fhe::{ bfv::{ @@ -40,10 +40,12 @@ impl Fhe { Self { params, crp, rng } } - pub fn from_encoded(bytes: &[u8], seed: u64) -> Result { + pub fn from_encoded(bytes: &[u8], seed: Seed, rng: SharedRng) -> Result { let params = Arc::new(BfvParameters::try_deserialize(bytes)?); - let rng = Arc::new(Mutex::new(ChaCha20Rng::seed_from_u64(seed))); - let crp = set_up_crp(params.clone(), rng.clone()); + let crp = set_up_crp( + params.clone(), + Arc::new(Mutex::new(ChaCha20Rng::from_seed(seed.into()))), + ); Ok(Fhe::new(params.clone(), crp, rng.clone())) } @@ -123,23 +125,17 @@ impl Fhe { pub struct FheFactory; impl FheFactory { - pub fn create(rng: Arc>) -> ActorFactory { + pub fn create(rng: SharedRng) -> ActorFactory { Box::new(move |ctx, evt| { // Saving the fhe on Committee Requested let EnclaveEvent::E3Requested { data, .. } = evt else { return; }; - let E3Requested { - // degree, - // moduli, - // plaintext_modulus, - // crp, - params, - seed, - .. - } = data; - - ctx.fhe = Some(Arc::new(Fhe::from_encoded(¶ms, seed).unwrap())); + let E3Requested { params, seed, .. } = data; + + ctx.fhe = Some(Arc::new( + Fhe::from_encoded(¶ms, seed, rng.clone()).unwrap(), + )); }) } } diff --git a/packages/ciphernode/core/src/keyshare.rs b/packages/ciphernode/core/src/keyshare.rs index 69f6aba6..eae84f2d 100644 --- a/packages/ciphernode/core/src/keyshare.rs +++ b/packages/ciphernode/core/src/keyshare.rs @@ -9,8 +9,8 @@ use crate::{ DecryptionshareCreated, Get, }; use actix::prelude::*; -use anyhow::Result; use anyhow::Context; +use anyhow::Result; pub struct Keyshare { fhe: Arc, @@ -47,26 +47,45 @@ impl Handler for Keyshare { } impl Handler for Keyshare { - type Result = ResponseFuture<()>; + type Result = (); fn handle(&mut self, event: CiphernodeSelected, _: &mut actix::Context) -> Self::Result { - let fhe = self.fhe.clone(); - let data = self.data.clone(); - let bus = self.bus.clone(); - let address = self.address.clone(); - Box::pin(async move { - on_ciphernode_selected(fhe, data, bus, event, address) - .await - .unwrap() - }) + let CiphernodeSelected { e3_id, .. } = event; + + // generate keyshare + // TODO: instead of unwrap we should broadcast an error on the event bus + let (sk, pubkey) = self.fhe.generate_keyshare().unwrap(); + + // TODO: decrypt from FHE actor + // save encrypted key against e3_id/sk + // reencrypt secretkey locally with env var - this is so we don't have to serialize a secret + // best practice would be as you boot up a node you enter in a configured password from + // which we derive a kdf which gets used to generate this key + self.data + .do_send(Insert(format!("{}/sk", e3_id).into(), sk)); + + // save public key against e3_id/pk + self.data + .do_send(Insert(format!("{}/pk", e3_id).into(), pubkey.clone())); + + // broadcast the KeyshareCreated message + let event = EnclaveEvent::from(KeyshareCreated { + pubkey, + e3_id, + node: self.address.clone(), + }); + self.bus.do_send(event); } } impl Handler for Keyshare { type Result = ResponseFuture<()>; - fn handle(&mut self, event: CiphertextOutputPublished, _: &mut actix::Context) -> Self::Result { - println!("Ciphernode::CiphertextOutputPublished"); + fn handle( + &mut self, + event: CiphertextOutputPublished, + _: &mut actix::Context, + ) -> Self::Result { let fhe = self.fhe.clone(); let data = self.data.clone(); let bus = self.bus.clone(); @@ -79,39 +98,6 @@ impl Handler for Keyshare { } } -async fn on_ciphernode_selected( - fhe: Arc, - data: Addr, - bus: Addr, - event: CiphernodeSelected, - address: String, -) -> Result<()> { - let CiphernodeSelected { e3_id, .. } = event; - - // generate keyshare - let (sk, pubkey) = fhe.generate_keyshare()?; - - // TODO: decrypt from FHE actor - // save encrypted key against e3_id/sk - // reencrypt secretkey locally with env var - this is so we don't have to serialize a secret - // best practice would be as you boot up a node you enter in a configured password from - // which we derive a kdf which gets used to generate this key - data.do_send(Insert(format!("{}/sk", e3_id).into(), sk)); - - // save public key against e3_id/pk - data.do_send(Insert(format!("{}/pk", e3_id).into(), pubkey.clone())); - - // broadcast the KeyshareCreated message - let event = EnclaveEvent::from(KeyshareCreated { - pubkey, - e3_id, - node: address, - }); - bus.do_send(event); - - Ok(()) -} - async fn on_decryption_requested( fhe: Arc, data: Addr, @@ -131,10 +117,12 @@ async fn on_decryption_requested( println!("\n\nDECRYPTING!\n\n"); - let decryption_share = fhe.decrypt_ciphertext(DecryptCiphertext { - ciphertext: ciphertext_output, - unsafe_secret, - }).context("error decrypting ciphertext")?; + let decryption_share = fhe + .decrypt_ciphertext(DecryptCiphertext { + ciphertext: ciphertext_output, + unsafe_secret, + }) + .context("error decrypting ciphertext")?; let event = EnclaveEvent::from(DecryptionshareCreated { e3_id, diff --git a/packages/ciphernode/core/src/lib.rs b/packages/ciphernode/core/src/lib.rs index 3ffd3efc..7df46bc4 100644 --- a/packages/ciphernode/core/src/lib.rs +++ b/packages/ciphernode/core/src/lib.rs @@ -12,6 +12,7 @@ mod evm_ciphernode_registry; mod evm_enclave; mod evm_listener; mod evm_manager; +mod evm_utils; mod fhe; mod keyshare; mod logger; @@ -25,7 +26,6 @@ mod public_key_writer; mod publickey_aggregator; mod sortition; mod utils; -mod evm_utils; // TODO: this is too permissive pub use actix::prelude::*; @@ -61,7 +61,8 @@ mod tests { utils::{setup_crp_params, ParamsWithCrp}, CiphernodeAdded, CiphernodeSelected, CiphertextOutputPublished, CommitteeMetaFactory, DecryptionshareCreated, E3RequestManager, FheFactory, KeyshareFactory, PlaintextAggregated, - PlaintextAggregatorFactory, PublicKeyAggregatorFactory, ResetHistory, SharedRng, Sortition, + PlaintextAggregatorFactory, PublicKeyAggregatorFactory, ResetHistory, Seed, SharedRng, + SimpleLogger, Sortition, }; use actix::prelude::*; use alloy::primitives::Address; @@ -79,12 +80,7 @@ mod tests { use tokio::{sync::mpsc::channel, time::sleep}; // Simulating a local node - async fn setup_local_ciphernode( - bus: Addr, - rng: SharedRng, - logging: bool, - addr: &str, - ) { + async fn setup_local_ciphernode(bus: Addr, rng:SharedRng, logging: bool, addr: &str) { // create data actor for saving data let data = Data::new(logging).start(); // TODO: Use a sled backed Data Actor @@ -94,7 +90,7 @@ mod tests { E3RequestManager::builder(bus.clone()) .add_hook(CommitteeMetaFactory::create()) - .add_hook(FheFactory::create(rng.clone())) + .add_hook(FheFactory::create(rng)) .add_hook(PublicKeyAggregatorFactory::create( bus.clone(), sortition.clone(), @@ -105,6 +101,8 @@ mod tests { )) .add_hook(KeyshareFactory::create(bus.clone(), data.clone(), addr)) .build(); + + SimpleLogger::attach(addr, bus.clone()); } fn generate_pk_share( @@ -121,8 +119,8 @@ mod tests { async fn test_public_key_aggregation_and_decryption() -> Result<()> { // Setup EventBus let bus = EventBus::new(true).start(); - let rng = Arc::new(std::sync::Mutex::new(ChaCha20Rng::seed_from_u64(42))); + let seed = Seed(ChaCha20Rng::seed_from_u64(123).get_seed()); let eth_addrs: Vec = (0..3) .map(|_| Address::from_slice(&rand::thread_rng().gen::<[u8; 20]>()).to_string()) @@ -135,16 +133,12 @@ mod tests { let e3_id = E3id::new("1234"); let ParamsWithCrp { - moduli, - degree, - plaintext_modulus, - crp_bytes, - params, + crp_bytes, params, .. } = setup_crp_params( &[0x3FFFFFFF000001], 2048, 1032193, - Arc::new(std::sync::Mutex::new(ChaCha20Rng::seed_from_u64(42))), + Arc::new(std::sync::Mutex::new(ChaCha20Rng::from_seed(seed.clone().into()))), ); let regevt_1 = EnclaveEvent::from(CiphernodeAdded { @@ -174,13 +168,9 @@ mod tests { let event = EnclaveEvent::from(E3Requested { e3_id: e3_id.clone(), threshold_m: 3, - seed: 123, - moduli: moduli.clone(), - degree, - plaintext_modulus, - crp: crp_bytes.clone(), + seed: seed.clone(), + params: params.to_bytes(), }); - // Send the computation requested event bus.send(event.clone()).await?; @@ -193,7 +183,6 @@ mod tests { let crpoly = CommonRandomPoly::deserialize(&crp_bytes.clone(), ¶ms)?; - // Passing rng through function chain to ensure it matches usage in system above let (p1, sk1) = generate_pk_share(params.clone(), crpoly.clone(), rng_test.clone())?; let (p2, sk2) = generate_pk_share(params.clone(), crpoly.clone(), rng_test.clone())?; let (p3, sk3) = generate_pk_share(params.clone(), crpoly.clone(), rng_test.clone())?; @@ -212,11 +201,8 @@ mod tests { EnclaveEvent::from(E3Requested { e3_id: e3_id.clone(), threshold_m: 3, - seed: 123, - moduli, - degree, - plaintext_modulus, - crp: crp_bytes, + seed: seed.clone(), + params: params.to_bytes() }), EnclaveEvent::from(CiphernodeSelected { e3_id: e3_id.clone(), @@ -378,6 +364,8 @@ mod tests { #[actix::test] async fn test_p2p_actor_forwards_events_to_bus() -> Result<()> { + let seed = Seed(ChaCha20Rng::seed_from_u64(123).get_seed()); + // Setup elements in test let (tx, _) = channel(100); // Transmit byte events to the network let (input, rx) = channel(100); // Receive byte events from the network @@ -388,11 +376,8 @@ mod tests { let event = EnclaveEvent::from(E3Requested { e3_id: E3id::new("1235"), threshold_m: 3, - seed: 123, - moduli: vec![0x3FFFFFFF000001], - degree: 2048, - plaintext_modulus: 1032193, - crp: vec![1, 2, 3, 4], + seed: seed.clone(), + params: vec![1, 2, 3, 4], }); // lets send an event from the network diff --git a/packages/ciphernode/core/src/logger.rs b/packages/ciphernode/core/src/logger.rs index 6cb5c104..2a6f8bba 100644 --- a/packages/ciphernode/core/src/logger.rs +++ b/packages/ciphernode/core/src/logger.rs @@ -43,7 +43,7 @@ impl Handler for SimpleLogger { println!("[{}]: CiphernodeAdded({})", self.name, data.address); }, EnclaveEvent::E3Requested { data,.. } => { - println!("[{}]: E3Requested(e3_id: {}, threshold_m: {} , seed: {})", self.name, data.e3_id, data.threshold_m, data.seed) + println!("[{}]: E3Requested(e3_id: {}, threshold_m: {} , seed: {:?})", self.name, data.e3_id, data.threshold_m, data.seed); } _ => println!("[{}]: {}", self.name, msg), } diff --git a/packages/ciphernode/core/src/main_aggregator.rs b/packages/ciphernode/core/src/main_aggregator.rs index a7ab5a15..bb25d0ad 100644 --- a/packages/ciphernode/core/src/main_aggregator.rs +++ b/packages/ciphernode/core/src/main_aggregator.rs @@ -43,18 +43,19 @@ impl MainAggregator { pubkey_write_path: Option<&str>, plaintext_write_path: Option<&str>, ) -> (Addr, JoinHandle<()>) { + let bus = EventBus::new(true).start(); let rng = Arc::new(Mutex::new( rand_chacha::ChaCha20Rng::from_rng(OsRng).expect("Failed to create RNG"), )); - let bus = EventBus::new(true).start(); + let sortition = Sortition::attach(bus.clone()); connect_evm_enclave(bus.clone(), rpc_url, enclave_contract).await; - connect_evm_ciphernode_registry(bus.clone(), rpc_url, registry_contract).await; + let _ = connect_evm_ciphernode_registry(bus.clone(), rpc_url, registry_contract).await; let e3_manager = E3RequestManager::builder(bus.clone()) .add_hook(CommitteeMetaFactory::create()) - .add_hook(FheFactory::create(rng.clone())) + .add_hook(FheFactory::create(rng)) .add_hook(PublicKeyAggregatorFactory::create( bus.clone(), sortition.clone(), diff --git a/packages/ciphernode/core/src/main_ciphernode.rs b/packages/ciphernode/core/src/main_ciphernode.rs index 027f5c7f..81a09095 100644 --- a/packages/ciphernode/core/src/main_ciphernode.rs +++ b/packages/ciphernode/core/src/main_ciphernode.rs @@ -2,8 +2,8 @@ use std::sync::{Arc, Mutex}; use crate::{ evm_ciphernode_registry::connect_evm_ciphernode_registry, evm_enclave::connect_evm_enclave, - KeyshareFactory, CiphernodeSelector, CommitteeMetaFactory, Data, E3RequestManager, EventBus, - FheFactory, P2p, SimpleLogger, Sortition, + CiphernodeSelector, CommitteeMetaFactory, Data, E3RequestManager, EventBus, FheFactory, + KeyshareFactory, P2p, SimpleLogger, Sortition, }; use actix::{Actor, Addr, Context}; use alloy::primitives::Address; @@ -61,11 +61,11 @@ impl MainCiphernode { CiphernodeSelector::attach(bus.clone(), sortition.clone(), &address.to_string()); connect_evm_enclave(bus.clone(), rpc_url, enclave_contract).await; - connect_evm_ciphernode_registry(bus.clone(), rpc_url, registry_contract).await; + let _ = connect_evm_ciphernode_registry(bus.clone(), rpc_url, registry_contract).await; let e3_manager = E3RequestManager::builder(bus.clone()) .add_hook(CommitteeMetaFactory::create()) - .add_hook(FheFactory::create(rng.clone())) + .add_hook(FheFactory::create(rng)) .add_hook(KeyshareFactory::create( bus.clone(), data.clone(), diff --git a/packages/ciphernode/core/src/plaintext_aggregator.rs b/packages/ciphernode/core/src/plaintext_aggregator.rs index 14d37000..3d78fb0b 100644 --- a/packages/ciphernode/core/src/plaintext_aggregator.rs +++ b/packages/ciphernode/core/src/plaintext_aggregator.rs @@ -1,8 +1,7 @@ use std::sync::Arc; use crate::{ - ordered_set::OrderedSet, ActorFactory, DecryptionshareCreated, E3id, EnclaveEvent, EventBus, - Fhe, GetAggregatePlaintext, GetHasNode, PlaintextAggregated, Sortition, + ordered_set::OrderedSet, ActorFactory, DecryptionshareCreated, E3id, EnclaveEvent, EventBus, Fhe, GetAggregatePlaintext, GetHasNode, PlaintextAggregated, Seed, Sortition }; use actix::prelude::*; use anyhow::Result; @@ -12,7 +11,7 @@ pub enum PlaintextAggregatorState { Collecting { threshold_m: usize, shares: OrderedSet>, - seed: u64, + seed: Seed, ciphertext_output: Vec, }, Computing { @@ -47,7 +46,7 @@ impl PlaintextAggregator { sortition: Addr, e3_id: E3id, threshold_m: usize, - seed: u64, + seed: Seed, ciphertext_output: Vec, ) -> Self { PlaintextAggregator { diff --git a/packages/ciphernode/core/src/publickey_aggregator.rs b/packages/ciphernode/core/src/publickey_aggregator.rs index 6222057c..ba17b34c 100644 --- a/packages/ciphernode/core/src/publickey_aggregator.rs +++ b/packages/ciphernode/core/src/publickey_aggregator.rs @@ -5,7 +5,7 @@ use crate::{ events::{E3id, EnclaveEvent, KeyshareCreated, PublicKeyAggregated}, fhe::{Fhe, GetAggregatePublicKey}, ordered_set::OrderedSet, - ActorFactory, GetHasNode, Sortition, + ActorFactory, GetHasNode, Seed, Sortition, }; use actix::prelude::*; use anyhow::Result; @@ -15,7 +15,7 @@ pub enum PublicKeyAggregatorState { Collecting { threshold_m: usize, keyshares: OrderedSet>, - seed: u64, + seed: Seed, }, Computing { keyshares: OrderedSet>, @@ -53,7 +53,7 @@ impl PublicKeyAggregator { sortition: Addr, e3_id: E3id, threshold_m: usize, - seed: u64, + seed: Seed, ) -> Self { PublicKeyAggregator { fhe, @@ -192,7 +192,7 @@ impl Handler for PublicKeyAggregator { // Return Ok(()) } -} +} pub struct PublicKeyAggregatorFactory; impl PublicKeyAggregatorFactory { diff --git a/packages/ciphernode/core/src/sortition.rs b/packages/ciphernode/core/src/sortition.rs index edbf942f..d82b2913 100644 --- a/packages/ciphernode/core/src/sortition.rs +++ b/packages/ciphernode/core/src/sortition.rs @@ -3,18 +3,18 @@ use std::collections::HashSet; use actix::prelude::*; use sortition::DistanceSortition; -use crate::{CiphernodeAdded, CiphernodeRemoved, EnclaveEvent, EventBus, Subscribe}; +use crate::{CiphernodeAdded, CiphernodeRemoved, EnclaveEvent, EventBus, Seed, Subscribe}; #[derive(Message, Clone, Debug, PartialEq, Eq)] #[rtype(result = "bool")] pub struct GetHasNode { - pub seed: u64, + pub seed: Seed, pub address: String, pub size: usize, } pub trait SortitionList { - fn contains(&self, seed: u64, size: usize, address: T) -> bool; + fn contains(&self, seed: Seed, size: usize, address: T) -> bool; fn add(&mut self, address: T); fn remove(&mut self, address: T); } @@ -38,9 +38,9 @@ impl Default for SortitionModule { } impl SortitionList for SortitionModule { - fn contains(&self, seed: u64, size: usize, address: String) -> bool { + fn contains(&self, seed: Seed, size: usize, address: String) -> bool { DistanceSortition::new( - seed, + seed.into(), self.nodes .clone() .into_iter() diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index d6531305..c19365ab 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -17,12 +17,12 @@ contract MockE3Program is IE3Program { returns (bytes32 encryptionSchemeId, IInputValidator inputValidator) { require( - e3ProgramParams.length == 32 && computeProviderParams.length == 32, + e3ProgramParams.length == 19 && computeProviderParams.length == 32, invalidParams(e3ProgramParams, computeProviderParams) ); // solhint-disable no-inline-assembly assembly { - inputValidator := mload(add(e3ProgramParams, 32)) + inputValidator := mload(add(e3ProgramParams, 19)) } encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; } From 0c6eab734890f284c7074a8bcab15f567a98bcb8 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 15:20:51 +1000 Subject: [PATCH 04/12] Encode address with fhe program params in e3ProgramParams --- packages/evm/contracts/test/MockE3Program.sol | 11 ++++++----- packages/evm/test/Enclave.spec.ts | 10 +++++----- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index c19365ab..846d048e 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -17,13 +17,14 @@ contract MockE3Program is IE3Program { returns (bytes32 encryptionSchemeId, IInputValidator inputValidator) { require( - e3ProgramParams.length == 19 && computeProviderParams.length == 32, + computeProviderParams.length == 32, invalidParams(e3ProgramParams, computeProviderParams) ); - // solhint-disable no-inline-assembly - assembly { - inputValidator := mload(add(e3ProgramParams, 19)) - } + (inputValidator, ) = abi.decode( + e3ProgramParams, + (IInputValidator, bytes) + ); + encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; } diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 9348802b..7143a5c8 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -80,8 +80,8 @@ describe("Enclave", function () { duration: time.duration.days(30), e3Program: await e3Program.getAddress(), e3ProgramParams: abiCoder.encode( - ["address"], - [await inputValidator.getAddress()], + ["address", "bytes"], + [await inputValidator.getAddress(), "0x12345678"], ), computeProviderParams: abiCoder.encode( ["address"], @@ -209,7 +209,7 @@ describe("Enclave", function () { expect(e3.e3Program).to.equal(request.e3Program); expect(e3.e3ProgramParams).to.equal(request.e3ProgramParams); expect(e3.inputValidator).to.equal( - abiCoder.decode(["address"], request.e3ProgramParams)[0], + abiCoder.decode(["address", "bytes"], request.e3ProgramParams)[0], ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], @@ -533,7 +533,7 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - ZeroHash, + abiCoder.encode(['address','bytes'],[ethers.ZeroAddress, ZeroHash]), request.computeProviderParams, { value: 10 }, ), @@ -551,7 +551,7 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - ZeroHash, + abiCoder.encode(['address','bytes'],[ethers.ZeroAddress, ZeroHash]), request.computeProviderParams, { value: 10 }, ), From e66ab8573353c71db250e79c81d125a33177251f Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 16:29:27 +1000 Subject: [PATCH 05/12] Decoding evm events in ciphernode --- packages/ciphernode/core/src/evm_enclave.rs | 15 +- packages/ciphernode/core/src/evm_utils.rs | 47 ----- packages/ciphernode/core/src/lib.rs | 2 - .../ciphernode/enclave_node/src/bin/bfvgen.rs | 3 +- packages/evm/contracts/test/MockE3Program.sol | 4 +- packages/evm/test/Enclave.spec.ts | 198 +++++++++--------- tests/.gitignore | 1 + .../lib/encode_e3_params.mjs | 23 ++ tests/basic_integration/test.sh | 7 +- tests/package.json | 10 + tests/yarn.lock | 50 +++++ 11 files changed, 202 insertions(+), 158 deletions(-) delete mode 100644 packages/ciphernode/core/src/evm_utils.rs create mode 100644 tests/.gitignore create mode 100755 tests/basic_integration/lib/encode_e3_params.mjs create mode 100644 tests/package.json create mode 100644 tests/yarn.lock diff --git a/packages/ciphernode/core/src/evm_enclave.rs b/packages/ciphernode/core/src/evm_enclave.rs index ca1a3562..bd2026db 100644 --- a/packages/ciphernode/core/src/evm_enclave.rs +++ b/packages/ciphernode/core/src/evm_enclave.rs @@ -2,13 +2,18 @@ use crate::{ events, evm_listener::{AddEventHandler, ContractEvent, StartListening}, evm_manager::{AddListener, EvmContractManager}, - EnclaveEvent, EventBus, Seed, + EnclaveEvent, EventBus, }; use actix::Addr; -use alloy::{primitives::Address, sol}; +use alloy::{primitives::Address, sol, sol_types::SolValue}; use anyhow::{Context, Result}; sol! { + struct EncodedE3ProgramParams { + bytes params; + address input_validator; + } + #[derive(Debug)] struct E3 { uint256 seed; @@ -44,10 +49,10 @@ sol! { impl TryFrom<&E3Requested> for events::E3Requested { type Error = anyhow::Error; fn try_from(value: &E3Requested) -> Result { - let params = value.e3.e3ProgramParams.to_vec(); - + let program_params = value.e3.e3ProgramParams.to_vec(); + let decoded = EncodedE3ProgramParams::abi_decode(&program_params, true)?; Ok(events::E3Requested { - params, + params: decoded.params.into(), threshold_m: value.e3.threshold[0] as usize, seed: value.e3.seed.into(), e3_id: value.e3Id.to_string().into(), diff --git a/packages/ciphernode/core/src/evm_utils.rs b/packages/ciphernode/core/src/evm_utils.rs deleted file mode 100644 index 1dbdf37b..00000000 --- a/packages/ciphernode/core/src/evm_utils.rs +++ /dev/null @@ -1,47 +0,0 @@ -use std::sync::{Arc, Mutex}; - -use alloy::{sol, sol_types::SolValue}; -use rand::SeedableRng; -use rand_chacha::ChaCha20Rng; -use anyhow::Result; -use crate::{setup_crp_params, ParamsWithCrp}; - -sol! { - struct EncodedBfvParams { - uint64[] moduli; - uint64 degree; - uint64 plaintext_modulus; - } - struct EncodedBfvParamsWithCrp { - uint64[] moduli; - uint64 degree; - uint64 plaintext_modulus; - bytes crp; - } -} - -pub fn abi_encode_params(moduli: Vec, degree: u64, plaintext_modulus: u64) -> Vec { - EncodedBfvParams::abi_encode(&EncodedBfvParams { - moduli, - degree, - plaintext_modulus, - }) -} - -pub fn abi_encode_params_crpgen(moduli: Vec, degree: u64, plaintext_modulus: u64) -> Vec { - let ParamsWithCrp { crp_bytes, .. } = setup_crp_params( - &moduli, - degree as usize, - plaintext_modulus, - Arc::new(Mutex::new(ChaCha20Rng::from_entropy())), - ); - - EncodedBfvParamsWithCrp::abi_encode(&EncodedBfvParamsWithCrp { - moduli: moduli.clone(), - degree, - plaintext_modulus, - crp: crp_bytes.into(), - }) -} - - diff --git a/packages/ciphernode/core/src/lib.rs b/packages/ciphernode/core/src/lib.rs index 7df46bc4..678cc561 100644 --- a/packages/ciphernode/core/src/lib.rs +++ b/packages/ciphernode/core/src/lib.rs @@ -12,7 +12,6 @@ mod evm_ciphernode_registry; mod evm_enclave; mod evm_listener; mod evm_manager; -mod evm_utils; mod fhe; mod keyshare; mod logger; @@ -35,7 +34,6 @@ pub use data::*; pub use e3_request::*; pub use eventbus::*; pub use events::*; -pub use evm_utils::*; pub use fhe::*; pub use keyshare::*; pub use logger::*; diff --git a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs index 74f7b518..e23fc091 100644 --- a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs +++ b/packages/ciphernode/enclave_node/src/bin/bfvgen.rs @@ -1,6 +1,5 @@ -use alloy::sol; use clap::{command, Parser}; -use enclave_core::{abi_encode_params, abi_encode_params_crpgen, encode_bfv_params}; +use enclave_core::encode_bfv_params; use std::{error::Error, num::ParseIntError, process}; fn parse_hex(arg: &str) -> Result { diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index 846d048e..dfae54bf 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -20,9 +20,9 @@ contract MockE3Program is IE3Program { computeProviderParams.length == 32, invalidParams(e3ProgramParams, computeProviderParams) ); - (inputValidator, ) = abi.decode( + (,inputValidator) = abi.decode( e3ProgramParams, - (IInputValidator, bytes) + (bytes, IInputValidator) ); encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index 7143a5c8..a68a9e79 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -35,7 +35,7 @@ const proof = "0x1337"; // Hash function used to compute the tree nodes. const hash = (a: bigint, b: bigint) => poseidon2([a, b]); -describe("Enclave", function () { +describe("Enclave", function() { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); @@ -80,8 +80,8 @@ describe("Enclave", function () { duration: time.duration.days(30), e3Program: await e3Program.getAddress(), e3ProgramParams: abiCoder.encode( - ["address", "bytes"], - [await inputValidator.getAddress(), "0x12345678"], + ["bytes", "address"], + ["0x12345678", await inputValidator.getAddress()], ), computeProviderParams: abiCoder.encode( ["address"], @@ -91,43 +91,43 @@ describe("Enclave", function () { }; } - describe("constructor / initialize()", function () { - it("correctly sets owner", async function () { + describe("constructor / initialize()", function() { + it("correctly sets owner", async function() { const { owner, enclave } = await loadFixture(setup); expect(await enclave.owner()).to.equal(owner.address); }); - it("correctly sets ciphernodeRegistry address", async function () { + it("correctly sets ciphernodeRegistry address", async function() { const { mocks, enclave } = await loadFixture(setup); expect(await enclave.ciphernodeRegistry()).to.equal( await mocks.registry.getAddress(), ); }); - it("correctly sets max duration", async function () { + it("correctly sets max duration", async function() { const { enclave } = await loadFixture(setup); expect(await enclave.maxDuration()).to.equal(60 * 60 * 24 * 30); }); }); - describe("setMaxDuration()", function () { - it("reverts if not called by owner", async function () { + describe("setMaxDuration()", function() { + it("reverts if not called by owner", async function() { const { enclave, notTheOwner } = await loadFixture(setup); await expect(enclave.connect(notTheOwner).setMaxDuration(1)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("set max duration correctly", async function () { + it("set max duration correctly", async function() { const { enclave } = await loadFixture(setup); await enclave.setMaxDuration(1); expect(await enclave.maxDuration()).to.equal(1); }); - it("returns true if max duration is set successfully", async function () { + it("returns true if max duration is set successfully", async function() { const { enclave } = await loadFixture(setup); const result = await enclave.setMaxDuration.staticCall(1); expect(result).to.be.true; }); - it("emits MaxDurationSet event", async function () { + it("emits MaxDurationSet event", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.setMaxDuration(1)) .to.emit(enclave, "MaxDurationSet") @@ -135,8 +135,8 @@ describe("Enclave", function () { }); }); - describe("setCiphernodeRegistry()", function () { - it("reverts if not called by owner", async function () { + describe("setCiphernodeRegistry()", function() { + it("reverts if not called by owner", async function() { const { enclave, notTheOwner } = await loadFixture(setup); await expect( @@ -145,13 +145,13 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if given address(0)", async function () { + it("reverts if given address(0)", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.setCiphernodeRegistry(ethers.ZeroAddress)) .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(ethers.ZeroAddress); }); - it("reverts if given address is the same as the current ciphernodeRegistry", async function () { + it("reverts if given address is the same as the current ciphernodeRegistry", async function() { const { enclave, mocks: { registry }, @@ -160,20 +160,20 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(registry); }); - it("sets ciphernodeRegistry correctly", async function () { + it("sets ciphernodeRegistry correctly", async function() { const { enclave } = await loadFixture(setup); expect(await enclave.ciphernodeRegistry()).to.not.equal(AddressTwo); await enclave.setCiphernodeRegistry(AddressTwo); expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); - it("returns true if ciphernodeRegistry is set successfully", async function () { + it("returns true if ciphernodeRegistry is set successfully", async function() { const { enclave } = await loadFixture(setup); const result = await enclave.setCiphernodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits CiphernodeRegistrySet event", async function () { + it("emits CiphernodeRegistrySet event", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.setCiphernodeRegistry(AddressTwo)) @@ -182,15 +182,15 @@ describe("Enclave", function () { }); }); - describe("getE3()", function () { - it("reverts if E3 does not exist", async function () { + describe("getE3()", function() { + it("reverts if E3 does not exist", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.getE3(1)) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(1); }); - it("returns correct E3 details", async function () { + it("returns correct E3 details", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( request.filter, @@ -209,7 +209,7 @@ describe("Enclave", function () { expect(e3.e3Program).to.equal(request.e3Program); expect(e3.e3ProgramParams).to.equal(request.e3ProgramParams); expect(e3.inputValidator).to.equal( - abiCoder.decode(["address", "bytes"], request.e3ProgramParams)[0], + abiCoder.decode(["bytes", "address"], request.e3ProgramParams)[1], ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], @@ -220,14 +220,14 @@ describe("Enclave", function () { }); }); - describe("getDecryptionVerifier()", function () { - it("returns true if encryption scheme is enabled", async function () { + describe("getDecryptionVerifier()", function() { + it("returns true if encryption scheme is enabled", async function() { const { enclave, mocks } = await loadFixture(setup); expect(await enclave.getDecryptionVerifier(encryptionSchemeId)).to.equal( await mocks.decryptionVerifier.getAddress(), ); }); - it("returns false if encryption scheme is not enabled", async function () { + it("returns false if encryption scheme is not enabled", async function() { const { enclave } = await loadFixture(setup); expect( await enclave.getDecryptionVerifier(newEncryptionSchemeId), @@ -235,8 +235,8 @@ describe("Enclave", function () { }); }); - describe("setDecryptionVerifier()", function () { - it("reverts if caller is not owner", async function () { + describe("setDecryptionVerifier()", function() { + it("reverts if caller is not owner", async function() { const { enclave, notTheOwner, mocks } = await loadFixture(setup); await expect( @@ -250,7 +250,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if encryption scheme is already enabled", async function () { + it("reverts if encryption scheme is already enabled", async function() { const { enclave, mocks } = await loadFixture(setup); await expect( @@ -262,7 +262,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); - it("enabled decryption verifier", async function () { + it("enabled decryption verifier", async function() { const { enclave, mocks } = await loadFixture(setup); expect( @@ -275,7 +275,7 @@ describe("Enclave", function () { await enclave.getDecryptionVerifier(newEncryptionSchemeId), ).to.equal(await mocks.decryptionVerifier.getAddress()); }); - it("returns true if decryption verifier is enabled successfully", async function () { + it("returns true if decryption verifier is enabled successfully", async function() { const { enclave, mocks } = await loadFixture(setup); const result = await enclave.setDecryptionVerifier.staticCall( @@ -284,7 +284,7 @@ describe("Enclave", function () { ); expect(result).to.be.true; }); - it("emits EncryptionSchemeEnabled", async function () { + it("emits EncryptionSchemeEnabled", async function() { const { enclave, mocks } = await loadFixture(setup); await expect( @@ -298,8 +298,8 @@ describe("Enclave", function () { }); }); - describe("disableEncryptionScheme()", function () { - it("reverts if caller is not owner", async function () { + describe("disableEncryptionScheme()", function() { + it("reverts if caller is not owner", async function() { const { enclave, notTheOwner } = await loadFixture(setup); await expect( @@ -310,14 +310,14 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if encryption scheme is not already enabled", async function () { + it("reverts if encryption scheme is not already enabled", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.disableEncryptionScheme(newEncryptionSchemeId)) .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(newEncryptionSchemeId); }); - it("disables encryption scheme", async function () { + it("disables encryption scheme", async function() { const { enclave } = await loadFixture(setup); expect(await enclave.disableEncryptionScheme(encryptionSchemeId)); @@ -325,14 +325,14 @@ describe("Enclave", function () { ethers.ZeroAddress, ); }); - it("returns true if encryption scheme is disabled successfully", async function () { + it("returns true if encryption scheme is disabled successfully", async function() { const { enclave } = await loadFixture(setup); const result = await enclave.disableEncryptionScheme.staticCall(encryptionSchemeId); expect(result).to.be.true; }); - it("emits EncryptionSchemeDisabled", async function () { + it("emits EncryptionSchemeDisabled", async function() { const { enclave } = await loadFixture(setup); await expect(await enclave.disableEncryptionScheme(encryptionSchemeId)) @@ -341,8 +341,8 @@ describe("Enclave", function () { }); }); - describe("enableE3Program()", function () { - it("reverts if not called by owner", async function () { + describe("enableE3Program()", function() { + it("reverts if not called by owner", async function() { const { notTheOwner, enclave, @@ -353,7 +353,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if E3 Program is already enabled", async function () { + it("reverts if E3 Program is already enabled", async function() { const { enclave, mocks: { e3Program }, @@ -363,7 +363,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") .withArgs(e3Program); }); - it("enables E3 Program correctly", async function () { + it("enables E3 Program correctly", async function() { const { enclave, mocks: { e3Program }, @@ -371,12 +371,12 @@ describe("Enclave", function () { const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.true; }); - it("returns true if E3 Program is enabled successfully", async function () { + it("returns true if E3 Program is enabled successfully", async function() { const { enclave } = await loadFixture(setup); const result = await enclave.enableE3Program.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits E3ProgramEnabled event", async function () { + it("emits E3ProgramEnabled event", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.enableE3Program(AddressTwo)) .to.emit(enclave, "E3ProgramEnabled") @@ -384,8 +384,8 @@ describe("Enclave", function () { }); }); - describe("disableE3Program()", function () { - it("reverts if not called by owner", async function () { + describe("disableE3Program()", function() { + it("reverts if not called by owner", async function() { const { notTheOwner, enclave, @@ -395,13 +395,13 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if E3 Program is not enabled", async function () { + it("reverts if E3 Program is not enabled", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.disableE3Program(AddressTwo)) .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); - it("disables E3 Program correctly", async function () { + it("disables E3 Program correctly", async function() { const { enclave, mocks: { e3Program }, @@ -411,7 +411,7 @@ describe("Enclave", function () { const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.false; }); - it("returns true if E3 Program is disabled successfully", async function () { + it("returns true if E3 Program is disabled successfully", async function() { const { enclave, mocks: { e3Program }, @@ -420,7 +420,7 @@ describe("Enclave", function () { expect(result).to.be.true; }); - it("emits E3ProgramDisabled event", async function () { + it("emits E3ProgramDisabled event", async function() { const { enclave, mocks: { e3Program }, @@ -431,8 +431,8 @@ describe("Enclave", function () { }); }); - describe("request()", function () { - it("reverts if msg.value is 0", async function () { + describe("request()", function() { + it("reverts if msg.value is 0", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -446,7 +446,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "PaymentRequired"); }); - it("reverts if threshold is 0", async function () { + it("reverts if threshold is 0", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -461,7 +461,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); - it("reverts if threshold is greater than number", async function () { + it("reverts if threshold is greater than number", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -476,7 +476,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); - it("reverts if duration is 0", async function () { + it("reverts if duration is 0", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -491,7 +491,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); - it("reverts if duration is greater than maxDuration", async function () { + it("reverts if duration is greater than maxDuration", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -506,7 +506,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); - it("reverts if E3 Program is not enabled", async function () { + it("reverts if E3 Program is not enabled", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -523,7 +523,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3ProgramNotAllowed") .withArgs(ethers.ZeroAddress); }); - it("reverts if given encryption scheme is not enabled", async function () { + it("reverts if given encryption scheme is not enabled", async function() { const { enclave, request } = await loadFixture(setup); await enclave.disableEncryptionScheme(encryptionSchemeId); await expect( @@ -533,7 +533,7 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - abiCoder.encode(['address','bytes'],[ethers.ZeroAddress, ZeroHash]), + abiCoder.encode(["bytes", "address"], [ZeroHash, ethers.ZeroAddress]), request.computeProviderParams, { value: 10 }, ), @@ -541,7 +541,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); - it("reverts if given E3 Program does not return input validator address", async function () { + it("reverts if given E3 Program does not return input validator address", async function() { const { enclave, request } = await loadFixture(setup); await expect( @@ -551,13 +551,13 @@ describe("Enclave", function () { request.startTime, request.duration, request.e3Program, - abiCoder.encode(['address','bytes'],[ethers.ZeroAddress, ZeroHash]), + abiCoder.encode(["bytes", "address"], [ZeroHash, ethers.ZeroAddress]), request.computeProviderParams, { value: 10 }, ), ).to.be.revertedWithCustomError(enclave, "InvalidComputationRequest"); }); - it("reverts if committee selection fails", async function () { + it("reverts if committee selection fails", async function() { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -572,7 +572,7 @@ describe("Enclave", function () { ), ).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); }); - it("instantiates a new E3", async function () { + it("instantiates a new E3", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( request.filter, @@ -590,7 +590,7 @@ describe("Enclave", function () { expect(e3.expiration).to.equal(0n); expect(e3.e3Program).to.equal(request.e3Program); expect(e3.inputValidator).to.equal( - abiCoder.decode(["address"], request.e3ProgramParams)[0], + abiCoder.decode(["bytes","address"], request.e3ProgramParams)[1], ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], @@ -599,7 +599,7 @@ describe("Enclave", function () { expect(e3.ciphertextOutput).to.equal(ethers.ZeroHash); expect(e3.plaintextOutput).to.equal(ethers.ZeroHash); }); - it("emits E3Requested event", async function () { + it("emits E3Requested event", async function() { const { enclave, request } = await loadFixture(setup); const tx = await enclave.request( request.filter, @@ -619,15 +619,15 @@ describe("Enclave", function () { }); }); - describe("activate()", function () { - it("reverts if E3 does not exist", async function () { + describe("activate()", function() { + it("reverts if E3 does not exist", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.activate(0)) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(0); }); - it("reverts if E3 has already been activated", async function () { + it("reverts if E3 has already been activated", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -647,7 +647,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3AlreadyActivated") .withArgs(0); }); - it("reverts if E3 is not yet ready to start", async function () { + it("reverts if E3 is not yet ready to start", async function() { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1000, @@ -670,7 +670,7 @@ describe("Enclave", function () { "E3NotReady", ); }); - it("reverts if E3 start has expired", async function () { + it("reverts if E3 start has expired", async function() { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1, @@ -695,7 +695,7 @@ describe("Enclave", function () { "E3Expired", ); }); - it("reverts if ciphernodeRegistry does not return a public key", async function () { + it("reverts if ciphernodeRegistry does not return a public key", async function() { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1000, @@ -718,7 +718,7 @@ describe("Enclave", function () { "E3NotReady", ); }); - it("reverts if E3 start has expired", async function () { + it("reverts if E3 start has expired", async function() { const { enclave, request } = await loadFixture(setup); const startTime = [await time.latest(), (await time.latest()) + 1] as [ number, @@ -743,7 +743,7 @@ describe("Enclave", function () { "E3Expired", ); }); - it("reverts if ciphernodeRegistry does not return a public key", async function () { + it("reverts if ciphernodeRegistry does not return a public key", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -841,8 +841,8 @@ describe("Enclave", function () { }); }); - describe("publishInput()", function () { - it("reverts if E3 does not exist", async function () { + describe("publishInput()", function() { + it("reverts if E3 does not exist", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.publishInput(0, "0x")) @@ -850,7 +850,7 @@ describe("Enclave", function () { .withArgs(0); }); - it("reverts if E3 has not been activated", async function () { + it("reverts if E3 has not been activated", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -874,7 +874,7 @@ describe("Enclave", function () { await enclave.activate(0); }); - it("reverts if input is not valid", async function () { + it("reverts if input is not valid", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -894,7 +894,7 @@ describe("Enclave", function () { ).to.be.revertedWithCustomError(enclave, "InvalidInput"); }); - it("reverts if outside of input window", async function () { + it("reverts if outside of input window", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -916,7 +916,7 @@ describe("Enclave", function () { enclave.publishInput(0, ZeroHash), ).to.be.revertedWithCustomError(enclave, "InputDeadlinePassed"); }); - it("returns true if input is published successfully", async function () { + it("returns true if input is published successfully", async function() { const { enclave, request } = await loadFixture(setup); const inputData = "0x12345678"; @@ -938,7 +938,7 @@ describe("Enclave", function () { ); }); - it("adds inputHash to merkle tree", async function () { + it("adds inputHash to merkle tree", async function() { const { enclave, request } = await loadFixture(setup); const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); @@ -970,7 +970,7 @@ describe("Enclave", function () { await enclave.publishInput(e3Id, secondInputData); expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); }); - it("emits InputPublished event", async function () { + it("emits InputPublished event", async function() { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -996,15 +996,15 @@ describe("Enclave", function () { }); }); - describe("publishCiphertextOutput()", function () { - it("reverts if E3 does not exist", async function () { + describe("publishCiphertextOutput()", function() { + it("reverts if E3 does not exist", async function() { const { enclave } = await loadFixture(setup); await expect(enclave.publishCiphertextOutput(0, "0x", "0x")) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(0); }); - it("reverts if E3 has not been activated", async function () { + it("reverts if E3 has not been activated", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1022,7 +1022,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3NotActivated") .withArgs(e3Id); }); - it("reverts if input deadline has not passed", async function () { + it("reverts if input deadline has not passed", async function() { const { enclave, request } = await loadFixture(setup); const tx = await enclave.request( request.filter, @@ -1045,7 +1045,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InputDeadlineNotPassed") .withArgs(e3Id, expectedExpiration); }); - it("reverts if output has already been published", async function () { + it("reverts if output has already been published", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1069,7 +1069,7 @@ describe("Enclave", function () { ) .withArgs(e3Id); }); - it("reverts if output is not valid", async function () { + it("reverts if output is not valid", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1089,7 +1089,7 @@ describe("Enclave", function () { enclave.publishCiphertextOutput(e3Id, "0x", "0x"), ).to.be.revertedWithCustomError(enclave, "InvalidOutput"); }); - it("sets ciphertextOutput correctly", async function () { + it("sets ciphertextOutput correctly", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1109,7 +1109,7 @@ describe("Enclave", function () { const e3 = await enclave.getE3(e3Id); expect(e3.ciphertextOutput).to.equal(dataHash); }); - it("returns true if output is published successfully", async function () { + it("returns true if output is published successfully", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1129,7 +1129,7 @@ describe("Enclave", function () { await enclave.publishCiphertextOutput.staticCall(e3Id, data, proof), ).to.equal(true); }); - it("emits CiphertextOutputPublished event", async function () { + it("emits CiphertextOutputPublished event", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1151,8 +1151,8 @@ describe("Enclave", function () { }); }); - describe("publishPlaintextOutput()", function () { - it("reverts if E3 does not exist", async function () { + describe("publishPlaintextOutput()", function() { + it("reverts if E3 does not exist", async function() { const { enclave } = await loadFixture(setup); const e3Id = 0; @@ -1160,7 +1160,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(e3Id); }); - it("reverts if E3 has not been activated", async function () { + it("reverts if E3 has not been activated", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1178,7 +1178,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "E3NotActivated") .withArgs(e3Id); }); - it("reverts if ciphertextOutput has not been published", async function () { + it("reverts if ciphertextOutput has not been published", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1197,7 +1197,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "CiphertextOutputNotPublished") .withArgs(e3Id); }); - it("reverts if plaintextOutput has already been published", async function () { + it("reverts if plaintextOutput has already been published", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1222,7 +1222,7 @@ describe("Enclave", function () { ) .withArgs(e3Id); }); - it("reverts if output is not valid", async function () { + it("reverts if output is not valid", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1243,7 +1243,7 @@ describe("Enclave", function () { .to.be.revertedWithCustomError(enclave, "InvalidOutput") .withArgs(data); }); - it("sets plaintextOutput correctly", async function () { + it("sets plaintextOutput correctly", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1265,7 +1265,7 @@ describe("Enclave", function () { const e3 = await enclave.getE3(e3Id); expect(e3.plaintextOutput).to.equal(dataHash); }); - it("returns true if output is published successfully", async function () { + it("returns true if output is published successfully", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1286,7 +1286,7 @@ describe("Enclave", function () { await enclave.publishPlaintextOutput.staticCall(e3Id, data, proof), ).to.equal(true); }); - it("emits PlaintextOutputPublished event", async function () { + it("emits PlaintextOutputPublished event", async function() { const { enclave, request } = await loadFixture(setup); const e3Id = 0; diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 00000000..3c3629e6 --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/tests/basic_integration/lib/encode_e3_params.mjs b/tests/basic_integration/lib/encode_e3_params.mjs new file mode 100755 index 00000000..5f7d7e90 --- /dev/null +++ b/tests/basic_integration/lib/encode_e3_params.mjs @@ -0,0 +1,23 @@ +#!/usr/bin/env node + +import { AbiCoder } from "ethers"; +import { Command } from "commander"; + +const program = new Command(); + +program + .name("crypto-params-cli") + .description("A CLI for specifying an input validator and BFV parameters") + .version("1.0.0") + .requiredOption("--input-validator ", "input validation rule") + .requiredOption("--bfv-params ", "BFV scheme parameters") + .action((options) => { + const abiCoder = new AbiCoder(); + const out = abiCoder.encode( + ["bytes", "address"], + [options.bfvParams, options.inputValidator], + ); + console.log(out); + }); + +program.parse(process.argv) diff --git a/tests/basic_integration/test.sh b/tests/basic_integration/test.sh index a0cf35ec..bc4811e0 100755 --- a/tests/basic_integration/test.sh +++ b/tests/basic_integration/test.sh @@ -15,8 +15,10 @@ fi # Environment variables export RPC_URL="ws://localhost:8545" # These contracts are based on the deterministic order of hardhat deploy +# We _may_ wish to get these off the hardhat environment somehow? export ENCLAVE_CONTRACT="0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" export REGISTRY_CONTRACT="0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" +export INPUT_VALIDATOR_CONTRACT="0x8A791620dd6260079BF849Dc5567aDC3F2FdC318" # These are random addresses for now export CIPHERNODE_ADDRESS_1="0x2546BcD3c84621e976D8185a91A922aE77ECEc30" export CIPHERNODE_ADDRESS_2="0xbDA5747bFD65F08deb54cb465eB87D40e51B197E" @@ -122,7 +124,10 @@ heading "Request Committee" PARAMS=0x$($SCRIPT_DIR/lib/bfvgen.sh --moduli 0x3FFFFFFF000001 --degree 2048 --plaintext-modulus 1032193) -yarn committee:new --network localhost --duration 4 --e3-params "$PARAMS" + +ENCODED_PARAMS=$($SCRIPT_DIR/lib/encode_e3_params.mjs --input-validator $INPUT_VALIDATOR_CONTRACT --bfv-params $PARAMS) + +yarn committee:new --network localhost --duration 4 --e3-params "$ENCODED_PARAMS" waiton "$SCRIPT_DIR/output/pubkey.bin" diff --git a/tests/package.json b/tests/package.json new file mode 100644 index 00000000..c7d8782a --- /dev/null +++ b/tests/package.json @@ -0,0 +1,10 @@ +{ + "name": "tests", + "version": "0.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "commander": "^12.1.0", + "ethers": "6.1.0" + } +} diff --git a/tests/yarn.lock b/tests/yarn.lock new file mode 100644 index 00000000..804297fb --- /dev/null +++ b/tests/yarn.lock @@ -0,0 +1,50 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@adraffy/ens-normalize@1.8.9": + version "1.8.9" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.8.9.tgz#67b3acadebbb551669c9a1da15fac951db795b85" + integrity sha512-93OmGCV0vO8+JQ3FHG+gZk/MPHzzMPDRiCiFcCQNTCnHaaxsacO3ScTPGlu2wX2dOtgfalbchPcw1cOYYjHCYQ== + +"@noble/hashes@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" + integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== + +"@noble/secp256k1@1.7.1": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" + integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== + +aes-js@4.0.0-beta.3: + version "4.0.0-beta.3" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.3.tgz#da2253f0ff03a0b3a9e445c8cbdf78e7fda7d48c" + integrity sha512-/xJX0/VTPcbc5xQE2VUP91y1xN8q/rDfhEzLm+vLc3hYvb5+qHCnpJRuFcrKn63zumK/sCwYYzhG8HP78JYSTA== + +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + +ethers@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.1.0.tgz#de9c3acbb865fda6c080e80ec88ae0aada046947" + integrity sha512-aC45YGbvgXt7Nses5WsdQwc1cUIrrQt32zeFShNW7ZT3RQCIHBnd4nmbE5sJmrp70uTdwkRHkr4cZr1D/YwFPg== + dependencies: + "@adraffy/ens-normalize" "1.8.9" + "@noble/hashes" "1.1.2" + "@noble/secp256k1" "1.7.1" + aes-js "4.0.0-beta.3" + tslib "2.4.0" + ws "8.5.0" + +tslib@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" + integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== + +ws@8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" + integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== From e7aa7ef698efe87e762aeecbfb95238d9f628e3d Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 21:51:28 +1000 Subject: [PATCH 06/12] Decoding events are working --- packages/ciphernode/core/src/evm_enclave.rs | 58 +++++- packages/ciphernode/core/src/lib.rs | 12 +- packages/ciphernode/core/src/logger.rs | 3 + .../src/bin/{bfvgen.rs => pack_e3_params.rs} | 10 +- packages/evm/contracts/test/MockE3Program.sol | 3 +- packages/evm/test/Enclave.spec.ts | 188 +++++++++--------- .../lib/encode_e3_params.mjs | 11 +- .../lib/{bfvgen.sh => pack_e3_params.sh} | 2 +- .../output/encoded_params.hex | 1 + tests/basic_integration/test.sh | 5 +- 10 files changed, 174 insertions(+), 119 deletions(-) rename packages/ciphernode/enclave_node/src/bin/{bfvgen.rs => pack_e3_params.rs} (75%) rename tests/basic_integration/lib/{bfvgen.sh => pack_e3_params.sh} (76%) create mode 100644 tests/basic_integration/output/encoded_params.hex diff --git a/packages/ciphernode/core/src/evm_enclave.rs b/packages/ciphernode/core/src/evm_enclave.rs index bd2026db..ccddfa33 100644 --- a/packages/ciphernode/core/src/evm_enclave.rs +++ b/packages/ciphernode/core/src/evm_enclave.rs @@ -5,15 +5,15 @@ use crate::{ EnclaveEvent, EventBus, }; use actix::Addr; -use alloy::{primitives::Address, sol, sol_types::SolValue}; +use alloy::{ + hex, + primitives::{Address, Bytes}, + sol, + sol_types::SolValue, +}; use anyhow::{Context, Result}; sol! { - struct EncodedE3ProgramParams { - bytes params; - address input_validator; - } - #[derive(Debug)] struct E3 { uint256 seed; @@ -50,9 +50,12 @@ impl TryFrom<&E3Requested> for events::E3Requested { type Error = anyhow::Error; fn try_from(value: &E3Requested) -> Result { let program_params = value.e3.e3ProgramParams.to_vec(); - let decoded = EncodedE3ProgramParams::abi_decode(&program_params, true)?; + println!("received: {}", hex::encode(&program_params)); + + let decoded = + decode_e3_params(&program_params).context("Failed to ABI decode program_params")?; Ok(events::E3Requested { - params: decoded.params.into(), + params: decoded.0.into(), threshold_m: value.e3.threshold[0] as usize, seed: value.e3.seed.into(), e3_id: value.e3Id.to_string().into(), @@ -71,9 +74,7 @@ impl From for events::CiphertextOutputPublished { impl ContractEvent for E3Requested { fn process(&self, bus: Addr) -> Result<()> { - let data: events::E3Requested = self - .try_into() - .context("Could not parse E3Requested event")?; + let data: events::E3Requested = self.try_into()?; bus.do_send(EnclaveEvent::from(data)); Ok(()) @@ -108,3 +109,38 @@ pub async fn connect_evm_enclave(bus: Addr, rpc_url: &str, contract_ad println!("Evm is listening to {}", contract_address); } + +pub fn decode_e3_params(bytes: &[u8]) -> Result<(Vec, String)> { + let decoded: (Bytes, Address) = SolValue::abi_decode_params(bytes, true)?; + Ok((decoded.0.into(), decoded.1.to_string())) +} + +pub fn encode_e3_params(params: &[u8], input_validator: Address) -> Vec { + (params, input_validator).abi_encode_params() +} + +#[cfg(test)] +mod tests { + use crate::encode_bfv_params; + + use super::{decode_e3_params, encode_e3_params}; + use alloy::{hex, primitives::address}; + use anyhow::*; + use fhe::bfv::BfvParameters; + use fhe_traits::Deserialize; + + #[test] + fn test_evm_decode() -> Result<()> { + let params_encoded = encode_bfv_params(vec![0x3FFFFFFF000001], 2048, 1032193); + + let add = address!("8A791620dd6260079BF849Dc5567aDC3F2FdC318"); + let encoded = hex::encode(&encode_e3_params(¶ms_encoded, add)); + assert_eq!(encoded, "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc31800000000000000000000000000000000000000000000000000000000000000130880101208818080f8ffffff1f1881803f200a00000000000000000000000000"); + let input: Vec = hex::decode(&encoded)?; + let (de_params, de_address) = decode_e3_params(&input)?; + let params_assemble = BfvParameters::try_deserialize(&de_params)?; + assert_eq!(params_assemble.degree(), 2048); + assert_eq!(de_address, "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318"); + Ok(()) + } +} diff --git a/packages/ciphernode/core/src/lib.rs b/packages/ciphernode/core/src/lib.rs index 678cc561..1b987b6b 100644 --- a/packages/ciphernode/core/src/lib.rs +++ b/packages/ciphernode/core/src/lib.rs @@ -34,6 +34,7 @@ pub use data::*; pub use e3_request::*; pub use eventbus::*; pub use events::*; +pub use evm_enclave::{decode_e3_params, encode_e3_params}; pub use fhe::*; pub use keyshare::*; pub use logger::*; @@ -78,7 +79,12 @@ mod tests { use tokio::{sync::mpsc::channel, time::sleep}; // Simulating a local node - async fn setup_local_ciphernode(bus: Addr, rng:SharedRng, logging: bool, addr: &str) { + async fn setup_local_ciphernode( + bus: Addr, + rng: SharedRng, + logging: bool, + addr: &str, + ) { // create data actor for saving data let data = Data::new(logging).start(); // TODO: Use a sled backed Data Actor @@ -136,7 +142,9 @@ mod tests { &[0x3FFFFFFF000001], 2048, 1032193, - Arc::new(std::sync::Mutex::new(ChaCha20Rng::from_seed(seed.clone().into()))), + Arc::new(std::sync::Mutex::new(ChaCha20Rng::from_seed( + seed.clone().into(), + ))), ); let regevt_1 = EnclaveEvent::from(CiphernodeAdded { diff --git a/packages/ciphernode/core/src/logger.rs b/packages/ciphernode/core/src/logger.rs index 2a6f8bba..540389dd 100644 --- a/packages/ciphernode/core/src/logger.rs +++ b/packages/ciphernode/core/src/logger.rs @@ -44,6 +44,9 @@ impl Handler for SimpleLogger { }, EnclaveEvent::E3Requested { data,.. } => { println!("[{}]: E3Requested(e3_id: {}, threshold_m: {} , seed: {:?})", self.name, data.e3_id, data.threshold_m, data.seed); + }, + EnclaveEvent::EnclaveError { data, .. } => { + println!("[{}]: EnclaveError('{}')", self.name, data.message); } _ => println!("[{}]: {}", self.name, msg), } diff --git a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs b/packages/ciphernode/enclave_node/src/bin/pack_e3_params.rs similarity index 75% rename from packages/ciphernode/enclave_node/src/bin/bfvgen.rs rename to packages/ciphernode/enclave_node/src/bin/pack_e3_params.rs index e23fc091..41974563 100644 --- a/packages/ciphernode/enclave_node/src/bin/bfvgen.rs +++ b/packages/ciphernode/enclave_node/src/bin/pack_e3_params.rs @@ -1,5 +1,6 @@ +use alloy::{hex::FromHex, primitives::{address, Address}}; use clap::{command, Parser}; -use enclave_core::encode_bfv_params; +use enclave_core::{encode_bfv_params, encode_e3_params}; use std::{error::Error, num::ParseIntError, process}; fn parse_hex(arg: &str) -> Result { @@ -21,6 +22,9 @@ struct Args { #[arg(short, long = "no-crp", help = "Skip the CRP generation")] no_crp: bool, + + #[arg(short, long = "input-validator", help = "The input validator address")] + input_validator: String } fn main() -> Result<(), Box> { @@ -32,8 +36,8 @@ fn main() -> Result<(), Box> { } let encoded = encode_bfv_params(args.moduli, args.degree, args.plaintext_modulus); - - for byte in encoded { + let abi_encoded = encode_e3_params(&encoded,Address::from_hex(args.input_validator)?); + for byte in abi_encoded { print!("{:02x}", byte); } diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index dfae54bf..27f7691a 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -20,11 +20,12 @@ contract MockE3Program is IE3Program { computeProviderParams.length == 32, invalidParams(e3ProgramParams, computeProviderParams) ); - (,inputValidator) = abi.decode( + (, IInputValidator _inputValidator) = abi.decode( e3ProgramParams, (bytes, IInputValidator) ); + inputValidator = _inputValidator; encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; } diff --git a/packages/evm/test/Enclave.spec.ts b/packages/evm/test/Enclave.spec.ts index a68a9e79..2cf2a2f2 100644 --- a/packages/evm/test/Enclave.spec.ts +++ b/packages/evm/test/Enclave.spec.ts @@ -35,7 +35,7 @@ const proof = "0x1337"; // Hash function used to compute the tree nodes. const hash = (a: bigint, b: bigint) => poseidon2([a, b]); -describe("Enclave", function() { +describe("Enclave", function () { async function setup() { const [owner, notTheOwner] = await ethers.getSigners(); @@ -91,43 +91,43 @@ describe("Enclave", function() { }; } - describe("constructor / initialize()", function() { - it("correctly sets owner", async function() { + describe("constructor / initialize()", function () { + it("correctly sets owner", async function () { const { owner, enclave } = await loadFixture(setup); expect(await enclave.owner()).to.equal(owner.address); }); - it("correctly sets ciphernodeRegistry address", async function() { + it("correctly sets ciphernodeRegistry address", async function () { const { mocks, enclave } = await loadFixture(setup); expect(await enclave.ciphernodeRegistry()).to.equal( await mocks.registry.getAddress(), ); }); - it("correctly sets max duration", async function() { + it("correctly sets max duration", async function () { const { enclave } = await loadFixture(setup); expect(await enclave.maxDuration()).to.equal(60 * 60 * 24 * 30); }); }); - describe("setMaxDuration()", function() { - it("reverts if not called by owner", async function() { + describe("setMaxDuration()", function () { + it("reverts if not called by owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); await expect(enclave.connect(notTheOwner).setMaxDuration(1)) .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("set max duration correctly", async function() { + it("set max duration correctly", async function () { const { enclave } = await loadFixture(setup); await enclave.setMaxDuration(1); expect(await enclave.maxDuration()).to.equal(1); }); - it("returns true if max duration is set successfully", async function() { + it("returns true if max duration is set successfully", async function () { const { enclave } = await loadFixture(setup); const result = await enclave.setMaxDuration.staticCall(1); expect(result).to.be.true; }); - it("emits MaxDurationSet event", async function() { + it("emits MaxDurationSet event", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.setMaxDuration(1)) .to.emit(enclave, "MaxDurationSet") @@ -135,8 +135,8 @@ describe("Enclave", function() { }); }); - describe("setCiphernodeRegistry()", function() { - it("reverts if not called by owner", async function() { + describe("setCiphernodeRegistry()", function () { + it("reverts if not called by owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); await expect( @@ -145,13 +145,13 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if given address(0)", async function() { + it("reverts if given address(0)", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.setCiphernodeRegistry(ethers.ZeroAddress)) .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(ethers.ZeroAddress); }); - it("reverts if given address is the same as the current ciphernodeRegistry", async function() { + it("reverts if given address is the same as the current ciphernodeRegistry", async function () { const { enclave, mocks: { registry }, @@ -160,20 +160,20 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "InvalidCiphernodeRegistry") .withArgs(registry); }); - it("sets ciphernodeRegistry correctly", async function() { + it("sets ciphernodeRegistry correctly", async function () { const { enclave } = await loadFixture(setup); expect(await enclave.ciphernodeRegistry()).to.not.equal(AddressTwo); await enclave.setCiphernodeRegistry(AddressTwo); expect(await enclave.ciphernodeRegistry()).to.equal(AddressTwo); }); - it("returns true if ciphernodeRegistry is set successfully", async function() { + it("returns true if ciphernodeRegistry is set successfully", async function () { const { enclave } = await loadFixture(setup); const result = await enclave.setCiphernodeRegistry.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits CiphernodeRegistrySet event", async function() { + it("emits CiphernodeRegistrySet event", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.setCiphernodeRegistry(AddressTwo)) @@ -182,15 +182,15 @@ describe("Enclave", function() { }); }); - describe("getE3()", function() { - it("reverts if E3 does not exist", async function() { + describe("getE3()", function () { + it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.getE3(1)) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(1); }); - it("returns correct E3 details", async function() { + it("returns correct E3 details", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( request.filter, @@ -220,14 +220,14 @@ describe("Enclave", function() { }); }); - describe("getDecryptionVerifier()", function() { - it("returns true if encryption scheme is enabled", async function() { + describe("getDecryptionVerifier()", function () { + it("returns true if encryption scheme is enabled", async function () { const { enclave, mocks } = await loadFixture(setup); expect(await enclave.getDecryptionVerifier(encryptionSchemeId)).to.equal( await mocks.decryptionVerifier.getAddress(), ); }); - it("returns false if encryption scheme is not enabled", async function() { + it("returns false if encryption scheme is not enabled", async function () { const { enclave } = await loadFixture(setup); expect( await enclave.getDecryptionVerifier(newEncryptionSchemeId), @@ -235,8 +235,8 @@ describe("Enclave", function() { }); }); - describe("setDecryptionVerifier()", function() { - it("reverts if caller is not owner", async function() { + describe("setDecryptionVerifier()", function () { + it("reverts if caller is not owner", async function () { const { enclave, notTheOwner, mocks } = await loadFixture(setup); await expect( @@ -250,7 +250,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if encryption scheme is already enabled", async function() { + it("reverts if encryption scheme is already enabled", async function () { const { enclave, mocks } = await loadFixture(setup); await expect( @@ -262,7 +262,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); - it("enabled decryption verifier", async function() { + it("enabled decryption verifier", async function () { const { enclave, mocks } = await loadFixture(setup); expect( @@ -275,7 +275,7 @@ describe("Enclave", function() { await enclave.getDecryptionVerifier(newEncryptionSchemeId), ).to.equal(await mocks.decryptionVerifier.getAddress()); }); - it("returns true if decryption verifier is enabled successfully", async function() { + it("returns true if decryption verifier is enabled successfully", async function () { const { enclave, mocks } = await loadFixture(setup); const result = await enclave.setDecryptionVerifier.staticCall( @@ -284,7 +284,7 @@ describe("Enclave", function() { ); expect(result).to.be.true; }); - it("emits EncryptionSchemeEnabled", async function() { + it("emits EncryptionSchemeEnabled", async function () { const { enclave, mocks } = await loadFixture(setup); await expect( @@ -298,8 +298,8 @@ describe("Enclave", function() { }); }); - describe("disableEncryptionScheme()", function() { - it("reverts if caller is not owner", async function() { + describe("disableEncryptionScheme()", function () { + it("reverts if caller is not owner", async function () { const { enclave, notTheOwner } = await loadFixture(setup); await expect( @@ -310,14 +310,14 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if encryption scheme is not already enabled", async function() { + it("reverts if encryption scheme is not already enabled", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.disableEncryptionScheme(newEncryptionSchemeId)) .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(newEncryptionSchemeId); }); - it("disables encryption scheme", async function() { + it("disables encryption scheme", async function () { const { enclave } = await loadFixture(setup); expect(await enclave.disableEncryptionScheme(encryptionSchemeId)); @@ -325,14 +325,14 @@ describe("Enclave", function() { ethers.ZeroAddress, ); }); - it("returns true if encryption scheme is disabled successfully", async function() { + it("returns true if encryption scheme is disabled successfully", async function () { const { enclave } = await loadFixture(setup); const result = await enclave.disableEncryptionScheme.staticCall(encryptionSchemeId); expect(result).to.be.true; }); - it("emits EncryptionSchemeDisabled", async function() { + it("emits EncryptionSchemeDisabled", async function () { const { enclave } = await loadFixture(setup); await expect(await enclave.disableEncryptionScheme(encryptionSchemeId)) @@ -341,8 +341,8 @@ describe("Enclave", function() { }); }); - describe("enableE3Program()", function() { - it("reverts if not called by owner", async function() { + describe("enableE3Program()", function () { + it("reverts if not called by owner", async function () { const { notTheOwner, enclave, @@ -353,7 +353,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if E3 Program is already enabled", async function() { + it("reverts if E3 Program is already enabled", async function () { const { enclave, mocks: { e3Program }, @@ -363,7 +363,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "ModuleAlreadyEnabled") .withArgs(e3Program); }); - it("enables E3 Program correctly", async function() { + it("enables E3 Program correctly", async function () { const { enclave, mocks: { e3Program }, @@ -371,12 +371,12 @@ describe("Enclave", function() { const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.true; }); - it("returns true if E3 Program is enabled successfully", async function() { + it("returns true if E3 Program is enabled successfully", async function () { const { enclave } = await loadFixture(setup); const result = await enclave.enableE3Program.staticCall(AddressTwo); expect(result).to.be.true; }); - it("emits E3ProgramEnabled event", async function() { + it("emits E3ProgramEnabled event", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.enableE3Program(AddressTwo)) .to.emit(enclave, "E3ProgramEnabled") @@ -384,8 +384,8 @@ describe("Enclave", function() { }); }); - describe("disableE3Program()", function() { - it("reverts if not called by owner", async function() { + describe("disableE3Program()", function () { + it("reverts if not called by owner", async function () { const { notTheOwner, enclave, @@ -395,13 +395,13 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "OwnableUnauthorizedAccount") .withArgs(notTheOwner); }); - it("reverts if E3 Program is not enabled", async function() { + it("reverts if E3 Program is not enabled", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.disableE3Program(AddressTwo)) .to.be.revertedWithCustomError(enclave, "ModuleNotEnabled") .withArgs(AddressTwo); }); - it("disables E3 Program correctly", async function() { + it("disables E3 Program correctly", async function () { const { enclave, mocks: { e3Program }, @@ -411,7 +411,7 @@ describe("Enclave", function() { const enabled = await enclave.e3Programs(e3Program); expect(enabled).to.be.false; }); - it("returns true if E3 Program is disabled successfully", async function() { + it("returns true if E3 Program is disabled successfully", async function () { const { enclave, mocks: { e3Program }, @@ -420,7 +420,7 @@ describe("Enclave", function() { expect(result).to.be.true; }); - it("emits E3ProgramDisabled event", async function() { + it("emits E3ProgramDisabled event", async function () { const { enclave, mocks: { e3Program }, @@ -431,8 +431,8 @@ describe("Enclave", function() { }); }); - describe("request()", function() { - it("reverts if msg.value is 0", async function() { + describe("request()", function () { + it("reverts if msg.value is 0", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -446,7 +446,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "PaymentRequired"); }); - it("reverts if threshold is 0", async function() { + it("reverts if threshold is 0", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -461,7 +461,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); - it("reverts if threshold is greater than number", async function() { + it("reverts if threshold is greater than number", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -476,7 +476,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "InvalidThreshold"); }); - it("reverts if duration is 0", async function() { + it("reverts if duration is 0", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -491,7 +491,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); - it("reverts if duration is greater than maxDuration", async function() { + it("reverts if duration is greater than maxDuration", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -506,7 +506,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "InvalidDuration"); }); - it("reverts if E3 Program is not enabled", async function() { + it("reverts if E3 Program is not enabled", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -523,7 +523,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "E3ProgramNotAllowed") .withArgs(ethers.ZeroAddress); }); - it("reverts if given encryption scheme is not enabled", async function() { + it("reverts if given encryption scheme is not enabled", async function () { const { enclave, request } = await loadFixture(setup); await enclave.disableEncryptionScheme(encryptionSchemeId); await expect( @@ -541,7 +541,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "InvalidEncryptionScheme") .withArgs(encryptionSchemeId); }); - it("reverts if given E3 Program does not return input validator address", async function() { + it("reverts if given E3 Program does not return input validator address", async function () { const { enclave, request } = await loadFixture(setup); await expect( @@ -557,7 +557,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "InvalidComputationRequest"); }); - it("reverts if committee selection fails", async function() { + it("reverts if committee selection fails", async function () { const { enclave, request } = await loadFixture(setup); await expect( enclave.request( @@ -572,7 +572,7 @@ describe("Enclave", function() { ), ).to.be.revertedWithCustomError(enclave, "CommitteeSelectionFailed"); }); - it("instantiates a new E3", async function() { + it("instantiates a new E3", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( request.filter, @@ -590,7 +590,7 @@ describe("Enclave", function() { expect(e3.expiration).to.equal(0n); expect(e3.e3Program).to.equal(request.e3Program); expect(e3.inputValidator).to.equal( - abiCoder.decode(["bytes","address"], request.e3ProgramParams)[1], + abiCoder.decode(["bytes", "address"], request.e3ProgramParams)[1], ); expect(e3.decryptionVerifier).to.equal( abiCoder.decode(["address"], request.computeProviderParams)[0], @@ -599,7 +599,7 @@ describe("Enclave", function() { expect(e3.ciphertextOutput).to.equal(ethers.ZeroHash); expect(e3.plaintextOutput).to.equal(ethers.ZeroHash); }); - it("emits E3Requested event", async function() { + it("emits E3Requested event", async function () { const { enclave, request } = await loadFixture(setup); const tx = await enclave.request( request.filter, @@ -619,15 +619,15 @@ describe("Enclave", function() { }); }); - describe("activate()", function() { - it("reverts if E3 does not exist", async function() { + describe("activate()", function () { + it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.activate(0)) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(0); }); - it("reverts if E3 has already been activated", async function() { + it("reverts if E3 has already been activated", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -647,7 +647,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "E3AlreadyActivated") .withArgs(0); }); - it("reverts if E3 is not yet ready to start", async function() { + it("reverts if E3 is not yet ready to start", async function () { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1000, @@ -670,7 +670,7 @@ describe("Enclave", function() { "E3NotReady", ); }); - it("reverts if E3 start has expired", async function() { + it("reverts if E3 start has expired", async function () { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1, @@ -695,7 +695,7 @@ describe("Enclave", function() { "E3Expired", ); }); - it("reverts if ciphernodeRegistry does not return a public key", async function() { + it("reverts if ciphernodeRegistry does not return a public key", async function () { const { enclave, request } = await loadFixture(setup); const startTime = [ (await time.latest()) + 1000, @@ -718,7 +718,7 @@ describe("Enclave", function() { "E3NotReady", ); }); - it("reverts if E3 start has expired", async function() { + it("reverts if E3 start has expired", async function () { const { enclave, request } = await loadFixture(setup); const startTime = [await time.latest(), (await time.latest()) + 1] as [ number, @@ -743,7 +743,7 @@ describe("Enclave", function() { "E3Expired", ); }); - it("reverts if ciphernodeRegistry does not return a public key", async function() { + it("reverts if ciphernodeRegistry does not return a public key", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -841,8 +841,8 @@ describe("Enclave", function() { }); }); - describe("publishInput()", function() { - it("reverts if E3 does not exist", async function() { + describe("publishInput()", function () { + it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.publishInput(0, "0x")) @@ -850,7 +850,7 @@ describe("Enclave", function() { .withArgs(0); }); - it("reverts if E3 has not been activated", async function() { + it("reverts if E3 has not been activated", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -874,7 +874,7 @@ describe("Enclave", function() { await enclave.activate(0); }); - it("reverts if input is not valid", async function() { + it("reverts if input is not valid", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -894,7 +894,7 @@ describe("Enclave", function() { ).to.be.revertedWithCustomError(enclave, "InvalidInput"); }); - it("reverts if outside of input window", async function() { + it("reverts if outside of input window", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -916,7 +916,7 @@ describe("Enclave", function() { enclave.publishInput(0, ZeroHash), ).to.be.revertedWithCustomError(enclave, "InputDeadlinePassed"); }); - it("returns true if input is published successfully", async function() { + it("returns true if input is published successfully", async function () { const { enclave, request } = await loadFixture(setup); const inputData = "0x12345678"; @@ -938,7 +938,7 @@ describe("Enclave", function() { ); }); - it("adds inputHash to merkle tree", async function() { + it("adds inputHash to merkle tree", async function () { const { enclave, request } = await loadFixture(setup); const inputData = abiCoder.encode(["bytes"], ["0xaabbccddeeff"]); @@ -970,7 +970,7 @@ describe("Enclave", function() { await enclave.publishInput(e3Id, secondInputData); expect(await enclave.getInputRoot(e3Id)).to.equal(tree.root); }); - it("emits InputPublished event", async function() { + it("emits InputPublished event", async function () { const { enclave, request } = await loadFixture(setup); await enclave.request( @@ -996,15 +996,15 @@ describe("Enclave", function() { }); }); - describe("publishCiphertextOutput()", function() { - it("reverts if E3 does not exist", async function() { + describe("publishCiphertextOutput()", function () { + it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); await expect(enclave.publishCiphertextOutput(0, "0x", "0x")) .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(0); }); - it("reverts if E3 has not been activated", async function() { + it("reverts if E3 has not been activated", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1022,7 +1022,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "E3NotActivated") .withArgs(e3Id); }); - it("reverts if input deadline has not passed", async function() { + it("reverts if input deadline has not passed", async function () { const { enclave, request } = await loadFixture(setup); const tx = await enclave.request( request.filter, @@ -1045,7 +1045,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "InputDeadlineNotPassed") .withArgs(e3Id, expectedExpiration); }); - it("reverts if output has already been published", async function() { + it("reverts if output has already been published", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1069,7 +1069,7 @@ describe("Enclave", function() { ) .withArgs(e3Id); }); - it("reverts if output is not valid", async function() { + it("reverts if output is not valid", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1089,7 +1089,7 @@ describe("Enclave", function() { enclave.publishCiphertextOutput(e3Id, "0x", "0x"), ).to.be.revertedWithCustomError(enclave, "InvalidOutput"); }); - it("sets ciphertextOutput correctly", async function() { + it("sets ciphertextOutput correctly", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1109,7 +1109,7 @@ describe("Enclave", function() { const e3 = await enclave.getE3(e3Id); expect(e3.ciphertextOutput).to.equal(dataHash); }); - it("returns true if output is published successfully", async function() { + it("returns true if output is published successfully", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1129,7 +1129,7 @@ describe("Enclave", function() { await enclave.publishCiphertextOutput.staticCall(e3Id, data, proof), ).to.equal(true); }); - it("emits CiphertextOutputPublished event", async function() { + it("emits CiphertextOutputPublished event", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1151,8 +1151,8 @@ describe("Enclave", function() { }); }); - describe("publishPlaintextOutput()", function() { - it("reverts if E3 does not exist", async function() { + describe("publishPlaintextOutput()", function () { + it("reverts if E3 does not exist", async function () { const { enclave } = await loadFixture(setup); const e3Id = 0; @@ -1160,7 +1160,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "E3DoesNotExist") .withArgs(e3Id); }); - it("reverts if E3 has not been activated", async function() { + it("reverts if E3 has not been activated", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1178,7 +1178,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "E3NotActivated") .withArgs(e3Id); }); - it("reverts if ciphertextOutput has not been published", async function() { + it("reverts if ciphertextOutput has not been published", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1197,7 +1197,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "CiphertextOutputNotPublished") .withArgs(e3Id); }); - it("reverts if plaintextOutput has already been published", async function() { + it("reverts if plaintextOutput has already been published", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1222,7 +1222,7 @@ describe("Enclave", function() { ) .withArgs(e3Id); }); - it("reverts if output is not valid", async function() { + it("reverts if output is not valid", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1243,7 +1243,7 @@ describe("Enclave", function() { .to.be.revertedWithCustomError(enclave, "InvalidOutput") .withArgs(data); }); - it("sets plaintextOutput correctly", async function() { + it("sets plaintextOutput correctly", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1265,7 +1265,7 @@ describe("Enclave", function() { const e3 = await enclave.getE3(e3Id); expect(e3.plaintextOutput).to.equal(dataHash); }); - it("returns true if output is published successfully", async function() { + it("returns true if output is published successfully", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; @@ -1286,7 +1286,7 @@ describe("Enclave", function() { await enclave.publishPlaintextOutput.staticCall(e3Id, data, proof), ).to.equal(true); }); - it("emits PlaintextOutputPublished event", async function() { + it("emits PlaintextOutputPublished event", async function () { const { enclave, request } = await loadFixture(setup); const e3Id = 0; diff --git a/tests/basic_integration/lib/encode_e3_params.mjs b/tests/basic_integration/lib/encode_e3_params.mjs index 5f7d7e90..0dc8adf9 100755 --- a/tests/basic_integration/lib/encode_e3_params.mjs +++ b/tests/basic_integration/lib/encode_e3_params.mjs @@ -1,6 +1,6 @@ #!/usr/bin/env node -import { AbiCoder } from "ethers"; +import { AbiCoder, solidityPacked } from "ethers"; import { Command } from "commander"; const program = new Command(); @@ -13,11 +13,16 @@ program .requiredOption("--bfv-params ", "BFV scheme parameters") .action((options) => { const abiCoder = new AbiCoder(); + const out = abiCoder.encode( ["bytes", "address"], - [options.bfvParams, options.inputValidator], + [ + options.bfvParams, + options.inputValidator, + ], ); + console.log(out); }); -program.parse(process.argv) +program.parse(process.argv); diff --git a/tests/basic_integration/lib/bfvgen.sh b/tests/basic_integration/lib/pack_e3_params.sh similarity index 76% rename from tests/basic_integration/lib/bfvgen.sh rename to tests/basic_integration/lib/pack_e3_params.sh index ff62f9e9..78502e2e 100755 --- a/tests/basic_integration/lib/bfvgen.sh +++ b/tests/basic_integration/lib/pack_e3_params.sh @@ -1,3 +1,3 @@ #!/usr/bin/env bash -cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo run --bin bfvgen -- "$@" +cd packages/ciphernode && RUSTFLAGS="-A warnings" cargo run --bin pack_e3_params -- "$@" diff --git a/tests/basic_integration/output/encoded_params.hex b/tests/basic_integration/output/encoded_params.hex new file mode 100644 index 00000000..8ff477d7 --- /dev/null +++ b/tests/basic_integration/output/encoded_params.hex @@ -0,0 +1 @@ +0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc31800000000000000000000000000000000000000000000000000000000000000130880101208818080f8ffffff1f1881803f200a00000000000000000000000000 diff --git a/tests/basic_integration/test.sh b/tests/basic_integration/test.sh index bc4811e0..6fde6f5e 100755 --- a/tests/basic_integration/test.sh +++ b/tests/basic_integration/test.sh @@ -122,10 +122,7 @@ yarn ciphernode:add --ciphernode-address $CIPHERNODE_ADDRESS_4 --network localho heading "Request Committee" -PARAMS=0x$($SCRIPT_DIR/lib/bfvgen.sh --moduli 0x3FFFFFFF000001 --degree 2048 --plaintext-modulus 1032193) - - -ENCODED_PARAMS=$($SCRIPT_DIR/lib/encode_e3_params.mjs --input-validator $INPUT_VALIDATOR_CONTRACT --bfv-params $PARAMS) +ENCODED_PARAMS=0x$($SCRIPT_DIR/lib/pack_e3_params.sh --moduli 0x3FFFFFFF000001 --degree 2048 --plaintext-modulus 1032193 --input-validator "$INPUT_VALIDATOR_CONTRACT") yarn committee:new --network localhost --duration 4 --e3-params "$ENCODED_PARAMS" From 7cad667f7c7eb5b1eea5d5d3377f9df5f36745c7 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 21:54:19 +1000 Subject: [PATCH 07/12] Remove comment --- packages/ciphernode/core/src/events.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index 225bc568..fbd16c35 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -304,9 +304,9 @@ pub struct PublicKeyAggregated { pub struct E3Requested { pub e3_id: E3id, pub threshold_m: usize, - pub seed: Seed, // Should actually be much larger eg [u8;32] + pub seed: Seed, pub params: Vec, - // threshold: usize, // TODO: + // threshold: usize, // TODO: // computation_type: ??, // TODO: // execution_model_type: ??, // TODO: // input_deadline: ??, // TODO: From 4e575c114536282f94d04ccf8e81800dd88762f3 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 22:14:36 +1000 Subject: [PATCH 08/12] Tidy up error trait --- packages/ciphernode/core/src/events.rs | 22 ++++++++++---------- packages/ciphernode/core/src/evm_listener.rs | 2 +- packages/ciphernode/core/src/keyshare.rs | 19 ++++++++--------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index fbd16c35..50c23ac4 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -2,8 +2,7 @@ use actix::Message; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{ - fmt::{self, Display}, - hash::{DefaultHasher, Hash, Hasher}, + error::Error, fmt::{self, Display}, hash::{DefaultHasher, Hash, Hasher} }; use alloy::primitives::Uint; @@ -166,11 +165,10 @@ impl EnclaveEvent { } } -pub trait FromError -where - E: ToString, +pub trait FromError { - fn from_error(err_type: EnclaveErrorType, error: E) -> Self; + type Error; + fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self; } impl From for EnclaveEvent { @@ -263,9 +261,10 @@ impl From for EnclaveEvent { } } -impl FromError for EnclaveEvent { - fn from_error(err_type: EnclaveErrorType, error: anyhow::Error) -> Self { - let error_event = EnclaveError::from_error(err_type, &error); +impl FromError for EnclaveEvent { + type Error = anyhow::Error; + fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self { + let error_event = EnclaveError::from_error(err_type, error); EnclaveEvent::from(error_event) } } @@ -398,8 +397,9 @@ impl EnclaveError { } } -impl FromError for EnclaveError { - fn from_error(err_type: EnclaveErrorType, error: E) -> Self { +impl FromError for EnclaveError { + type Error = anyhow::Error; + fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self { Self { err_type, message: error.to_string(), diff --git a/packages/ciphernode/core/src/evm_listener.rs b/packages/ciphernode/core/src/evm_listener.rs index 7e6b47b1..f12a09e7 100644 --- a/packages/ciphernode/core/src/evm_listener.rs +++ b/packages/ciphernode/core/src/evm_listener.rs @@ -12,7 +12,7 @@ use std::collections::HashMap; use std::marker::PhantomData; use std::sync::Arc; -use crate::{EnclaveError, EnclaveErrorType, EnclaveEvent, EventBus, FromError}; +use crate::{EnclaveErrorType, EnclaveEvent, EventBus, FromError}; pub trait ContractEvent: Send + Sync + 'static { fn process(&self, bus: Addr) -> Result<()>; diff --git a/packages/ciphernode/core/src/keyshare.rs b/packages/ciphernode/core/src/keyshare.rs index eae84f2d..5d87bfc1 100644 --- a/packages/ciphernode/core/src/keyshare.rs +++ b/packages/ciphernode/core/src/keyshare.rs @@ -1,16 +1,10 @@ use std::sync::Arc; use crate::{ - data::{Data, Insert}, - eventbus::EventBus, - events::{EnclaveEvent, KeyshareCreated}, - fhe::Fhe, - ActorFactory, CiphernodeSelected, CiphertextOutputPublished, DecryptCiphertext, - DecryptionshareCreated, Get, + data::{Data, Insert}, eventbus::EventBus, events::{EnclaveEvent, KeyshareCreated}, fhe::Fhe, ActorFactory, CiphernodeSelected, CiphertextOutputPublished, DecryptCiphertext, DecryptionshareCreated, EnclaveErrorType, FromError, Get }; use actix::prelude::*; -use anyhow::Context; -use anyhow::Result; +use anyhow::{anyhow, Context, Result}; pub struct Keyshare { fhe: Arc, @@ -53,8 +47,13 @@ impl Handler for Keyshare { let CiphernodeSelected { e3_id, .. } = event; // generate keyshare - // TODO: instead of unwrap we should broadcast an error on the event bus - let (sk, pubkey) = self.fhe.generate_keyshare().unwrap(); + let Ok((sk, pubkey)) = self.fhe.generate_keyshare() else { + self.bus.do_send(EnclaveEvent::from_error( + EnclaveErrorType::KeyGeneration, + anyhow!("Error creating Keyshare"), + )); + return; + }; // TODO: decrypt from FHE actor // save encrypted key against e3_id/sk From f50208b690253f515f9f4d83775fcec0f7e04b35 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 22:18:03 +1000 Subject: [PATCH 09/12] Remove old code --- tests/.gitignore | 1 - .../lib/encode_e3_params.mjs | 28 ----------- tests/package.json | 10 ---- tests/yarn.lock | 50 ------------------- 4 files changed, 89 deletions(-) delete mode 100644 tests/.gitignore delete mode 100755 tests/basic_integration/lib/encode_e3_params.mjs delete mode 100644 tests/package.json delete mode 100644 tests/yarn.lock diff --git a/tests/.gitignore b/tests/.gitignore deleted file mode 100644 index 3c3629e6..00000000 --- a/tests/.gitignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/tests/basic_integration/lib/encode_e3_params.mjs b/tests/basic_integration/lib/encode_e3_params.mjs deleted file mode 100755 index 0dc8adf9..00000000 --- a/tests/basic_integration/lib/encode_e3_params.mjs +++ /dev/null @@ -1,28 +0,0 @@ -#!/usr/bin/env node - -import { AbiCoder, solidityPacked } from "ethers"; -import { Command } from "commander"; - -const program = new Command(); - -program - .name("crypto-params-cli") - .description("A CLI for specifying an input validator and BFV parameters") - .version("1.0.0") - .requiredOption("--input-validator ", "input validation rule") - .requiredOption("--bfv-params ", "BFV scheme parameters") - .action((options) => { - const abiCoder = new AbiCoder(); - - const out = abiCoder.encode( - ["bytes", "address"], - [ - options.bfvParams, - options.inputValidator, - ], - ); - - console.log(out); - }); - -program.parse(process.argv); diff --git a/tests/package.json b/tests/package.json deleted file mode 100644 index c7d8782a..00000000 --- a/tests/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "tests", - "version": "0.0.0", - "main": "index.js", - "license": "MIT", - "dependencies": { - "commander": "^12.1.0", - "ethers": "6.1.0" - } -} diff --git a/tests/yarn.lock b/tests/yarn.lock deleted file mode 100644 index 804297fb..00000000 --- a/tests/yarn.lock +++ /dev/null @@ -1,50 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@adraffy/ens-normalize@1.8.9": - version "1.8.9" - resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.8.9.tgz#67b3acadebbb551669c9a1da15fac951db795b85" - integrity sha512-93OmGCV0vO8+JQ3FHG+gZk/MPHzzMPDRiCiFcCQNTCnHaaxsacO3ScTPGlu2wX2dOtgfalbchPcw1cOYYjHCYQ== - -"@noble/hashes@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.1.2.tgz#e9e035b9b166ca0af657a7848eb2718f0f22f183" - integrity sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA== - -"@noble/secp256k1@1.7.1": - version "1.7.1" - resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-1.7.1.tgz#b251c70f824ce3ca7f8dc3df08d58f005cc0507c" - integrity sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw== - -aes-js@4.0.0-beta.3: - version "4.0.0-beta.3" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-4.0.0-beta.3.tgz#da2253f0ff03a0b3a9e445c8cbdf78e7fda7d48c" - integrity sha512-/xJX0/VTPcbc5xQE2VUP91y1xN8q/rDfhEzLm+vLc3hYvb5+qHCnpJRuFcrKn63zumK/sCwYYzhG8HP78JYSTA== - -commander@^12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - -ethers@6.1.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-6.1.0.tgz#de9c3acbb865fda6c080e80ec88ae0aada046947" - integrity sha512-aC45YGbvgXt7Nses5WsdQwc1cUIrrQt32zeFShNW7ZT3RQCIHBnd4nmbE5sJmrp70uTdwkRHkr4cZr1D/YwFPg== - dependencies: - "@adraffy/ens-normalize" "1.8.9" - "@noble/hashes" "1.1.2" - "@noble/secp256k1" "1.7.1" - aes-js "4.0.0-beta.3" - tslib "2.4.0" - ws "8.5.0" - -tslib@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" - integrity sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ== - -ws@8.5.0: - version "8.5.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.5.0.tgz#bfb4be96600757fe5382de12c670dab984a1ed4f" - integrity sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg== From 48507b6369bbf7a6cc30b9f91e956039c41fb5fd Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 22:18:47 +1000 Subject: [PATCH 10/12] Remove params hex file --- tests/basic_integration/output/.gitignore | 1 + tests/basic_integration/output/encoded_params.hex | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 tests/basic_integration/output/encoded_params.hex diff --git a/tests/basic_integration/output/.gitignore b/tests/basic_integration/output/.gitignore index 1d5b85f9..730ffd4a 100644 --- a/tests/basic_integration/output/.gitignore +++ b/tests/basic_integration/output/.gitignore @@ -1,2 +1,3 @@ *.bin plaintext.txt +*.hex diff --git a/tests/basic_integration/output/encoded_params.hex b/tests/basic_integration/output/encoded_params.hex deleted file mode 100644 index 8ff477d7..00000000 --- a/tests/basic_integration/output/encoded_params.hex +++ /dev/null @@ -1 +0,0 @@ -0x00000000000000000000000000000000000000000000000000000000000000400000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc31800000000000000000000000000000000000000000000000000000000000000130880101208818080f8ffffff1f1881803f200a00000000000000000000000000 From 160ce287a82a4b21fcb60425e0acaba1ddd7d79b Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 22:34:10 +1000 Subject: [PATCH 11/12] Tidy up output --- packages/ciphernode/core/src/events.rs | 27 +++++++++++-------- packages/ciphernode/core/src/logger.rs | 2 +- packages/evm/contracts/test/MockE3Program.sol | 4 +-- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/packages/ciphernode/core/src/events.rs b/packages/ciphernode/core/src/events.rs index 50c23ac4..0bd50b22 100644 --- a/packages/ciphernode/core/src/events.rs +++ b/packages/ciphernode/core/src/events.rs @@ -1,10 +1,12 @@ use actix::Message; +use alloy::{hex, primitives::Uint}; use serde::{Deserialize, Serialize}; use sha2::{Digest, Sha256}; use std::{ - error::Error, fmt::{self, Display}, hash::{DefaultHasher, Hash, Hasher} + error::Error, + fmt::{self, Display}, + hash::{DefaultHasher, Hash, Hasher}, }; -use alloy::primitives::Uint; #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct E3id(pub String); @@ -165,8 +167,7 @@ impl EnclaveEvent { } } -pub trait FromError -{ +pub trait FromError { type Error; fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self; } @@ -349,8 +350,6 @@ pub struct CiphernodeRemoved { pub num_nodes: usize, } - - #[derive(Message, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] #[rtype(result = "()")] pub struct EnclaveError { @@ -359,25 +358,31 @@ pub struct EnclaveError { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub struct Seed(pub [u8;32]); +pub struct Seed(pub [u8; 32]); impl From for u64 { fn from(value: Seed) -> Self { u64::from_le_bytes(value.0[..8].try_into().unwrap()) } } -impl From for [u8;32] { +impl From for [u8; 32] { fn from(value: Seed) -> Self { value.0 } } -impl From> for Seed { - fn from(value: Uint<256,4>) -> Self { +impl From> for Seed { + fn from(value: Uint<256, 4>) -> Self { Seed(value.to_le_bytes()) } } +impl Display for Seed { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Seed(0x{})", hex::encode(self.0)) + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)] pub enum EnclaveErrorType { Evm, @@ -385,7 +390,7 @@ pub enum EnclaveErrorType { PublickeyAggregation, IO, PlaintextAggregation, - Decryption + Decryption, } impl EnclaveError { diff --git a/packages/ciphernode/core/src/logger.rs b/packages/ciphernode/core/src/logger.rs index 540389dd..c2e736a6 100644 --- a/packages/ciphernode/core/src/logger.rs +++ b/packages/ciphernode/core/src/logger.rs @@ -43,7 +43,7 @@ impl Handler for SimpleLogger { println!("[{}]: CiphernodeAdded({})", self.name, data.address); }, EnclaveEvent::E3Requested { data,.. } => { - println!("[{}]: E3Requested(e3_id: {}, threshold_m: {} , seed: {:?})", self.name, data.e3_id, data.threshold_m, data.seed); + println!("[{}]: E3Requested(e3_id: {}, threshold_m: {} , seed: {})", self.name, data.e3_id, data.threshold_m, data.seed); }, EnclaveEvent::EnclaveError { data, .. } => { println!("[{}]: EnclaveError('{}')", self.name, data.message); diff --git a/packages/evm/contracts/test/MockE3Program.sol b/packages/evm/contracts/test/MockE3Program.sol index 27f7691a..e20a8066 100644 --- a/packages/evm/contracts/test/MockE3Program.sol +++ b/packages/evm/contracts/test/MockE3Program.sol @@ -20,12 +20,10 @@ contract MockE3Program is IE3Program { computeProviderParams.length == 32, invalidParams(e3ProgramParams, computeProviderParams) ); - (, IInputValidator _inputValidator) = abi.decode( + (, inputValidator) = abi.decode( e3ProgramParams, (bytes, IInputValidator) ); - - inputValidator = _inputValidator; encryptionSchemeId = 0x0000000000000000000000000000000000000000000000000000000000000001; } From 002607c170023e74836bf1d203aec3d164903831 Mon Sep 17 00:00:00 2001 From: ryardley Date: Mon, 30 Sep 2024 22:36:23 +1000 Subject: [PATCH 12/12] Wait on fake_encrypt --- tests/basic_integration/test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/basic_integration/test.sh b/tests/basic_integration/test.sh index 6fde6f5e..4d5de51d 100755 --- a/tests/basic_integration/test.sh +++ b/tests/basic_integration/test.sh @@ -106,7 +106,7 @@ yarn ciphernode:aggregator --rpc "$RPC_URL" --enclave-contract $ENCLAVE_CONTRACT sleep 1 -waiton-files "$ROOT_DIR/packages/ciphernode/target/debug/node" "$ROOT_DIR/packages/ciphernode/target/debug/aggregator" "$ROOT_DIR/packages/ciphernode/target/debug/test_encryptor" +waiton-files "$ROOT_DIR/packages/ciphernode/target/debug/node" "$ROOT_DIR/packages/ciphernode/target/debug/aggregator" "$ROOT_DIR/packages/ciphernode/target/debug/fake_encrypt" heading "Add ciphernode $CIPHERNODE_ADDRESS_1" yarn ciphernode:add --ciphernode-address $CIPHERNODE_ADDRESS_1 --network localhost