mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-01-02 13:23:10 +00:00
add root history
This commit is contained in:
parent
9ff6a5bc85
commit
20897596b0
@ -38,11 +38,10 @@ pub mod error;
|
||||
|
||||
pub type CommitmentSetDigest = [u8; 32];
|
||||
pub type MembershipProof = (usize, Vec<[u8; 32]>);
|
||||
pub fn verify_membership_proof(
|
||||
pub fn compute_root_associated_to_path(
|
||||
commitment: &Commitment,
|
||||
proof: &MembershipProof,
|
||||
digest: &CommitmentSetDigest,
|
||||
) -> bool {
|
||||
) -> CommitmentSetDigest {
|
||||
let value_bytes = commitment.to_byte_array();
|
||||
let mut result: [u8; 32] = Impl::hash_bytes(&value_bytes)
|
||||
.as_bytes()
|
||||
@ -64,7 +63,7 @@ pub fn verify_membership_proof(
|
||||
}
|
||||
level_index >>= 1;
|
||||
}
|
||||
&result == digest
|
||||
result
|
||||
}
|
||||
|
||||
pub type EphemeralPublicKey = Secp256k1Point;
|
||||
@ -243,7 +242,6 @@ pub struct PrivacyPreservingCircuitInput {
|
||||
)>,
|
||||
pub private_account_auth: Vec<(NullifierSecretKey, MembershipProof)>,
|
||||
pub program_id: ProgramId,
|
||||
pub commitment_set_digest: CommitmentSetDigest,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
@ -253,8 +251,7 @@ pub struct PrivacyPreservingCircuitOutput {
|
||||
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,
|
||||
pub new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "host")]
|
||||
@ -313,11 +310,13 @@ mod tests {
|
||||
&NullifierPublicKey::from(&[1; 32]),
|
||||
&Account::default(),
|
||||
)],
|
||||
new_nullifiers: vec![Nullifier::new(
|
||||
&Commitment::new(&NullifierPublicKey::from(&[2; 32]), &Account::default()),
|
||||
&[1; 32],
|
||||
new_nullifiers: vec![(
|
||||
Nullifier::new(
|
||||
&Commitment::new(&NullifierPublicKey::from(&[2; 32]), &Account::default()),
|
||||
&[1; 32],
|
||||
),
|
||||
[0xab; 32],
|
||||
)],
|
||||
commitment_set_digest: [0xab; 32],
|
||||
};
|
||||
let bytes = output.to_bytes();
|
||||
let output_from_slice: PrivacyPreservingCircuitOutput = from_slice(&bytes).unwrap();
|
||||
|
||||
@ -2,8 +2,9 @@ use risc0_zkvm::{guest::env, serde::to_vec};
|
||||
|
||||
use nssa_core::{
|
||||
account::{Account, AccountWithMetadata, Commitment, Nullifier, NullifierPublicKey},
|
||||
compute_root_associated_to_path,
|
||||
program::{validate_execution, ProgramOutput, DEFAULT_PROGRAM_ID},
|
||||
verify_membership_proof, EncryptedAccountData, EphemeralPublicKey, EphemeralSecretKey,
|
||||
CommitmentSetDigest, EncryptedAccountData, EphemeralPublicKey, EphemeralSecretKey,
|
||||
IncomingViewingPublicKey, PrivacyPreservingCircuitInput, PrivacyPreservingCircuitOutput,
|
||||
};
|
||||
|
||||
@ -15,7 +16,6 @@ fn main() {
|
||||
private_account_keys,
|
||||
private_account_auth,
|
||||
program_id,
|
||||
commitment_set_digest,
|
||||
} = env::read();
|
||||
|
||||
// TODO: Check that `program_execution_proof` is one of the allowed built-in programs
|
||||
@ -44,7 +44,7 @@ fn main() {
|
||||
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();
|
||||
let mut new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)> = Vec::new();
|
||||
|
||||
let mut private_nonces_iter = private_account_nonces.iter();
|
||||
let mut private_keys_iter = private_account_keys.iter();
|
||||
@ -80,15 +80,10 @@ fn main() {
|
||||
panic!("Npk mismatch");
|
||||
}
|
||||
|
||||
// Verify pre-state commitment membership
|
||||
// Compute commitment set digest associated with provided auth path
|
||||
let commitment_pre = Commitment::new(Npk, &pre_states[i].account);
|
||||
if !verify_membership_proof(
|
||||
&commitment_pre,
|
||||
membership_proof,
|
||||
&commitment_set_digest,
|
||||
) {
|
||||
panic!("Membership proof invalid");
|
||||
}
|
||||
let set_digest =
|
||||
compute_root_associated_to_path(&commitment_pre, membership_proof);
|
||||
|
||||
// Check pre_state authorization
|
||||
if !pre_states[i].is_authorized {
|
||||
@ -97,7 +92,7 @@ fn main() {
|
||||
|
||||
// Compute nullifier
|
||||
let nullifier = Nullifier::new(&commitment_pre, nsk);
|
||||
new_nullifiers.push(nullifier);
|
||||
new_nullifiers.push((nullifier, set_digest));
|
||||
} else {
|
||||
if pre_states[i].account != Account::default() {
|
||||
panic!("Found new private account with non default values.");
|
||||
@ -156,7 +151,6 @@ fn main() {
|
||||
encrypted_private_post_states,
|
||||
new_commitments,
|
||||
new_nullifiers,
|
||||
commitment_set_digest,
|
||||
};
|
||||
|
||||
env::commit(&output);
|
||||
|
||||
@ -173,7 +173,7 @@ fn verify_authentication_path(value: &Value, index: usize, path: &[Node], root:
|
||||
|
||||
fn prev_power_of_two(x: usize) -> usize {
|
||||
if x == 0 {
|
||||
return 0; // define as 0
|
||||
return 0;
|
||||
}
|
||||
1 << (usize::BITS as usize - x.leading_zeros() as usize - 1)
|
||||
}
|
||||
@ -314,10 +314,10 @@ mod tests {
|
||||
let expected_root =
|
||||
hex!("48c73f7821a58a8d2a703e5b39c571c0aa20cf14abcd0af8f2b955bc202998de");
|
||||
|
||||
tree.insert(values[0]);
|
||||
tree.insert(values[1]);
|
||||
tree.insert(values[2]);
|
||||
tree.insert(values[3]);
|
||||
assert_eq!(0, tree.insert(values[0]));
|
||||
assert_eq!(1, tree.insert(values[1]));
|
||||
assert_eq!(2, tree.insert(values[2]));
|
||||
assert_eq!(3, tree.insert(values[3]));
|
||||
|
||||
assert_eq!(tree.root(), expected_root);
|
||||
}
|
||||
@ -331,9 +331,9 @@ mod tests {
|
||||
let expected_root =
|
||||
hex!("c8d3d8d2b13f27ceeccdc699119871f9f32ea7ed86ff45d0ad11f77b28cd7568");
|
||||
|
||||
tree.insert(values[0]);
|
||||
tree.insert(values[1]);
|
||||
tree.insert(values[2]);
|
||||
assert_eq!(0, tree.insert(values[0]));
|
||||
assert_eq!(1, tree.insert(values[1]));
|
||||
assert_eq!(2, tree.insert(values[2]));
|
||||
|
||||
assert_eq!(tree.root(), expected_root);
|
||||
}
|
||||
@ -347,9 +347,9 @@ mod tests {
|
||||
let expected_root =
|
||||
hex!("c8d3d8d2b13f27ceeccdc699119871f9f32ea7ed86ff45d0ad11f77b28cd7568");
|
||||
|
||||
tree.insert(values[0]);
|
||||
tree.insert(values[1]);
|
||||
tree.insert(values[2]);
|
||||
assert_eq!(0, tree.insert(values[0]));
|
||||
assert_eq!(1, tree.insert(values[1]));
|
||||
assert_eq!(2, tree.insert(values[2]));
|
||||
|
||||
assert_eq!(tree.root(), expected_root);
|
||||
}
|
||||
@ -361,9 +361,9 @@ mod tests {
|
||||
let values = [[1; 32], [2; 32], [3; 32]];
|
||||
let expected_tree = MerkleTree::new(&values);
|
||||
|
||||
tree.insert(values[0]);
|
||||
tree.insert(values[1]);
|
||||
tree.insert(values[2]);
|
||||
assert_eq!(0, tree.insert(values[0]));
|
||||
assert_eq!(1, tree.insert(values[1]));
|
||||
assert_eq!(2, tree.insert(values[2]));
|
||||
|
||||
assert_eq!(expected_tree, tree);
|
||||
}
|
||||
@ -375,10 +375,10 @@ mod tests {
|
||||
let values = [[1; 32], [2; 32], [3; 32], [4; 32]];
|
||||
let expected_tree = MerkleTree::new(&values);
|
||||
|
||||
tree.insert(values[0]);
|
||||
tree.insert(values[1]);
|
||||
tree.insert(values[2]);
|
||||
tree.insert(values[3]);
|
||||
assert_eq!(0, tree.insert(values[0]));
|
||||
assert_eq!(1, tree.insert(values[1]));
|
||||
assert_eq!(2, tree.insert(values[2]));
|
||||
assert_eq!(3, tree.insert(values[3]));
|
||||
|
||||
assert_eq!(expected_tree, tree);
|
||||
}
|
||||
|
||||
@ -33,7 +33,6 @@ pub fn execute_and_prove(
|
||||
)],
|
||||
private_account_auth: &[(NullifierSecretKey, MembershipProof)],
|
||||
program: &Program,
|
||||
commitment_set_digest: &CommitmentSetDigest,
|
||||
) -> Result<(PrivacyPreservingCircuitOutput, Proof), NssaError> {
|
||||
let inner_receipt = execute_and_prove_program(program, pre_states, instruction_data)?;
|
||||
|
||||
@ -49,7 +48,6 @@ pub fn execute_and_prove(
|
||||
private_account_keys: private_account_keys.to_vec(),
|
||||
private_account_auth: private_account_auth.to_vec(),
|
||||
program_id: program.id(),
|
||||
commitment_set_digest: *commitment_set_digest,
|
||||
};
|
||||
|
||||
// Prove circuit.
|
||||
@ -157,7 +155,6 @@ mod tests {
|
||||
&[(recipient_keys.npk(), recipient_keys.ivk(), [3; 32])],
|
||||
&[],
|
||||
&Program::authenticated_transfer_program(),
|
||||
&[99; 32],
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -169,7 +166,6 @@ mod tests {
|
||||
assert_eq!(sender_post, expected_sender_post);
|
||||
assert_eq!(output.new_commitments.len(), 1);
|
||||
assert_eq!(output.new_nullifiers.len(), 0);
|
||||
assert_eq!(output.commitment_set_digest, [99; 32]);
|
||||
assert_eq!(output.encrypted_private_post_states.len(), 1);
|
||||
|
||||
let recipient_post = output.encrypted_private_post_states[0]
|
||||
@ -199,7 +195,13 @@ mod tests {
|
||||
};
|
||||
let balance_to_move: u128 = 37;
|
||||
|
||||
let expected_new_nullifiers = vec![Nullifier::new(&commitment_sender, &sender_keys.nsk)];
|
||||
let mut commitment_set = CommitmentSet::with_capacity(2);
|
||||
commitment_set.extend(&[commitment_sender.clone()]);
|
||||
|
||||
let expected_new_nullifiers = vec![(
|
||||
Nullifier::new(&commitment_sender, &sender_keys.nsk),
|
||||
commitment_set.digest(),
|
||||
)];
|
||||
|
||||
let program = Program::authenticated_transfer_program();
|
||||
|
||||
@ -220,9 +222,6 @@ mod tests {
|
||||
Commitment::new(&recipient_keys.npk(), &expected_private_account_2),
|
||||
];
|
||||
|
||||
let mut commitment_set = CommitmentSet::with_capacity(2);
|
||||
commitment_set.extend(&[commitment_sender.clone()]);
|
||||
|
||||
let (output, proof) = execute_and_prove(
|
||||
&[sender_pre.clone(), recipient],
|
||||
&Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
@ -237,7 +236,6 @@ mod tests {
|
||||
commitment_set.get_proof_for(&commitment_sender).unwrap(),
|
||||
)],
|
||||
&program,
|
||||
&commitment_set.digest(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -246,7 +244,6 @@ mod tests {
|
||||
assert!(output.public_post_states.is_empty());
|
||||
assert_eq!(output.new_commitments, expected_new_commitments);
|
||||
assert_eq!(output.new_nullifiers, expected_new_nullifiers);
|
||||
assert_eq!(output.commitment_set_digest, commitment_set.digest());
|
||||
assert_eq!(output.encrypted_private_post_states.len(), 2);
|
||||
|
||||
let recipient_post_1 = output.encrypted_private_post_states[0]
|
||||
|
||||
@ -12,8 +12,7 @@ use crate::{Address, error::NssaError};
|
||||
use super::message::Message;
|
||||
|
||||
const MESSAGE_ENCODING_PREFIX_LEN: usize = 22;
|
||||
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] =
|
||||
b"\x01/NSSA/v0.1/TxMessage/";
|
||||
const MESSAGE_ENCODING_PREFIX: &[u8; MESSAGE_ENCODING_PREFIX_LEN] = b"\x01/NSSA/v0.1/TxMessage/";
|
||||
|
||||
impl Message {
|
||||
pub(crate) fn to_bytes(&self) -> Vec<u8> {
|
||||
@ -56,9 +55,11 @@ impl Message {
|
||||
// New nullifiers
|
||||
let new_nullifiers_len: u32 = self.new_nullifiers.len() as u32;
|
||||
bytes.extend_from_slice(&new_nullifiers_len.to_le_bytes());
|
||||
for nullifier in &self.new_nullifiers {
|
||||
for (nullifier, commitment_set_digest) in &self.new_nullifiers {
|
||||
bytes.extend_from_slice(&nullifier.to_byte_array());
|
||||
bytes.extend_from_slice(commitment_set_digest);
|
||||
}
|
||||
|
||||
bytes
|
||||
}
|
||||
|
||||
@ -125,7 +126,10 @@ impl Message {
|
||||
let new_nullifiers_len = u32::from_le_bytes(len_bytes) as usize;
|
||||
let mut new_nullifiers = Vec::with_capacity(new_nullifiers_len);
|
||||
for _ in 0..new_nullifiers_len {
|
||||
new_nullifiers.push(Nullifier::from_cursor(cursor)?);
|
||||
let nullifier = Nullifier::from_cursor(cursor)?;
|
||||
let mut commitment_set_digest = [0; 32];
|
||||
cursor.read_exact(&mut commitment_set_digest);
|
||||
new_nullifiers.push((nullifier, commitment_set_digest));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use nssa_core::{
|
||||
EncryptedAccountData,
|
||||
CommitmentSetDigest, EncryptedAccountData,
|
||||
account::{Account, Commitment, Nonce, Nullifier},
|
||||
};
|
||||
|
||||
@ -12,7 +12,7 @@ pub struct Message {
|
||||
pub(crate) public_post_states: Vec<Account>,
|
||||
pub(crate) encrypted_private_post_states: Vec<EncryptedAccountData>,
|
||||
pub(crate) new_commitments: Vec<Commitment>,
|
||||
pub(crate) new_nullifiers: Vec<Nullifier>,
|
||||
pub(crate) new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
|
||||
}
|
||||
|
||||
impl Message {
|
||||
@ -22,7 +22,7 @@ impl Message {
|
||||
public_post_states: Vec<Account>,
|
||||
encrypted_private_post_states: Vec<EncryptedAccountData>,
|
||||
new_commitments: Vec<Commitment>,
|
||||
new_nullifiers: Vec<Nullifier>,
|
||||
new_nullifiers: Vec<(Nullifier, CommitmentSetDigest)>,
|
||||
) -> Self {
|
||||
Self {
|
||||
public_addresses,
|
||||
@ -66,7 +66,7 @@ pub mod tests {
|
||||
let new_commitments = vec![Commitment::new(&Npk2, &account2)];
|
||||
|
||||
let old_commitment = Commitment::new(&Npk1, &account1);
|
||||
let new_nullifiers = vec![Nullifier::new(&old_commitment, &nsk1)];
|
||||
let new_nullifiers = vec![(Nullifier::new(&old_commitment, &nsk1), [0; 32])];
|
||||
|
||||
Message {
|
||||
public_addresses: public_addresses.clone(),
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
use nssa_core::account::{Account, AccountWithMetadata};
|
||||
use nssa_core::account::{Account, AccountWithMetadata, Commitment, Nullifier};
|
||||
use nssa_core::{CommitmentSetDigest, EncryptedAccountData, PrivacyPreservingCircuitOutput};
|
||||
|
||||
use crate::error::NssaError;
|
||||
@ -93,8 +93,6 @@ impl PrivacyPreservingTransaction {
|
||||
})
|
||||
.collect();
|
||||
|
||||
let set_commitment = state.commitment_set_digest();
|
||||
|
||||
// 4. Proof verification
|
||||
check_privacy_preserving_circuit_proof_is_valid(
|
||||
&witness_set.proof,
|
||||
@ -103,14 +101,13 @@ impl PrivacyPreservingTransaction {
|
||||
&message.encrypted_private_post_states,
|
||||
&message.new_commitments,
|
||||
&message.new_nullifiers,
|
||||
set_commitment,
|
||||
)?;
|
||||
|
||||
// 5. Commitment freshness
|
||||
state.check_commitments_are_new(&message.new_commitments)?;
|
||||
|
||||
// 6. Nullifier uniqueness
|
||||
state.check_nullifiers_are_new(&message.new_nullifiers)?;
|
||||
state.check_nullifiers_are_valid(&message.new_nullifiers)?;
|
||||
|
||||
Ok(message
|
||||
.public_addresses
|
||||
@ -142,9 +139,8 @@ fn check_privacy_preserving_circuit_proof_is_valid(
|
||||
public_pre_states: &[AccountWithMetadata],
|
||||
public_post_states: &[Account],
|
||||
encrypted_private_post_states: &[EncryptedAccountData],
|
||||
new_commitments: &[nssa_core::account::Commitment],
|
||||
new_nullifiers: &[nssa_core::account::Nullifier],
|
||||
commitment_set_digest: CommitmentSetDigest,
|
||||
new_commitments: &[Commitment],
|
||||
new_nullifiers: &[(Nullifier, CommitmentSetDigest)],
|
||||
) -> Result<(), NssaError> {
|
||||
let output = PrivacyPreservingCircuitOutput {
|
||||
public_pre_states: public_pre_states.to_vec(),
|
||||
@ -152,7 +148,6 @@ fn check_privacy_preserving_circuit_proof_is_valid(
|
||||
encrypted_private_post_states: encrypted_private_post_states.to_vec(),
|
||||
new_commitments: new_commitments.to_vec(),
|
||||
new_nullifiers: new_nullifiers.to_vec(),
|
||||
commitment_set_digest,
|
||||
};
|
||||
proof
|
||||
.is_valid_for(&output)
|
||||
|
||||
@ -13,6 +13,7 @@ use std::collections::{HashMap, HashSet};
|
||||
pub(crate) struct CommitmentSet {
|
||||
merkle_tree: MerkleTree,
|
||||
commitments: HashMap<Commitment, usize>,
|
||||
pub root_history: HashSet<CommitmentSetDigest>,
|
||||
}
|
||||
|
||||
impl CommitmentSet {
|
||||
@ -22,9 +23,11 @@ impl CommitmentSet {
|
||||
|
||||
pub(crate) fn get_proof_for(&self, commitment: &Commitment) -> Option<MembershipProof> {
|
||||
let index = *self.commitments.get(commitment)?;
|
||||
self.merkle_tree
|
||||
let proof = self
|
||||
.merkle_tree
|
||||
.get_authentication_path_for(index)
|
||||
.map(|path| (index, path))
|
||||
.map(|path| (index, path));
|
||||
proof
|
||||
}
|
||||
|
||||
pub(crate) fn extend(&mut self, commitments: &[Commitment]) {
|
||||
@ -32,6 +35,7 @@ impl CommitmentSet {
|
||||
let index = self.merkle_tree.insert(commitment.to_byte_array());
|
||||
self.commitments.insert(commitment, index);
|
||||
}
|
||||
self.root_history.insert(self.digest());
|
||||
}
|
||||
|
||||
fn contains(&self, commitment: &Commitment) -> bool {
|
||||
@ -42,6 +46,7 @@ impl CommitmentSet {
|
||||
Self {
|
||||
merkle_tree: MerkleTree::with_capacity(capacity),
|
||||
commitments: HashMap::new(),
|
||||
root_history: HashSet::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -50,7 +55,7 @@ type NullifierSet = HashSet<Nullifier>;
|
||||
|
||||
pub struct V01State {
|
||||
public_state: HashMap<Address, Account>,
|
||||
private_state: (CommitmentSet, NullifierSet),
|
||||
pub private_state: (CommitmentSet, NullifierSet),
|
||||
builtin_programs: HashMap<ProgramId, Program>,
|
||||
}
|
||||
|
||||
@ -122,7 +127,13 @@ impl V01State {
|
||||
self.private_state.0.extend(&message.new_commitments);
|
||||
|
||||
// 3. Add new nullifiers
|
||||
self.private_state.1.extend(message.new_nullifiers.clone());
|
||||
let new_nullifiers = message
|
||||
.new_nullifiers
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|(nullifier, _)| nullifier)
|
||||
.collect::<Vec<Nullifier>>();
|
||||
self.private_state.1.extend(new_nullifiers);
|
||||
|
||||
// 4. Update public accounts
|
||||
for (address, post) in public_state_diff.into_iter() {
|
||||
@ -172,19 +183,34 @@ impl V01State {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn check_nullifiers_are_new(
|
||||
pub(crate) fn check_nullifiers_are_valid(
|
||||
&self,
|
||||
new_nullifiers: &[Nullifier],
|
||||
new_nullifiers: &[(Nullifier, CommitmentSetDigest)],
|
||||
) -> Result<(), NssaError> {
|
||||
for nullifier in new_nullifiers.iter() {
|
||||
for (nullifier, digest) in new_nullifiers.iter() {
|
||||
if self.private_state.1.contains(nullifier) {
|
||||
return Err(NssaError::InvalidInput(
|
||||
"Nullifier already seen".to_string(),
|
||||
));
|
||||
}
|
||||
if !self.private_state.0.root_history.contains(digest) {
|
||||
return Err(NssaError::InvalidInput(
|
||||
"Unrecognized commitment set digest".to_string(),
|
||||
));
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn check_commitment_set_digest_is_valid(
|
||||
&self,
|
||||
commitment_set_digest: &CommitmentSetDigest,
|
||||
) -> bool {
|
||||
self.private_state
|
||||
.0
|
||||
.root_history
|
||||
.contains(commitment_set_digest)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -774,7 +800,6 @@ pub mod tests {
|
||||
&[(recipient_keys.npk(), recipient_keys.ivk(), esk)],
|
||||
&[],
|
||||
&Program::authenticated_transfer_program(),
|
||||
&state.commitment_set_digest(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -828,7 +853,6 @@ pub mod tests {
|
||||
.unwrap(),
|
||||
)],
|
||||
&program,
|
||||
&state.private_state.0.digest(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -880,7 +904,6 @@ pub mod tests {
|
||||
.unwrap(),
|
||||
)],
|
||||
&program,
|
||||
&state.private_state.0.digest(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user