mirror of
https://github.com/logos-blockchain/lssa.git
synced 2026-04-12 22:23:11 +00:00
update nullifiers and tags
This commit is contained in:
parent
d7adc391a4
commit
15a41375e4
@ -212,6 +212,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
let sender_vsk = [99; 32];
|
||||
let sender_vpk = ViewingPublicKey::from_scalar(sender_vsk);
|
||||
let sender_npk = NullifierPublicKey::from(&sender_nsk);
|
||||
let sender_id = AccountId::account_id_without_identifier(&sender_npk);
|
||||
let sender_pre = AccountWithMetadata::new(
|
||||
Account {
|
||||
balance: 100,
|
||||
@ -226,6 +227,7 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
let recipient_vsk = [99; 32];
|
||||
let recipient_vpk = ViewingPublicKey::from_scalar(recipient_vsk);
|
||||
let recipient_npk = NullifierPublicKey::from(&recipient_nsk);
|
||||
let recipient_id = AccountId::account_id_without_identifier(&recipient_npk);
|
||||
let recipient_pre =
|
||||
AccountWithMetadata::new(Account::default(), false, AccountId::account_id_without_identifier(&recipient_npk));
|
||||
|
||||
@ -250,8 +252,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
Program::serialize_instruction(balance_to_move).unwrap(),
|
||||
vec![1, 2],
|
||||
vec![
|
||||
(sender_npk.clone(), sender_ss),
|
||||
(recipient_npk.clone(), recipient_ss),
|
||||
(sender_npk, sender_ss),
|
||||
(recipient_npk, recipient_ss),
|
||||
],
|
||||
vec![sender_nsk],
|
||||
vec![Some(proof)],
|
||||
@ -262,8 +264,8 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(sender_npk, sender_vpk, sender_epk),
|
||||
(recipient_npk, recipient_vpk, recipient_epk),
|
||||
(sender_id, sender_vpk, sender_epk),
|
||||
(recipient_id, recipient_vpk, recipient_epk),
|
||||
],
|
||||
output,
|
||||
)
|
||||
|
||||
@ -27,7 +27,6 @@ pub type ViewingSecretKey = Scalar;
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
/// Private key holder. Produces public keys. Can produce `account_id`. Can produce shared secret
|
||||
/// for recepient.
|
||||
#[expect(clippy::partial_pub_fields, reason = "TODO: fix later")]
|
||||
pub struct PrivateKeyHolder {
|
||||
pub nullifier_secret_key: NullifierSecretKey,
|
||||
pub viewing_secret_key: ViewingSecretKey,
|
||||
|
||||
@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use risc0_zkvm::sha::{Impl, Sha256 as _};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{Commitment};
|
||||
use crate::{Commitment, account::AccountId};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
|
||||
#[cfg_attr(any(feature = "host", test), derive(Clone, Hash))]
|
||||
@ -68,10 +68,10 @@ impl Nullifier {
|
||||
|
||||
/// Computes a nullifier for an account initialization.
|
||||
#[must_use]
|
||||
pub fn for_account_initialization(npk: &NullifierPublicKey) -> Self {
|
||||
pub fn for_account_initialization(account_id: &AccountId) -> Self {
|
||||
const INIT_PREFIX: &[u8; 32] = b"/LEE/v0.3/Nullifier/Initialize/\x00";
|
||||
let mut bytes = INIT_PREFIX.to_vec();
|
||||
bytes.extend_from_slice(&npk.to_byte_array());
|
||||
bytes.extend_from_slice(account_id.value());
|
||||
Self(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap())
|
||||
}
|
||||
}
|
||||
@ -98,11 +98,11 @@ mod tests {
|
||||
112, 188, 193, 129, 150, 55, 228, 67, 88, 168, 29, 151, 5, 92, 23, 190, 17, 162, 164,
|
||||
255, 29, 105, 42, 186, 43, 11, 157, 168, 132, 225, 17, 163,
|
||||
]);
|
||||
let expected_nullifier = Nullifier([
|
||||
149, 59, 95, 181, 2, 194, 20, 143, 72, 233, 104, 243, 59, 70, 67, 243, 110, 77, 109,
|
||||
132, 139, 111, 51, 125, 128, 92, 107, 46, 252, 4, 20, 149,
|
||||
]);
|
||||
let nullifier = Nullifier::for_account_initialization(&npk);
|
||||
|
||||
let account_id = AccountId::account_id_with_identifier(&npk, 0_u128);
|
||||
|
||||
let expected_nullifier = Nullifier([63, 58, 51, 159, 15, 100, 240, 243, 60, 143, 151, 108, 116, 144, 101, 6, 134, 72, 198, 249, 108, 80, 237, 194, 143, 66, 225, 191, 111, 49, 66, 54]);
|
||||
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||
assert_eq!(nullifier, expected_nullifier);
|
||||
}
|
||||
|
||||
|
||||
@ -266,6 +266,7 @@ mod tests {
|
||||
let program = Program::authenticated_transfer_program();
|
||||
let sender_keys = test_private_account_keys_1();
|
||||
let recipient_keys = test_private_account_keys_2();
|
||||
let recipient_id = AccountId::account_id_without_identifier(&test_private_account_keys_2().npk());
|
||||
|
||||
let sender_nonce = Nonce(0xdead_beef);
|
||||
let sender_pre = AccountWithMetadata::new(
|
||||
@ -296,7 +297,7 @@ mod tests {
|
||||
commitment_set.digest(),
|
||||
),
|
||||
(
|
||||
Nullifier::for_account_initialization(&recipient_keys.npk()),
|
||||
Nullifier::for_account_initialization(&recipient_id),
|
||||
DUMMY_COMMITMENT_HASH,
|
||||
),
|
||||
];
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use borsh::{BorshDeserialize, BorshSerialize};
|
||||
use nssa_core::{
|
||||
Commitment, CommitmentSetDigest, Nullifier, NullifierPublicKey, PrivacyPreservingCircuitOutput,
|
||||
Commitment, CommitmentSetDigest, Nullifier, PrivacyPreservingCircuitOutput,
|
||||
account::{Account, Nonce},
|
||||
encryption::{Ciphertext, EphemeralPublicKey, ViewingPublicKey},
|
||||
program::ValidityWindow,
|
||||
@ -21,11 +21,11 @@ pub struct EncryptedAccountData {
|
||||
impl EncryptedAccountData {
|
||||
fn new(
|
||||
ciphertext: Ciphertext,
|
||||
npk: &NullifierPublicKey,
|
||||
account_id: &AccountId,
|
||||
vpk: &ViewingPublicKey,
|
||||
epk: EphemeralPublicKey,
|
||||
) -> Self {
|
||||
let view_tag = Self::compute_view_tag(npk, vpk);
|
||||
let view_tag = Self::compute_view_tag(account_id, vpk);
|
||||
Self {
|
||||
ciphertext,
|
||||
epk,
|
||||
@ -35,10 +35,13 @@ impl EncryptedAccountData {
|
||||
|
||||
/// Computes the tag as the first byte of SHA256("/LEE/v0.3/ViewTag/" || Npk || vpk).
|
||||
#[must_use]
|
||||
pub fn compute_view_tag(npk: &NullifierPublicKey, vpk: &ViewingPublicKey) -> ViewTag {
|
||||
pub fn compute_view_tag(account_id: &AccountId, vpk: &ViewingPublicKey) -> ViewTag {
|
||||
const VIEWTAG_PREFIX: &[u8; 32] =
|
||||
b"/LEE/v0.3/ViewTag\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(b"/LEE/v0.3/ViewTag/");
|
||||
hasher.update(npk.to_byte_array());
|
||||
hasher.update(VIEWTAG_PREFIX);
|
||||
hasher.update(account_id.to_bytes());
|
||||
hasher.update(vpk.to_bytes());
|
||||
let digest: [u8; 32] = hasher.finalize().into();
|
||||
digest[0]
|
||||
@ -88,7 +91,7 @@ impl Message {
|
||||
pub fn try_from_circuit_output(
|
||||
public_account_ids: Vec<AccountId>,
|
||||
nonces: Vec<Nonce>,
|
||||
public_keys: Vec<(NullifierPublicKey, ViewingPublicKey, EphemeralPublicKey)>,
|
||||
public_keys: Vec<(AccountId, ViewingPublicKey, EphemeralPublicKey)>, //TODO: Rename `public_keys` to account for `account_id`.
|
||||
output: PrivacyPreservingCircuitOutput,
|
||||
) -> Result<Self, NssaError> {
|
||||
if public_keys.len() != output.ciphertexts.len() {
|
||||
@ -101,8 +104,8 @@ impl Message {
|
||||
.ciphertexts
|
||||
.into_iter()
|
||||
.zip(public_keys)
|
||||
.map(|(ciphertext, (npk, vpk, epk))| {
|
||||
EncryptedAccountData::new(ciphertext, &npk, &vpk, epk)
|
||||
.map(|(ciphertext, (account_id, vpk, epk))| {
|
||||
EncryptedAccountData::new(ciphertext, &account_id, &vpk, epk)
|
||||
})
|
||||
.collect();
|
||||
Ok(Self {
|
||||
@ -183,7 +186,7 @@ pub mod tests {
|
||||
let epk = EphemeralPublicKey::from_scalar(esk);
|
||||
let ciphertext = EncryptionScheme::encrypt(&account, &shared_secret, &commitment, 2);
|
||||
let encrypted_account_data =
|
||||
EncryptedAccountData::new(ciphertext.clone(), &npk, &vpk, epk.clone());
|
||||
EncryptedAccountData::new(ciphertext.clone(), &account_id, &vpk, epk.clone());
|
||||
|
||||
let expected_view_tag = {
|
||||
let mut hasher = Sha256::new();
|
||||
@ -198,7 +201,7 @@ pub mod tests {
|
||||
assert_eq!(encrypted_account_data.epk, epk);
|
||||
assert_eq!(
|
||||
encrypted_account_data.view_tag,
|
||||
EncryptedAccountData::compute_view_tag(&npk, &vpk)
|
||||
EncryptedAccountData::compute_view_tag(&account_id, &vpk)
|
||||
);
|
||||
assert_eq!(encrypted_account_data.view_tag, expected_view_tag);
|
||||
}
|
||||
|
||||
@ -953,7 +953,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![sender_keys.account_id()],
|
||||
vec![sender_nonce],
|
||||
vec![(recipient_keys.npk(), recipient_keys.vpk(), epk)],
|
||||
vec![(recipient_id, recipient_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -1004,8 +1004,8 @@ pub mod tests {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(sender_keys.npk(), sender_keys.vpk(), epk_1),
|
||||
(recipient_keys.npk(), recipient_keys.vpk(), epk_2),
|
||||
(sender_id, sender_keys.vpk(), epk_1),
|
||||
(recipient_id, recipient_keys.vpk(), epk_2),
|
||||
],
|
||||
output,
|
||||
)
|
||||
@ -1052,7 +1052,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![*recipient_account_id],
|
||||
vec![],
|
||||
vec![(sender_keys.npk(), sender_keys.vpk(), epk)],
|
||||
vec![(sender_id, sender_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -2557,8 +2557,8 @@ pub mod tests {
|
||||
vec![],
|
||||
vec![],
|
||||
vec![
|
||||
(to_keys.npk(), to_keys.vpk(), to_epk),
|
||||
(from_keys.npk(), from_keys.vpk(), from_epk),
|
||||
(to_account_id, to_keys.vpk(), to_epk),
|
||||
(from_account_id, from_keys.vpk(), from_epk),
|
||||
],
|
||||
output,
|
||||
)
|
||||
@ -2791,7 +2791,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![(private_keys.npk(), private_keys.vpk(), epk)],
|
||||
vec![(account_id, private_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -2802,7 +2802,7 @@ pub mod tests {
|
||||
let result = state.transition_from_privacy_preserving_transaction(&tx, 1);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let nullifier = Nullifier::for_account_initialization(&private_keys.npk());
|
||||
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||
assert!(state.private_state.1.contains(&nullifier));
|
||||
}
|
||||
|
||||
@ -2842,7 +2842,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![(private_keys.npk(), private_keys.vpk(), epk)],
|
||||
vec![(account_id, private_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
@ -2858,7 +2858,7 @@ pub mod tests {
|
||||
);
|
||||
|
||||
// Verify the account is now initialized (nullifier exists)
|
||||
let nullifier = Nullifier::for_account_initialization(&private_keys.npk());
|
||||
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||
assert!(state.private_state.1.contains(&nullifier));
|
||||
|
||||
// Prepare new state of account
|
||||
@ -3111,7 +3111,8 @@ pub mod tests {
|
||||
let validity_window: ValidityWindow = validity_window.try_into().unwrap();
|
||||
let validity_window_program = Program::validity_window();
|
||||
let account_keys = test_private_account_keys_1();
|
||||
let pre = AccountWithMetadata::new(Account::default(), false, &account_keys.npk());
|
||||
let account_id = AccountId::account_id_without_identifier(&account_keys.npk());
|
||||
let pre = AccountWithMetadata::new(Account::default(), false, account_id);
|
||||
let mut state = V03State::new_with_genesis_accounts(&[], &[]).with_test_programs();
|
||||
let tx = {
|
||||
let esk = [3; 32];
|
||||
@ -3132,7 +3133,7 @@ pub mod tests {
|
||||
let message = Message::try_from_circuit_output(
|
||||
vec![],
|
||||
vec![],
|
||||
vec![(account_keys.npk(), account_keys.vpk(), epk)],
|
||||
vec![(account_id, account_keys.vpk(), epk)],
|
||||
output,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@ -317,7 +317,8 @@ fn compute_circuit_output(
|
||||
"Membership proof must be None for unauthorized accounts"
|
||||
);
|
||||
|
||||
let nullifier = Nullifier::for_account_initialization(npk);
|
||||
let account_id = AccountId::account_id_without_identifier(npk);
|
||||
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||
|
||||
let new_nonce = Nonce::private_account_nonce_init(npk);
|
||||
|
||||
@ -386,7 +387,7 @@ fn compute_nullifier_and_set_digest(
|
||||
);
|
||||
|
||||
// Compute initialization nullifier
|
||||
let nullifier = Nullifier::for_account_initialization(npk);
|
||||
let nullifier = Nullifier::for_account_initialization(&account_id);
|
||||
(nullifier, DUMMY_COMMITMENT_HASH)
|
||||
},
|
||||
|membership_proof| {
|
||||
|
||||
@ -393,7 +393,7 @@ impl WalletCore {
|
||||
Vec::from_iter(acc_manager.public_account_nonces()),
|
||||
private_account_keys
|
||||
.iter()
|
||||
.map(|keys| (keys.npk.clone(), keys.vpk.clone(), keys.epk.clone()))
|
||||
.map(|keys| (AccountId::account_id_without_identifier(&keys.npk.clone()), keys.vpk.clone(), keys.epk.clone()))
|
||||
.collect(),
|
||||
output,
|
||||
)
|
||||
@ -484,7 +484,7 @@ impl WalletCore {
|
||||
let affected_accounts = private_account_key_chains
|
||||
.flat_map(|(acc_account_id, key_chain, index)| {
|
||||
let view_tag = EncryptedAccountData::compute_view_tag(
|
||||
&key_chain.nullifier_public_key,
|
||||
&AccountId::account_id_without_identifier(&key_chain.nullifier_public_key),
|
||||
&key_chain.viewing_public_key,
|
||||
);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user