mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 13:23:10 +00:00
file refactor
This commit is contained in:
parent
fd74216249
commit
66b5efaacb
@ -9,7 +9,8 @@ serde = { version = "1.0", default-features = false }
|
||||
thiserror = { version = "2.0.12", optional = true }
|
||||
bytemuck = { version = "1.13", optional = true }
|
||||
chacha20 = { version = "0.9", default-features = false }
|
||||
k256 = { version = "0.13.3", optional = true}
|
||||
|
||||
[features]
|
||||
default = []
|
||||
host = ["thiserror", "bytemuck"]
|
||||
host = ["thiserror", "bytemuck", "k256"]
|
||||
|
||||
@ -1,16 +1,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::program::ProgramId;
|
||||
|
||||
mod commitment;
|
||||
mod encoding;
|
||||
mod nullifier;
|
||||
|
||||
pub use commitment::Commitment;
|
||||
pub use nullifier::{Nullifier, NullifierPublicKey, NullifierSecretKey};
|
||||
|
||||
pub type Nonce = u128;
|
||||
// TODO: Consider changing `Data` to `Vec<u32>` for r0 friendlinenss
|
||||
type Data = Vec<u8>;
|
||||
|
||||
/// Account to be used both in public and private contexts
|
||||
@ -1,34 +0,0 @@
|
||||
use risc0_zkvm::{
|
||||
serde::to_vec,
|
||||
sha::{Impl, Sha256},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::account::{Account, NullifierPublicKey};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq, Hash))]
|
||||
pub struct Commitment(pub(super) [u8; 32]);
|
||||
|
||||
impl Commitment {
|
||||
pub fn new(Npk: &NullifierPublicKey, account: &Account) -> Self {
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&Npk.to_byte_array());
|
||||
let account_bytes_with_hashed_data = {
|
||||
let mut this = Vec::new();
|
||||
for word in &account.program_owner {
|
||||
this.extend_from_slice(&word.to_le_bytes());
|
||||
}
|
||||
this.extend_from_slice(&account.balance.to_le_bytes());
|
||||
this.extend_from_slice(&account.nonce.to_le_bytes());
|
||||
let hashed_data: [u8; 32] = Impl::hash_bytes(&account.data)
|
||||
.as_bytes()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
this.extend_from_slice(&hashed_data);
|
||||
this
|
||||
};
|
||||
bytes.extend_from_slice(&account_bytes_with_hashed_data);
|
||||
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
93
nssa/core/src/circuit_io.rs
Normal file
93
nssa/core/src/circuit_io.rs
Normal file
@ -0,0 +1,93 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Commitment, CommitmentSetDigest, MembershipProof, Nullifier, NullifierPublicKey,
|
||||
NullifierSecretKey, SharedSecretKey,
|
||||
account::{Account, AccountWithMetadata, Nonce},
|
||||
encryption::Ciphertext,
|
||||
program::{ProgramId, ProgramOutput},
|
||||
};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PrivacyPreservingCircuitInput {
|
||||
pub program_output: ProgramOutput,
|
||||
pub visibility_mask: Vec<u8>,
|
||||
pub private_account_nonces: Vec<Nonce>,
|
||||
pub private_account_keys: Vec<(NullifierPublicKey, SharedSecretKey)>,
|
||||
pub private_account_auth: Vec<(NullifierSecretKey, MembershipProof)>,
|
||||
pub program_id: ProgramId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
|
||||
pub struct PrivacyPreservingCircuitOutput {
|
||||
pub public_pre_states: Vec<AccountWithMetadata>,
|
||||
pub public_post_states: Vec<Account>,
|
||||
pub ciphertexts: Vec<Ciphertext>,
|
||||
pub new_commitments: Vec<Commitment>,
|
||||
pub new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
impl PrivacyPreservingCircuitOutput {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
bytemuck::cast_slice(&risc0_zkvm::serde::to_vec(&self).unwrap()).to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
Commitment, Nullifier, NullifierPublicKey,
|
||||
account::{Account, AccountWithMetadata},
|
||||
};
|
||||
use risc0_zkvm::serde::from_slice;
|
||||
|
||||
#[test]
|
||||
fn test_privacy_preserving_circuit_output_to_bytes_is_compatible_with_from_slice() {
|
||||
let output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states: vec![
|
||||
AccountWithMetadata {
|
||||
account: Account {
|
||||
program_owner: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
balance: 12345678901234567890,
|
||||
data: b"test data".to_vec(),
|
||||
nonce: 18446744073709551614,
|
||||
},
|
||||
is_authorized: true,
|
||||
},
|
||||
AccountWithMetadata {
|
||||
account: Account {
|
||||
program_owner: [9, 9, 9, 8, 8, 8, 7, 7],
|
||||
balance: 123123123456456567112,
|
||||
data: b"test data".to_vec(),
|
||||
nonce: 9999999999999999999999,
|
||||
},
|
||||
is_authorized: false,
|
||||
},
|
||||
],
|
||||
public_post_states: vec![Account {
|
||||
program_owner: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
balance: 100,
|
||||
data: b"post state data".to_vec(),
|
||||
nonce: 18446744073709551615,
|
||||
}],
|
||||
ciphertexts: vec![Ciphertext(vec![255, 255, 1, 1, 2, 2])],
|
||||
new_commitments: vec![Commitment::new(
|
||||
&NullifierPublicKey::from(&[1; 32]),
|
||||
&Account::default(),
|
||||
)],
|
||||
new_nullifiers: vec![(
|
||||
Nullifier::new(
|
||||
&Commitment::new(&NullifierPublicKey::from(&[2; 32]), &Account::default()),
|
||||
&[1; 32],
|
||||
),
|
||||
[0xab; 32],
|
||||
)],
|
||||
};
|
||||
let bytes = output.to_bytes();
|
||||
let output_from_slice: PrivacyPreservingCircuitOutput = from_slice(&bytes).unwrap();
|
||||
assert_eq!(output, output_from_slice);
|
||||
}
|
||||
}
|
||||
63
nssa/core/src/commitment.rs
Normal file
63
nssa/core/src/commitment.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use risc0_zkvm::sha::{Impl, Sha256};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{account::Account, NullifierPublicKey};
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq, Hash))]
|
||||
pub struct Commitment(pub(super) [u8; 32]);
|
||||
|
||||
impl Commitment {
|
||||
pub fn new(npk: &NullifierPublicKey, account: &Account) -> Self {
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&npk.to_byte_array());
|
||||
let account_bytes_with_hashed_data = {
|
||||
let mut this = Vec::new();
|
||||
for word in &account.program_owner {
|
||||
this.extend_from_slice(&word.to_le_bytes());
|
||||
}
|
||||
this.extend_from_slice(&account.balance.to_le_bytes());
|
||||
this.extend_from_slice(&account.nonce.to_le_bytes());
|
||||
let hashed_data: [u8; 32] = Impl::hash_bytes(&account.data)
|
||||
.as_bytes()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
this.extend_from_slice(&hashed_data);
|
||||
this
|
||||
};
|
||||
bytes.extend_from_slice(&account_bytes_with_hashed_data);
|
||||
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
pub type CommitmentSetDigest = [u8; 32];
|
||||
|
||||
pub type MembershipProof = (usize, Vec<[u8; 32]>);
|
||||
|
||||
pub fn compute_digest_for_path(
|
||||
commitment: &Commitment,
|
||||
proof: &MembershipProof,
|
||||
) -> CommitmentSetDigest {
|
||||
let value_bytes = commitment.to_byte_array();
|
||||
let mut result: [u8; 32] = Impl::hash_bytes(&value_bytes)
|
||||
.as_bytes()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let mut level_index = proof.0;
|
||||
for node in &proof.1 {
|
||||
let is_left_child = level_index & 1 == 0;
|
||||
if is_left_child {
|
||||
let mut bytes = [0u8; 64];
|
||||
bytes[..32].copy_from_slice(&result);
|
||||
bytes[32..].copy_from_slice(node);
|
||||
result = Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap();
|
||||
} else {
|
||||
let mut bytes = [0u8; 64];
|
||||
bytes[..32].copy_from_slice(node);
|
||||
bytes[32..].copy_from_slice(&result);
|
||||
result = Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap();
|
||||
}
|
||||
level_index >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
@ -1,17 +1,25 @@
|
||||
// TODO: Consider switching to deriving Borsh
|
||||
|
||||
use risc0_zkvm::sha::{Impl, Sha256};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use std::io::Cursor;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use std::io::Read;
|
||||
|
||||
use crate::account::{Account, Commitment, Nullifier, NullifierPublicKey};
|
||||
use crate::account::Account;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use crate::encryption::shared_key_derivation::Secp256k1Point;
|
||||
|
||||
use crate::encryption::Ciphertext;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use crate::error::NssaCoreError;
|
||||
|
||||
use crate::Commitment;
|
||||
#[cfg(feature = "host")]
|
||||
use crate::Nullifier;
|
||||
use crate::NullifierPublicKey;
|
||||
|
||||
impl Account {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
@ -93,6 +101,42 @@ impl Nullifier {
|
||||
}
|
||||
}
|
||||
|
||||
impl Ciphertext {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
let ciphertext_length: u32 = self.0.len() as u32;
|
||||
bytes.extend_from_slice(&ciphertext_length.to_le_bytes());
|
||||
bytes.extend_from_slice(&self.0);
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||
let mut u32_bytes = [0; 4];
|
||||
|
||||
cursor.read_exact(&mut u32_bytes)?;
|
||||
let ciphertext_lenght = u32::from_le_bytes(u32_bytes);
|
||||
let mut ciphertext = vec![0; ciphertext_lenght as usize];
|
||||
cursor.read_exact(&mut ciphertext)?;
|
||||
|
||||
Ok(Self(ciphertext))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
impl Secp256k1Point {
|
||||
pub fn to_bytes(&self) -> [u8; 33] {
|
||||
self.0.clone().try_into().unwrap()
|
||||
}
|
||||
|
||||
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||
let mut value = vec![0; 33];
|
||||
cursor.read_exact(&mut value)?;
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
77
nssa/core/src/encryption/mod.rs
Normal file
77
nssa/core/src/encryption/mod.rs
Normal file
@ -0,0 +1,77 @@
|
||||
use chacha20::{
|
||||
ChaCha20,
|
||||
cipher::{KeyIvInit, StreamCipher},
|
||||
};
|
||||
use risc0_zkvm::sha::{Impl, Sha256};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub(crate) mod shared_key_derivation;
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub use shared_key_derivation::{EphemeralPublicKey, EphemeralSecretKey, IncomingViewingPublicKey};
|
||||
|
||||
use crate::{Commitment, NullifierPublicKey, account::Account};
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone)]
|
||||
pub struct SharedSecretKey([u8; 32]);
|
||||
|
||||
pub struct EncryptionScheme;
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq))]
|
||||
pub struct Ciphertext(pub(crate) Vec<u8>);
|
||||
|
||||
impl EncryptionScheme {
|
||||
pub fn encrypt(
|
||||
account: &Account,
|
||||
shared_secret: &SharedSecretKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> Ciphertext {
|
||||
let mut buffer = account.to_bytes().to_vec();
|
||||
Self::symmetric_transform(&mut buffer, shared_secret, commitment, output_index);
|
||||
Ciphertext(buffer)
|
||||
}
|
||||
|
||||
fn symmetric_transform(
|
||||
buffer: &mut [u8],
|
||||
shared_secret: &SharedSecretKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) {
|
||||
let key = Self::kdf(shared_secret, commitment, output_index);
|
||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||
cipher.apply_keystream(buffer);
|
||||
}
|
||||
|
||||
fn kdf(
|
||||
shared_secret: &SharedSecretKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> [u8; 32] {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
bytes.extend_from_slice(b"NSSA/v0.1/KDF-SHA256");
|
||||
bytes.extend_from_slice(&shared_secret.0);
|
||||
bytes.extend_from_slice(&commitment.to_byte_array());
|
||||
bytes.extend_from_slice(&output_index.to_le_bytes());
|
||||
|
||||
Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub fn decrypt(
|
||||
ciphertext: &Ciphertext,
|
||||
shared_secret: &SharedSecretKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> Option<Account> {
|
||||
use std::io::Cursor;
|
||||
let mut buffer = ciphertext.0.to_owned();
|
||||
Self::symmetric_transform(&mut buffer, shared_secret, commitment, output_index);
|
||||
|
||||
let mut cursor = Cursor::new(buffer.as_slice());
|
||||
Account::from_cursor(&mut cursor).ok()
|
||||
}
|
||||
}
|
||||
56
nssa/core/src/encryption/shared_key_derivation.rs
Normal file
56
nssa/core/src/encryption/shared_key_derivation.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use k256::{
|
||||
AffinePoint, EncodedPoint, FieldBytes, ProjectivePoint, Scalar,
|
||||
elliptic_curve::{
|
||||
PrimeField,
|
||||
sec1::{FromEncodedPoint, ToEncodedPoint},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::SharedSecretKey;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct Secp256k1Point(pub(crate) Vec<u8>);
|
||||
|
||||
impl Secp256k1Point {
|
||||
pub fn from_scalar(value: [u8; 32]) -> Secp256k1Point {
|
||||
let x_bytes: FieldBytes = value.into();
|
||||
let x = Scalar::from_repr(x_bytes).unwrap();
|
||||
|
||||
let p = ProjectivePoint::GENERATOR * x;
|
||||
let q = AffinePoint::from(p);
|
||||
let enc = q.to_encoded_point(true);
|
||||
|
||||
Self(enc.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
pub type EphemeralSecretKey = [u8; 32];
|
||||
pub type EphemeralPublicKey = Secp256k1Point;
|
||||
pub type IncomingViewingPublicKey = Secp256k1Point;
|
||||
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
|
||||
fn from(value: &EphemeralSecretKey) -> Self {
|
||||
Secp256k1Point::from_scalar(*value)
|
||||
}
|
||||
}
|
||||
|
||||
impl SharedSecretKey {
|
||||
pub fn new(scalar: &[u8; 32], point: &Secp256k1Point) -> Self {
|
||||
let scalar = Scalar::from_repr((*scalar).into()).unwrap();
|
||||
let point: [u8; 33] = point.0.clone().try_into().unwrap();
|
||||
|
||||
let encoded = EncodedPoint::from_bytes(point).unwrap();
|
||||
let pubkey_affine = AffinePoint::from_encoded_point(&encoded).unwrap();
|
||||
|
||||
let shared = ProjectivePoint::from(pubkey_affine) * scalar;
|
||||
let shared_affine = shared.to_affine();
|
||||
|
||||
let encoded = shared_affine.to_encoded_point(false);
|
||||
let x_bytes_slice = encoded.x().unwrap();
|
||||
let mut x_bytes = [0u8; 32];
|
||||
x_bytes.copy_from_slice(x_bytes_slice);
|
||||
|
||||
Self(x_bytes)
|
||||
}
|
||||
}
|
||||
@ -1,237 +1,15 @@
|
||||
use chacha20::{
|
||||
ChaCha20,
|
||||
cipher::{KeyIvInit, StreamCipher},
|
||||
};
|
||||
|
||||
use risc0_zkvm::{
|
||||
serde::to_vec,
|
||||
sha::{Impl, Sha256},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use crate::error::NssaCoreError;
|
||||
|
||||
use crate::{
|
||||
account::{
|
||||
Account, AccountWithMetadata, Commitment, Nonce, Nullifier, NullifierPublicKey,
|
||||
NullifierSecretKey,
|
||||
},
|
||||
program::{ProgramId, ProgramOutput},
|
||||
};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
pub mod account;
|
||||
mod circuit_io;
|
||||
mod commitment;
|
||||
mod encoding;
|
||||
pub mod encryption;
|
||||
mod nullifier;
|
||||
pub mod program;
|
||||
|
||||
pub use circuit_io::{PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput};
|
||||
pub use commitment::{Commitment, CommitmentSetDigest, MembershipProof, compute_digest_for_path};
|
||||
pub use encryption::{EncryptionScheme, SharedSecretKey};
|
||||
pub use nullifier::{Nullifier, NullifierPublicKey, NullifierSecretKey};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub mod error;
|
||||
|
||||
pub type CommitmentSetDigest = [u8; 32];
|
||||
pub type MembershipProof = (usize, Vec<[u8; 32]>);
|
||||
pub fn compute_root_associated_to_path(
|
||||
commitment: &Commitment,
|
||||
proof: &MembershipProof,
|
||||
) -> CommitmentSetDigest {
|
||||
let value_bytes = commitment.to_byte_array();
|
||||
let mut result: [u8; 32] = Impl::hash_bytes(&value_bytes)
|
||||
.as_bytes()
|
||||
.try_into()
|
||||
.unwrap();
|
||||
let mut level_index = proof.0;
|
||||
for node in &proof.1 {
|
||||
let is_left_child = level_index & 1 == 0;
|
||||
if is_left_child {
|
||||
let mut bytes = [0u8; 64];
|
||||
bytes[..32].copy_from_slice(&result);
|
||||
bytes[32..].copy_from_slice(node);
|
||||
result = Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap();
|
||||
} else {
|
||||
let mut bytes = [0u8; 64];
|
||||
bytes[..32].copy_from_slice(node);
|
||||
bytes[32..].copy_from_slice(&result);
|
||||
result = Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap();
|
||||
}
|
||||
level_index >>= 1;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub type SharedSecretKey = [u8; 32];
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, PartialEq, Eq))]
|
||||
pub struct Ciphertext(Vec<u8>);
|
||||
|
||||
impl Ciphertext {
|
||||
#[cfg(feature = "host")]
|
||||
pub fn decrypt(
|
||||
self,
|
||||
shared_secret: &[u8; 32],
|
||||
npk: &NullifierPublicKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> Option<Account> {
|
||||
let key = Self::kdf(&shared_secret, npk, commitment, output_index);
|
||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||
let mut buffer = self.0;
|
||||
|
||||
cipher.apply_keystream(&mut buffer);
|
||||
let mut cursor = Cursor::new(buffer.as_slice());
|
||||
Account::from_cursor(&mut cursor).ok()
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
account: &Account,
|
||||
shared_secret: &[u8; 32],
|
||||
npk: &NullifierPublicKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> Self {
|
||||
let mut buffer = account.to_bytes().to_vec();
|
||||
|
||||
let key = Self::kdf(shared_secret, npk, commitment, output_index);
|
||||
let mut cipher = ChaCha20::new(&key.into(), &[0; 12].into());
|
||||
cipher.apply_keystream(&mut buffer);
|
||||
|
||||
Self(buffer)
|
||||
}
|
||||
|
||||
pub fn kdf(
|
||||
ss_bytes: &[u8; 32],
|
||||
npk: &NullifierPublicKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> [u8; 32] {
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
bytes.extend_from_slice(b"NSSA/v0.1/KDF-SHA256");
|
||||
bytes.extend_from_slice(ss_bytes);
|
||||
bytes.extend_from_slice(&npk.to_byte_array());
|
||||
bytes.extend_from_slice(&commitment.to_byte_array());
|
||||
bytes.extend_from_slice(&output_index.to_le_bytes());
|
||||
|
||||
Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaCoreError> {
|
||||
let mut u32_bytes = [0; 4];
|
||||
|
||||
cursor.read_exact(&mut u32_bytes)?;
|
||||
let ciphertext_lenght = u32::from_le_bytes(u32_bytes);
|
||||
let mut ciphertext = vec![0; ciphertext_lenght as usize];
|
||||
cursor.read_exact(&mut ciphertext)?;
|
||||
|
||||
Ok(Self(ciphertext))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ciphertext {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = Vec::new();
|
||||
let ciphertext_length: u32 = self.0.len() as u32;
|
||||
bytes.extend_from_slice(&ciphertext_length.to_le_bytes());
|
||||
bytes.extend_from_slice(&self.0);
|
||||
|
||||
bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PrivacyPreservingCircuitInput {
|
||||
pub program_output: ProgramOutput,
|
||||
pub visibility_mask: Vec<u8>,
|
||||
pub private_account_nonces: Vec<Nonce>,
|
||||
pub private_account_keys: Vec<(NullifierPublicKey, SharedSecretKey)>,
|
||||
pub private_account_auth: Vec<(NullifierSecretKey, MembershipProof)>,
|
||||
pub program_id: ProgramId,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, PartialEq, Eq))]
|
||||
pub struct PrivacyPreservingCircuitOutput {
|
||||
pub public_pre_states: Vec<AccountWithMetadata>,
|
||||
pub public_post_states: Vec<Account>,
|
||||
pub ciphertexts: Vec<Ciphertext>,
|
||||
pub new_commitments: Vec<Commitment>,
|
||||
pub new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
impl PrivacyPreservingCircuitOutput {
|
||||
pub fn to_bytes(&self) -> Vec<u8> {
|
||||
bytemuck::cast_slice(&to_vec(&self).unwrap()).to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use risc0_zkvm::serde::from_slice;
|
||||
|
||||
use crate::{
|
||||
Ciphertext, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
};
|
||||
|
||||
#[test]
|
||||
fn test_privacy_preserving_circuit_output_to_bytes_is_compatible_with_from_slice() {
|
||||
let output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states: vec![
|
||||
AccountWithMetadata {
|
||||
account: Account {
|
||||
program_owner: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
balance: 12345678901234567890,
|
||||
data: b"test data".to_vec(),
|
||||
nonce: 18446744073709551614,
|
||||
},
|
||||
is_authorized: true,
|
||||
},
|
||||
AccountWithMetadata {
|
||||
account: Account {
|
||||
program_owner: [9, 9, 9, 8, 8, 8, 7, 7],
|
||||
balance: 123123123456456567112,
|
||||
data: b"test data".to_vec(),
|
||||
nonce: 9999999999999999999999,
|
||||
},
|
||||
is_authorized: false,
|
||||
},
|
||||
],
|
||||
public_post_states: vec![Account {
|
||||
program_owner: [1, 2, 3, 4, 5, 6, 7, 8],
|
||||
balance: 100,
|
||||
data: b"post state data".to_vec(),
|
||||
nonce: 18446744073709551615,
|
||||
}],
|
||||
ciphertexts: vec![Ciphertext(vec![255, 255, 1, 1, 2, 2])],
|
||||
new_commitments: vec![Commitment::new(
|
||||
&NullifierPublicKey::from(&[1; 32]),
|
||||
&Account::default(),
|
||||
)],
|
||||
new_nullifiers: vec![(
|
||||
Nullifier::new(
|
||||
&Commitment::new(&NullifierPublicKey::from(&[2; 32]), &Account::default()),
|
||||
&[1; 32],
|
||||
),
|
||||
[0xab; 32],
|
||||
)],
|
||||
};
|
||||
let bytes = output.to_bytes();
|
||||
let output_from_slice: PrivacyPreservingCircuitOutput = from_slice(&bytes).unwrap();
|
||||
assert_eq!(output, output_from_slice);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ciphertext_to_bytes_roundtrip() {
|
||||
let data = Ciphertext(vec![255, 255, 1, 1, 2, 2]);
|
||||
|
||||
let bytes = data.to_bytes();
|
||||
let mut cursor = Cursor::new(bytes.as_slice());
|
||||
let data_from_cursor = Ciphertext::from_cursor(&mut cursor).unwrap();
|
||||
assert_eq!(data, data_from_cursor);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use risc0_zkvm::sha::{Impl, Sha256};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::account::Commitment;
|
||||
use crate::Commitment;
|
||||
|
||||
#[derive(Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Debug, Clone, Hash))]
|
||||
@ -58,11 +58,11 @@ mod tests {
|
||||
57, 5, 64, 115, 153, 56, 184, 51, 207, 238, 99, 165, 147, 214, 213, 151, 30, 251, 30,
|
||||
196, 134, 22, 224, 211, 237, 120, 136, 225, 188, 220, 249, 28,
|
||||
];
|
||||
let expected_Npk = NullifierPublicKey([
|
||||
let expected_npk = NullifierPublicKey([
|
||||
202, 120, 42, 189, 194, 218, 78, 244, 31, 6, 108, 169, 29, 61, 22, 221, 69, 138, 197,
|
||||
161, 241, 39, 142, 242, 242, 50, 188, 201, 99, 28, 176, 238,
|
||||
]);
|
||||
let Npk = NullifierPublicKey::from(&nsk);
|
||||
assert_eq!(Npk, expected_Npk);
|
||||
assert_eq!(Npk, expected_npk);
|
||||
}
|
||||
}
|
||||
@ -3,9 +3,6 @@ use risc0_zkvm::serde::Deserializer;
|
||||
use risc0_zkvm::{DeserializeOwned, guest::env};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
use crate::error::NssaCoreError;
|
||||
|
||||
pub type ProgramId = [u32; 8];
|
||||
pub type InstructionData = Vec<u32>;
|
||||
pub const DEFAULT_PROGRAM_ID: ProgramId = [0; 8];
|
||||
|
||||
@ -1,10 +1,12 @@
|
||||
use risc0_zkvm::{guest::env, serde::to_vec};
|
||||
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
compute_root_associated_to_path,
|
||||
account::{Account, AccountWithMetadata},
|
||||
compute_digest_for_path,
|
||||
encryption::Ciphertext,
|
||||
program::{validate_execution, ProgramOutput, DEFAULT_PROGRAM_ID},
|
||||
Ciphertext, CommitmentSetDigest, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput,
|
||||
Commitment, CommitmentSetDigest, EncryptionScheme, Nullifier, NullifierPublicKey,
|
||||
PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
@ -82,8 +84,7 @@ fn main() {
|
||||
|
||||
// Compute commitment set digest associated with provided auth path
|
||||
let commitment_pre = Commitment::new(Npk, &pre_states[i].account);
|
||||
let set_digest =
|
||||
compute_root_associated_to_path(&commitment_pre, membership_proof);
|
||||
let set_digest = compute_digest_for_path(&commitment_pre, membership_proof);
|
||||
|
||||
// Check pre_state authorization
|
||||
if !pre_states[i].is_authorized {
|
||||
@ -116,10 +117,9 @@ fn main() {
|
||||
let commitment_post = Commitment::new(Npk, &post_with_updated_values);
|
||||
|
||||
// Encrypt and push post state
|
||||
let encrypted_account = Ciphertext::new(
|
||||
let encrypted_account = EncryptionScheme::encrypt(
|
||||
&post_with_updated_values,
|
||||
shared_secret,
|
||||
Npk,
|
||||
&commitment_post,
|
||||
output_index,
|
||||
);
|
||||
|
||||
@ -181,7 +181,6 @@ fn prev_power_of_two(x: usize) -> usize {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use hex_literal::hex;
|
||||
use nssa_core::account::{Account, NullifierPublicKey};
|
||||
|
||||
use super::*;
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
use nssa_core::{
|
||||
CommitmentSetDigest, MembershipProof, PrivacyPreservingCircuitInput,
|
||||
PrivacyPreservingCircuitOutput, SharedSecretKey,
|
||||
account::{Account, AccountWithMetadata, Nonce, NullifierPublicKey, NullifierSecretKey},
|
||||
CommitmentSetDigest, MembershipProof, NullifierPublicKey, NullifierSecretKey,
|
||||
PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput, SharedSecretKey,
|
||||
account::{Account, AccountWithMetadata, Nonce},
|
||||
program::{InstructionData, ProgramId, ProgramOutput},
|
||||
};
|
||||
use risc0_zkvm::{ExecutorEnv, InnerReceipt, Receipt, default_prover};
|
||||
@ -91,11 +91,9 @@ fn execute_and_prove_program(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use nssa_core::{
|
||||
Ciphertext,
|
||||
account::{
|
||||
Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey,
|
||||
NullifierSecretKey,
|
||||
},
|
||||
Commitment, EncryptionScheme, Nullifier, NullifierPublicKey, NullifierSecretKey,
|
||||
account::{Account, AccountWithMetadata},
|
||||
encryption::EphemeralPublicKey,
|
||||
};
|
||||
use risc0_zkvm::{InnerReceipt, Journal, Receipt};
|
||||
|
||||
@ -104,7 +102,7 @@ mod tests {
|
||||
merkle_tree::MerkleTree,
|
||||
privacy_preserving_transaction::{
|
||||
circuit::{Proof, execute_and_prove},
|
||||
message::{EncryptedAccountData, EphemeralPublicKey},
|
||||
message::EncryptedAccountData,
|
||||
},
|
||||
program::Program,
|
||||
state::{
|
||||
@ -153,8 +151,7 @@ mod tests {
|
||||
let recipient_keys = test_private_account_keys_1();
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret =
|
||||
EncryptedAccountData::compute_shared_secret(&esk, &recipient_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
@ -162,7 +159,7 @@ mod tests {
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
&[0, 2],
|
||||
&[0xdeadbeef],
|
||||
&[(recipient_keys.npk(), shared_secret)],
|
||||
&[(recipient_keys.npk(), shared_secret.clone())],
|
||||
&[],
|
||||
&Program::authenticated_transfer_program(),
|
||||
)
|
||||
@ -178,15 +175,13 @@ mod tests {
|
||||
assert_eq!(output.new_nullifiers.len(), 0);
|
||||
assert_eq!(output.ciphertexts.len(), 1);
|
||||
|
||||
let recipient_post = output.ciphertexts[0]
|
||||
.clone()
|
||||
.decrypt(
|
||||
&shared_secret,
|
||||
&recipient_keys.npk(),
|
||||
&output.new_commitments[0],
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let recipient_post = EncryptionScheme::decrypt(
|
||||
&output.ciphertexts[0],
|
||||
&shared_secret,
|
||||
&output.new_commitments[0],
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post, expected_recipient_post);
|
||||
}
|
||||
|
||||
@ -238,13 +233,11 @@ mod tests {
|
||||
];
|
||||
|
||||
let esk_1 = [3; 32];
|
||||
let shared_secret_1 =
|
||||
EncryptedAccountData::compute_shared_secret(&esk_1, &sender_keys.ivk());
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
|
||||
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
|
||||
|
||||
let esk_2 = [5; 32];
|
||||
let shared_secret_2 =
|
||||
EncryptedAccountData::compute_shared_secret(&esk_2, &recipient_keys.ivk());
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
|
||||
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
@ -253,8 +246,8 @@ mod tests {
|
||||
&[1, 2],
|
||||
&[0xdeadbeef1, 0xdeadbeef2],
|
||||
&[
|
||||
(sender_keys.npk(), shared_secret_1),
|
||||
(recipient_keys.npk(), shared_secret_2),
|
||||
(sender_keys.npk(), shared_secret_1.clone()),
|
||||
(recipient_keys.npk(), shared_secret_2.clone()),
|
||||
],
|
||||
&[(
|
||||
sender_keys.nsk,
|
||||
@ -271,26 +264,22 @@ mod tests {
|
||||
assert_eq!(output.new_nullifiers, expected_new_nullifiers);
|
||||
assert_eq!(output.ciphertexts.len(), 2);
|
||||
|
||||
let sender_post = output.ciphertexts[0]
|
||||
.clone()
|
||||
.decrypt(
|
||||
&shared_secret_1,
|
||||
&sender_keys.npk(),
|
||||
&expected_new_commitments[0],
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
let sender_post = EncryptionScheme::decrypt(
|
||||
&output.ciphertexts[0],
|
||||
&shared_secret_1,
|
||||
&expected_new_commitments[0],
|
||||
0,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(sender_post, expected_private_account_1);
|
||||
|
||||
let recipient_post = output.ciphertexts[1]
|
||||
.clone()
|
||||
.decrypt(
|
||||
&shared_secret_2,
|
||||
&recipient_keys.npk(),
|
||||
&expected_new_commitments[1],
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
let recipient_post = EncryptionScheme::decrypt(
|
||||
&output.ciphertexts[1],
|
||||
&shared_secret_2,
|
||||
&expected_new_commitments[1],
|
||||
1,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(recipient_post, expected_private_account_2);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,18 +1,13 @@
|
||||
// TODO: Consider switching to deriving Borsh
|
||||
|
||||
use std::io::{Cursor, Read};
|
||||
|
||||
use nssa_core::{
|
||||
Ciphertext,
|
||||
account::{Account, Commitment, Nullifier},
|
||||
Commitment, Nullifier,
|
||||
account::Account,
|
||||
encryption::{Ciphertext, EphemeralPublicKey},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
Address,
|
||||
error::NssaError,
|
||||
privacy_preserving_transaction::message::{
|
||||
EncryptedAccountData, EphemeralPublicKey, Secp256k1Point,
|
||||
},
|
||||
Address, error::NssaError, privacy_preserving_transaction::message::EncryptedAccountData,
|
||||
};
|
||||
|
||||
use super::message::Message;
|
||||
@ -23,17 +18,14 @@ const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"\x01/NSSA/
|
||||
impl EncryptedAccountData {
|
||||
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||
let mut bytes = self.ciphertext.to_bytes();
|
||||
bytes.extend_from_slice(&self.epk.0);
|
||||
bytes.extend_from_slice(&self.epk.to_bytes());
|
||||
bytes.push(self.view_tag);
|
||||
bytes
|
||||
}
|
||||
|
||||
pub fn from_cursor(cursor: &mut Cursor<&[u8]>) -> Result<Self, NssaError> {
|
||||
let ciphertext = Ciphertext::from_cursor(cursor)?;
|
||||
|
||||
let mut epk_bytes = vec![0; 33];
|
||||
cursor.read_exact(&mut epk_bytes)?;
|
||||
let epk = Secp256k1Point(epk_bytes);
|
||||
let epk = EphemeralPublicKey::from_cursor(cursor)?;
|
||||
|
||||
let mut tag_bytes = [0; 1];
|
||||
cursor.read_exact(&mut tag_bytes)?;
|
||||
|
||||
@ -1,44 +1,14 @@
|
||||
use std::io::Cursor;
|
||||
|
||||
use k256::{
|
||||
AffinePoint, EncodedPoint, FieldBytes, ProjectivePoint, PublicKey, Scalar,
|
||||
elliptic_curve::{
|
||||
PrimeField,
|
||||
sec1::{FromEncodedPoint, ToEncodedPoint},
|
||||
},
|
||||
};
|
||||
use nssa_core::{
|
||||
Ciphertext, CommitmentSetDigest, PrivacyPreservingCircuitOutput, SharedSecretKey,
|
||||
account::{Account, Commitment, Nonce, Nullifier, NullifierPublicKey},
|
||||
Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, Nonce},
|
||||
encryption::{Ciphertext, EphemeralPublicKey},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Address, error::NssaError};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
pub struct Secp256k1Point(pub(crate) Vec<u8>);
|
||||
impl Secp256k1Point {
|
||||
pub fn from_scalar(value: [u8; 32]) -> Secp256k1Point {
|
||||
let x_bytes: FieldBytes = value.into();
|
||||
let x = Scalar::from_repr(x_bytes).unwrap();
|
||||
|
||||
let p = ProjectivePoint::GENERATOR * x;
|
||||
let q = AffinePoint::from(p);
|
||||
let enc = q.to_encoded_point(true);
|
||||
|
||||
Self(enc.as_bytes().to_vec())
|
||||
}
|
||||
}
|
||||
|
||||
pub type EphemeralSecretKey = [u8; 32];
|
||||
pub type EphemeralPublicKey = Secp256k1Point;
|
||||
pub type IncomingViewingPublicKey = Secp256k1Point;
|
||||
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
|
||||
fn from(value: &EphemeralSecretKey) -> Self {
|
||||
Secp256k1Point::from_scalar(*value)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EncryptedAccountData {
|
||||
pub(crate) ciphertext: Ciphertext,
|
||||
@ -46,38 +16,6 @@ pub struct EncryptedAccountData {
|
||||
pub(crate) view_tag: u8,
|
||||
}
|
||||
|
||||
impl EncryptedAccountData {
|
||||
pub fn decrypt(
|
||||
self,
|
||||
isk: &[u8; 32],
|
||||
epk: &EphemeralPublicKey,
|
||||
npk: &NullifierPublicKey,
|
||||
commitment: &Commitment,
|
||||
output_index: u32,
|
||||
) -> Option<Account> {
|
||||
let shared_secret = Self::compute_shared_secret(isk, &epk);
|
||||
self.ciphertext.decrypt(&shared_secret, npk, commitment, output_index)
|
||||
}
|
||||
|
||||
pub fn compute_shared_secret(scalar: &[u8; 32], point: &Secp256k1Point) -> SharedSecretKey {
|
||||
let scalar = Scalar::from_repr((*scalar).into()).unwrap();
|
||||
let point: [u8; 33] = point.0.clone().try_into().unwrap();
|
||||
|
||||
let encoded = EncodedPoint::from_bytes(point).unwrap();
|
||||
let pubkey_affine = AffinePoint::from_encoded_point(&encoded).unwrap();
|
||||
|
||||
let shared = ProjectivePoint::from(pubkey_affine) * scalar;
|
||||
let shared_affine = shared.to_affine();
|
||||
|
||||
let encoded = shared_affine.to_encoded_point(false);
|
||||
let x_bytes_slice = encoded.x().unwrap();
|
||||
let mut x_bytes = [0u8; 32];
|
||||
x_bytes.copy_from_slice(x_bytes_slice);
|
||||
|
||||
x_bytes
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Message {
|
||||
pub(crate) public_addresses: Vec<Address>,
|
||||
@ -126,9 +64,7 @@ impl Message {
|
||||
pub mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use nssa_core::account::{
|
||||
Account, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey,
|
||||
};
|
||||
use nssa_core::{account::Account, Commitment, Nullifier, NullifierPublicKey};
|
||||
|
||||
use crate::{Address, privacy_preserving_transaction::message::Message};
|
||||
|
||||
|
||||
@ -5,6 +5,6 @@ mod witness_set;
|
||||
|
||||
pub mod circuit;
|
||||
|
||||
pub use message::{Message, IncomingViewingPublicKey, EphemeralPublicKey, EphemeralSecretKey, EncryptedAccountData};
|
||||
pub use message::{Message, EncryptedAccountData};
|
||||
pub use transaction::PrivacyPreservingTransaction;
|
||||
pub use witness_set::WitnessSet;
|
||||
|
||||
@ -1,7 +1,10 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use nssa_core::account::{Account, AccountWithMetadata, Commitment, Nullifier};
|
||||
use nssa_core::{Ciphertext, CommitmentSetDigest, PrivacyPreservingCircuitOutput};
|
||||
use nssa_core::{
|
||||
Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, AccountWithMetadata},
|
||||
encryption::Ciphertext,
|
||||
};
|
||||
|
||||
use crate::error::NssaError;
|
||||
use crate::privacy_preserving_transaction::circuit::Proof;
|
||||
|
||||
@ -4,9 +4,7 @@ use crate::{
|
||||
public_transaction::PublicTransaction,
|
||||
};
|
||||
use nssa_core::{
|
||||
CommitmentSetDigest, MembershipProof,
|
||||
account::{Account, Commitment, Nullifier},
|
||||
program::{DEFAULT_PROGRAM_ID, ProgramId},
|
||||
account::Account, program::{ProgramId, DEFAULT_PROGRAM_ID}, Commitment, CommitmentSetDigest, MembershipProof, Nullifier
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
@ -222,19 +220,17 @@ pub mod tests {
|
||||
Address, PublicKey, PublicTransaction, V01State,
|
||||
error::NssaError,
|
||||
privacy_preserving_transaction::{
|
||||
EncryptedAccountData, EphemeralPublicKey, IncomingViewingPublicKey, Message,
|
||||
PrivacyPreservingTransaction, WitnessSet, circuit,
|
||||
EncryptedAccountData, Message, PrivacyPreservingTransaction, WitnessSet, circuit,
|
||||
},
|
||||
program::Program,
|
||||
public_transaction,
|
||||
signature::PrivateKey,
|
||||
};
|
||||
|
||||
use nssa_core::{
|
||||
Ciphertext,
|
||||
account::{
|
||||
Account, AccountWithMetadata, Commitment, Nonce, Nullifier, NullifierPublicKey,
|
||||
NullifierSecretKey,
|
||||
},
|
||||
Account, AccountWithMetadata, Nonce,
|
||||
}, encryption::{EphemeralPublicKey, IncomingViewingPublicKey}, Commitment, Nullifier, NullifierPublicKey, NullifierSecretKey, SharedSecretKey
|
||||
};
|
||||
use program_methods::AUTHENTICATED_TRANSFER_ID;
|
||||
|
||||
@ -794,8 +790,7 @@ pub mod tests {
|
||||
};
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret =
|
||||
EncryptedAccountData::compute_shared_secret(&esk, &recipient_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &recipient_keys.ivk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -814,7 +809,8 @@ pub mod tests {
|
||||
vec![sender_nonce],
|
||||
vec![epk],
|
||||
output,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[&sender_keys.signing_key]);
|
||||
PrivacyPreservingTransaction::new(message, witness_set)
|
||||
@ -840,13 +836,11 @@ pub mod tests {
|
||||
};
|
||||
|
||||
let esk_1 = [3; 32];
|
||||
let shared_secret_1 =
|
||||
EncryptedAccountData::compute_shared_secret(&esk_1, &sender_keys.ivk());
|
||||
let shared_secret_1 = SharedSecretKey::new(&esk_1, &sender_keys.ivk());
|
||||
let epk_1 = EphemeralPublicKey::from_scalar(esk_1);
|
||||
|
||||
let esk_2 = [3; 32];
|
||||
let shared_secret_2 =
|
||||
EncryptedAccountData::compute_shared_secret(&esk_2, &recipient_keys.ivk());
|
||||
let shared_secret_2 = SharedSecretKey::new(&esk_2, &recipient_keys.ivk());
|
||||
let epk_2 = EphemeralPublicKey::from_scalar(esk_2);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -870,7 +864,8 @@ pub mod tests {
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let message = Message::try_from_circuit_output(vec![], vec![], vec![epk_1, epk_2], output).unwrap();
|
||||
let message =
|
||||
Message::try_from_circuit_output(vec![], vec![], vec![epk_1, epk_2], output).unwrap();
|
||||
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[]);
|
||||
|
||||
@ -897,7 +892,7 @@ pub mod tests {
|
||||
};
|
||||
|
||||
let esk = [3; 32];
|
||||
let shared_secret = EncryptedAccountData::compute_shared_secret(&esk, &sender_keys.ivk());
|
||||
let shared_secret = SharedSecretKey::new(&esk, &sender_keys.ivk());
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
|
||||
let (output, proof) = circuit::execute_and_prove(
|
||||
@ -923,7 +918,8 @@ pub mod tests {
|
||||
vec![],
|
||||
vec![epk],
|
||||
output,
|
||||
).unwrap();
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let witness_set = WitnessSet::for_message(&message, proof, &[]);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user