Added public account id changes
update tests (public account id and private account id)
nullifier fixes
This commit is contained in:
jonesmarvin8 2026-04-02 17:20:52 -04:00
parent a4af07bc6d
commit c3c26b6c23
68 changed files with 1401 additions and 629 deletions

4
Cargo.lock generated
View File

@ -5287,11 +5287,14 @@ dependencies = [
"bytemuck",
"bytesize",
"chacha20",
"hex",
"k256",
"rand 0.8.5",
"risc0-zkvm",
"serde",
"serde_json",
"serde_with",
"sha2",
"thiserror 2.0.18",
]
@ -7600,6 +7603,7 @@ dependencies = [
"borsh",
"common",
"nssa",
"nssa_core",
"rocksdb",
"tempfile",
"thiserror 2.0.18",

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -35,7 +35,7 @@ pub struct BlockHeader {
pub prev_block_hash: BlockHash,
pub hash: BlockHash,
pub timestamp: Timestamp,
pub signature: nssa::Signature,
pub signature: nssa_core::Signature,
}
#[derive(Debug, Clone, BorshSerialize, BorshDeserialize)]
@ -82,11 +82,11 @@ impl HashableBlockData {
#[must_use]
pub fn into_pending_block(
self,
signing_key: &nssa::PrivateKey,
signing_key: &nssa_core::PrivateKey,
bedrock_parent_id: MantleMsgId,
) -> Block {
let data_bytes = borsh::to_vec(&self).unwrap();
let signature = nssa::Signature::new(signing_key, &data_bytes);
let signature = nssa_core::Signature::new(signing_key, &data_bytes);
let hash = OwnHasher::hash(&data_bytes);
Block {
header: BlockHeader {

View File

@ -9,8 +9,8 @@ use crate::{
// Helpers
#[must_use]
pub fn sequencer_sign_key_for_testing() -> nssa::PrivateKey {
nssa::PrivateKey::try_new([37; 32]).unwrap()
pub fn sequencer_sign_key_for_testing() -> nssa_core::PrivateKey {
nssa_core::PrivateKey::try_new([37; 32]).unwrap()
}
// Dummy producers
@ -51,7 +51,7 @@ pub fn produce_dummy_empty_transaction() -> NSSATransaction {
instruction_data,
)
.unwrap();
let private_key = nssa::PrivateKey::try_new([1; 32]).unwrap();
let private_key = nssa_core::PrivateKey::try_new([1; 32]).unwrap();
let witness_set = nssa::public_transaction::WitnessSet::for_message(&message, &[&private_key]);
let nssa_tx = nssa::PublicTransaction::new(message, witness_set);
@ -65,7 +65,7 @@ pub fn create_transaction_native_token_transfer(
nonce: u128,
to: AccountId,
balance_to_move: u128,
signing_key: &nssa::PrivateKey,
signing_key: &nssa_core::PrivateKey,
) -> NSSATransaction {
let account_ids = vec![from, to];
let nonces = vec![nonce.into()];

View File

@ -52,7 +52,7 @@ The derivation works as follows:
```
seed = SHA256(owner_id || definition_id)
ata_address = AccountId::from((ata_program_id, seed))
ata_address = AccountId::public_account_id((ata_program_id, seed))
```
Because the computation is pure, anyone who knows the owner and definition can reproduce the exact same ATA address — no network call required.

View File

@ -145,7 +145,8 @@ impl IndexerStore {
#[cfg(test)]
mod tests {
use nssa::{AccountId, PublicKey};
use nssa::AccountId;
use nssa_core::PublicKey;
use tempfile::tempdir;
use super::*;
@ -154,20 +155,20 @@ mod tests {
common::test_utils::produce_dummy_block(1, None, vec![])
}
fn acc1_sign_key() -> nssa::PrivateKey {
nssa::PrivateKey::try_new([1; 32]).unwrap()
fn acc1_sign_key() -> nssa_core::PrivateKey {
nssa_core::PrivateKey::try_new([1; 32]).unwrap()
}
fn acc2_sign_key() -> nssa::PrivateKey {
nssa::PrivateKey::try_new([2; 32]).unwrap()
fn acc2_sign_key() -> nssa_core::PrivateKey {
nssa_core::PrivateKey::try_new([2; 32]).unwrap()
}
fn acc1() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(&acc1_sign_key()))
AccountId::public_account_id(&PublicKey::new_from_private_key(&acc1_sign_key()), None)
}
fn acc2() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(&acc2_sign_key()))
AccountId::public_account_id(&PublicKey::new_from_private_key(&acc2_sign_key()), None)
}
#[test]

View File

@ -53,7 +53,7 @@ impl IndexerCore {
// because it will be overwritten by sequencer.
// Therefore:
// ToDo: remove key from indexer config, use some default.
let signing_key = nssa::PrivateKey::try_new(config.signing_key).unwrap();
let signing_key = nssa_core::PrivateKey::try_new(config.signing_key).unwrap();
let channel_genesis_msg_id = [0; 32];
let genesis_block = hashable_data.into_pending_block(&signing_key, channel_genesis_msg_id);
@ -71,10 +71,7 @@ impl IndexerCore {
acc.program_owner =
nssa::program::Program::authenticated_transfer_program().id();
nssa_core::Commitment::new(
&AccountId::account_id_without_identifier(npk),
&acc,
)
nssa_core::Commitment::new(&AccountId::private_account_id(npk, None), &acc)
})
.collect()
});

View File

@ -165,28 +165,28 @@ impl From<EphemeralPublicKey> for nssa_core::encryption::EphemeralPublicKey {
// Signature and PublicKey conversions
// ============================================================================
impl From<nssa::Signature> for Signature {
fn from(value: nssa::Signature) -> Self {
let nssa::Signature { value } = value;
impl From<nssa_core::Signature> for Signature {
fn from(value: nssa_core::Signature) -> Self {
let nssa_core::Signature { value } = value;
Self(value)
}
}
impl From<Signature> for nssa::Signature {
impl From<Signature> for nssa_core::Signature {
fn from(value: Signature) -> Self {
let Signature(sig_value) = value;
Self { value: sig_value }
}
}
impl From<nssa::PublicKey> for PublicKey {
fn from(value: nssa::PublicKey) -> Self {
impl From<nssa_core::PublicKey> for PublicKey {
fn from(value: nssa_core::PublicKey) -> Self {
Self(*value.value())
}
}
impl TryFrom<PublicKey> for nssa::PublicKey {
type Error = nssa::error::NssaError;
impl TryFrom<PublicKey> for nssa_core::PublicKey {
type Error = nssa_core::error::NssaCoreError;
fn try_from(value: PublicKey) -> Result<Self, Self::Error> {
Self::try_new(value.0)

View File

@ -4,8 +4,8 @@ use anyhow::{Context as _, Result};
use bytesize::ByteSize;
use indexer_service::{BackoffConfig, ChannelId, ClientConfig, IndexerConfig};
use key_protocol::key_management::KeyChain;
use nssa::{Account, AccountId, PrivateKey, PublicKey};
use nssa_core::{account::Data, program::DEFAULT_PROGRAM_ID};
use nssa::{Account, AccountId};
use nssa_core::{PrivateKey, PublicKey, account::Data, program::DEFAULT_PROGRAM_ID};
use sequencer_core::config::{BedrockConfig, SequencerConfig};
use testnet_initial_state::{
PrivateAccountPrivateInitialData, PrivateAccountPublicInitialData,
@ -45,11 +45,12 @@ impl InitialData {
let mut public_alice_private_key = PrivateKey::new_os_random();
let mut public_alice_public_key =
PublicKey::new_from_private_key(&public_alice_private_key);
let mut public_alice_account_id = AccountId::from(&public_alice_public_key);
let mut public_alice_account_id =
AccountId::public_account_id(&public_alice_public_key, None);
let mut public_bob_private_key = PrivateKey::new_os_random();
let mut public_bob_public_key = PublicKey::new_from_private_key(&public_bob_private_key);
let mut public_bob_account_id = AccountId::from(&public_bob_public_key);
let mut public_bob_account_id = AccountId::public_account_id(&public_bob_public_key, None);
// Ensure consistent ordering
if public_alice_account_id > public_bob_account_id {
@ -59,13 +60,12 @@ impl InitialData {
}
let mut private_charlie_key_chain = KeyChain::new_os_random();
let mut private_charlie_account_id = AccountId::account_id_without_identifier(
&private_charlie_key_chain.nullifier_public_key,
);
let mut private_charlie_account_id =
AccountId::private_account_id(&private_charlie_key_chain.nullifier_public_key, None);
let mut private_david_key_chain = KeyChain::new_os_random();
let mut private_david_account_id =
AccountId::account_id_without_identifier(&private_david_key_chain.nullifier_public_key);
AccountId::private_account_id(&private_david_key_chain.nullifier_public_key, None);
// Ensure consistent ordering
if private_charlie_account_id > private_david_account_id {
@ -109,7 +109,7 @@ impl InitialData {
.iter()
.map(|(priv_key, balance)| {
let pub_key = PublicKey::new_from_private_key(priv_key);
let account_id = AccountId::from(&pub_key);
let account_id = AccountId::public_account_id(&pub_key, None);
PublicAccountPublicInitialData {
account_id,
balance: *balance,
@ -133,7 +133,7 @@ impl InitialData {
.iter()
.map(|(priv_key, _)| {
let pub_key = PublicKey::new_from_private_key(priv_key);
let account_id = AccountId::from(&pub_key);
let account_id = AccountId::public_account_id(&pub_key, None);
InitialAccountData::Public(PublicAccountPrivateInitialData {
account_id,
pub_sign_key: priv_key.clone(),
@ -141,7 +141,7 @@ impl InitialData {
})
.chain(self.private_accounts.iter().map(|(key_chain, account)| {
let account_id =
AccountId::account_id_without_identifier(&key_chain.nullifier_public_key);
AccountId::private_account_id(&key_chain.nullifier_public_key, None);
InitialAccountData::Private(Box::new(PrivateAccountPrivateInitialData {
account_id,
account: account.clone(),

View File

@ -21,13 +21,13 @@ use integration_tests::{
use key_protocol::key_management::{KeyChain, ephemeral_key_holder::EphemeralKeyHolder};
use log::info;
use nssa::{
Account, AccountId, PrivacyPreservingTransaction, PrivateKey, PublicKey, PublicTransaction,
Account, AccountId, PrivacyPreservingTransaction, PublicTransaction,
privacy_preserving_transaction::{self as pptx, circuit},
program::Program,
public_transaction as putx,
};
use nssa_core::{
MembershipProof, NullifierPublicKey,
MembershipProof, NullifierPublicKey, PrivateKey, PublicKey,
account::{AccountWithMetadata, Nonce, data::Data},
encryption::ViewingPublicKey,
};
@ -49,7 +49,7 @@ impl TpsTestManager {
private_key_bytes[..8].copy_from_slice(&i.to_le_bytes());
let private_key = PrivateKey::try_new(private_key_bytes).unwrap();
let public_key = PublicKey::new_from_private_key(&private_key);
let account_id = AccountId::from(&public_key);
let account_id = AccountId::public_account_id(&public_key, None);
(private_key, account_id)
})
.collect();
@ -212,7 +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_id = AccountId::private_account_id(&sender_npk, None);
let sender_pre = AccountWithMetadata::new(
Account {
balance: 100,
@ -221,17 +221,17 @@ fn build_privacy_transaction() -> PrivacyPreservingTransaction {
data: Data::default(),
},
true,
AccountId::account_id_without_identifier(&sender_npk),
AccountId::private_account_id(&sender_npk, None),
);
let recipient_nsk = [2; 32];
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_id = AccountId::private_account_id(&recipient_npk, None);
let recipient_pre = AccountWithMetadata::new(
Account::default(),
false,
AccountId::account_id_without_identifier(&recipient_npk),
AccountId::private_account_id(&recipient_npk, None),
);
let eph_holder_from = EphemeralKeyHolder::new(&sender_npk);

View File

@ -21,8 +21,8 @@ use std::{
use anyhow::Result;
use integration_tests::{BlockingTestContext, TIME_TO_WAIT_FOR_BLOCK_SECONDS};
use log::info;
use nssa::{Account, AccountId, PrivateKey, PublicKey, program::Program};
use nssa_core::program::DEFAULT_PROGRAM_ID;
use nssa::{Account, AccountId, program::Program};
use nssa_core::{PrivateKey, PublicKey, program::DEFAULT_PROGRAM_ID};
use tempfile::tempdir;
use wallet_ffi::{
FfiAccount, FfiAccountList, FfiBytes32, FfiPrivateAccountKeys, FfiPublicAccountKey,
@ -332,7 +332,7 @@ fn wallet_ffi_save_and_load_persistent_storage() -> Result<()> {
};
assert_eq!(
nssa::AccountId::account_id_without_identifier(&private_account_keys.npk()),
nssa::AccountId::private_account_id(&private_account_keys.npk(), None),
out_private_account_id.into()
);
@ -607,7 +607,7 @@ fn test_wallet_ffi_get_private_account_keys() -> Result<()> {
fn test_wallet_ffi_account_id_to_base58() -> Result<()> {
let private_key = PrivateKey::new_os_random();
let public_key = PublicKey::new_from_private_key(&private_key);
let account_id = AccountId::from(&public_key);
let account_id = AccountId::public_account_id(&public_key, None);
let ffi_bytes: FfiBytes32 = (&account_id).into();
let ptr = unsafe { wallet_ffi_account_id_to_base58(&raw const ffi_bytes) };
@ -626,7 +626,7 @@ fn test_wallet_ffi_account_id_to_base58() -> Result<()> {
fn wallet_ffi_base58_to_account_id() -> Result<()> {
let private_key = PrivateKey::new_os_random();
let public_key = PublicKey::new_from_private_key(&private_key);
let account_id = AccountId::from(&public_key);
let account_id = AccountId::public_account_id(&public_key, None);
let account_id_str = account_id.to_string();
let account_id_c_str = CString::new(account_id_str.clone())?;
let account_id: AccountId = unsafe {

View File

@ -111,7 +111,7 @@ impl KeyNode for ChildKeysPrivate {
}
fn account_id(&self) -> nssa::AccountId {
nssa::AccountId::account_id_without_identifier(&self.value.0.nullifier_public_key)
nssa::AccountId::private_account_id(&self.value.0.nullifier_public_key, None)
}
}

View File

@ -5,8 +5,8 @@ use crate::key_management::key_tree::traits::KeyNode;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ChildKeysPublic {
pub csk: nssa::PrivateKey,
pub cpk: nssa::PublicKey,
pub csk: nssa_core::PrivateKey,
pub cpk: nssa_core::PublicKey,
pub ccc: [u8; 32],
/// Can be [`None`] if root.
pub cci: Option<u32>,
@ -41,14 +41,14 @@ impl KeyNode for ChildKeysPublic {
fn root(seed: [u8; 64]) -> Self {
let hash_value = hmac_sha512::HMAC::mac(seed, "LEE_master_pub");
let csk = nssa::PrivateKey::try_new(
let csk = nssa_core::PrivateKey::try_new(
*hash_value
.first_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get first 32"),
)
.expect("Expect a valid Private Key");
let ccc = *hash_value.last_chunk::<32>().unwrap();
let cpk = nssa::PublicKey::new_from_private_key(&csk);
let cpk = nssa_core::PublicKey::new_from_private_key(&csk);
Self {
csk,
@ -61,7 +61,7 @@ impl KeyNode for ChildKeysPublic {
fn nth_child(&self, cci: u32) -> Self {
let hash_value = self.compute_hash_value(cci);
let csk = nssa::PrivateKey::try_new({
let csk = nssa_core::PrivateKey::try_new({
let hash_value = hash_value
.first_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get first 32");
@ -80,7 +80,7 @@ impl KeyNode for ChildKeysPublic {
.last_chunk::<32>()
.expect("hash_value is 64 bytes, must be safe to get last 32");
let cpk = nssa::PublicKey::new_from_private_key(&csk);
let cpk = nssa_core::PublicKey::new_from_private_key(&csk);
Self {
csk,
@ -99,7 +99,7 @@ impl KeyNode for ChildKeysPublic {
}
fn account_id(&self) -> nssa::AccountId {
nssa::AccountId::from(&self.cpk)
nssa::AccountId::public_account_id(&self.cpk, None)
}
}
@ -107,7 +107,7 @@ impl KeyNode for ChildKeysPublic {
clippy::single_char_lifetime_names,
reason = "TODO add meaningful name"
)]
impl<'a> From<&'a ChildKeysPublic> for &'a nssa::PrivateKey {
impl<'a> From<&'a ChildKeysPublic> for &'a nssa_core::PrivateKey {
fn from(value: &'a ChildKeysPublic) -> Self {
&value.csk
}
@ -115,7 +115,7 @@ impl<'a> From<&'a ChildKeysPublic> for &'a nssa::PrivateKey {
#[cfg(test)]
mod tests {
use nssa::{PrivateKey, PublicKey};
use nssa_core::{PrivateKey, PublicKey};
use super::*;

View File

@ -125,11 +125,11 @@ mod tests {
let nullifier_public_key = utxo_secret_key_holder.generate_nullifier_public_key();
let viewing_public_key = utxo_secret_key_holder.generate_viewing_public_key();
let pub_account_signing_key = nssa::PrivateKey::new_os_random();
let pub_account_signing_key = nssa_core::PrivateKey::new_os_random();
let public_key = nssa::PublicKey::new_from_private_key(&pub_account_signing_key);
let public_key = nssa_core::PublicKey::new_from_private_key(&pub_account_signing_key);
let account = nssa::AccountId::from(&public_key);
let account = nssa::AccountId::public_account_id(&public_key, None);
println!("======Prerequisites======");
println!();

View File

@ -15,7 +15,7 @@ pub type PublicKey = AffinePoint;
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct NSSAUserData {
/// Default public accounts.
pub default_pub_account_signing_keys: BTreeMap<nssa::AccountId, nssa::PrivateKey>,
pub default_pub_account_signing_keys: BTreeMap<nssa::AccountId, nssa_core::PrivateKey>,
/// Default private accounts.
pub default_user_private_accounts:
BTreeMap<nssa::AccountId, (KeyChain, nssa_core::account::Account)>,
@ -27,12 +27,14 @@ pub struct NSSAUserData {
impl NSSAUserData {
fn valid_public_key_transaction_pairing_check(
accounts_keys_map: &BTreeMap<nssa::AccountId, nssa::PrivateKey>,
accounts_keys_map: &BTreeMap<nssa::AccountId, nssa_core::PrivateKey>,
) -> bool {
let mut check_res = true;
for (account_id, key) in accounts_keys_map {
let expected_account_id =
nssa::AccountId::from(&nssa::PublicKey::new_from_private_key(key));
let expected_account_id = nssa::AccountId::public_account_id(
&nssa_core::PublicKey::new_from_private_key(key),
None,
);
if &expected_account_id != account_id {
println!("{expected_account_id}, {account_id}");
check_res = false;
@ -47,7 +49,7 @@ impl NSSAUserData {
let mut check_res = true;
for (account_id, (key, _)) in accounts_keys_map {
let expected_account_id =
nssa::AccountId::account_id_without_identifier(&key.nullifier_public_key);
nssa::AccountId::private_account_id(&key.nullifier_public_key, None);
if expected_account_id != *account_id {
println!("{expected_account_id}, {account_id}");
check_res = false;
@ -57,7 +59,7 @@ impl NSSAUserData {
}
pub fn new_with_accounts(
default_accounts_keys: BTreeMap<nssa::AccountId, nssa::PrivateKey>,
default_accounts_keys: BTreeMap<nssa::AccountId, nssa_core::PrivateKey>,
default_accounts_key_chains: BTreeMap<
nssa::AccountId,
(KeyChain, nssa_core::account::Account),
@ -109,7 +111,7 @@ impl NSSAUserData {
pub fn get_pub_account_signing_key(
&self,
account_id: nssa::AccountId,
) -> Option<&nssa::PrivateKey> {
) -> Option<&nssa_core::PrivateKey> {
self.default_pub_account_signing_keys
.get(&account_id)
.or_else(|| self.public_key_tree.get_node(account_id).map(Into::into))

View File

@ -12,10 +12,13 @@ risc0-zkvm.workspace = true
borsh.workspace = true
serde.workspace = true
serde_with.workspace = true
sha2.workspace = true
rand.workspace = true
thiserror.workspace = true
bytemuck.workspace = true
bytesize.workspace = true
base58.workspace = true
hex.workspace = true
k256 = { workspace = true, optional = true }
chacha20 = { version = "0.10" }
@ -23,5 +26,5 @@ chacha20 = { version = "0.10" }
serde_json.workspace = true
[features]
default = []
default = ["dep:k256"]
host = ["dep:k256"]

View File

@ -10,7 +10,7 @@ use risc0_zkvm::sha::{Impl, Sha256 as _};
use serde::{Deserialize, Serialize};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use crate::{NullifierPublicKey, NullifierSecretKey, program::ProgramId};
use crate::{NullifierPublicKey, NullifierSecretKey, PublicKey, program::ProgramId};
pub mod data;
@ -180,7 +180,7 @@ impl AccountId {
}
#[must_use]
pub fn generate_account_id(value: &NullifierPublicKey, identifier: Option<u128>) -> Self {
pub fn private_account_id(value: &NullifierPublicKey, identifier: Option<u128>) -> Self {
const PRIVATE_ACCOUNT_ID_PREFIX: &[u8; 32] =
b"/LEE/v0.3/AccountId/Private/\x00\x00\x00\x00";
@ -202,13 +202,25 @@ impl AccountId {
}
#[must_use]
pub fn account_id_with_identifier(value: &NullifierPublicKey, identifier: u128) -> Self {
Self::generate_account_id(value, Some(identifier))
}
pub fn public_account_id(value: &PublicKey, identifier: Option<u128>) -> Self {
const PUBLIC_ACCOUNT_ID_PREFIX: &[u8; 32] =
b"/LEE/v0.3/AccountId/Public/\x00\x00\x00\x00\x00";
#[must_use]
pub fn account_id_without_identifier(value: &NullifierPublicKey) -> Self {
Self::generate_account_id(value, None)
let mut bytes = Vec::<u8>::new();
bytes.extend_from_slice(PUBLIC_ACCOUNT_ID_PREFIX);
bytes.extend_from_slice(value.value());
match identifier {
None => {}
Some(identifier) => bytes.extend_from_slice(&identifier.to_le_bytes()),
}
Self::new(
Impl::hash_bytes(&bytes)
.as_bytes()
.try_into()
.expect("Conversion should not fail"),
)
}
}
@ -393,11 +405,25 @@ mod tests {
];
let npk = NullifierPublicKey::from(&nsk);
let expected_account_id = AccountId::new([
139, 72, 194, 222, 215, 187, 147, 56, 55, 35, 222, 205, 156, 12, 204, 227, 166, 44, 30,
81, 186, 14, 167, 234, 28, 236, 32, 213, 125, 251, 193, 233,
48, 66, 236, 142, 62, 81, 247, 114, 151, 55, 109, 108, 34, 132, 216, 182, 239, 250,
126, 85, 106, 222, 127, 193, 125, 168, 62, 150, 129, 194, 135, 114,
]);
let account_id = AccountId::account_id_without_identifier(&npk);
let account_id = AccountId::private_account_id(&npk, Some(13_u128));
assert_eq!(account_id, expected_account_id);
}
#[test]
fn account_id_from_public_key() {
let pub_key = PublicKey::try_new([42_u8; 32]).expect("Expect valid Public Key");
let expected_account_id = AccountId::new([
75, 60, 223, 47, 170, 89, 187, 173, 89, 16, 96, 18, 76, 101, 203, 128, 241, 4, 253, 18,
61, 201, 37, 226, 199, 119, 9, 1, 239, 131, 221, 142,
]);
let account_id = AccountId::public_account_id(&pub_key, Some(13_u128));
assert_eq!(account_id, expected_account_id);
}

View File

@ -93,15 +93,16 @@ mod tests {
}],
ciphertexts: vec![Ciphertext(vec![255, 255, 1, 1, 2, 2])],
new_commitments: vec![Commitment::new(
&AccountId::account_id_without_identifier(&NullifierPublicKey::from(&[1_u8; 32])),
&AccountId::private_account_id(&NullifierPublicKey::from(&[1_u8; 32]), None),
&Account::default(),
)],
new_nullifiers: vec![(
Nullifier::for_account_update(
&Commitment::new(
&AccountId::account_id_without_identifier(&NullifierPublicKey::from(
&[2_u8; 32],
)),
&AccountId::private_account_id(
&NullifierPublicKey::from(&[2_u8; 32]),
None,
),
&Account::default(),
),
&[1; 32],

View File

@ -9,4 +9,13 @@ pub enum NssaCoreError {
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error("Invalid Public Key")]
InvalidPublicKey(#[source] k256::schnorr::Error),
#[error("Invalid hex for public key")]
InvalidHexPublicKey(hex::FromHexError),
#[error("Invalid private key")]
InvalidPrivateKey,
}

View File

@ -10,6 +10,7 @@ pub use commitment::{
};
pub use encryption::{EncryptionScheme, SharedSecretKey};
pub use nullifier::{Nullifier, NullifierPublicKey, NullifierSecretKey};
pub use signature::{PrivateKey, PublicKey, Signature};
pub mod account;
mod circuit_io;
@ -18,8 +19,9 @@ mod encoding;
pub mod encryption;
mod nullifier;
pub mod program;
pub mod signature;
#[cfg(feature = "host")]
// TODO: temp#[cfg(feature = "host")]
pub mod error;
pub type BlockId = u64;

View File

@ -99,7 +99,7 @@ mod tests {
255, 29, 105, 42, 186, 43, 11, 157, 168, 132, 225, 17, 163,
]);
let account_id = AccountId::account_id_with_identifier(&npk, 0_u128);
let account_id = AccountId::private_account_id(&npk, Some(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,

View File

@ -0,0 +1,367 @@
use crate::{PrivateKey, PublicKey, Signature};
pub struct TestVector {
pub seckey: Option<PrivateKey>,
pub pubkey: PublicKey,
pub aux_rand: Option<[u8; 32]>,
pub message: Option<Vec<u8>>,
pub signature: Signature,
pub verification_result: bool,
}
/// Test vectors from
/// <https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv>.
//
pub fn test_vectors() -> Vec<TestVector> {
vec![
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0000000000000000000000000000000000000000000000000000000000000003",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"F9308A019258C31049344F85F89D5229B531C845836F99B08601F113BCE036F9",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000000",
)),
message: Some(
hex::decode("0000000000000000000000000000000000000000000000000000000000000000")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"E907831F80848D1069A5371B402410364BDF1C5F8307B0084C55F1CE2DCA821525F66A4A85EA8B71E482A74F382D2CE5EBEEE8FDB2172F477DF4900D310536C0",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"B7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000001",
)),
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"6896BD60EEAE296DB48A229FF71DFE071BDE413E6D43F917DC8DCF8C78DE33418906D11AC976ABCCB20B091292BFF4EA897EFCB639EA871CFA95F6DE339E4B0A",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"C90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B14E5C9",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"DD308AFEC5777E13121FA72B9CC1B7CC0139715309B086C960E18FD969774EB8",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"C87AA53824B4D7AE2EB035A2B5BBBCCC080E76CDC6D1692C4B0B62D798E6D906",
)),
message: Some(
hex::decode("7E2D58D8B3BCDF1ABADEC7829054F90DDA9805AAB56C77333024B9D0A508B75C")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"5831AAEED7B44BB74E5EAB94BA9D4294C49BCF2A60728D8B4C200F50DD313C1BAB745879A5AD954A72C45A91C3A51D3C7ADEA98D82F8481E0E1E03674A6F3FB7",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0B432B2677937381AEF05BB02A66ECD012773062CF3FA2549E44F58ED2401710",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"25D1DFF95105F5253C4022F628A996AD3A0D95FBF21D468A1B33F8C160D8F517",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
)),
message: Some(
hex::decode("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"7EB0509757E246F19449885651611CB965ECC1A187DD51B64FDA1EDC9637D5EC97582B9CB13DB3933705B32BA982AF5AF25FD78881EBB32771FC5922EFC66EA3",
),
},
verification_result: true,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"D69C3509BB99E412E68B0FE8544E72837DFA30746D8BE2AA65975F29D22DC7B9",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("4DF3C3F68FCC83B27E9D42C90431A72499F17875C81A599B566C9889B9696703")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"00000000000000000000003B78CE563F89A0ED9414F5AA28AD0D96D6795F9C6376AFB1548AF603B3EB45C9F8207DEE1060CB71C04E80F593060B07D28308D7F4",
),
},
verification_result: true,
},
// Test with invalid public key
// TestVector {
// seckey: None,
// pubkey: PublicKey::new(hex_to_bytes(
// "EEFDEA4CDB677750A420FEE807EACF21EB9898AE79B9768766E4FAA04A2D4A34",
// )).unwrap(),
// aux_rand: None,
// message: Some(
// hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89").unwrap(),
// ),
// signature: Signature {
// value: hex_to_bytes(
// "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
// ),
// },
// verification_result: false,
// },
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"FFF97BD5755EEEA420453A14355235D382F6472F8568A18B2F057A14602975563CC27944640AC607CD107AE10923D9EF7A73C643E166BE5EBEAFA34B1AC553E2",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"1FA62E331EDBC21C394792D2AB1100A7B432B013DF3F6FF4F99FCB33E0E1515F28890B3EDB6E7189B630448B515CE4F8622A954CFE545735AAEA5134FCCDB2BD",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769961764B3AA9B2FFCB6EF947B6887A226E8D7C93E00C5ED0C1834FF0D0C2E6DA6",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"0000000000000000000000000000000000000000000000000000000000000000123DDA8328AF9C23A94C1FEECFD123BA4FB73476F0D594DCB65C6425BD186051",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"00000000000000000000000000000000000000000000000000000000000000017615FBAF5AE28864013C099742DEADB4DBA87F11AC6754F93780D5A1837CF197",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"4A298DACAE57395A15D0795DDBFD1DCB564DA82B0F269BC70A74F8220429BA1D69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F69E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
),
},
verification_result: false,
},
TestVector {
seckey: None,
pubkey: PublicKey::try_new(hex_to_bytes(
"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659",
)).unwrap(),
aux_rand: None,
message: Some(
hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89")
.unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E177769FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
),
},
verification_result: false,
},
// Test with invalid public key
// TestVector {
// seckey: None,
// pubkey: PublicKey::new(hex_to_bytes(
// "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC30",
// )).unwrap(),
// aux_rand: None,
// message: Some(
// hex::decode("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89").unwrap(),
// ),
// signature: Signature {
// value: hex_to_bytes(
// "6CFF5C3BA86C69EA4B7376F31A9BCB4F74C1976089B2D9963DA2E5543E17776969E89B4C5564D00349106B8497785DD7D1D713A8AE82B32FA79D5F7FC407D39B",
// ),
// },
// verification_result: false,
// },
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0340034003400340034003400340034003400340034003400340034003400340",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000000",
)),
message: None,
signature: Signature {
value: hex_to_bytes(
"71535DB165ECD9FBBC046E5FFAEA61186BB6AD436732FCCC25291A55895464CF6069CE26BF03466228F19A3A62DB8A649F2D560FAC652827D1AF0574E427AB63",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0340034003400340034003400340034003400340034003400340034003400340",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000000",
)),
message: Some(hex::decode("11").unwrap()),
signature: Signature {
value: hex_to_bytes(
"08A20A0AFEF64124649232E0693C583AB1B9934AE63B4C3511F3AE1134C6A303EA3173BFEA6683BD101FA5AA5DBC1996FE7CACFC5A577D33EC14564CEC2BACBF",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0340034003400340034003400340034003400340034003400340034003400340",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000000",
)),
message: Some(hex::decode("0102030405060708090A0B0C0D0E0F1011").unwrap()),
signature: Signature {
value: hex_to_bytes(
"5130F39A4059B43BC7CAC09A19ECE52B5D8699D1A71E3C52DA9AFDB6B50AC370C4A482B77BF960F8681540E25B6771ECE1E5A37FD80E5A51897C5566A97EA5A5",
),
},
verification_result: true,
},
TestVector {
seckey: Some(PrivateKey::try_new(hex_to_bytes(
"0340034003400340034003400340034003400340034003400340034003400340",
)).unwrap()),
pubkey: PublicKey::try_new(hex_to_bytes(
"778CAA53B4393AC467774D09497A87224BF9FAB6F6E68B23086497324D6FD117",
)).unwrap(),
aux_rand: Some(hex_to_bytes::<32>(
"0000000000000000000000000000000000000000000000000000000000000000",
)),
message: Some(
hex::decode("99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999").unwrap(),
),
signature: Signature {
value: hex_to_bytes(
"403B12B0D8555A344175EA7EC746566303321E5DBFA8BE6F091635163ECA79A8585ED3E3170807E7C03B720FC54C7B23897FCBA0E9D0B4A06894CFD249F22367",
),
},
verification_result: true,
},
]
}
fn hex_to_bytes<const N: usize>(hex: &str) -> [u8; N] {
hex::decode(hex).unwrap().try_into().unwrap()
}

View File

@ -0,0 +1,127 @@
use std::str::FromStr;
use borsh::{BorshDeserialize, BorshSerialize};
pub use private_key::PrivateKey;
pub use public_key::PublicKey;
use rand::{RngCore as _, rngs::OsRng};
mod private_key;
mod public_key;
#[derive(Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct Signature {
pub value: [u8; 64],
}
impl std::fmt::Debug for Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
impl std::fmt::Display for Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", hex::encode(self.value))
}
}
impl FromStr for Signature {
type Err = hex::FromHexError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut bytes = [0_u8; 64];
hex::decode_to_slice(s, &mut bytes)?;
Ok(Self { value: bytes })
}
}
impl Signature {
#[must_use]
pub fn new(key: &PrivateKey, message: &[u8]) -> Self {
let mut aux_random = [0_u8; 32];
OsRng.fill_bytes(&mut aux_random);
Self::new_with_aux_random(key, message, aux_random)
}
pub(crate) fn new_with_aux_random(
key: &PrivateKey,
message: &[u8],
aux_random: [u8; 32],
) -> Self {
let value = {
let signing_key = k256::schnorr::SigningKey::from_bytes(key.value())
.expect("Expect valid signing key");
signing_key
.sign_raw(message, &aux_random)
.expect("Expect to produce a valid signature")
.to_bytes()
};
Self { value }
}
#[must_use]
pub fn is_valid_for(&self, bytes: &[u8], public_key: &PublicKey) -> bool {
let Ok(pk) = k256::schnorr::VerifyingKey::from_bytes(public_key.value()) else {
return false;
};
let Ok(sig) = k256::schnorr::Signature::try_from(self.value.as_slice()) else {
return false;
};
pk.verify_raw(bytes, &sig).is_ok()
}
}
#[cfg(test)]
mod bip340_test_vectors;
#[cfg(test)]
mod tests {
use crate::{Signature, signature::bip340_test_vectors};
impl Signature {
pub(crate) fn _new_for_tests(value: [u8; 64]) -> Self {
Self { value }
}
}
#[test]
fn signature_generation_from_bip340_test_vectors() {
for (i, test_vector) in bip340_test_vectors::test_vectors().into_iter().enumerate() {
let Some(private_key) = test_vector.seckey else {
continue;
};
let Some(aux_random) = test_vector.aux_rand else {
continue;
};
let Some(message) = test_vector.message else {
continue;
};
if !test_vector.verification_result {
continue;
}
let expected_signature = &test_vector.signature;
let signature = Signature::new_with_aux_random(&private_key, &message, aux_random);
assert_eq!(&signature, expected_signature, "Failed test vector {i}");
}
}
#[test]
fn signature_verification_from_bip340_test_vectors() {
for (i, test_vector) in bip340_test_vectors::test_vectors().into_iter().enumerate() {
let message = test_vector.message.unwrap_or(vec![]);
let expected_result = test_vector.verification_result;
let result = test_vector
.signature
.is_valid_for(&message, &test_vector.pubkey);
assert_eq!(result, expected_result, "Failed test vector {i}");
}
}
}

View File

@ -0,0 +1,78 @@
use std::str::FromStr;
use rand::{Rng as _, rngs::OsRng};
use serde_with::{DeserializeFromStr, SerializeDisplay};
use crate::error::NssaCoreError;
// TODO: Remove Debug, Clone, Serialize, Deserialize, PartialEq and Eq for security reasons
// TODO: Implement Zeroize
#[derive(Clone, SerializeDisplay, DeserializeFromStr, PartialEq, Eq)]
pub struct PrivateKey([u8; 32]);
impl std::fmt::Debug for PrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
impl std::fmt::Display for PrivateKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl FromStr for PrivateKey {
type Err = NssaCoreError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut bytes = [0_u8; 32];
hex::decode_to_slice(s, &mut bytes).map_err(|_err| NssaCoreError::InvalidPrivateKey)?;
Self::try_new(bytes)
}
}
impl PrivateKey {
#[must_use]
pub fn new_os_random() -> Self {
let mut rng = OsRng;
loop {
if let Ok(key) = Self::try_new(rng.r#gen()) {
break key;
}
}
}
fn is_valid_key(value: [u8; 32]) -> bool {
k256::SecretKey::from_bytes(&value.into()).is_ok()
}
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaCoreError> {
if Self::is_valid_key(value) {
Ok(Self(value))
} else {
Err(NssaCoreError::InvalidPrivateKey)
}
}
#[must_use]
pub const fn value(&self) -> &[u8; 32] {
&self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn value_getter() {
let key = PrivateKey::try_new([1; 32]).unwrap();
assert_eq!(key.value(), &key.0);
}
#[test]
fn produce_key() {
let _key = PrivateKey::new_os_random();
}
}

View File

@ -0,0 +1,135 @@
use std::str::FromStr;
use borsh::{BorshDeserialize, BorshSerialize};
use k256::elliptic_curve::sec1::ToEncodedPoint as _;
use serde_with::{DeserializeFromStr, SerializeDisplay};
use crate::{PrivateKey, error::NssaCoreError};
#[derive(Clone, PartialEq, Eq, BorshSerialize, SerializeDisplay, DeserializeFromStr)]
pub struct PublicKey([u8; 32]);
impl std::fmt::Debug for PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self, f)
}
}
impl std::fmt::Display for PublicKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", hex::encode(self.0))
}
}
impl FromStr for PublicKey {
type Err = NssaCoreError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut bytes = [0_u8; 32];
hex::decode_to_slice(s, &mut bytes).map_err(NssaCoreError::InvalidHexPublicKey)?;
Self::try_new(bytes)
}
}
impl BorshDeserialize for PublicKey {
fn deserialize_reader<R: std::io::Read>(reader: &mut R) -> std::io::Result<Self> {
let mut buf = [0_u8; 32];
reader.read_exact(&mut buf)?;
Self::try_new(buf).map_err(|err| std::io::Error::new(std::io::ErrorKind::InvalidData, err))
}
}
impl PublicKey {
#[must_use]
pub fn new_from_private_key(key: &PrivateKey) -> Self {
let value = {
let secret_key = k256::SecretKey::from_bytes(&(*key.value()).into())
.expect("Expect a valid private key");
let encoded = secret_key.public_key().to_encoded_point(false);
let x_only = encoded
.x()
.expect("Expect k256 point to have a x-coordinate");
*x_only.first_chunk().expect("x_only is exactly 32 bytes")
};
Self(value)
}
pub fn try_new(value: [u8; 32]) -> Result<Self, NssaCoreError> {
// Check point is a valid x-only public key
let _ = k256::schnorr::VerifyingKey::from_bytes(&value)
.map_err(NssaCoreError::InvalidPublicKey)?;
Ok(Self(value))
}
#[must_use]
pub const fn value(&self) -> &[u8; 32] {
&self.0
}
}
#[cfg(test)]
mod test {
use crate::{PublicKey, error::NssaCoreError, signature::bip340_test_vectors};
#[test]
fn try_new_invalid_public_key_from_bip340_test_vectors_5() {
let value_invalid_key = [
238, 253, 234, 76, 219, 103, 119, 80, 164, 32, 254, 232, 7, 234, 207, 33, 235, 152,
152, 174, 121, 185, 118, 135, 102, 228, 250, 160, 74, 45, 74, 52,
];
let result = PublicKey::try_new(value_invalid_key);
assert!(matches!(result, Err(NssaCoreError::InvalidPublicKey(_))));
}
#[test]
fn try_new_invalid_public_key_from_bip340_test_vector_14() {
let value_invalid_key = [
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 254, 255, 255, 252, 48,
];
let result = PublicKey::try_new(value_invalid_key);
assert!(matches!(result, Err(NssaCoreError::InvalidPublicKey(_))));
}
#[test]
fn try_new_valid_public_keys() {
for (i, test_vector) in bip340_test_vectors::test_vectors().into_iter().enumerate() {
let expected_public_key = test_vector.pubkey;
let public_key = PublicKey::try_new(*expected_public_key.value()).unwrap();
assert_eq!(public_key, expected_public_key, "Failed on test vector {i}");
}
}
#[test]
fn public_key_generation_from_bip340_test_vectors() {
for (i, test_vector) in bip340_test_vectors::test_vectors().into_iter().enumerate() {
let Some(private_key) = &test_vector.seckey else {
continue;
};
let public_key = PublicKey::new_from_private_key(private_key);
let expected_public_key = &test_vector.pubkey;
assert_eq!(
&public_key, expected_public_key,
"Failed test vector at index {i}"
);
}
}
#[test]
fn correct_ser_deser_roundtrip() {
let pub_key = PublicKey::try_new([42; 32]).unwrap();
let pub_key_borsh_ser = borsh::to_vec(&pub_key).unwrap();
let pub_key_new: PublicKey = borsh::from_slice(&pub_key_borsh_ser).unwrap();
assert_eq!(pub_key, pub_key_new);
}
}

View File

@ -22,18 +22,9 @@ pub enum NssaError {
#[error("Serialization error: {0}")]
InstructionSerializationError(String),
#[error("Invalid private key")]
InvalidPrivateKey,
#[error("IO error: {0}")]
Io(#[from] io::Error),
#[error("Invalid Public Key")]
InvalidPublicKey(#[source] k256::schnorr::Error),
#[error("Invalid hex for public key")]
InvalidHexPublicKey(hex::FromHexError),
#[error("Risc0 error: {0}")]
ProgramWriteInputFailed(String),

View File

@ -15,7 +15,6 @@ pub use privacy_preserving_transaction::{
pub use program_deployment_transaction::ProgramDeploymentTransaction;
pub use program_methods::PRIVACY_PRESERVING_CIRCUIT_ID;
pub use public_transaction::PublicTransaction;
pub use signature::{PrivateKey, PublicKey, Signature};
pub use state::V03State;
pub mod encoding;
@ -25,7 +24,6 @@ pub mod privacy_preserving_transaction;
pub mod program;
pub mod program_deployment_transaction;
pub mod public_transaction;
mod signature;
mod state;
pub mod program_methods {

View File

@ -206,7 +206,7 @@ mod tests {
let recipient = AccountWithMetadata::new(
Account::default(),
false,
AccountId::account_id_without_identifier(&recipient_keys.npk()),
AccountId::private_account_id(&recipient_keys.npk(), None),
);
let balance_to_move: u128 = 37;
@ -267,7 +267,7 @@ mod tests {
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());
AccountId::private_account_id(&test_private_account_keys_2().npk(), None);
let sender_nonce = Nonce(0xdead_beef);
let sender_pre = AccountWithMetadata::new(
@ -278,14 +278,14 @@ mod tests {
data: Data::default(),
},
true,
AccountId::account_id_without_identifier(&sender_keys.npk()),
AccountId::private_account_id(&sender_keys.npk(), None),
);
let commitment_sender = Commitment::new(&sender_pre.account_id, &sender_pre.account);
let recipient = AccountWithMetadata::new(
Account::default(),
false,
AccountId::account_id_without_identifier(&recipient_keys.npk()),
AccountId::private_account_id(&recipient_keys.npk(), None),
);
let balance_to_move: u128 = 37;
@ -374,7 +374,7 @@ mod tests {
let pre = AccountWithMetadata::new(
Account::default(),
false,
AccountId::account_id_without_identifier(&account_keys.npk()),
AccountId::private_account_id(&account_keys.npk(), None),
);
let validity_window_chain_caller = Program::validity_window_chain_caller();

View File

@ -152,8 +152,8 @@ pub mod tests {
let npk1 = NullifierPublicKey::from(&nsk1);
let npk2 = NullifierPublicKey::from(&nsk2);
let account_id1 = AccountId::generate_account_id(&npk1, None);
let account_id2 = AccountId::generate_account_id(&npk2, None);
let account_id1 = AccountId::private_account_id(&npk1, None);
let account_id2 = AccountId::private_account_id(&npk2, None);
let public_account_ids = vec![account_id1, account_id2];
let nonces = vec![1_u128.into(), 2_u128.into(), 3_u128.into()];
@ -186,7 +186,7 @@ pub mod tests {
fn encrypted_account_data_constructor() {
let npk = NullifierPublicKey::from(&[1; 32]);
let vpk = ViewingPublicKey::from_scalar([2; 32]);
let account_id = AccountId::generate_account_id(&npk, None);
let account_id = AccountId::private_account_id(&npk, None);
let account = Account::default();
let commitment = Commitment::new(&account_id, &account);
let esk = [3; 32];

View File

@ -154,7 +154,7 @@ impl PrivacyPreservingTransaction {
self.witness_set
.signatures_and_public_keys()
.iter()
.map(|(_, public_key)| AccountId::from(public_key))
.map(|(_, public_key)| AccountId::public_account_id(public_key, None))
.collect()
}
@ -202,8 +202,10 @@ fn n_unique<T: Eq + Hash>(data: &[T]) -> usize {
#[cfg(test)]
mod tests {
use nssa_core::{PrivateKey, PublicKey};
use crate::{
AccountId, PrivacyPreservingTransaction, PrivateKey, PublicKey,
AccountId, PrivacyPreservingTransaction,
privacy_preserving_transaction::{
circuit::Proof, message::tests::message_for_tests, witness_set::WitnessSet,
},
@ -212,8 +214,8 @@ mod tests {
fn keys_for_tests() -> (PrivateKey, PrivateKey, AccountId, AccountId) {
let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let addr1 = AccountId::from(&PublicKey::new_from_private_key(&key1));
let addr2 = AccountId::from(&PublicKey::new_from_private_key(&key2));
let addr1 = AccountId::public_account_id(&PublicKey::new_from_private_key(&key1), None);
let addr2 = AccountId::public_account_id(&PublicKey::new_from_private_key(&key2), None);
(key1, key2, addr1, addr2)
}

View File

@ -1,9 +1,7 @@
use borsh::{BorshDeserialize, BorshSerialize};
use nssa_core::{PrivateKey, PublicKey, Signature};
use crate::{
PrivateKey, PublicKey, Signature,
privacy_preserving_transaction::{circuit::Proof, message::Message},
};
use crate::privacy_preserving_transaction::{circuit::Proof, message::Message};
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct WitnessSet {

View File

@ -45,7 +45,7 @@ impl PublicTransaction {
self.witness_set
.signatures_and_public_keys()
.iter()
.map(|(_, public_key)| AccountId::from(public_key))
.map(|(_, public_key)| AccountId::public_account_id(public_key, None))
.collect()
}
@ -276,10 +276,11 @@ impl PublicTransaction {
#[cfg(test)]
pub mod tests {
use nssa_core::{PrivateKey, PublicKey};
use sha2::{Digest as _, digest::FixedOutput as _};
use crate::{
AccountId, PrivateKey, PublicKey, PublicTransaction, Signature, V03State,
AccountId, PublicTransaction, V03State,
error::NssaError,
program::Program,
public_transaction::{Message, WitnessSet},
@ -288,8 +289,8 @@ pub mod tests {
fn keys_for_tests() -> (PrivateKey, PrivateKey, AccountId, AccountId) {
let key1 = PrivateKey::try_new([1; 32]).unwrap();
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let addr1 = AccountId::from(&PublicKey::new_from_private_key(&key1));
let addr2 = AccountId::from(&PublicKey::new_from_private_key(&key2));
let addr1 = AccountId::public_account_id(&PublicKey::new_from_private_key(&key1), None);
let addr2 = AccountId::public_account_id(&PublicKey::new_from_private_key(&key2), None);
(key1, key2, addr1, addr2)
}
@ -415,26 +416,27 @@ pub mod tests {
assert!(matches!(result, Err(NssaError::InvalidInput(_))));
}
#[test]
fn all_signatures_must_be_valid() {
let (key1, key2, addr1, addr2) = keys_for_tests();
let state = state_for_tests();
let nonces = vec![0_u128.into(), 0_u128.into()];
let instruction = 1337;
let message = Message::try_new(
Program::authenticated_transfer_program().id(),
vec![addr1, addr2],
nonces,
instruction,
)
.unwrap();
let mut witness_set = WitnessSet::for_message(&message, &[&key1, &key2]);
witness_set.signatures_and_public_keys[0].0 = Signature::new_for_tests([1; 64]);
let tx = PublicTransaction::new(message, witness_set);
let result = tx.validate_and_produce_public_state_diff(&state, 1, 0);
assert!(matches!(result, Err(NssaError::InvalidInput(_))));
}
// TODO: fix Marvin (commented out since that test is local to nssa-core)
// #[test]
// fn all_signatures_must_be_valid() {
// let (key1, key2, addr1, addr2) = keys_for_tests();
// let state = state_for_tests();
// let nonces = vec![0_u128.into(), 0_u128.into()];
// let instruction = 1337;
// let message = Message::try_new(
// Program::authenticated_transfer_program().id(),
// vec![addr1, addr2],
// nonces,
// instruction,
// )
// .unwrap();
//
// let mut witness_set = WitnessSet::for_message(&message, &[&key1, &key2]);
// witness_set.signatures_and_public_keys[0].0 = Signature::new_for_tests([1; 64]);
// let tx = PublicTransaction::new(message, witness_set);
// let result = tx.validate_and_produce_public_state_diff(&state, 1, 0);
// assert!(matches!(result, Err(NssaError::InvalidInput(_))));
// }
#[test]
fn nonces_must_match_the_state_current_nonces() {

View File

@ -1,6 +1,7 @@
use borsh::{BorshDeserialize, BorshSerialize};
use nssa_core::{PrivateKey, PublicKey, Signature};
use crate::{PrivateKey, PublicKey, Signature, public_transaction::Message};
use crate::public_transaction::Message;
#[derive(Debug, Clone, PartialEq, Eq, BorshSerialize, BorshDeserialize)]
pub struct WitnessSet {
@ -65,8 +66,8 @@ mod tests {
let key2 = PrivateKey::try_new([2; 32]).unwrap();
let pubkey1 = PublicKey::new_from_private_key(&key1);
let pubkey2 = PublicKey::new_from_private_key(&key2);
let addr1 = AccountId::from(&pubkey1);
let addr2 = AccountId::from(&pubkey2);
let addr1 = AccountId::public_account_id(&pubkey1, None);
let addr2 = AccountId::public_account_id(&pubkey2, None);
let nonces = vec![1_u128.into(), 2_u128.into()];
let instruction = vec![1, 2, 3, 4];
let message = Message::try_new([0; 8], vec![addr1, addr2], nonces, instruction).unwrap();

File diff suppressed because it is too large Load Diff

View File

@ -326,8 +326,10 @@ fn compute_circuit_output(
panic!("Missing private account key");
};
// TODO: (Marvin) identifier used here)
// Relevant here as this applies for both cases (authenicated and not authenicated).
assert_eq!(
AccountId::generate_account_id(npk, None),
AccountId::private_account_id(npk, None),
pre_state.account_id,
"AccountId mismatch"
);
@ -389,7 +391,10 @@ fn compute_circuit_output(
"Membership proof must be None for unauthorized accounts"
);
let account_id = AccountId::account_id_without_identifier(npk);
// TODO: (Marvin) need to add a Vec<identifier> as input.
// TODO: use here
let account_id = AccountId::private_account_id(npk, None);
let nullifier = Nullifier::for_account_initialization(&account_id);
let new_nonce = Nonce::private_account_nonce_init(npk);
@ -450,7 +455,7 @@ fn compute_nullifier_and_set_digest(
) -> (Nullifier, CommitmentSetDigest) {
// TODO: consider rewriting the function to receive account id instead of npk.
// NOTE: this does not use the identifier at all.
let account_id = AccountId::generate_account_id(npk, None);
let account_id = AccountId::private_account_id(npk, None);
membership_proof_opt.as_ref().map_or_else(
|| {
assert_eq!(

View File

@ -4,10 +4,9 @@ use amm_core::{
PoolDefinition, compute_liquidity_token_pda, compute_liquidity_token_pda_seed,
compute_pool_pda, compute_vault_pda, compute_vault_pda_seed,
};
use nssa::{
PrivateKey, PublicKey, PublicTransaction, V03State, program::Program, public_transaction,
};
use nssa::{PublicTransaction, V03State, program::Program, public_transaction};
use nssa_core::{
PrivateKey, PublicKey,
account::{Account, AccountId, AccountWithMetadata, Data},
program::{ChainedCall, ProgramId},
};
@ -1314,21 +1313,24 @@ impl IdForExeTests {
}
fn user_token_a_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_a_key(),
))
AccountId::public_account_id(
&PublicKey::new_from_private_key(&PrivateKeysForTests::user_token_a_key()),
None,
)
}
fn user_token_b_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_b_key(),
))
AccountId::public_account_id(
&PublicKey::new_from_private_key(&PrivateKeysForTests::user_token_b_key()),
None,
)
}
fn user_token_lp_id() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(
&PrivateKeysForTests::user_token_lp_key(),
))
AccountId::public_account_id(
&PublicKey::new_from_private_key(&PrivateKeysForTests::user_token_lp_key()),
None,
)
}
fn vault_a_id() -> AccountId {

View File

@ -14,7 +14,7 @@ pub struct SequencerStore {
// TODO: Consider adding the hashmap to the database for faster recovery.
tx_hash_to_block_map: HashMap<HashType, u64>,
genesis_id: u64,
signing_key: nssa::PrivateKey,
signing_key: nssa_core::PrivateKey,
}
impl SequencerStore {
@ -26,7 +26,7 @@ impl SequencerStore {
location: &Path,
genesis_block: &Block,
genesis_msg_id: MantleMsgId,
signing_key: nssa::PrivateKey,
signing_key: nssa_core::PrivateKey,
) -> Result<Self> {
let tx_hash_to_block_map = block_to_transactions_map(genesis_block);
@ -80,7 +80,7 @@ impl SequencerStore {
self.genesis_id
}
pub const fn signing_key(&self) -> &nssa::PrivateKey {
pub const fn signing_key(&self) -> &nssa_core::PrivateKey {
&self.signing_key
}

View File

@ -63,7 +63,7 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
timestamp: 0,
};
let signing_key = nssa::PrivateKey::try_new(config.signing_key).unwrap();
let signing_key = nssa_core::PrivateKey::try_new(config.signing_key).unwrap();
let genesis_parent_msg_id = [0; 32];
let genesis_block = hashable_data.into_pending_block(&signing_key, genesis_parent_msg_id);
@ -114,7 +114,7 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
let npk = &init_comm_data.npk;
let mut acc = init_comm_data.account.clone();
let acc_id = &AccountId::generate_account_id(npk, None);
let acc_id = &AccountId::private_account_id(npk, None);
acc.program_owner =
nssa::program::Program::authenticated_transfer_program().id();
@ -434,11 +434,11 @@ mod tests {
}
}
fn create_signing_key_for_account1() -> nssa::PrivateKey {
fn create_signing_key_for_account1() -> nssa_core::PrivateKey {
initial_pub_accounts_private_keys()[0].pub_sign_key.clone()
}
fn create_signing_key_for_account2() -> nssa::PrivateKey {
fn create_signing_key_for_account2() -> nssa_core::PrivateKey {
initial_pub_accounts_private_keys()[1].pub_sign_key.clone()
}

View File

@ -10,6 +10,7 @@ workspace = true
[dependencies]
common.workspace = true
nssa.workspace = true
nssa_core.workspace = true
thiserror.workspace = true
borsh.workspace = true

View File

@ -224,7 +224,8 @@ fn closest_breakpoint_id(block_id: u64) -> u64 {
#[expect(clippy::shadow_unrelated, reason = "Fine for tests")]
#[cfg(test)]
mod tests {
use nssa::{AccountId, PublicKey};
use nssa::AccountId;
use nssa_core::PublicKey;
use tempfile::tempdir;
use super::*;
@ -233,20 +234,20 @@ mod tests {
common::test_utils::produce_dummy_block(1, None, vec![])
}
fn acc1_sign_key() -> nssa::PrivateKey {
nssa::PrivateKey::try_new([1; 32]).unwrap()
fn acc1_sign_key() -> nssa_core::PrivateKey {
nssa_core::PrivateKey::try_new([1; 32]).unwrap()
}
fn acc2_sign_key() -> nssa::PrivateKey {
nssa::PrivateKey::try_new([2; 32]).unwrap()
fn acc2_sign_key() -> nssa_core::PrivateKey {
nssa_core::PrivateKey::try_new([2; 32]).unwrap()
}
fn acc1() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(&acc1_sign_key()))
AccountId::public_account_id(&PublicKey::new_from_private_key(&acc1_sign_key()), None)
}
fn acc2() -> AccountId {
AccountId::from(&PublicKey::new_from_private_key(&acc2_sign_key()))
AccountId::public_account_id(&PublicKey::new_from_private_key(&acc2_sign_key()), None)
}
#[test]

View File

@ -3,8 +3,10 @@ use key_protocol::key_management::{
KeyChain,
secret_holders::{PrivateKeyHolder, SecretSpendingKey},
};
use nssa::{Account, AccountId, Data, PrivateKey, PublicKey, V03State};
use nssa_core::{NullifierPublicKey, encryption::shared_key_derivation::Secp256k1Point};
use nssa::{Account, AccountId, Data, V03State};
use nssa_core::{
NullifierPublicKey, PrivateKey, PublicKey, encryption::shared_key_derivation::Secp256k1Point,
};
use serde::{Deserialize, Serialize};
const PRIVATE_KEY_PUB_ACC_A: [u8; 32] = [
@ -90,7 +92,7 @@ pub struct PrivateAccountPublicInitialData {
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct PublicAccountPrivateInitialData {
pub account_id: nssa::AccountId,
pub pub_sign_key: nssa::PrivateKey,
pub pub_sign_key: nssa_core::PrivateKey,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
@ -108,11 +110,17 @@ pub fn initial_pub_accounts_private_keys() -> Vec<PublicAccountPrivateInitialDat
vec![
PublicAccountPrivateInitialData {
account_id: AccountId::from(&PublicKey::new_from_private_key(&acc1_pub_sign_key)),
account_id: AccountId::public_account_id(
&PublicKey::new_from_private_key(&acc1_pub_sign_key),
None,
),
pub_sign_key: acc1_pub_sign_key,
},
PublicAccountPrivateInitialData {
account_id: AccountId::from(&PublicKey::new_from_private_key(&acc2_pub_sign_key)),
account_id: AccountId::public_account_id(
&PublicKey::new_from_private_key(&acc2_pub_sign_key),
None,
),
pub_sign_key: acc2_pub_sign_key,
},
]
@ -142,7 +150,7 @@ pub fn initial_priv_accounts_private_keys() -> Vec<PrivateAccountPrivateInitialD
vec![
PrivateAccountPrivateInitialData {
account_id: AccountId::generate_account_id(&key_chain_1.nullifier_public_key, None),
account_id: AccountId::private_account_id(&key_chain_1.nullifier_public_key, None),
account: Account {
program_owner: DEFAULT_PROGRAM_OWNER,
balance: PRIV_ACC_A_INITIAL_BALANCE,
@ -152,7 +160,7 @@ pub fn initial_priv_accounts_private_keys() -> Vec<PrivateAccountPrivateInitialD
key_chain: key_chain_1,
},
PrivateAccountPrivateInitialData {
account_id: AccountId::generate_account_id(&key_chain_2.nullifier_public_key, None),
account_id: AccountId::private_account_id(&key_chain_2.nullifier_public_key, None),
account: Account {
program_owner: DEFAULT_PROGRAM_OWNER,
balance: PRIV_ACC_B_INITIAL_BALANCE,
@ -200,7 +208,7 @@ pub fn initial_state() -> V03State {
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
let acc_id = &AccountId::generate_account_id(npk, None);
let acc_id = &AccountId::private_account_id(npk, None);
let mut acc = init_comm_data.account.clone();

View File

@ -2,7 +2,8 @@
use std::ptr;
use nssa::{AccountId, PublicKey};
use nssa::AccountId;
use nssa_core::PublicKey;
use crate::{
error::{print_error, WalletFfiError},

View File

@ -249,15 +249,15 @@ impl TryFrom<&FfiAccount> for nssa::Account {
}
}
impl From<nssa::PublicKey> for FfiPublicAccountKey {
fn from(value: nssa::PublicKey) -> Self {
impl From<nssa_core::PublicKey> for FfiPublicAccountKey {
fn from(value: nssa_core::PublicKey) -> Self {
Self {
public_key: FfiBytes32::from_bytes(*value.value()),
}
}
}
impl TryFrom<&FfiPublicAccountKey> for nssa::PublicKey {
impl TryFrom<&FfiPublicAccountKey> for nssa_core::PublicKey {
type Error = WalletFfiError;
fn try_from(value: &FfiPublicAccountKey) -> Result<Self, Self::Error> {

View File

@ -2,7 +2,8 @@ use anyhow::{Context as _, Result};
use clap::Subcommand;
use itertools::Itertools as _;
use key_protocol::key_management::key_tree::chain_index::ChainIndex;
use nssa::{Account, PublicKey, program::Program};
use nssa::{Account, program::Program};
use nssa_core::PublicKey;
use sequencer_service_rpc::RpcClient as _;
use token_core::{TokenDefinition, TokenHolding};

View File

@ -284,7 +284,7 @@ impl WalletCore {
pub fn get_account_public_signing_key(
&self,
account_id: AccountId,
) -> Option<&nssa::PrivateKey> {
) -> Option<&nssa_core::PrivateKey> {
self.storage
.user_data
.get_pub_account_signing_key(account_id)
@ -409,7 +409,7 @@ impl WalletCore {
.iter()
.map(|keys| {
(
AccountId::account_id_without_identifier(&keys.npk.clone()),
AccountId::private_account_id(&keys.npk.clone(), None),
keys.vpk.clone(),
keys.epk.clone(),
)
@ -504,7 +504,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(
&AccountId::account_id_without_identifier(&key_chain.nullifier_public_key),
&AccountId::private_account_id(&key_chain.nullifier_public_key, None),
&key_chain.viewing_public_key,
);

View File

@ -1,8 +1,8 @@
use anyhow::Result;
use key_protocol::key_management::ephemeral_key_holder::EphemeralKeyHolder;
use nssa::{AccountId, PrivateKey};
use nssa::AccountId;
use nssa_core::{
MembershipProof, NullifierPublicKey, NullifierSecretKey, SharedSecretKey,
MembershipProof, NullifierPublicKey, NullifierSecretKey, PrivateKey, SharedSecretKey,
account::{AccountWithMetadata, Nonce},
encryption::{EphemeralPublicKey, ViewingPublicKey},
};
@ -82,7 +82,7 @@ impl AccountManager {
(State::Private(pre), mask)
}
PrivacyPreservingAccount::PrivateForeign { npk, vpk } => {
let account_id = AccountId::generate_account_id(&npk, None);
let account_id = AccountId::private_account_id(&npk, None);
let acc = nssa_core::account::Account::default();
let auth_acc = AccountWithMetadata::new(acc, false, account_id);
let pre = AccountPreparedData {