mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-10 09:13:12 +00:00
wip
This commit is contained in:
parent
1a10dade25
commit
b20a97e5a1
@ -1,2 +1,13 @@
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::account::{Account, NullifierPublicKey};
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Commitment([u8; 32]);
|
||||
|
||||
impl Commitment {
|
||||
pub fn new(Npk: &NullifierPublicKey, account: &Account) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@ mod commitment;
|
||||
mod nullifier;
|
||||
|
||||
pub use commitment::Commitment;
|
||||
pub use nullifier::Nullifier;
|
||||
pub use nullifier::{Nullifier, NullifierPublicKey, NullifierSecretKey};
|
||||
|
||||
pub type Nonce = u128;
|
||||
type Data = Vec<u8>;
|
||||
|
||||
@ -1,2 +1,23 @@
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::account::Commitment;
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
pub struct NullifierPublicKey([u8; 32]);
|
||||
|
||||
impl From<&NullifierSecretKey> for NullifierPublicKey {
|
||||
fn from(_value: &NullifierSecretKey) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub type NullifierSecretKey = [u8; 32];
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Nullifier([u8; 32]);
|
||||
|
||||
impl Nullifier {
|
||||
pub fn new(commitment: &Commitment, nsk: &NullifierSecretKey) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,2 +1,79 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
account::{
|
||||
Account, AccountWithMetadata, Commitment, Nonce, Nullifier, NullifierPublicKey,
|
||||
NullifierSecretKey,
|
||||
},
|
||||
program::{ProgramId, ProgramOutput},
|
||||
};
|
||||
|
||||
pub mod account;
|
||||
pub mod program;
|
||||
|
||||
pub type CommitmentSetDigest = [u32; 8];
|
||||
pub type MembershipProof = Vec<[u8; 32]>;
|
||||
pub fn verify_membership_proof(
|
||||
commitment: &Commitment,
|
||||
proof: &MembershipProof,
|
||||
digest: &CommitmentSetDigest,
|
||||
) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub type IncomingViewingPublicKey = [u8; 32];
|
||||
pub type EphemeralSecretKey = [u8; 32];
|
||||
pub struct EphemeralPublicKey;
|
||||
|
||||
impl From<&EphemeralSecretKey> for EphemeralPublicKey {
|
||||
fn from(value: &EphemeralSecretKey) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tag(u8);
|
||||
impl Tag {
|
||||
pub fn new(Npk: &NullifierPublicKey, Ipk: &IncomingViewingPublicKey) -> Self {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EncryptedAccountData;
|
||||
|
||||
impl EncryptedAccountData {
|
||||
pub fn new(
|
||||
account: &Account,
|
||||
esk: &EphemeralSecretKey,
|
||||
Npk: &NullifierPublicKey,
|
||||
Ivk: &IncomingViewingPublicKey,
|
||||
) -> Self {
|
||||
// TODO: implement
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PrivacyPreservingCircuitInput {
|
||||
pub program_output: ProgramOutput,
|
||||
pub visibility_mask: Vec<u8>,
|
||||
pub private_account_data: Vec<(
|
||||
Nonce,
|
||||
NullifierPublicKey,
|
||||
IncomingViewingPublicKey,
|
||||
EphemeralSecretKey,
|
||||
)>,
|
||||
pub private_account_auth: Vec<(NullifierSecretKey, MembershipProof)>,
|
||||
pub program_id: ProgramId,
|
||||
pub commitment_set_digest: CommitmentSetDigest,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct PrivacyPreservingCircuitOutput {
|
||||
pub public_pre_states: Vec<AccountWithMetadata>,
|
||||
pub public_post_states: Vec<Account>,
|
||||
pub encrypted_private_post_states: Vec<EncryptedAccountData>,
|
||||
pub new_commitments: Vec<Commitment>,
|
||||
pub new_nullifiers: Vec<Nullifier>,
|
||||
pub commitment_set_digest: CommitmentSetDigest,
|
||||
}
|
||||
|
||||
118
nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs
Normal file
118
nssa/program_methods/guest/src/bin/privacy_preserving_circuit.rs
Normal file
@ -0,0 +1,118 @@
|
||||
use risc0_zkvm::{guest::env, serde::to_vec};
|
||||
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
program::{validate_execution, ProgramOutput},
|
||||
verify_membership_proof, EncryptedAccountData, EphemeralPublicKey, EphemeralSecretKey,
|
||||
IncomingViewingPublicKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput, Tag,
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let PrivacyPreservingCircuitInput {
|
||||
program_output,
|
||||
visibility_mask,
|
||||
private_account_data,
|
||||
private_account_auth,
|
||||
program_id,
|
||||
commitment_set_digest,
|
||||
} = env::read();
|
||||
|
||||
// TODO: Check that `program_execution_proof` is one of the allowed built-in programs
|
||||
// assert!(BUILTIN_PROGRAM_IDS.contains(executing_program_id));
|
||||
|
||||
// Check that `program_output` is consistent with the execution of the corresponding program.
|
||||
env::verify(program_id, &to_vec(&program_output).unwrap()).unwrap();
|
||||
|
||||
let ProgramOutput {
|
||||
pre_states,
|
||||
post_states,
|
||||
} = program_output;
|
||||
|
||||
// Check that the program is well behaved.
|
||||
// See the # Programs section for the definition of the `validate_execution` method.
|
||||
validate_execution(&pre_states, &post_states, program_id);
|
||||
|
||||
let n_accounts = pre_states.len();
|
||||
assert_eq!(visibility_mask.len(), n_accounts);
|
||||
|
||||
let n_private_accounts = visibility_mask.iter().filter(|&&flag| flag != 0).count();
|
||||
assert_eq!(private_account_data.len(), n_private_accounts);
|
||||
|
||||
let n_auth_private_accounts = visibility_mask.iter().filter(|&&flag| flag == 1).count();
|
||||
assert_eq!(private_account_auth.len(), n_auth_private_accounts);
|
||||
|
||||
// These lists will be the public outputs of this circuit
|
||||
// and will be populated next.
|
||||
let mut public_pre_states: Vec<AccountWithMetadata> = Vec::new();
|
||||
let mut public_post_states: Vec<Account> = Vec::new();
|
||||
let mut encrypted_private_post_states: Vec<EncryptedAccountData> = Vec::new();
|
||||
let mut new_commitments: Vec<Commitment> = Vec::new();
|
||||
let mut new_nullifiers: Vec<Nullifier> = Vec::new();
|
||||
|
||||
for i in 0..n_accounts {
|
||||
// visibility_mask[i] equal to 0 means public
|
||||
if visibility_mask[i] == 0 {
|
||||
// If the account is marked as public, add the pre and post
|
||||
// states to the corresponding lists.
|
||||
public_pre_states.push(pre_states[i].clone());
|
||||
public_post_states.push(post_states[i].clone());
|
||||
} else {
|
||||
let (new_nonce, Npk, Ipk, esk) = &private_account_data[i];
|
||||
|
||||
// Verify authentication
|
||||
if visibility_mask[i] == 1 {
|
||||
let (nsk, membership_proof) = &private_account_auth[i];
|
||||
|
||||
// 1. Compute Npk from the provided nsk and assert it is equal to the provided Npk
|
||||
let expected_Npk = NullifierPublicKey::from(nsk);
|
||||
assert_eq!(&expected_Npk, Npk);
|
||||
// 2. Compute the commitment of the pre_state account using the provided Npk
|
||||
let commitment_pre = Commitment::new(Npk, &pre_states[i].account);
|
||||
// 3. Verify that the commitment belongs to the global commitment set
|
||||
assert!(verify_membership_proof(
|
||||
&commitment_pre,
|
||||
membership_proof,
|
||||
&commitment_set_digest,
|
||||
));
|
||||
// At this point the account is correctly authenticated as a private account.
|
||||
// Assert that `pre_states` marked this account as authenticated.
|
||||
assert!(pre_states[i].is_authorized);
|
||||
// Compute the nullifier of the pre state version of this private account
|
||||
// and include it in the `new_nullifiers` list.
|
||||
let nullifier = Nullifier::new(&commitment_pre, nsk);
|
||||
new_nullifiers.push(nullifier);
|
||||
} else if visibility_mask[i] == 2 {
|
||||
assert_eq!(pre_states[i].account, Account::default());
|
||||
assert!(!pre_states[i].is_authorized);
|
||||
} else {
|
||||
panic!();
|
||||
}
|
||||
|
||||
// Update the nonce for the post state of this private account.
|
||||
let mut post_with_updated_nonce = post_states[i].clone();
|
||||
post_with_updated_nonce.nonce = *new_nonce;
|
||||
|
||||
// Compute the commitment of the post state of the private account,
|
||||
// with the updated nonce, and include it in the `new_commitments` list.
|
||||
let commitment_post = Commitment::new(Npk, &post_with_updated_nonce);
|
||||
new_commitments.push(commitment_post);
|
||||
|
||||
// Encrypt the post state of the private account with the updated
|
||||
// nonce and include it in the `encrypted_private_post_states` list.
|
||||
//
|
||||
let encrypted_account = EncryptedAccountData::new(&post_with_updated_nonce, esk, Npk, Ipk);
|
||||
encrypted_private_post_states.push(encrypted_account);
|
||||
}
|
||||
}
|
||||
|
||||
let output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states,
|
||||
public_post_states,
|
||||
encrypted_private_post_states,
|
||||
new_commitments,
|
||||
new_nullifiers,
|
||||
commitment_set_digest,
|
||||
};
|
||||
|
||||
env::commit(&output);
|
||||
}
|
||||
@ -1,10 +1,10 @@
|
||||
use nssa_core::account::{Account, Commitment, Nonce, Nullifier};
|
||||
use nssa_core::{
|
||||
EncryptedAccountData,
|
||||
account::{Account, Commitment, Nonce, Nullifier},
|
||||
};
|
||||
|
||||
use crate::Address;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct EncryptedAccountData;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct Message {
|
||||
pub(crate) public_addresses: Vec<Address>,
|
||||
|
||||
@ -1,10 +1,9 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use nssa_core::{CommitmentSetDigest, EncryptedAccountData};
|
||||
use nssa_core::account::{Account, AccountWithMetadata};
|
||||
|
||||
use crate::error::NssaError;
|
||||
use crate::privacy_preserving_transaction::message::EncryptedAccountData;
|
||||
use crate::state::CommitmentSetDigest;
|
||||
use crate::{Address, V01State};
|
||||
|
||||
use super::message::Message;
|
||||
@ -45,7 +44,7 @@ impl PrivacyPreservingTransaction {
|
||||
));
|
||||
}
|
||||
|
||||
// Check there are no duplicate commitments in the new_nullifiers list
|
||||
// Check there are no duplicate commitments in the new_commitments list
|
||||
if n_unique(&message.new_commitments) != message.new_commitments.len() {
|
||||
return Err(NssaError::InvalidInput(
|
||||
"Duplicate commitments found in message".into(),
|
||||
@ -61,7 +60,7 @@ impl PrivacyPreservingTransaction {
|
||||
}
|
||||
|
||||
// Check the signatures are valid
|
||||
if !witness_set.is_valid_for(message) {
|
||||
if !witness_set.signatures_are_valid_for(message) {
|
||||
return Err(NssaError::InvalidInput(
|
||||
"Invalid signature for given message and public key".into(),
|
||||
));
|
||||
@ -89,7 +88,7 @@ impl PrivacyPreservingTransaction {
|
||||
let set_commitment = state.commitment_set_digest();
|
||||
|
||||
// 4. Proof verification
|
||||
check_privacy_preserving_circuit_execution_proof_is_valid(
|
||||
check_privacy_preserving_circuit_proof_is_valid(
|
||||
witness_set.proof,
|
||||
&public_pre_states,
|
||||
&message.public_post_states,
|
||||
@ -130,7 +129,7 @@ impl PrivacyPreservingTransaction {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_privacy_preserving_circuit_execution_proof_is_valid(
|
||||
fn check_privacy_preserving_circuit_proof_is_valid(
|
||||
proof: (),
|
||||
public_pre_states: &[AccountWithMetadata],
|
||||
public_post_states: &[Account],
|
||||
|
||||
@ -15,7 +15,7 @@ impl WitnessSet {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn is_valid_for(&self, message: &Message) -> bool {
|
||||
pub fn signatures_are_valid_for(&self, message: &Message) -> bool {
|
||||
todo!()
|
||||
}
|
||||
|
||||
|
||||
@ -4,13 +4,13 @@ use crate::{
|
||||
public_transaction::PublicTransaction,
|
||||
};
|
||||
use nssa_core::{
|
||||
CommitmentSetDigest,
|
||||
account::{Account, Commitment, Nullifier},
|
||||
program::{DEFAULT_PROGRAM_ID, ProgramId},
|
||||
};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
struct CommitmentSet(HashSet<Commitment>);
|
||||
pub type CommitmentSetDigest = [u32; 8];
|
||||
|
||||
impl CommitmentSet {
|
||||
fn extend(&mut self, commitments: Vec<Commitment>) {
|
||||
@ -22,6 +22,7 @@ impl CommitmentSet {
|
||||
[0; 8]
|
||||
}
|
||||
}
|
||||
|
||||
type NullifierSet = HashSet<Nullifier>;
|
||||
|
||||
pub struct V01State {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user