Skip to content

Commit

Permalink
Merge pull request #117 from gnosisguild:ry/encode_params
Browse files Browse the repository at this point in the history
Decoding params from contract
  • Loading branch information
auryn-macmillan authored Sep 30, 2024
2 parents cf50fd6 + 002607c commit e8b6ce9
Show file tree
Hide file tree
Showing 23 changed files with 346 additions and 181 deletions.
4 changes: 2 additions & 2 deletions packages/ciphernode/core/src/committee_meta.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
103 changes: 95 additions & 8 deletions packages/ciphernode/core/src/events.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use actix::Message;
use alloy::{hex, primitives::Uint};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::{
fmt,
error::Error,
fmt::{self, Display},
hash::{DefaultHasher, Hash, Hasher},
};

Expand Down Expand Up @@ -98,6 +100,10 @@ pub enum EnclaveEvent {
id: EventId,
data: CiphernodeRemoved,
},
EnclaveError {
id: EventId,
data: EnclaveError,
},
// CommitteeSelected,
// OutputDecrypted,
// CiphernodeRegistered,
Expand Down Expand Up @@ -141,6 +147,7 @@ impl From<EnclaveEvent> for EventId {
EnclaveEvent::CiphernodeSelected { id, .. } => id,
EnclaveEvent::CiphernodeAdded { id, .. } => id,
EnclaveEvent::CiphernodeRemoved { id, .. } => id,
EnclaveEvent::EnclaveError { id, .. } => id,
}
}
}
Expand All @@ -160,6 +167,11 @@ impl EnclaveEvent {
}
}

pub trait FromError {
type Error;
fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> Self;
}

impl From<KeyshareCreated> for EnclaveEvent {
fn from(data: KeyshareCreated) -> Self {
EnclaveEvent::KeyshareCreated {
Expand Down Expand Up @@ -240,6 +252,24 @@ impl From<CiphernodeRemoved> for EnclaveEvent {
}
}
}

impl From<EnclaveError> for EnclaveEvent {
fn from(data: EnclaveError) -> Self {
EnclaveEvent::EnclaveError {
id: EventId::from(data.clone()),
data: data.clone(),
}
}
}

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)
}
}

impl fmt::Display for EnclaveEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&format!("{}({})", self.event_type(), self.get_id()))
Expand Down Expand Up @@ -274,13 +304,8 @@ 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]

// fhe params
pub moduli: Vec<u64>,
pub degree: usize,
pub plaintext_modulus: u64,
pub crp: Vec<u8>,
pub seed: Seed,
pub params: Vec<u8>,
// threshold: usize, // TODO:
// computation_type: ??, // TODO:
// execution_model_type: ??, // TODO:
Expand Down Expand Up @@ -325,6 +350,68 @@ 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, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Seed(pub [u8; 32]);
impl From<Seed> for u64 {
fn from(value: Seed) -> Self {
u64::from_le_bytes(value.0[..8].try_into().unwrap())
}
}

impl From<Seed> for [u8; 32] {
fn from(value: Seed) -> Self {
value.0
}
}

