From 75b7fdd069f59b98a304d71fb6f547a2cf3d6722 Mon Sep 17 00:00:00 2001 From: Sergio Chouhy Date: Tue, 16 Sep 2025 07:51:40 -0300 Subject: [PATCH] add domain separation for private and public account ids --- nssa/core/src/account.rs | 1 + nssa/core/src/nullifier.rs | 11 ++++++++--- nssa/src/address.rs | 13 +++++++++++-- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/nssa/core/src/account.rs b/nssa/core/src/account.rs index fdd51e1..e7f8558 100644 --- a/nssa/core/src/account.rs +++ b/nssa/core/src/account.rs @@ -78,6 +78,7 @@ mod tests { assert_eq!(new_acc.program_owner, DEFAULT_PROGRAM_ID); } + #[cfg(feature = "host")] #[test] fn test_account_with_metadata_constructor() { let account = Account { diff --git a/nssa/core/src/nullifier.rs b/nssa/core/src/nullifier.rs index c7ee26e..cafa47c 100644 --- a/nssa/core/src/nullifier.rs +++ b/nssa/core/src/nullifier.rs @@ -9,7 +9,12 @@ pub struct NullifierPublicKey(pub(super) [u8; 32]); impl From<&NullifierPublicKey> for AccountId { fn from(value: &NullifierPublicKey) -> Self { - AccountId::new(value.0) + const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.1/AccountId/Private/\x00\x00\x00"; + + let mut bytes = [0; 64]; + bytes[0..32].copy_from_slice(PRIVATE_ACCOUNT_ID_PREFIX); + bytes[32..].copy_from_slice(&value.0); + AccountId::new(Impl::hash_bytes(&bytes).as_bytes().try_into().unwrap()) } } @@ -80,8 +85,8 @@ mod tests { ]; let npk = NullifierPublicKey::from(&nsk); let expected_account_id = AccountId::new([ - 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, + 69, 160, 50, 67, 12, 56, 150, 116, 62, 145, 17, 161, 17, 45, 24, 53, 33, 167, 83, 178, + 47, 114, 111, 233, 251, 30, 54, 244, 184, 22, 100, 236, ]); let account_id = AccountId::from(&npk); diff --git a/nssa/src/address.rs b/nssa/src/address.rs index 5837e20..72144b2 100644 --- a/nssa/src/address.rs +++ b/nssa/src/address.rs @@ -2,6 +2,7 @@ use std::{fmt::Display, str::FromStr}; use nssa_core::account::AccountId; use serde::{Deserialize, Serialize}; +use sha2::{Digest, Sha256}; use crate::signature::PublicKey; @@ -84,7 +85,12 @@ impl<'de> Deserialize<'de> for Address { impl From<&Address> for AccountId { fn from(address: &Address) -> Self { - AccountId::new(address.value) + const PUBLIC_ACCOUNT_ID_PREFIX: &[u8; 32] = b"/NSSA/v0.1/AccountId/Public/\x00\x00\x00\x00"; + + let mut hasher = Sha256::new(); + hasher.update(PUBLIC_ACCOUNT_ID_PREFIX); + hasher.update(address.value); + AccountId::new(hasher.finalize().into()) } } @@ -125,7 +131,10 @@ mod tests { #[test] fn test_account_id_from_address() { let address: Address = "37".repeat(32).parse().unwrap(); - let expected_account_id = AccountId::new([55; 32]); + let expected_account_id = AccountId::new([ + 93, 223, 66, 245, 78, 230, 157, 188, 110, 161, 134, 255, 137, 177, 220, 88, 37, 44, + 243, 91, 236, 4, 36, 147, 185, 112, 21, 49, 234, 4, 107, 185, + ]); let account_id = AccountId::from(&address);