diff --git a/lee/state_machine/src/privacy_preserving_transaction/message.rs b/lee/state_machine/src/privacy_preserving_transaction/message.rs index 6a289a0a..899771bf 100644 --- a/lee/state_machine/src/privacy_preserving_transaction/message.rs +++ b/lee/state_machine/src/privacy_preserving_transaction/message.rs @@ -1,8 +1,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use lee_core::{ - Commitment, CommitmentSetDigest, Nullifier, NullifierPublicKey, PrivacyPreservingCircuitOutput, + Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput, account::{Account, Nonce}, - encryption::{Ciphertext, EphemeralPublicKey, ViewingPublicKey}, program::{BlockValidityWindow, TimestampValidityWindow}, }; use sha2::{Digest as _, Sha256}; @@ -11,41 +10,7 @@ use crate::{AccountId, error::LeeError}; const PREFIX: &[u8; 32] = b"/LEE/v0.3/Message/Privacy/\x00\x00\x00\x00\x00\x00"; -pub type ViewTag = u8; - -#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] -pub struct EncryptedAccountData { - pub ciphertext: Ciphertext, - pub epk: EphemeralPublicKey, - pub view_tag: ViewTag, -} - -impl EncryptedAccountData { - fn new( - ciphertext: Ciphertext, - npk: &NullifierPublicKey, - vpk: &ViewingPublicKey, - epk: EphemeralPublicKey, - ) -> Self { - let view_tag = Self::compute_view_tag(npk, vpk); - Self { - ciphertext, - epk, - view_tag, - } - } - - /// Computes the tag as the first byte of SHA256("/LEE/v0.3/ViewTag/" || Npk || vpk). - #[must_use] - pub fn compute_view_tag(npk: &NullifierPublicKey, vpk: &ViewingPublicKey) -> ViewTag { - let mut hasher = Sha256::new(); - hasher.update(b"/LEE/v0.3/ViewTag/"); - hasher.update(npk.to_byte_array()); - hasher.update(vpk.to_bytes()); - let digest: [u8; 32] = hasher.finalize().into(); - digest[0] - } -} +pub use lee_core::{EncryptedAccountData, ViewTag}; #[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)] pub struct Message { @@ -92,28 +57,13 @@ impl Message { pub fn try_from_circuit_output( public_account_ids: Vec, nonces: Vec, - public_keys: Vec<(NullifierPublicKey, ViewingPublicKey, EphemeralPublicKey)>, output: PrivacyPreservingCircuitOutput, ) -> Result { - if public_keys.len() != output.ciphertexts.len() { - return Err(LeeError::InvalidInput( - "Ephemeral public keys and ciphertexts length mismatch".into(), - )); - } - - let encrypted_private_post_states = output - .ciphertexts - .into_iter() - .zip(public_keys) - .map(|(ciphertext, (npk, vpk, epk))| { - EncryptedAccountData::new(ciphertext, &npk, &vpk, epk) - }) - .collect(); Ok(Self { public_account_ids, nonces, public_post_states: output.public_post_states, - encrypted_private_post_states, + encrypted_private_post_states: output.encrypted_private_post_states, new_commitments: output.new_commitments, new_nullifiers: output.new_nullifiers, block_validity_window: output.block_validity_window, diff --git a/lee/state_machine/src/validated_state_diff.rs b/lee/state_machine/src/validated_state_diff.rs index cfbd1703..9efd8005 100644 --- a/lee/state_machine/src/validated_state_diff.rs +++ b/lee/state_machine/src/validated_state_diff.rs @@ -492,12 +492,7 @@ fn check_privacy_preserving_circuit_proof_is_valid( let output = PrivacyPreservingCircuitOutput { public_pre_states: public_pre_states.to_vec(), public_post_states: message.public_post_states.clone(), - ciphertexts: message - .encrypted_private_post_states - .iter() - .cloned() - .map(|value| value.ciphertext) - .collect(), + encrypted_private_post_states: message.encrypted_private_post_states.clone(), new_commitments: message.new_commitments.clone(), new_nullifiers: message.new_nullifiers.clone(), block_validity_window: message.block_validity_window, @@ -542,7 +537,7 @@ mod tests { #[test] fn privacy_malicious_programs_cannot_drain_public_victim() { use lee_core::{ - Commitment, InputAccountIdentity, SharedSecretKey, + Commitment, EncryptedAccountData, InputAccountIdentity, SharedSecretKey, account::{Account, AccountWithMetadata}, }; @@ -626,6 +621,11 @@ mod tests { // [2] recipient — first seen in authenticated_transfer's program_output.pre_states let account_identities = vec![ InputAccountIdentity::PrivateAuthorizedUpdate { + epk: attacker_epk, + view_tag: EncryptedAccountData::compute_view_tag( + &attacker_keys.npk(), + &attacker_keys.vpk(), + ), ssk: attacker_ssk, nsk: attacker_keys.nsk, membership_proof, @@ -650,7 +650,6 @@ mod tests { let message = Message::try_from_circuit_output( vec![victim_id, recipient_id], vec![], // no public signers, no nonces - vec![(attacker_keys.npk(), attacker_keys.vpk(), attacker_epk)], circuit_output, ) .unwrap(); @@ -690,7 +689,7 @@ mod tests { #[test] fn privacy_malicious_programs_cannot_drain_private_victim() { use lee_core::{ - Commitment, InputAccountIdentity, SharedSecretKey, + Commitment, EncryptedAccountData, InputAccountIdentity, SharedSecretKey, account::{Account, AccountWithMetadata}, }; @@ -782,6 +781,11 @@ mod tests { // so PrivateAuthorizedUpdate is not an option. let account_identities = vec![ InputAccountIdentity::PrivateAuthorizedUpdate { + epk: attacker_epk, + view_tag: EncryptedAccountData::compute_view_tag( + &attacker_keys.npk(), + &attacker_keys.vpk(), + ), ssk: attacker_ssk, nsk: attacker_keys.nsk, membership_proof, @@ -807,7 +811,6 @@ mod tests { let message = Message::try_from_circuit_output( vec![victim_id, recipient_id], vec![], // no public signers, no nonces - vec![(attacker_keys.npk(), attacker_keys.vpk(), attacker_epk)], circuit_output, ) .unwrap();