mirror of
https://github.com/logos-blockchain/logos-execution-zone.git
synced 2026-08-02 11:03:14 +00:00
Merge pull request #564 from logos-blockchain/artem/obfuscate-note-order
feat!: obfuscate note and cipher order
This commit is contained in:
commit
397d6d49b3
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -81,7 +81,7 @@ async fn private_transfer_to_foreign_account() -> Result<()> {
|
|||||||
.context("Failed to get private account commitment for sender")?;
|
.context("Failed to get private account commitment for sender")?;
|
||||||
|
|
||||||
let tx = fetch_privacy_preserving_tx(ctx.sequencer_client(), tx_hash).await;
|
let tx = fetch_privacy_preserving_tx(ctx.sequencer_client(), tx_hash).await;
|
||||||
assert_eq!(tx.message.new_commitments[0], new_commitment1);
|
assert!(tx.message.new_commitments.contains(&new_commitment1));
|
||||||
|
|
||||||
for commitment in tx.message.new_commitments {
|
for commitment in tx.message.new_commitments {
|
||||||
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
||||||
@ -210,7 +210,7 @@ async fn private_transfer_to_owned_account_using_claiming_path() -> Result<()> {
|
|||||||
.wallet()
|
.wallet()
|
||||||
.get_private_account_commitment(from)
|
.get_private_account_commitment(from)
|
||||||
.context("Failed to get private account commitment for sender")?;
|
.context("Failed to get private account commitment for sender")?;
|
||||||
assert_eq!(tx.message.new_commitments[0], sender_commitment);
|
assert!(tx.message.new_commitments.contains(&sender_commitment));
|
||||||
|
|
||||||
for commitment in tx.message.new_commitments {
|
for commitment in tx.message.new_commitments {
|
||||||
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
||||||
@ -286,9 +286,9 @@ async fn shielded_transfer_to_foreign_account() -> Result<()> {
|
|||||||
|
|
||||||
let acc_1_balance = account_balance(&ctx, from).await?;
|
let acc_1_balance = account_balance(&ctx, from).await?;
|
||||||
|
|
||||||
assert!(
|
for commitment in tx.message.new_commitments {
|
||||||
verify_commitment_is_in_state(tx.message.new_commitments[0], ctx.sequencer_client()).await
|
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
||||||
);
|
}
|
||||||
|
|
||||||
assert_eq!(acc_1_balance, 9900);
|
assert_eq!(acc_1_balance, 9900);
|
||||||
|
|
||||||
|
|||||||
@ -71,7 +71,7 @@ async fn sync_private_account_with_non_zero_chain_index() -> Result<()> {
|
|||||||
.wallet()
|
.wallet()
|
||||||
.get_private_account_commitment(from)
|
.get_private_account_commitment(from)
|
||||||
.context("Failed to get private account commitment for sender")?;
|
.context("Failed to get private account commitment for sender")?;
|
||||||
assert_eq!(tx.message.new_commitments[0], new_commitment1);
|
assert!(tx.message.new_commitments.contains(&new_commitment1));
|
||||||
|
|
||||||
for commitment in tx.message.new_commitments {
|
for commitment in tx.message.new_commitments {
|
||||||
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
assert!(verify_commitment_is_in_state(commitment, ctx.sequencer_client()).await);
|
||||||
|
|||||||
@ -15,3 +15,6 @@ workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
lee_core.workspace = true
|
lee_core.workspace = true
|
||||||
risc0-zkvm.workspace = true
|
risc0-zkvm.workspace = true
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
lee_core = { workspace = true, features = ["host"] }
|
||||||
|
|||||||
@ -32,7 +32,6 @@ pub fn compute_circuit_output(
|
|||||||
"Invalid account_identities length"
|
"Invalid account_identities length"
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut output_index = 0;
|
|
||||||
for (pos, (account_identity, (pre_state, post_state))) in
|
for (pos, (account_identity, (pre_state, post_state))) in
|
||||||
account_identities.iter().zip(states_iter).enumerate()
|
account_identities.iter().zip(states_iter).enumerate()
|
||||||
{
|
{
|
||||||
@ -71,7 +70,6 @@ pub fn compute_circuit_output(
|
|||||||
|
|
||||||
emit_private_output(
|
emit_private_output(
|
||||||
&mut output,
|
&mut output,
|
||||||
&mut output_index,
|
|
||||||
post_state,
|
post_state,
|
||||||
&account_id,
|
&account_id,
|
||||||
&PrivateAccountKind::Regular(*identifier),
|
&PrivateAccountKind::Regular(*identifier),
|
||||||
@ -109,7 +107,6 @@ pub fn compute_circuit_output(
|
|||||||
|
|
||||||
emit_private_output(
|
emit_private_output(
|
||||||
&mut output,
|
&mut output,
|
||||||
&mut output_index,
|
|
||||||
post_state,
|
post_state,
|
||||||
&account_id,
|
&account_id,
|
||||||
&PrivateAccountKind::Regular(*identifier),
|
&PrivateAccountKind::Regular(*identifier),
|
||||||
@ -149,7 +146,6 @@ pub fn compute_circuit_output(
|
|||||||
|
|
||||||
emit_private_output(
|
emit_private_output(
|
||||||
&mut output,
|
&mut output,
|
||||||
&mut output_index,
|
|
||||||
post_state,
|
post_state,
|
||||||
&account_id,
|
&account_id,
|
||||||
&PrivateAccountKind::Regular(*identifier),
|
&PrivateAccountKind::Regular(*identifier),
|
||||||
@ -197,7 +193,6 @@ pub fn compute_circuit_output(
|
|||||||
let view_tag = EncryptedAccountData::compute_view_tag(npk, vpk);
|
let view_tag = EncryptedAccountData::compute_view_tag(npk, vpk);
|
||||||
emit_private_output(
|
emit_private_output(
|
||||||
&mut output,
|
&mut output,
|
||||||
&mut output_index,
|
|
||||||
post_state,
|
post_state,
|
||||||
&account_id,
|
&account_id,
|
||||||
&PrivateAccountKind::Pda {
|
&PrivateAccountKind::Pda {
|
||||||
@ -245,7 +240,6 @@ pub fn compute_circuit_output(
|
|||||||
.expect("PrivatePdaUpdate position must be in pda_seed_by_position");
|
.expect("PrivatePdaUpdate position must be in pda_seed_by_position");
|
||||||
emit_private_output(
|
emit_private_output(
|
||||||
&mut output,
|
&mut output,
|
||||||
&mut output_index,
|
|
||||||
post_state,
|
post_state,
|
||||||
&account_id,
|
&account_id,
|
||||||
&PrivateAccountKind::Pda {
|
&PrivateAccountKind::Pda {
|
||||||
@ -267,9 +261,24 @@ pub fn compute_circuit_output(
|
|||||||
emit_dummy_output(&mut output, dummy);
|
emit_dummy_output(&mut output, dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
obfuscate_output_ordering(&mut output);
|
||||||
|
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn obfuscate_output_ordering(output: &mut PrivacyPreservingCircuitOutput) {
|
||||||
|
output
|
||||||
|
.new_commitments
|
||||||
|
.sort_unstable_by_key(Commitment::to_byte_array);
|
||||||
|
|
||||||
|
let mut notes: Vec<_> = core::mem::take(&mut output.new_nullifiers)
|
||||||
|
.into_iter()
|
||||||
|
.zip(core::mem::take(&mut output.encrypted_private_post_states))
|
||||||
|
.collect();
|
||||||
|
notes.sort_unstable_by_key(|((nullifier, _), _)| nullifier.to_byte_array());
|
||||||
|
(output.new_nullifiers, output.encrypted_private_post_states) = notes.into_iter().unzip();
|
||||||
|
}
|
||||||
|
|
||||||
fn emit_dummy_output(output: &mut PrivacyPreservingCircuitOutput, dummy: DummyInput) {
|
fn emit_dummy_output(output: &mut PrivacyPreservingCircuitOutput, dummy: DummyInput) {
|
||||||
// Note: the nullifiers and commitments are generated from seeds.
|
// Note: the nullifiers and commitments are generated from seeds.
|
||||||
// The prover is responsible for their randomness.
|
// The prover is responsible for their randomness.
|
||||||
@ -294,7 +303,6 @@ fn emit_dummy_output(output: &mut PrivacyPreservingCircuitOutput, dummy: DummyIn
|
|||||||
)]
|
)]
|
||||||
fn emit_private_output(
|
fn emit_private_output(
|
||||||
output: &mut PrivacyPreservingCircuitOutput,
|
output: &mut PrivacyPreservingCircuitOutput,
|
||||||
output_index: &mut u32,
|
|
||||||
post_state: Account,
|
post_state: Account,
|
||||||
account_id: &AccountId,
|
account_id: &AccountId,
|
||||||
kind: &PrivateAccountKind,
|
kind: &PrivateAccountKind,
|
||||||
@ -304,8 +312,6 @@ fn emit_private_output(
|
|||||||
new_nullifier: (Nullifier, CommitmentSetDigest),
|
new_nullifier: (Nullifier, CommitmentSetDigest),
|
||||||
new_nonce: Nonce,
|
new_nonce: Nonce,
|
||||||
) {
|
) {
|
||||||
output.new_nullifiers.push(new_nullifier);
|
|
||||||
|
|
||||||
let mut post_with_updated_nonce = post_state;
|
let mut post_with_updated_nonce = post_state;
|
||||||
post_with_updated_nonce.nonce = new_nonce;
|
post_with_updated_nonce.nonce = new_nonce;
|
||||||
|
|
||||||
@ -318,10 +324,10 @@ fn emit_private_output(
|
|||||||
&post_with_updated_nonce,
|
&post_with_updated_nonce,
|
||||||
kind,
|
kind,
|
||||||
&shared_secret,
|
&shared_secret,
|
||||||
&commitment_post,
|
&new_nullifier.0,
|
||||||
*output_index,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
output.new_nullifiers.push(new_nullifier);
|
||||||
output.new_commitments.push(commitment_post);
|
output.new_commitments.push(commitment_post);
|
||||||
output
|
output
|
||||||
.encrypted_private_post_states
|
.encrypted_private_post_states
|
||||||
@ -330,9 +336,6 @@ fn emit_private_output(
|
|||||||
epk,
|
epk,
|
||||||
view_tag,
|
view_tag,
|
||||||
});
|
});
|
||||||
*output_index = output_index
|
|
||||||
.checked_add(1)
|
|
||||||
.unwrap_or_else(|| panic!("Too many private accounts, output index overflow"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_update_nullifier_and_set_digest(
|
fn compute_update_nullifier_and_set_digest(
|
||||||
@ -346,3 +349,83 @@ fn compute_update_nullifier_and_set_digest(
|
|||||||
let nullifier = Nullifier::for_account_update(&commitment_pre, nsk);
|
let nullifier = Nullifier::for_account_update(&commitment_pre, nsk);
|
||||||
(nullifier, set_digest)
|
(nullifier, set_digest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use lee_core::{DUMMY_COMMITMENT_HASH, EphemeralPublicKey};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
fn note(tag: u8) -> (Nullifier, Commitment, EncryptedAccountData) {
|
||||||
|
let nullifier = Nullifier::for_dummy(&[tag; 32]);
|
||||||
|
let commitment = Commitment::for_dummy(&nullifier, &[tag; 32]);
|
||||||
|
let ciphertext = EncryptionScheme::encrypt(
|
||||||
|
&Account::default(),
|
||||||
|
&PrivateAccountKind::Regular(0),
|
||||||
|
&SharedSecretKey([0; 32]),
|
||||||
|
&nullifier,
|
||||||
|
);
|
||||||
|
let encrypted = EncryptedAccountData {
|
||||||
|
ciphertext,
|
||||||
|
epk: EphemeralPublicKey(vec![tag]),
|
||||||
|
view_tag: 0,
|
||||||
|
};
|
||||||
|
(nullifier, commitment, encrypted)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn obfuscate_byte_sorts_commitments_and_nullifiers() {
|
||||||
|
let mut output = PrivacyPreservingCircuitOutput::default();
|
||||||
|
for tag in 0..3 {
|
||||||
|
let (nullifier, commitment, encrypted) = note(tag);
|
||||||
|
output
|
||||||
|
.new_nullifiers
|
||||||
|
.push((nullifier, DUMMY_COMMITMENT_HASH));
|
||||||
|
output.new_commitments.push(commitment);
|
||||||
|
output.encrypted_private_post_states.push(encrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
obfuscate_output_ordering(&mut output);
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
output
|
||||||
|
.new_commitments
|
||||||
|
.is_sorted_by_key(Commitment::to_byte_array)
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
output
|
||||||
|
.new_nullifiers
|
||||||
|
.is_sorted_by_key(|(nullifier, _)| nullifier.to_byte_array())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn obfuscate_keeps_each_nullifier_with_its_ciphertext() {
|
||||||
|
let mut output = PrivacyPreservingCircuitOutput::default();
|
||||||
|
for tag in 0..3 {
|
||||||
|
let (nullifier, _, encrypted) = note(tag);
|
||||||
|
output
|
||||||
|
.new_nullifiers
|
||||||
|
.push((nullifier, DUMMY_COMMITMENT_HASH));
|
||||||
|
output.encrypted_private_post_states.push(encrypted);
|
||||||
|
}
|
||||||
|
let paired: HashMap<[u8; 32], EphemeralPublicKey> = output
|
||||||
|
.new_nullifiers
|
||||||
|
.iter()
|
||||||
|
.zip(&output.encrypted_private_post_states)
|
||||||
|
.map(|((nullifier, _), note)| (nullifier.to_byte_array(), note.epk.clone()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
obfuscate_output_ordering(&mut output);
|
||||||
|
|
||||||
|
for ((nullifier, _), note) in output
|
||||||
|
.new_nullifiers
|
||||||
|
.iter()
|
||||||
|
.zip(&output.encrypted_private_post_states)
|
||||||
|
{
|
||||||
|
assert_eq!(paired[&nullifier.to_byte_array()], note.epk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -148,7 +148,7 @@ impl InputAccountIdentity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
|
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq, Default))]
|
||||||
pub struct PrivacyPreservingCircuitOutput {
|
pub struct PrivacyPreservingCircuitOutput {
|
||||||
pub public_pre_states: Vec<AccountWithMetadata>,
|
pub public_pre_states: Vec<AccountWithMetadata>,
|
||||||
pub public_post_states: Vec<Account>,
|
pub public_post_states: Vec<Account>,
|
||||||
|
|||||||
@ -97,11 +97,6 @@ impl NullifierPublicKey {
|
|||||||
|
|
||||||
#[cfg(feature = "host")]
|
#[cfg(feature = "host")]
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
#[must_use]
|
|
||||||
pub const fn to_byte_array(&self) -> [u8; 32] {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "host")]
|
#[cfg(feature = "host")]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub const fn from_byte_array(bytes: [u8; 32]) -> Self {
|
pub const fn from_byte_array(bytes: [u8; 32]) -> Self {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use risc0_zkvm::sha::{Impl, Sha256 as _};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use shared_key_derivation::{MlKem768EncapsulationKey, ViewingPublicKey};
|
pub use shared_key_derivation::{MlKem768EncapsulationKey, ViewingPublicKey};
|
||||||
|
|
||||||
use crate::{Commitment, account::Account, program::PrivateAccountKind};
|
use crate::{Nullifier, account::Account, program::PrivateAccountKind};
|
||||||
pub mod shared_key_derivation;
|
pub mod shared_key_derivation;
|
||||||
|
|
||||||
/// Length in bytes of an ML-KEM-768 ciphertext (the `EphemeralPublicKey` payload).
|
/// Length in bytes of an ML-KEM-768 ciphertext (the `EphemeralPublicKey` payload).
|
||||||
@ -114,39 +114,32 @@ impl EncryptionScheme {
|
|||||||
account: &Account,
|
account: &Account,
|
||||||
kind: &PrivateAccountKind,
|
kind: &PrivateAccountKind,
|
||||||
shared_secret: &SharedSecretKey,
|
shared_secret: &SharedSecretKey,
|
||||||
commitment: &Commitment,
|
nullifier: &Nullifier,
|
||||||
output_index: u32,
|
|
||||||
) -> Ciphertext {
|
) -> Ciphertext {
|
||||||
// Plaintext: PrivateAccountKind::HEADER_LEN bytes header || account bytes.
|
// Plaintext: PrivateAccountKind::HEADER_LEN bytes header || account bytes.
|
||||||
// Both variants produce the same header length — see PrivateAccountKind::to_header_bytes.
|
// Both variants produce the same header length — see PrivateAccountKind::to_header_bytes.
|
||||||
let mut buffer = kind.to_header_bytes().to_vec();
|
let mut buffer = kind.to_header_bytes().to_vec();
|
||||||
buffer.extend_from_slice(&account.to_bytes());
|
buffer.extend_from_slice(&account.to_bytes());
|
||||||
Self::symmetric_transform(&mut buffer, shared_secret, commitment, output_index);
|
Self::symmetric_transform(&mut buffer, shared_secret, nullifier);
|
||||||
Ciphertext(buffer)
|
Ciphertext(buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn symmetric_transform(
|
fn symmetric_transform(
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
shared_secret: &SharedSecretKey,
|
shared_secret: &SharedSecretKey,
|
||||||
commitment: &Commitment,
|
nullifier: &Nullifier,
|
||||||
output_index: u32,
|
|
||||||
) {
|
) {
|
||||||
let key = Self::kdf(shared_secret, commitment, output_index);
|
let key = Self::kdf(shared_secret, nullifier);
|
||||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||||
cipher.apply_keystream(buffer);
|
cipher.apply_keystream(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn kdf(
|
fn kdf(shared_secret: &SharedSecretKey, nullifier: &Nullifier) -> [u8; 32] {
|
||||||
shared_secret: &SharedSecretKey,
|
const PREFIX: &[u8; 20] = b"LEE/v0.3/KDF-SHA256/";
|
||||||
commitment: &Commitment,
|
let mut bytes = [0_u8; 20 + 32 + 32];
|
||||||
output_index: u32,
|
|
||||||
) -> [u8; 32] {
|
|
||||||
const PREFIX: &[u8; 20] = b"LEE/v0.2/KDF-SHA256/";
|
|
||||||
let mut bytes = [0_u8; 20 + 32 + 32 + 4];
|
|
||||||
bytes[0..20].copy_from_slice(PREFIX);
|
bytes[0..20].copy_from_slice(PREFIX);
|
||||||
bytes[20..52].copy_from_slice(&shared_secret.0);
|
bytes[20..52].copy_from_slice(&shared_secret.0);
|
||||||
bytes[52..84].copy_from_slice(&commitment.to_byte_array());
|
bytes[52..84].copy_from_slice(&nullifier.to_byte_array());
|
||||||
bytes[84..88].copy_from_slice(&output_index.to_le_bytes());
|
|
||||||
|
|
||||||
Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()
|
Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()
|
||||||
}
|
}
|
||||||
@ -160,12 +153,11 @@ impl EncryptionScheme {
|
|||||||
pub fn decrypt(
|
pub fn decrypt(
|
||||||
ciphertext: &Ciphertext,
|
ciphertext: &Ciphertext,
|
||||||
shared_secret: &SharedSecretKey,
|
shared_secret: &SharedSecretKey,
|
||||||
commitment: &Commitment,
|
nullifier: &Nullifier,
|
||||||
output_index: u32,
|
|
||||||
) -> Option<(PrivateAccountKind, Account)> {
|
) -> Option<(PrivateAccountKind, Account)> {
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
let mut buffer = ciphertext.0.clone();
|
let mut buffer = ciphertext.0.clone();
|
||||||
Self::symmetric_transform(&mut buffer, shared_secret, commitment, output_index);
|
Self::symmetric_transform(&mut buffer, shared_secret, nullifier);
|
||||||
|
|
||||||
if buffer.len() < PrivateAccountKind::HEADER_LEN {
|
if buffer.len() < PrivateAccountKind::HEADER_LEN {
|
||||||
return None;
|
return None;
|
||||||
@ -180,8 +172,7 @@ impl EncryptionScheme {
|
|||||||
println!(
|
println!(
|
||||||
"Failed to decode {ciphertext:?} \n
|
"Failed to decode {ciphertext:?} \n
|
||||||
with secret {:?} ,\n
|
with secret {:?} ,\n
|
||||||
commitment {commitment:?} ,\n
|
nullifier {nullifier:?} ,\n
|
||||||
and output_index {output_index} ,\n
|
|
||||||
with error {err:?}",
|
with error {err:?}",
|
||||||
shared_secret.0
|
shared_secret.0
|
||||||
);
|
);
|
||||||
@ -203,14 +194,13 @@ mod tests {
|
|||||||
fn encrypt_same_length_for_account_and_pda() {
|
fn encrypt_same_length_for_account_and_pda() {
|
||||||
let account = Account::default();
|
let account = Account::default();
|
||||||
let secret = SharedSecretKey([0_u8; 32]);
|
let secret = SharedSecretKey([0_u8; 32]);
|
||||||
let commitment = crate::Commitment::new(&AccountId::new([0_u8; 32]), &Account::default());
|
let nullifier = Nullifier::for_account_initialization(&AccountId::new([0_u8; 32]));
|
||||||
|
|
||||||
let account_ct = EncryptionScheme::encrypt(
|
let account_ct = EncryptionScheme::encrypt(
|
||||||
&account,
|
&account,
|
||||||
&PrivateAccountKind::Regular(42),
|
&PrivateAccountKind::Regular(42),
|
||||||
&secret,
|
&secret,
|
||||||
&commitment,
|
&nullifier,
|
||||||
0,
|
|
||||||
);
|
);
|
||||||
let pda_ct = EncryptionScheme::encrypt(
|
let pda_ct = EncryptionScheme::encrypt(
|
||||||
&account,
|
&account,
|
||||||
@ -220,8 +210,7 @@ mod tests {
|
|||||||
identifier: 42,
|
identifier: 42,
|
||||||
},
|
},
|
||||||
&secret,
|
&secret,
|
||||||
&commitment,
|
&nullifier,
|
||||||
0,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(account_ct.0.len(), pda_ct.0.len());
|
assert_eq!(account_ct.0.len(), pda_ct.0.len());
|
||||||
@ -245,11 +234,11 @@ mod tests {
|
|||||||
..Account::default()
|
..Account::default()
|
||||||
};
|
};
|
||||||
let kind = PrivateAccountKind::Regular(0);
|
let kind = PrivateAccountKind::Regular(0);
|
||||||
let commitment = crate::Commitment::new(&AccountId::new([7_u8; 32]), &account);
|
let nullifier = Nullifier::for_account_initialization(&AccountId::new([7_u8; 32]));
|
||||||
|
|
||||||
let ct = EncryptionScheme::encrypt(&account, &kind, &sender_ss, &commitment, 0);
|
let ct = EncryptionScheme::encrypt(&account, &kind, &sender_ss, &nullifier);
|
||||||
let (decoded_kind, decoded_account) =
|
let (decoded_kind, decoded_account) =
|
||||||
EncryptionScheme::decrypt(&ct, &receiver_ss, &commitment, 0)
|
EncryptionScheme::decrypt(&ct, &receiver_ss, &nullifier)
|
||||||
.expect("decryption must succeed with correct shared secret");
|
.expect("decryption must succeed with correct shared secret");
|
||||||
|
|
||||||
assert_eq!(decoded_account, account);
|
assert_eq!(decoded_account, account);
|
||||||
@ -257,11 +246,19 @@ mod tests {
|
|||||||
|
|
||||||
// Wrong shared secret must not decrypt correctly.
|
// Wrong shared secret must not decrypt correctly.
|
||||||
let wrong_ss = SharedSecretKey([0_u8; 32]);
|
let wrong_ss = SharedSecretKey([0_u8; 32]);
|
||||||
let bad = EncryptionScheme::decrypt(&ct, &wrong_ss, &commitment, 0);
|
let bad_via_ss = EncryptionScheme::decrypt(&ct, &wrong_ss, &nullifier);
|
||||||
assert!(
|
assert!(
|
||||||
bad.is_none() || bad.is_some_and(|(_, a)| a.balance != 999),
|
bad_via_ss.is_none() || bad_via_ss.is_some_and(|(_, a)| a.balance != 999),
|
||||||
"wrong shared secret must not produce the correct plaintext"
|
"wrong shared secret must not produce the correct plaintext"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Wrong nullifier must not decrypt correctly.
|
||||||
|
let wrong_nullifier = Nullifier::for_account_initialization(&AccountId::new([9; 32]));
|
||||||
|
let bad_via_nlf = EncryptionScheme::decrypt(&ct, &receiver_ss, &wrong_nullifier);
|
||||||
|
assert!(
|
||||||
|
bad_via_nlf.is_none() || bad_via_nlf.is_some_and(|(_, a)| a.balance != 999),
|
||||||
|
"wrong nullifier must not produce the correct plaintext"
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
@ -117,6 +117,11 @@ impl Nullifier {
|
|||||||
bytes.extend_from_slice(nullifier_seed);
|
bytes.extend_from_slice(nullifier_seed);
|
||||||
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub const fn to_byte_array(&self) -> [u8; 32] {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|||||||
@ -26,8 +26,7 @@ fn decrypt_kind(
|
|||||||
let (kind, _) = EncryptionScheme::decrypt(
|
let (kind, _) = EncryptionScheme::decrypt(
|
||||||
&output.encrypted_private_post_states[idx].ciphertext,
|
&output.encrypted_private_post_states[idx].ciphertext,
|
||||||
ssk,
|
ssk,
|
||||||
&output.new_commitments[idx],
|
&output.new_nullifiers[idx].0,
|
||||||
u32::try_from(idx).expect("idx fits in u32"),
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
kind
|
kind
|
||||||
@ -114,8 +113,7 @@ fn prove_privacy_preserving_execution_circuit_public_and_private_pre_accounts()
|
|||||||
let (_identifier, recipient_post) = EncryptionScheme::decrypt(
|
let (_identifier, recipient_post) = EncryptionScheme::decrypt(
|
||||||
&output.encrypted_private_post_states[0].ciphertext,
|
&output.encrypted_private_post_states[0].ciphertext,
|
||||||
&shared_secret,
|
&shared_secret,
|
||||||
&output.new_commitments[0],
|
&output.new_nullifiers[0].0,
|
||||||
0,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(recipient_post, expected_recipient_post);
|
assert_eq!(recipient_post, expected_recipient_post);
|
||||||
@ -220,24 +218,41 @@ fn prove_privacy_preserving_execution_circuit_fully_private() {
|
|||||||
assert!(proof.is_valid_for(&output));
|
assert!(proof.is_valid_for(&output));
|
||||||
assert!(output.public_pre_states.is_empty());
|
assert!(output.public_pre_states.is_empty());
|
||||||
assert!(output.public_post_states.is_empty());
|
assert!(output.public_post_states.is_empty());
|
||||||
|
let sender_nullifier = expected_new_nullifiers[0].0;
|
||||||
|
let recipient_nullifier = expected_new_nullifiers[1].0;
|
||||||
|
|
||||||
|
let mut expected_new_commitments = expected_new_commitments;
|
||||||
|
expected_new_commitments.sort_unstable_by_key(Commitment::to_byte_array);
|
||||||
assert_eq!(output.new_commitments, expected_new_commitments);
|
assert_eq!(output.new_commitments, expected_new_commitments);
|
||||||
|
|
||||||
|
let mut expected_new_nullifiers = expected_new_nullifiers;
|
||||||
|
expected_new_nullifiers.sort_unstable_by_key(|(nullifier, _)| nullifier.to_byte_array());
|
||||||
assert_eq!(output.new_nullifiers, expected_new_nullifiers);
|
assert_eq!(output.new_nullifiers, expected_new_nullifiers);
|
||||||
|
|
||||||
assert_eq!(output.encrypted_private_post_states.len(), 2);
|
assert_eq!(output.encrypted_private_post_states.len(), 2);
|
||||||
|
|
||||||
|
let sender_slot = output
|
||||||
|
.new_nullifiers
|
||||||
|
.iter()
|
||||||
|
.position(|(nullifier, _)| *nullifier == sender_nullifier)
|
||||||
|
.unwrap();
|
||||||
let (_identifier, sender_post) = EncryptionScheme::decrypt(
|
let (_identifier, sender_post) = EncryptionScheme::decrypt(
|
||||||
&output.encrypted_private_post_states[0].ciphertext,
|
&output.encrypted_private_post_states[sender_slot].ciphertext,
|
||||||
&shared_secret_1,
|
&shared_secret_1,
|
||||||
&expected_new_commitments[0],
|
&output.new_nullifiers[sender_slot].0,
|
||||||
0,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(sender_post, expected_private_account_1);
|
assert_eq!(sender_post, expected_private_account_1);
|
||||||
|
|
||||||
|
let recipient_slot = output
|
||||||
|
.new_nullifiers
|
||||||
|
.iter()
|
||||||
|
.position(|(nullifier, _)| *nullifier == recipient_nullifier)
|
||||||
|
.unwrap();
|
||||||
let (_identifier, recipient_post) = EncryptionScheme::decrypt(
|
let (_identifier, recipient_post) = EncryptionScheme::decrypt(
|
||||||
&output.encrypted_private_post_states[1].ciphertext,
|
&output.encrypted_private_post_states[recipient_slot].ciphertext,
|
||||||
&shared_secret_2,
|
&shared_secret_2,
|
||||||
&expected_new_commitments[1],
|
&output.new_nullifiers[recipient_slot].0,
|
||||||
1,
|
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(recipient_post, expected_private_account_2);
|
assert_eq!(recipient_post, expected_private_account_2);
|
||||||
|
|||||||
@ -227,15 +227,14 @@ pub mod tests {
|
|||||||
let vpk = ViewingPublicKey::from_seed(&[2_u8; 32], &[3_u8; 32]);
|
let vpk = ViewingPublicKey::from_seed(&[2_u8; 32], &[3_u8; 32]);
|
||||||
let account = Account::default();
|
let account = Account::default();
|
||||||
let account_id = lee_core::account::AccountId::for_regular_private_account(&npk, &vpk, 0);
|
let account_id = lee_core::account::AccountId::for_regular_private_account(&npk, &vpk, 0);
|
||||||
let commitment = Commitment::new(&account_id, &account);
|
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||||
let (shared_secret, epk) =
|
let (shared_secret, epk) =
|
||||||
SharedSecretKey::encapsulate_deterministic(&vpk, &EphemeralSecretKey([0_u8; 32]));
|
SharedSecretKey::encapsulate_deterministic(&vpk, &EphemeralSecretKey([0_u8; 32]));
|
||||||
let ciphertext = EncryptionScheme::encrypt(
|
let ciphertext = EncryptionScheme::encrypt(
|
||||||
&account,
|
&account,
|
||||||
&PrivateAccountKind::Regular(0),
|
&PrivateAccountKind::Regular(0),
|
||||||
&shared_secret,
|
&shared_secret,
|
||||||
&commitment,
|
&nullifier,
|
||||||
2,
|
|
||||||
);
|
);
|
||||||
let encrypted_account_data =
|
let encrypted_account_data =
|
||||||
EncryptedAccountData::new(ciphertext.clone(), &npk, &vpk, epk.clone());
|
EncryptedAccountData::new(ciphertext.clone(), &npk, &vpk, epk.clone());
|
||||||
|
|||||||
@ -29,7 +29,7 @@ use lee_core::{
|
|||||||
BlockId, Commitment, CommitmentSetDigest, MembershipProof, SharedSecretKey, account::Nonce,
|
BlockId, Commitment, CommitmentSetDigest, MembershipProof, SharedSecretKey, account::Nonce,
|
||||||
program::InstructionData,
|
program::InstructionData,
|
||||||
};
|
};
|
||||||
use log::info;
|
use log::{info, warn};
|
||||||
use sequencer_service_rpc::{RpcClient as _, SequencerClient};
|
use sequencer_service_rpc::{RpcClient as _, SequencerClient};
|
||||||
use storage::Storage;
|
use storage::Storage;
|
||||||
use tokio::io::AsyncWriteExt as _;
|
use tokio::io::AsyncWriteExt as _;
|
||||||
@ -683,21 +683,21 @@ impl WalletCore {
|
|||||||
"Decode mask has {} entries but the transaction has {note_count} notes",
|
"Decode mask has {} entries but the transaction has {note_count} notes",
|
||||||
acc_decode_mask.len(),
|
acc_decode_mask.len(),
|
||||||
);
|
);
|
||||||
for (output_index, acc_decode_data) in acc_decode_mask.iter().enumerate() {
|
for acc_decode_data in acc_decode_mask {
|
||||||
match acc_decode_data {
|
match acc_decode_data {
|
||||||
AccDecodeData::Decode(secret, acc_account_id) => {
|
AccDecodeData::Decode(secret, acc_account_id) => {
|
||||||
let acc_ead = tx.message.encrypted_private_post_states[output_index].clone();
|
let Some(output_index) = self
|
||||||
let acc_comm = tx.message.new_commitments[output_index];
|
.storage
|
||||||
|
.key_chain()
|
||||||
let (kind, res_acc) = lee_core::EncryptionScheme::decrypt(
|
.locate_spend(*acc_account_id, &tx.message)
|
||||||
&acc_ead.ciphertext,
|
else {
|
||||||
secret,
|
warn!(
|
||||||
&acc_comm,
|
"No note located for {acc_account_id}; cached state stays stale until the next sync"
|
||||||
output_index
|
);
|
||||||
.try_into()
|
continue;
|
||||||
.expect("Output index is expected to fit in u32"),
|
};
|
||||||
)
|
let (kind, res_acc) =
|
||||||
.unwrap();
|
decrypt_note_at(&tx.message, output_index, secret).unwrap();
|
||||||
|
|
||||||
println!("Received new acc {res_acc:#?}");
|
println!("Received new acc {res_acc:#?}");
|
||||||
|
|
||||||
@ -971,8 +971,6 @@ impl WalletCore {
|
|||||||
&key_chain.nullifier_public_key,
|
&key_chain.nullifier_public_key,
|
||||||
&key_chain.viewing_public_key,
|
&key_chain.viewing_public_key,
|
||||||
);
|
);
|
||||||
let new_commitments = &message.new_commitments;
|
|
||||||
|
|
||||||
message
|
message
|
||||||
.encrypted_private_post_states
|
.encrypted_private_post_states
|
||||||
.iter()
|
.iter()
|
||||||
@ -984,20 +982,10 @@ impl WalletCore {
|
|||||||
!handled.contains(ciph_id) && encrypted_data.view_tag == view_tag
|
!handled.contains(ciph_id) && encrypted_data.view_tag == view_tag
|
||||||
})
|
})
|
||||||
.filter_map(move |(ciph_id, encrypted_data)| {
|
.filter_map(move |(ciph_id, encrypted_data)| {
|
||||||
let ciphertext = &encrypted_data.ciphertext;
|
|
||||||
let commitment = &new_commitments[ciph_id];
|
|
||||||
let shared_secret =
|
let shared_secret =
|
||||||
key_chain.calculate_shared_secret_receiver(&encrypted_data.epk)?;
|
key_chain.calculate_shared_secret_receiver(&encrypted_data.epk)?;
|
||||||
|
|
||||||
lee_core::EncryptionScheme::decrypt(
|
decrypt_note_at(message, ciph_id, &shared_secret).map(|(kind, res_acc)| {
|
||||||
ciphertext,
|
|
||||||
&shared_secret,
|
|
||||||
commitment,
|
|
||||||
ciph_id
|
|
||||||
.try_into()
|
|
||||||
.expect("Ciphertext ID is expected to fit in u32"),
|
|
||||||
)
|
|
||||||
.map(|(kind, res_acc)| {
|
|
||||||
let npk = &key_chain.nullifier_public_key;
|
let npk = &key_chain.nullifier_public_key;
|
||||||
let account_id = lee::AccountId::for_private_account(
|
let account_id = lee::AccountId::for_private_account(
|
||||||
npk,
|
npk,
|
||||||
@ -1065,16 +1053,7 @@ impl WalletCore {
|
|||||||
else {
|
else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
let commitment = &message.new_commitments[ciph_id];
|
if let Some((_kind, new_acc)) = decrypt_note_at(message, ciph_id, &shared_secret) {
|
||||||
|
|
||||||
if let Some((_kind, new_acc)) = lee_core::EncryptionScheme::decrypt(
|
|
||||||
&encrypted_data.ciphertext,
|
|
||||||
&shared_secret,
|
|
||||||
commitment,
|
|
||||||
ciph_id
|
|
||||||
.try_into()
|
|
||||||
.expect("Ciphertext ID is expected to fit in u32"),
|
|
||||||
) {
|
|
||||||
info!("Synced shared account {account_id:#?} with new state {new_acc:#?}");
|
info!("Synced shared account {account_id:#?} with new state {new_acc:#?}");
|
||||||
index.track(account_id, &new_acc, &nsk);
|
index.track(account_id, &new_acc, &nsk);
|
||||||
self.storage
|
self.storage
|
||||||
@ -1101,6 +1080,18 @@ impl WalletCore {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn decrypt_note_at(
|
||||||
|
message: &Message,
|
||||||
|
i: usize,
|
||||||
|
secret: &SharedSecretKey,
|
||||||
|
) -> Option<(lee_core::PrivateAccountKind, Account)> {
|
||||||
|
lee_core::EncryptionScheme::decrypt(
|
||||||
|
&message.encrypted_private_post_states[i].ciphertext,
|
||||||
|
secret,
|
||||||
|
&message.new_nullifiers[i].0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use std::{ffi::CString, str::FromStr as _};
|
use std::{ffi::CString, str::FromStr as _};
|
||||||
|
|||||||
@ -10,8 +10,7 @@ use key_protocol::key_management::{
|
|||||||
};
|
};
|
||||||
use lee::{Account, AccountId, privacy_preserving_transaction::message::Message};
|
use lee::{Account, AccountId, privacy_preserving_transaction::message::Message};
|
||||||
use lee_core::{
|
use lee_core::{
|
||||||
Commitment, EncryptionScheme, Identifier, Nullifier, NullifierSecretKey, PrivateAccountKind,
|
Commitment, Identifier, Nullifier, NullifierSecretKey, PrivateAccountKind, SharedSecretKey,
|
||||||
SharedSecretKey,
|
|
||||||
};
|
};
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -418,8 +417,6 @@ impl UserKeyChain {
|
|||||||
i: usize,
|
i: usize,
|
||||||
) -> Option<Nullifier> {
|
) -> Option<Nullifier> {
|
||||||
let encrypted = &message.encrypted_private_post_states[i];
|
let encrypted = &message.encrypted_private_post_states[i];
|
||||||
let commitment = &message.new_commitments[i];
|
|
||||||
let ciph_id = u32::try_from(i).ok()?;
|
|
||||||
|
|
||||||
let (nsk, secret, is_shared) = if let Some(entry) = self.shared_private_account(account_id)
|
let (nsk, secret, is_shared) = if let Some(entry) = self.shared_private_account(account_id)
|
||||||
{
|
{
|
||||||
@ -442,8 +439,7 @@ impl UserKeyChain {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (kind, new_account) =
|
let (kind, new_account) = crate::decrypt_note_at(message, i, &secret)?;
|
||||||
EncryptionScheme::decrypt(&encrypted.ciphertext, &secret, commitment, ciph_id)?;
|
|
||||||
let new_nullifier = NullifierIndex::next_update_nullifier(account_id, &new_account, &nsk);
|
let new_nullifier = NullifierIndex::next_update_nullifier(account_id, &new_account, &nsk);
|
||||||
|
|
||||||
if is_shared {
|
if is_shared {
|
||||||
@ -455,6 +451,35 @@ impl UserKeyChain {
|
|||||||
Some(new_nullifier)
|
Some(new_nullifier)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Constructs the next nullifier based on current account state
|
||||||
|
/// of the ID.
|
||||||
|
fn next_update_nullifier(&self, account_id: AccountId) -> Option<Nullifier> {
|
||||||
|
if let Some(entry) = self.shared_private_account(account_id) {
|
||||||
|
let keys = self.derive_shared_account_keys(entry)?;
|
||||||
|
return Some(NullifierIndex::next_update_nullifier(
|
||||||
|
account_id,
|
||||||
|
&entry.account,
|
||||||
|
&keys.nullifier_secret_key,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let acc = self.private_account(account_id)?;
|
||||||
|
Some(NullifierIndex::next_update_nullifier(
|
||||||
|
account_id,
|
||||||
|
acc.account,
|
||||||
|
&acc.key_chain.private_key_holder.nullifier_secret_key,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn locate_spend(&self, account_id: AccountId, message: &Message) -> Option<usize> {
|
||||||
|
let init = Nullifier::for_account_initialization(&account_id);
|
||||||
|
let update = self.next_update_nullifier(account_id);
|
||||||
|
message
|
||||||
|
.new_nullifiers
|
||||||
|
.iter()
|
||||||
|
.position(|(nullifier, _)| *nullifier == init || Some(nullifier) == update.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_imported_public_account(&mut self, private_key: lee::PrivateKey) {
|
pub fn add_imported_public_account(&mut self, private_key: lee::PrivateKey) {
|
||||||
let account_id = AccountId::from(&lee::PublicKey::new_from_private_key(&private_key));
|
let account_id = AccountId::from(&lee::PublicKey::new_from_private_key(&private_key));
|
||||||
|
|
||||||
@ -865,7 +890,7 @@ impl Default for UserKeyChain {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use lee_core::encryption::EncryptedAccountData;
|
use lee_core::{EncryptionScheme, encryption::EncryptedAccountData};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -900,8 +925,7 @@ mod tests {
|
|||||||
&new_account,
|
&new_account,
|
||||||
&PrivateAccountKind::Regular(identifier),
|
&PrivateAccountKind::Regular(identifier),
|
||||||
&sender_ss,
|
&sender_ss,
|
||||||
&new_commitment,
|
&old_nullifier,
|
||||||
0,
|
|
||||||
);
|
);
|
||||||
let note = EncryptedAccountData::new(
|
let note = EncryptedAccountData::new(
|
||||||
ciphertext,
|
ciphertext,
|
||||||
@ -971,8 +995,7 @@ mod tests {
|
|||||||
&new_account,
|
&new_account,
|
||||||
&PrivateAccountKind::Regular(identifier),
|
&PrivateAccountKind::Regular(identifier),
|
||||||
&sender_ss,
|
&sender_ss,
|
||||||
&new_commitment,
|
&old_nullifier,
|
||||||
0,
|
|
||||||
);
|
);
|
||||||
let note = EncryptedAccountData::new(ciphertext, &npk, &vpk, epk);
|
let note = EncryptedAccountData::new(ciphertext, &npk, &vpk, epk);
|
||||||
let message = Message {
|
let message = Message {
|
||||||
@ -1034,8 +1057,7 @@ mod tests {
|
|||||||
next,
|
next,
|
||||||
&PrivateAccountKind::Regular(identifier),
|
&PrivateAccountKind::Regular(identifier),
|
||||||
&sender_ss,
|
&sender_ss,
|
||||||
&commitment,
|
&spent,
|
||||||
0,
|
|
||||||
);
|
);
|
||||||
let note = EncryptedAccountData::new(ciphertext, &npk, &vpk, epk);
|
let note = EncryptedAccountData::new(ciphertext, &npk, &vpk, epk);
|
||||||
Message {
|
Message {
|
||||||
|
|||||||
Binary file not shown.
@ -11,7 +11,7 @@ use std::time::Duration;
|
|||||||
use criterion::{Criterion, criterion_group, criterion_main};
|
use criterion::{Criterion, criterion_group, criterion_main};
|
||||||
use key_protocol::key_management::KeyChain;
|
use key_protocol::key_management::KeyChain;
|
||||||
use lee_core::{
|
use lee_core::{
|
||||||
Commitment, EncryptionScheme, SharedSecretKey,
|
EncryptionScheme, Nullifier, SharedSecretKey,
|
||||||
account::{Account, AccountId},
|
account::{Account, AccountId},
|
||||||
program::PrivateAccountKind,
|
program::PrivateAccountKind,
|
||||||
};
|
};
|
||||||
@ -50,19 +50,18 @@ fn bench_encryption(c: &mut Criterion) {
|
|||||||
let account = Account::default();
|
let account = Account::default();
|
||||||
let account_id =
|
let account_id =
|
||||||
AccountId::for_regular_private_account(&npk, &recipient_kc.viewing_public_key, 0);
|
AccountId::for_regular_private_account(&npk, &recipient_kc.viewing_public_key, 0);
|
||||||
let commitment = Commitment::new(&account_id, &account);
|
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||||
let (shared, _epk) = SharedSecretKey::encapsulate(&recipient_kc.viewing_public_key);
|
let (shared, _epk) = SharedSecretKey::encapsulate(&recipient_kc.viewing_public_key);
|
||||||
let kind = PrivateAccountKind::Regular(0_u128);
|
let kind = PrivateAccountKind::Regular(0_u128);
|
||||||
let output_index: u32 = 0;
|
|
||||||
|
|
||||||
let mut g = c.benchmark_group("encryption");
|
let mut g = c.benchmark_group("encryption");
|
||||||
g.sample_size(50).noise_threshold(0.05);
|
g.sample_size(50).noise_threshold(0.05);
|
||||||
g.bench_function("encrypt", |b| {
|
g.bench_function("encrypt", |b| {
|
||||||
b.iter(|| EncryptionScheme::encrypt(&account, &kind, &shared, &commitment, output_index));
|
b.iter(|| EncryptionScheme::encrypt(&account, &kind, &shared, &nullifier));
|
||||||
});
|
});
|
||||||
let ct = EncryptionScheme::encrypt(&account, &kind, &shared, &commitment, output_index);
|
let ct = EncryptionScheme::encrypt(&account, &kind, &shared, &nullifier);
|
||||||
g.bench_function("decrypt", |b| {
|
g.bench_function("decrypt", |b| {
|
||||||
b.iter(|| EncryptionScheme::decrypt(&ct, &shared, &commitment, output_index));
|
b.iter(|| EncryptionScheme::decrypt(&ct, &shared, &nullifier));
|
||||||
});
|
});
|
||||||
g.finish();
|
g.finish();
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user