impl From<Uint<256, 4>> 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,
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 {
type Error = anyhow::Error;
fn from_error(err_type: EnclaveErrorType, error: Self::Error) -> 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() {
Expand Down
94 changes: 57 additions & 37 deletions packages/ciphernode/core/src/evm_enclave.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
use std::sync::Arc;

use crate::{
events,
evm_listener::{AddEventHandler, ContractEvent, StartListening},
evm_manager::{AddListener, EvmContractManager},
setup_crp_params, EnclaveEvent, EventBus, ParamsWithCrp,
EnclaveEvent, EventBus,
};
use actix::Addr;
use alloy::{primitives::Address, sol};
use anyhow::Result;
use rand::SeedableRng;
use rand_chacha::ChaCha20Rng;
use alloy::{
hex,
primitives::{Address, Bytes},
sol,
sol_types::SolValue,
};
use anyhow::{Context, Result};

sol! {
#[derive(Debug)]
Expand Down Expand Up @@ -45,37 +46,20 @@ sol! {
);
}

impl From<E3Requested> 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 {
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 {
moduli,
plaintext_modulus,
degree,
impl TryFrom<&E3Requested> for events::E3Requested {
type Error = anyhow::Error;
fn try_from(value: &E3Requested) -> Result<Self, Self::Error> {
let program_params = value.e3.e3ProgramParams.to_vec();
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.0.into(),
threshold_m: value.e3.threshold[0] as usize,
crp: crp_bytes,
// 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(),
}
})
}
}

Expand All @@ -90,7 +74,8 @@ impl From<CiphertextOutputPublished> for events::CiphertextOutputPublished {

impl ContractEvent for E3Requested {
fn process(&self, bus: Addr<EventBus>) -> Result<()> {
let data: events::E3Requested = self.clone().into();
let data: events::E3Requested = self.try_into()?;

bus.do_send(EnclaveEvent::from(data));
Ok(())
}
Expand Down Expand Up @@ -124,3 +109,38 @@ pub async fn connect_evm_enclave(bus: Addr<EventBus>, rpc_url: &str, contract_ad

println!("Evm is listening to {}", contract_address);
}

pub fn decode_e3_params(bytes: &[u8]) -> Result<(Vec<u8>, 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<u8> {
(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(&params_encoded, add));
assert_eq!(encoded, "00000000000000000000000000000000000000000000000000000000000000400000000000000000000000008a791620dd6260079bf849dc5567adc3f2fdc31800000000000000000000000000000000000000000000000000000000000000130880101208818080f8ffffff1f1881803f200a00000000000000000000000000");
let input: Vec<u8> = 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(())
}
}
12 changes: 10 additions & 2 deletions packages/ciphernode/core/src/evm_listener.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use std::collections::HashMap;
use std::marker::PhantomData;
use std::sync::Arc;

use crate::EventBus;
use crate::{EnclaveErrorType, EnclaveEvent, EventBus, FromError};

pub trait ContractEvent: Send + Sync + 'static {
fn process(&self, bus: Addr<EventBus>) -> Result<()>;
Expand Down Expand Up @@ -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,
));
}
}
}
}
Expand Down
27 changes: 15 additions & 12 deletions packages/ciphernode/core/src/fhe.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use crate::{ordered_set::OrderedSet, ActorFactory, E3Requested, EnclaveEvent};
use crate::{ordered_set::OrderedSet, set_up_crp, ActorFactory, E3Requested, EnclaveEvent, Seed};
use anyhow::*;
use fhe::{
bfv::{
BfvParameters, BfvParametersBuilder, Ciphertext, Encoding, Plaintext, PublicKey, SecretKey,
},
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};

Expand Down Expand Up @@ -39,6 +40,15 @@ impl Fhe {
Self { params, crp, rng }
}

pub fn from_encoded(bytes: &[u8], seed: Seed, rng: SharedRng) -> Result<Self> {
let params = Arc::new(BfvParameters::try_deserialize(bytes)?);
let crp = set_up_crp(
params.clone(),
Arc::new(Mutex::new(ChaCha20Rng::from_seed(seed.into()))),
);
Ok(Fhe::new(params.clone(), crp, rng.clone()))
}

pub fn from_raw_params(
moduli: &[u64],
degree: usize,
Expand Down Expand Up @@ -115,23 +125,16 @@ impl Fhe {
pub struct FheFactory;

impl FheFactory {
pub fn create(rng: Arc<Mutex<ChaCha20Rng>>) -> 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,
..
} = data;
let E3Requested { params, seed, .. } = data;

ctx.fhe = Some(Arc::new(
Fhe::from_raw_params(&moduli, degree, plaintext_modulus, &crp, rng.clone())
.unwrap(),
Fhe::from_encoded(&params, seed, rng.clone()).unwrap(),
));
})
}
Expand Down
Loading

0 comments on commit e8b6ce9

Please sign in to comment.