add nullifiers for preconfigured accounts on genesis

This commit is contained in:
Sergio Chouhy 2026-04-06 16:25:53 -03:00
parent 42a2f04cd5
commit 50d402880c
4 changed files with 97 additions and 42 deletions

View File

@ -57,11 +57,9 @@ impl IndexerCore {
let channel_genesis_msg_id = [0; 32];
let genesis_block = hashable_data.into_pending_block(&signing_key, channel_genesis_msg_id);
let initial_commitments: Option<Vec<nssa_core::Commitment>> = config
.initial_private_accounts
.as_ref()
.map(|initial_commitments| {
initial_commitments
let initial_private_accounts: Option<Vec<(nssa_core::Nullifier, nssa_core::Commitment)>> =
config.initial_private_accounts.as_ref().map(|accounts| {
accounts
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
@ -71,7 +69,10 @@ impl IndexerCore {
acc.program_owner =
nssa::program::Program::authenticated_transfer_program().id();
nssa_core::Commitment::new(npk, &acc)
(
nssa_core::Nullifier::for_account_initialization(npk),
nssa_core::Commitment::new(npk, &acc),
)
})
.collect()
});
@ -88,10 +89,10 @@ impl IndexerCore {
// If initial commitments or accounts are present in config, need to construct state from
// them
let state = if initial_commitments.is_some() || init_accs.is_some() {
let state = if initial_private_accounts.is_some() || init_accs.is_some() {
let mut state = V03State::new_with_genesis_accounts(
&init_accs.unwrap_or_default(),
&initial_commitments.unwrap_or_default(),
&initial_private_accounts.unwrap_or_default(),
);
// ToDo: Remove after testnet

View File

@ -118,7 +118,7 @@ impl V03State {
#[must_use]
pub fn new_with_genesis_accounts(
initial_data: &[(AccountId, u128)],
initial_commitments: &[nssa_core::Commitment],
initial_private_accounts: &[(Nullifier, Commitment)],
) -> Self {
let authenticated_transfer_program = Program::authenticated_transfer_program();
let public_state = initial_data
@ -134,13 +134,24 @@ impl V03State {
})
.collect();
let initial_commitments: Vec<Commitment> = initial_private_accounts
.iter()
.map(|(_, c)| c.clone())
.collect();
let mut private_state = CommitmentSet::with_capacity(32);
private_state.extend(&[DUMMY_COMMITMENT]);
private_state.extend(initial_commitments);
private_state.extend(&initial_commitments);
let init_nullifiers: Vec<Nullifier> = initial_private_accounts
.iter()
.map(|(n, _)| n.clone())
.collect();
let mut nullifier_set = NullifierSet::new();
nullifier_set.extend(init_nullifiers);
let mut this = Self {
public_state,
private_state: (private_state, NullifierSet::new()),
private_state: (private_state, nullifier_set),
programs: HashMap::new(),
};
@ -523,6 +534,34 @@ pub mod tests {
assert_eq!(state.programs, expected_builtin_programs);
}
#[test]
fn new_with_genesis_includes_nullifiers_for_private_accounts() {
let keys1 = test_private_account_keys_1();
let keys2 = test_private_account_keys_2();
let account = Account {
balance: 100,
program_owner: Program::authenticated_transfer_program().id(),
..Account::default()
};
let npk1 = keys1.npk();
let npk2 = keys2.npk();
let init_nullifier1 = Nullifier::for_account_initialization(&npk1);
let init_nullifier2 = Nullifier::for_account_initialization(&npk2);
let initial_private_accounts = vec![
(init_nullifier1.clone(), Commitment::new(&npk1, &account)),
(init_nullifier2.clone(), Commitment::new(&npk2, &account)),
];
let state = V03State::new_with_genesis_accounts(&[], &initial_private_accounts);
assert!(state.private_state.1.contains(&init_nullifier1));
assert!(state.private_state.1.contains(&init_nullifier2));
}
#[test]
fn insert_program() {
let mut state = V03State::new_with_genesis_accounts(&[], &[]);
@ -2542,8 +2581,11 @@ pub mod tests {
..Account::default()
};
let sender_commitment = Commitment::new(&sender_keys.npk(), &sender_private_account);
let mut state =
V03State::new_with_genesis_accounts(&[], std::slice::from_ref(&sender_commitment));
let sender_init_nullifier = Nullifier::for_account_initialization(&sender_keys.npk());
let mut state = V03State::new_with_genesis_accounts(
&[],
&[(sender_init_nullifier, sender_commitment.clone())],
);
let sender_pre = AccountWithMetadata::new(sender_private_account, true, &sender_keys.npk());
let recipient_private_key = PrivateKey::try_new([2; 32]).unwrap();
let recipient_account_id =
@ -2623,9 +2665,14 @@ pub mod tests {
let from_commitment = Commitment::new(&from_keys.npk(), &from_account.account);
let to_commitment = Commitment::new(&to_keys.npk(), &to_account.account);
let from_init_nullifier = Nullifier::for_account_initialization(&from_keys.npk());
let to_init_nullifier = Nullifier::for_account_initialization(&to_keys.npk());
let mut state = V03State::new_with_genesis_accounts(
&[],
&[from_commitment.clone(), to_commitment.clone()],
&[
(from_init_nullifier, from_commitment.clone()),
(to_init_nullifier, to_commitment.clone()),
],
)
.with_test_programs();
let amount: u128 = 37;
@ -3192,9 +3239,10 @@ pub mod tests {
let recipient_commitment =
Commitment::new(&recipient_keys.npk(), &recipient_account.account);
let recipient_init_nullifier = Nullifier::for_account_initialization(&recipient_keys.npk());
let state = V03State::new_with_genesis_accounts(
&[(sender_account.account_id, sender_account.account.balance)],
std::slice::from_ref(&recipient_commitment),
&[(recipient_init_nullifier, recipient_commitment.clone())],
)
.with_test_programs();

View File

@ -104,24 +104,26 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
"No database found when starting the sequencer. Creating a fresh new with the initial data"
);
let initial_commitments: Option<Vec<nssa_core::Commitment>> = config
.initial_private_accounts
.clone()
.map(|initial_commitments| {
initial_commitments
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
let initial_private_accounts: Option<
Vec<(nssa_core::Nullifier, nssa_core::Commitment)>,
> = config.initial_private_accounts.clone().map(|accounts| {
accounts
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
let mut acc = init_comm_data.account.clone();
let mut acc = init_comm_data.account.clone();
acc.program_owner =
nssa::program::Program::authenticated_transfer_program().id();
acc.program_owner =
nssa::program::Program::authenticated_transfer_program().id();
nssa_core::Commitment::new(npk, &acc)
})
.collect()
});
(
nssa_core::Nullifier::for_account_initialization(npk),
nssa_core::Commitment::new(npk, &acc),
)
})
.collect()
});
let init_accs: Option<Vec<(nssa::AccountId, u128)>> = config
.initial_public_accounts
@ -135,10 +137,10 @@ impl<BC: BlockSettlementClientTrait, IC: IndexerClientTrait> SequencerCore<BC, I
// If initial commitments or accounts are present in config, need to construct state
// from them
if initial_commitments.is_some() || init_accs.is_some() {
if initial_private_accounts.is_some() || init_accs.is_some() {
V03State::new_with_genesis_accounts(
&init_accs.unwrap_or_default(),
&initial_commitments.unwrap_or_default(),
&initial_private_accounts.unwrap_or_default(),
)
} else {
initial_state()

View File

@ -196,25 +196,29 @@ pub fn initial_accounts() -> Vec<PublicAccountPublicInitialData> {
#[must_use]
pub fn initial_state() -> V03State {
let initial_commitments: Vec<nssa_core::Commitment> = initial_commitments()
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
let initial_private_accounts: Vec<(nssa_core::Nullifier, nssa_core::Commitment)> =
initial_commitments()
.iter()
.map(|init_comm_data| {
let npk = &init_comm_data.npk;
let mut acc = init_comm_data.account.clone();
let mut acc = init_comm_data.account.clone();
acc.program_owner = nssa::program::Program::authenticated_transfer_program().id();
acc.program_owner = nssa::program::Program::authenticated_transfer_program().id();
nssa_core::Commitment::new(npk, &acc)
})
.collect();
(
nssa_core::Nullifier::for_account_initialization(npk),
nssa_core::Commitment::new(npk, &acc),
)
})
.collect();
let init_accs: Vec<(nssa::AccountId, u128)> = initial_accounts()
.iter()
.map(|acc_data| (acc_data.account_id, acc_data.balance))
.collect();
nssa::V03State::new_with_genesis_accounts(&init_accs, &initial_commitments)
nssa::V03State::new_with_genesis_accounts(&init_accs, &initial_private_accounts)
}
#[must_use]