rollback and remove identifier arguments in new private account wallet command

This commit is contained in:
Sergio Chouhy 2026-04-17 14:26:50 -03:00
parent f28ac0f092
commit b34e301023
6 changed files with 67 additions and 70 deletions

View File

@ -2,6 +2,7 @@ use std::collections::BTreeMap;
use anyhow::Result;
use nssa::{Account, AccountId};
use nssa_core::Identifier;
use serde::{Deserialize, Serialize};
use crate::key_management::{
@ -255,26 +256,30 @@ impl KeyTree<ChildKeysPublic> {
}
impl KeyTree<ChildKeysPrivate> {
/// Generate a new private key node, registering the identifier=0 account_id immediately.
pub fn generate_new_private_node(
&mut self,
parent_cci: &ChainIndex,
) -> Option<(nssa::AccountId, ChainIndex)> {
let cci = self.generate_new_node(parent_cci)?;
let node = self.key_map.get(&cci)?;
let account_id = nssa::AccountId::from((&node.value.0.nullifier_public_key, 0_u128));
self.account_id_map.insert(account_id, cci.clone());
Some((account_id, cci))
pub fn generate_new_private_node(&mut self, parent_cci: &ChainIndex) -> Option<ChainIndex> {
self.generate_new_node(parent_cci)
}
/// Generate a new private key node using layered placement, registering the identifier=0
/// account_id immediately.
pub fn generate_new_private_node_layered(&mut self) -> Option<(nssa::AccountId, ChainIndex)> {
let cci = self.generate_new_node_layered()?;
let node = self.key_map.get(&cci)?;
let account_id = nssa::AccountId::from((&node.value.0.nullifier_public_key, 0_u128));
pub fn generate_new_private_node_layered(&mut self) -> Option<ChainIndex> {
self.generate_new_node_layered()
}
/// Register an additional identifier on an existing private key node, inserting the derived
/// `AccountId` into `account_id_map`. Returns `None` if the node does not exist or the
/// `AccountId` is already registered.
pub fn register_identifier_on_node(
&mut self,
cci: &ChainIndex,
identifier: Identifier,
) -> Option<nssa::AccountId> {
let node = self.key_map.get(cci)?;
let account_id =
nssa::AccountId::from((&node.value.0.nullifier_public_key, identifier));
if self.account_id_map.contains_key(&account_id) {
return None;
}
self.account_id_map.insert(account_id, cci.clone());
Some((account_id, cci))
Some(account_id)
}
/// Cleanup of non-initialized accounts in a private tree.

View File

@ -121,13 +121,11 @@ impl NSSAUserData {
.or_else(|| self.public_key_tree.get_node(account_id).map(Into::into))
}
/// Generated new private key for privacy preserving transactions.
///
/// Returns the `AccountId` (for identifier=0) and `ChainIndex` of the new node.
/// Generates a new private key node and returns its `ChainIndex`.
pub fn generate_new_privacy_preserving_transaction_key_chain(
&mut self,
parent_cci: Option<ChainIndex>,
) -> (nssa::AccountId, ChainIndex) {
) -> ChainIndex {
match parent_cci {
Some(parent_cci) => self
.private_key_tree
@ -140,6 +138,18 @@ impl NSSAUserData {
}
}
/// Registers an additional identifier on an existing private key node, deriving and recording
/// the corresponding `AccountId`. Returns `None` if the node does not exist or the identifier
/// is already registered.
pub fn register_identifier_on_private_key_chain(
&mut self,
cci: ChainIndex,
identifier: Identifier,
) -> Option<nssa::AccountId> {
self.private_key_tree
.register_identifier_on_node(&cci, identifier)
}
/// Returns the key chain and account data for the given private account ID.
#[must_use]
pub fn get_private_account(
@ -211,16 +221,12 @@ mod tests {
fn new_account() {
let mut user_data = NSSAUserData::default();
let (account_id, chain_index) = user_data
let chain_index = user_data
.generate_new_privacy_preserving_transaction_key_chain(Some(ChainIndex::root()));
let is_key_chain_generated = user_data.private_key_tree.key_map.contains_key(&chain_index);
assert!(is_key_chain_generated);
let is_account_id_registered =
user_data.private_key_tree.account_id_map.contains_key(&account_id);
assert!(is_account_id_registered);
let key_chain = &user_data.private_key_tree.key_map[&chain_index].value.0;
println!("{key_chain:#?}");
}

View File

@ -59,14 +59,14 @@ pub unsafe extern "C" fn wallet_ffi_create_account_public(
WalletFfiError::Success
}
/// Create a new private account.
/// Create a new private key node.
///
/// Private accounts use privacy-preserving transactions with nullifiers
/// and commitments.
/// Returns the nullifier public key (npk) to share with senders. Account IDs are
/// discovered later via sync when senders initialize accounts under this key.
///
/// # Parameters
/// - `handle`: Valid wallet handle
/// - `out_account_id`: Output pointer for the new account ID (32 bytes)
/// - `out_npk`: Output pointer for the nullifier public key (32 bytes)
///
/// # Returns
/// - `Success` on successful creation
@ -74,19 +74,19 @@ pub unsafe extern "C" fn wallet_ffi_create_account_public(
///
/// # Safety
/// - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
/// - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
/// - `out_npk` must be a valid pointer to a `FfiBytes32` struct
#[no_mangle]
pub unsafe extern "C" fn wallet_ffi_create_account_private(
handle: *mut WalletHandle,
out_account_id: *mut FfiBytes32,
out_npk: *mut FfiBytes32,
) -> WalletFfiError {
let wrapper = match get_wallet(handle) {
Ok(w) => w,
Err(e) => return e,
};
if out_account_id.is_null() {
print_error("Null output pointer for account_id");
if out_npk.is_null() {
print_error("Null output pointer for npk");
return WalletFfiError::NullPointer;
}
@ -98,10 +98,18 @@ pub unsafe extern "C" fn wallet_ffi_create_account_private(
}
};
let (account_id, _chain_index) = wallet.create_new_account_private(None);
let chain_index = wallet.create_new_account_private(None);
let node = wallet
.storage()
.user_data
.private_key_tree
.key_map
.get(&chain_index)
.expect("Node was just inserted");
unsafe {
(*out_account_id).data = *account_id.value();
(*out_npk).data = node.value.0.nullifier_public_key.0;
}
WalletFfiError::Success

View File

@ -243,14 +243,14 @@ enum WalletFfiError wallet_ffi_create_account_public(struct WalletHandle *handle
struct FfiBytes32 *out_account_id);
/**
* Create a new private account.
* Create a new private key node.
*
* Private accounts use privacy-preserving transactions with nullifiers
* and commitments.
* Returns the nullifier public key (npk) to share with senders. Account IDs are
* discovered later via sync when senders initialize accounts under this key.
*
* # Parameters
* - `handle`: Valid wallet handle
* - `out_account_id`: Output pointer for the new account ID (32 bytes)
* - `out_npk`: Output pointer for the nullifier public key (32 bytes)
*
* # Returns
* - `Success` on successful creation
@ -258,10 +258,10 @@ enum WalletFfiError wallet_ffi_create_account_public(struct WalletHandle *handle
*
* # Safety
* - `handle` must be a valid wallet handle from `wallet_ffi_create_new` or `wallet_ffi_open`
* - `out_account_id` must be a valid pointer to a `FfiBytes32` struct
* - `out_npk` must be a valid pointer to a `FfiBytes32` struct
*/
enum WalletFfiError wallet_ffi_create_account_private(struct WalletHandle *handle,
struct FfiBytes32 *out_account_id);
struct FfiBytes32 *out_npk);
/**
* List all accounts in the wallet.

View File

@ -2,7 +2,7 @@ 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, AccountId, PublicKey, program::Program};
use nssa::{Account, PublicKey, program::Program};
use sequencer_service_rpc::RpcClient as _;
use token_core::{TokenDefinition, TokenHolding};
@ -87,9 +87,6 @@ pub enum NewSubcommand {
#[arg(long)]
/// Chain index of a parent node.
cci: Option<ChainIndex>,
#[arg(short, long)]
/// Label to assign to the new account.
label: Option<String>,
},
}
@ -136,18 +133,8 @@ impl WalletSubcommand for NewSubcommand {
Ok(SubcommandReturnValue::RegisterAccount { account_id })
}
Self::Private { cci, label } => {
if let Some(label) = &label
&& wallet_core
.storage
.labels
.values()
.any(|l| l.to_string() == *label)
{
anyhow::bail!("Label '{label}' is already in use by another account");
}
let (account_id, chain_index) = wallet_core.create_new_account_private(cci);
Self::Private { cci } => {
let chain_index = wallet_core.create_new_account_private(cci);
let node = wallet_core
.storage
@ -158,16 +145,7 @@ impl WalletSubcommand for NewSubcommand {
.expect("Node was just inserted");
let key = &node.value.0;
if let Some(label) = label {
wallet_core
.storage
.labels
.insert(account_id.to_string(), Label::new(label));
}
println!(
"Generated new account with account_id Private/{account_id} at path {chain_index}",
);
println!("Generated new private key node at path {chain_index}");
println!("With npk {}", hex::encode(key.nullifier_public_key.0));
println!(
"With vpk {}",
@ -176,7 +154,7 @@ impl WalletSubcommand for NewSubcommand {
wallet_core.store_persistent_data().await?;
Ok(SubcommandReturnValue::RegisterAccount { account_id })
Ok(SubcommandReturnValue::Empty)
}
}
}

View File

@ -259,7 +259,7 @@ impl WalletCore {
pub fn create_new_account_private(
&mut self,
chain_index: Option<ChainIndex>,
) -> (AccountId, ChainIndex) {
) -> ChainIndex {
self.storage
.user_data
.generate_new_privacy_preserving_transaction_key_chain(chain_index)