Skip to content

Commit

Permalink
Sync coprocessor signing with fhevm signing
Browse files Browse the repository at this point in the history
  • Loading branch information
david-zk committed Sep 24, 2024
1 parent 3a92474 commit a0d9443
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 46 deletions.
70 changes: 36 additions & 34 deletions fhevm-engine/coprocessor/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,38 +98,40 @@ pub async fn run_server_iteration(

// for EIP712 signature
alloy::sol! {
struct CiphertextVerification {
struct CiphertextVerificationForCopro {
address aclAddress;
bytes32 hashOfCiphertext;
uint256[] handlesList;
address userAddress;
address contractAddress;
address callerAddress;
}
}

// copied from go coprocessor
// theData := signerApi.TypedData{
// Types: signerApi.Types{
// "EIP712Domain": domainType,
// "CiphertextVerification": []signerApi.Type{
// {Name: "handlesList", Type: "uint256[]"},
// {Name: "contractAddress", Type: "address"},
// {Name: "callerAddress", Type: "address"},
// },
// },
// Domain: signerApi.TypedDataDomain{
// Name: "FHEVMCoprocessor",
// Version: "1",
// ChainId: chainId,
// VerifyingContract: verifyingContract.Hex(),
// },
// PrimaryType: "CiphertextVerification",
// Message: signerApi.TypedDataMessage{
// "handlesList": hexInputs,
// "contractAddress": contractAddress.Hex(),
// "callerAddress": callerAddress.Hex(),
// },
// }
// copied from fhevm-go coprocessor
// const types = {
// CiphertextVerificationForCopro: [
// {
// name: 'aclAddress',
// type: 'address',
// },
// {
// name: 'hashOfCiphertext',
// type: 'bytes32',
// },
// {
// name: 'handlesList',
// type: 'uint256[]',
// },
// {
// name: 'userAddress',
// type: 'address',
// },
// {
// name: 'contractAddress',
// type: 'address',
// },
// ],
// };

#[tonic::async_trait]
impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorService {
Expand Down Expand Up @@ -185,7 +187,7 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
})?;

let eip_712_domain = alloy::sol_types::eip712_domain! {
name: "FHEVMCoprocessor",
name: "InputVerifier",
version: "1",
chain_id: chain_id as u64,
verifying_contract: verifying_contract_address,
Expand All @@ -196,7 +198,7 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
// server key is biiig, clone the pointer
let server_key = std::sync::Arc::new(server_key);
let mut contract_addresses = Vec::with_capacity(req.input_ciphertexts.len());
let mut caller_addresses = Vec::with_capacity(req.input_ciphertexts.len());
let mut user_addresses = Vec::with_capacity(req.input_ciphertexts.len());
for ci in &req.input_ciphertexts {
// parse addresses
contract_addresses.push(
Expand All @@ -207,8 +209,8 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
}
})?,
);
caller_addresses.push(
alloy::primitives::Address::from_str(&ci.caller_address).map_err(|e| {
user_addresses.push(
alloy::primitives::Address::from_str(&ci.user_address).map_err(|e| {
CoprocessorError::CannotParseEthereumAddress {
bad_address: ci.contract_address.clone(),
parsing_error: e.to_string(),
Expand Down Expand Up @@ -300,11 +302,11 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
let mut hash_of_ciphertext: [u8; 32] = [0; 32];
hash_of_ciphertext.copy_from_slice(&blob_hash);

let mut ct_verification = CiphertextVerification {
let mut ct_verification = CiphertextVerificationForCopro {
hashOfCiphertext: alloy::primitives::FixedBytes(hash_of_ciphertext),
aclAddress: acl_contract_address,
contractAddress: contract_addresses[idx],
callerAddress: caller_addresses[idx],
userAddress: user_addresses[idx],
handlesList: Vec::with_capacity(corresponding_unpacked.len()),
};

Expand All @@ -313,9 +315,9 @@ impl coprocessor::fhevm_coprocessor_server::FhevmCoprocessor for CoprocessorServ
hash_of_ciphertext: hash_of_ciphertext.to_vec(),
input_handles: Vec::with_capacity(corresponding_unpacked.len()),
eip712_signature: Vec::new(),
eip712_contract_address: contract_addresses[idx].to_string(),
eip712_caller_address: caller_addresses[idx].to_string(),
eip712_signer_address: self.signer.address().to_string(),
contract_address: contract_addresses[idx].to_string(),
user_address: user_addresses[idx].to_string(),
signer_address: self.signer.address().to_string(),
};

for (ct_idx, the_ct) in corresponding_unpacked.iter().enumerate() {
Expand Down
10 changes: 5 additions & 5 deletions fhevm-engine/coprocessor/src/tests/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use crate::{
},
},
tests::{
inputs::{test_random_caller_address, test_random_contract_address},
inputs::{test_random_user_address, test_random_contract_address},
utils::{default_api_key, default_tenant_id, setup_test_app},
},
};
Expand Down Expand Up @@ -55,7 +55,7 @@ async fn test_coprocessor_input_errors() -> Result<(), Box<dyn std::error::Error
input_ciphertexts.push(InputToUpload {
input_payload: serialized.clone(),
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
});
}
Expand Down Expand Up @@ -97,7 +97,7 @@ async fn test_coprocessor_input_errors() -> Result<(), Box<dyn std::error::Error
input_ciphertexts.push(InputToUpload {
input_payload: serialized[0..32].to_vec(),
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
});

Expand Down Expand Up @@ -134,7 +134,7 @@ async fn test_coprocessor_input_errors() -> Result<(), Box<dyn std::error::Error
input_ciphertexts.push(InputToUpload {
input_payload: serialized,
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
});

Expand Down Expand Up @@ -299,7 +299,7 @@ async fn test_coprocessor_computation_errors() -> Result<(), Box<dyn std::error:
input_ciphertexts.push(InputToUpload {
input_payload: serialized,
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
});

Expand Down
33 changes: 30 additions & 3 deletions fhevm-engine/coprocessor/src/tests/inputs.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::str::FromStr;

use alloy::primitives::keccak256;
use fhevm_engine_common::utils::safe_serialize;
use tfhe::integer::{bigint::StaticUnsignedBigInt, U256};
use tonic::metadata::MetadataValue;
Expand All @@ -12,7 +13,7 @@ use crate::{
tests::utils::{decrypt_ciphertexts, default_api_key, default_tenant_id, setup_test_app},
};

pub fn test_random_caller_address() -> String {
pub fn test_random_user_address() -> String {
let _private_key = "bd2400c676871534a682ca1c5e4cd647ec9c3e122f188c6e3f54e6900d586c7b";
let public_key = "0x1BdA2a485c339C95a9AbfDe52E80ca38e34C199E";
public_key.to_string()
Expand Down Expand Up @@ -40,6 +41,7 @@ async fn test_fhe_inputs() -> Result<(), Box<dyn std::error::Error>> {
})?;
let keys = &keys[0];

println!("Building list");
let mut builder = tfhe::ProvenCompactCiphertextList::builder(&keys.pks);
let the_list = builder
.push(false)
Expand All @@ -57,13 +59,15 @@ async fn test_fhe_inputs() -> Result<(), Box<dyn std::error::Error>> {
.unwrap();

let serialized = safe_serialize(&the_list);
let input_bytes = keccak256(&serialized);
println!("input hash: 0x{}", hex::encode(input_bytes));

println!("Encrypting inputs...");
let mut input_request = tonic::Request::new(InputUploadBatch {
input_ciphertexts: vec![InputToUpload {
input_payload: serialized,
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
}],
});
Expand All @@ -74,6 +78,25 @@ async fn test_fhe_inputs() -> Result<(), Box<dyn std::error::Error>> {
let resp = client.upload_inputs(input_request).await?;
let resp = resp.get_ref();
assert_eq!(resp.upload_responses.len(), 1);
for resp in &resp.upload_responses {
println!(r#"response
acl address: {}
contract address: {}
hash: 0x{}
caller: {}
signer: {}
signature: 0x{}
handles: {:#?}
"#,
resp.acl_address,
resp.contract_address,
hex::encode(&resp.hash_of_ciphertext),
resp.user_address,
resp.signer_address,
hex::encode(&resp.eip712_signature),
resp.input_handles.iter().map(|i| hex::encode(&i.handle)).collect::<Vec<_>>()
);
}

let first_resp = &resp.upload_responses[0];

Expand Down Expand Up @@ -134,6 +157,7 @@ async fn custom_insert_inputs() -> Result<(), Box<dyn std::error::Error>> {
})?;
let keys = &keys[0];

println!("Building list");
let mut builder = tfhe::ProvenCompactCiphertextList::builder(&keys.pks);
let the_list = builder
.push(false)
Expand All @@ -146,13 +170,15 @@ async fn custom_insert_inputs() -> Result<(), Box<dyn std::error::Error>> {
.unwrap();

let serialized = safe_serialize(&the_list);
let input_bytes = keccak256(&serialized);
println!("input hash: 0x{}", hex::encode(input_bytes));

println!("Encrypting inputs...");
let mut input_request = tonic::Request::new(InputUploadBatch {
input_ciphertexts: vec![InputToUpload {
input_payload: serialized,
signature: Vec::new(),
caller_address: test_random_caller_address(),
user_address: test_random_user_address(),
contract_address: test_random_contract_address(),
}],
});
Expand All @@ -168,6 +194,7 @@ async fn custom_insert_inputs() -> Result<(), Box<dyn std::error::Error>> {
println!("request {idx}");
for (idx, h) in ur.input_handles.iter().enumerate() {
println!(" ct {idx} 0x{}", hex::encode(&h.handle));
println!(" response {:?}", ur);
}
}

Expand Down
8 changes: 4 additions & 4 deletions proto/coprocessor.proto
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ message AsyncComputationInput {
message InputToUpload {
bytes input_payload = 1;
string contract_address = 2;
string caller_address = 3;
string user_address = 3;
bytes signature = 4;
}

Expand All @@ -75,9 +75,9 @@ message InputCiphertextResponse {
string aclAddress = 1;
bytes hashOfCiphertext = 2;
repeated InputCiphertextResponseHandle input_handles = 3;
string eip712ContractAddress = 5;
string eip712CallerAddress = 6;
string eip712SignerAddress = 7;
string contractAddress = 5;
string userAddress = 6;
string signerAddress = 7;
bytes eip712Signature = 8;
}

Expand Down

0 comments on commit a0d9443

Please sign in to comment.