logos-execution-zone/lez/wallet/src/account_manager.rs

688 lines
24 KiB
Rust
Raw Normal View History

2026-06-03 14:51:15 +03:00
use core::fmt;
2025-12-16 14:05:34 +02:00
use anyhow::Result;
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
use keycard_wallet::{KeycardWallet, python_path};
use lee::{AccountId, PrivateKey, PublicKey, Signature};
use lee_core::{
Commitment, CommitmentSetDigest, DummyInput, Identifier, InputAccountIdentity, MembershipProof,
NullifierPublicKey, NullifierSecretKey, PrivateAccountKind, SharedSecretKey,
account::{Account, AccountWithMetadata, Nonce},
encryption::{
Ciphertext, EncryptedAccountData, MlKem768EncapsulationKey, ViewTag, ViewingPublicKey,
},
};
2026-06-19 22:37:36 +04:00
use rand::{RngCore as _, rngs::OsRng};
use crate::{ExecutionFailureKind, WalletCore};
2026-06-03 14:51:15 +03:00
#[derive(Clone, PartialEq, Eq)]
2026-05-20 18:55:39 +03:00
pub enum AccountIdentity {
Public(AccountId),
2026-05-19 17:54:25 +03:00
/// A public account without signing. Would not try to sign, even if account is owned.
PublicNoSign(AccountId),
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
/// A public account from keycard. Mandatory signing.
PublicKeycard {
account_id: AccountId,
key_path: String,
},
PrivateOwned(AccountId),
PrivateForeign {
npk: NullifierPublicKey,
2026-01-21 17:27:23 -05:00
vpk: ViewingPublicKey,
identifier: Identifier,
},
2026-05-07 13:21:05 -03:00
/// An owned private PDA: wallet holds the nsk/npk; `account_id` was derived via
2026-05-08 21:41:48 -03:00
/// [`AccountId::for_private_pda`].
PrivatePdaOwned(AccountId),
/// A foreign private PDA: wallet knows the recipient's npk/vpk but not their nsk.
2026-05-08 21:41:48 -03:00
/// Uses a default (uninitialised) account.
PrivatePdaForeign {
account_id: AccountId,
npk: NullifierPublicKey,
vpk: ViewingPublicKey,
identifier: Identifier,
},
/// A shared regular private account with externally-provided keys (e.g. from GMS).
2026-05-07 22:48:32 +02:00
/// Uses standard `AccountId = from((&npk, identifier))` with authorized/unauthorized private
/// paths. Works with `authenticated_transfer` and all existing programs out of the box.
PrivateShared {
nsk: NullifierSecretKey,
npk: NullifierPublicKey,
vpk: ViewingPublicKey,
identifier: Identifier,
},
2026-05-11 20:26:03 -03:00
/// A shared private PDA with externally-provided keys (e.g. from GMS).
/// `account_id` was derived via [`AccountId::for_private_pda`].
PrivatePdaShared {
account_id: AccountId,
nsk: NullifierSecretKey,
npk: NullifierPublicKey,
vpk: ViewingPublicKey,
identifier: Identifier,
},
}
2026-06-03 14:51:15 +03:00
impl fmt::Debug for AccountIdentity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Public(id) => f.debug_tuple("Public").field(id).finish(),
Self::PublicNoSign(id) => f.debug_tuple("PublicNoSign").field(id).finish(),
Self::PublicKeycard {
account_id,
key_path: _,
} => f
.debug_struct("PublicKeycard")
.field("account_id", account_id)
.field("key_path", &"<redacted>")
.finish(),
2026-06-03 14:51:15 +03:00
Self::PrivateOwned(id) => f.debug_tuple("PrivateOwned").field(id).finish(),
Self::PrivateForeign {
npk,
vpk,
identifier,
} => f
.debug_struct("PrivateForeign")
.field("npk", npk)
.field("vpk", vpk)
.field("identifier", identifier)
.finish(),
Self::PrivatePdaOwned(id) => f.debug_tuple("PrivatePdaOwned").field(id).finish(),
Self::PrivatePdaForeign {
account_id,
npk,
vpk,
identifier,
} => f
.debug_struct("PrivatePdaForeign")
.field("account_id", account_id)
.field("npk", npk)
.field("vpk", vpk)
.field("identifier", identifier)
.finish(),
Self::PrivateShared {
npk,
vpk,
identifier,
..
} => f
.debug_struct("PrivateShared")
.field("nsk", &"<redacted>")
.field("npk", npk)
.field("vpk", vpk)
.field("identifier", identifier)
.finish(),
Self::PrivatePdaShared {
account_id,
npk,
vpk,
identifier,
..
} => f
.debug_struct("PrivatePdaShared")
.field("account_id", account_id)
.field("nsk", &"<redacted>")
.field("npk", npk)
.field("vpk", vpk)
.field("identifier", identifier)
.finish(),
}
}
}
2026-05-20 18:55:39 +03:00
impl AccountIdentity {
2026-03-03 23:21:08 +03:00
#[must_use]
2026-05-21 13:02:18 +03:00
/// Note: `PublicNoSign` still counts as public, the variant just suppresses the signing-key
/// lookup.
2026-03-09 18:27:56 +03:00
pub const fn is_public(&self) -> bool {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
matches!(
&self,
Self::Public(_) | Self::PublicNoSign(_) | Self::PublicKeycard { .. }
)
}
/// Returns the `AccountId` for public variants. Used by facades that need the raw ID
/// for derived-address computation alongside the identity.
#[must_use]
pub const fn public_account_id(&self) -> Option<lee::AccountId> {
match self {
Self::Public(id) | Self::PublicNoSign(id) => Some(*id),
Self::PublicKeycard { account_id, .. } => Some(*account_id),
Self::PrivateOwned(_)
| Self::PrivateForeign { .. }
| Self::PrivatePdaOwned(_)
| Self::PrivatePdaForeign { .. }
| Self::PrivateShared { .. }
| Self::PrivatePdaShared { .. } => None,
}
2025-12-16 14:05:34 +02:00
}
2026-03-03 23:21:08 +03:00
#[must_use]
2026-03-09 18:27:56 +03:00
pub const fn is_private(&self) -> bool {
2025-12-16 14:05:34 +02:00
matches!(
&self,
2026-04-19 23:13:51 -03:00
Self::PrivateOwned(_)
| Self::PrivateForeign { .. }
| Self::PrivatePdaOwned(_)
| Self::PrivatePdaForeign { .. }
| Self::PrivateShared { .. }
2026-05-11 20:26:03 -03:00
| Self::PrivatePdaShared { .. }
2025-12-16 14:05:34 +02:00
)
}
}
pub struct PrivateAccountKeys {
pub ssk: SharedSecretKey,
}
enum State {
Public {
account: AccountWithMetadata,
sk: Option<PrivateKey>,
},
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
PublicKeycard {
account: AccountWithMetadata,
key_path: String,
},
Private(AccountPreparedData),
}
pub struct AccountManager {
states: Vec<State>,
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
pin: Option<String>,
refactor(privacy_preserving_circuit): introduce helper functions to shorten long functions (#545) * refactor(privacy_preserving_circuit): extract functions for readability * refactor(privacy_preserving_circuit): address PR review comments Bundle shared handle_* arguments into PrivateOutputHandler struct in output.rs and fix misplaced docstring on resolve_external_seed in execution_state.rs. * feat: update commitment mechanism for new private account (#546) * refactor(privacy_preserving_circuit): extract functions for readability * feat: update commitment mechanism for new private accounts Allow init accounts to optionally use a real membership proof for DUMMY_COMMITMENT instead of hardcoding DUMMY_COMMITMENT_HASH as the CommitmentSetDigest. The wallet fetches the proof from the sequencer and passes it through the circuit. * fix: address clippy lints and fix integration test visibility * add tests * refactor: removed duplicated code * refactor: simplify init nullifier mechanism Replace Option<MembershipProof> with Option<CommitmentSetDigest> on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit). The circuit now receives the commitment tree root directly instead of recomputing it from a Merkle proof. * refactor: use CommitmentSetDigest directly instead of Option for init commitment root Address PR #546 review feedback: the circuit now accepts CommitmentSetDigest directly on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit), with callers providing DUMMY_COMMITMENT_HASH as the default. Also fixes duplicate resolve_external_seed from rebase and rebuilds artifacts. * style: run cargo +nightly fmt
2026-07-01 10:14:32 -04:00
dummy_commitment_root: CommitmentSetDigest,
}
impl AccountManager {
pub async fn new(
wallet: &WalletCore,
2026-05-20 18:55:39 +03:00
accounts: Vec<AccountIdentity>,
) -> Result<Self, ExecutionFailureKind> {
let mut states = Vec::with_capacity(accounts.len());
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
let mut pin = None;
for account in accounts {
let state = match account {
2026-05-20 18:55:39 +03:00
AccountIdentity::Public(account_id) => {
let acc = wallet
.get_account_public(account_id)
.await
2026-03-04 18:42:33 +03:00
.map_err(ExecutionFailureKind::SequencerError)?;
let sk = wallet.get_account_public_signing_key(account_id).cloned();
let account = AccountWithMetadata::new(acc.clone(), sk.is_some(), account_id);
2026-05-19 17:54:25 +03:00
State::Public { account, sk }
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PublicNoSign(account_id) => {
2026-05-19 17:54:25 +03:00
let acc = wallet
.get_account_public(account_id)
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let sk = None;
let account = AccountWithMetadata::new(acc.clone(), sk.is_some(), account_id);
State::Public { account, sk }
}
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
AccountIdentity::PublicKeycard {
account_id,
key_path,
} => {
let acc = wallet
.get_account_public(account_id)
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let account = AccountWithMetadata::new(acc.clone(), true, account_id);
if pin.is_none() {
pin = Some(
crate::helperfunctions::read_pin()
.map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<
pyo3::exceptions::PyRuntimeError,
_,
>(
e.to_string()
))
})?
.as_str()
.to_owned(),
);
}
State::PublicKeycard { account, key_path }
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivateOwned(account_id) => {
let pre = private_key_tree_acc_preparation(wallet, account_id, false)?;
State::Private(pre)
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivateForeign {
2026-04-19 23:13:51 -03:00
npk,
vpk,
identifier,
} => {
let acc = lee_core::account::Account::default();
2026-06-19 22:37:36 +04:00
let auth_acc = AccountWithMetadata::new(acc, false, (&npk, &vpk, identifier));
let random_seed = random_bytes();
let pre = AccountPreparedData {
nsk: None,
npk,
identifier,
2026-01-21 17:27:23 -05:00
vpk,
2025-12-11 20:59:37 -03:00
pre_state: auth_acc,
proof: None,
random_seed,
is_pda: false,
};
2026-05-05 12:37:54 +02:00
State::Private(pre)
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivatePdaOwned(account_id) => {
let pre = private_key_tree_acc_preparation(wallet, account_id, true)?;
State::Private(pre)
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivatePdaForeign {
account_id,
npk,
vpk,
identifier,
} => {
let acc = lee_core::account::Account::default();
let auth_acc = AccountWithMetadata::new(acc, false, account_id);
let random_seed = random_bytes();
let pre = AccountPreparedData {
nsk: None,
npk,
identifier,
vpk,
pre_state: auth_acc,
proof: None,
random_seed,
is_pda: true,
};
State::Private(pre)
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivateShared {
nsk,
npk,
vpk,
identifier,
} => {
2026-06-19 22:37:36 +04:00
let account_id = lee::AccountId::from((&npk, &vpk, identifier));
2026-05-11 20:26:03 -03:00
let pre = private_shared_acc_preparation(
wallet, account_id, nsk, npk, vpk, identifier, false,
);
2026-05-11 20:26:03 -03:00
State::Private(pre)
}
2026-05-20 18:55:39 +03:00
AccountIdentity::PrivatePdaShared {
2026-05-11 20:26:03 -03:00
account_id,
nsk,
npk,
vpk,
identifier,
} => {
let pre = private_shared_acc_preparation(
wallet, account_id, nsk, npk, vpk, identifier, true,
);
State::Private(pre)
}
};
states.push(state);
}
let dummy_commitment_root = fetch_private_proofs_and_root(wallet, &mut states).await?;
refactor(privacy_preserving_circuit): introduce helper functions to shorten long functions (#545) * refactor(privacy_preserving_circuit): extract functions for readability * refactor(privacy_preserving_circuit): address PR review comments Bundle shared handle_* arguments into PrivateOutputHandler struct in output.rs and fix misplaced docstring on resolve_external_seed in execution_state.rs. * feat: update commitment mechanism for new private account (#546) * refactor(privacy_preserving_circuit): extract functions for readability * feat: update commitment mechanism for new private accounts Allow init accounts to optionally use a real membership proof for DUMMY_COMMITMENT instead of hardcoding DUMMY_COMMITMENT_HASH as the CommitmentSetDigest. The wallet fetches the proof from the sequencer and passes it through the circuit. * fix: address clippy lints and fix integration test visibility * add tests * refactor: removed duplicated code * refactor: simplify init nullifier mechanism Replace Option<MembershipProof> with Option<CommitmentSetDigest> on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit). The circuit now receives the commitment tree root directly instead of recomputing it from a Merkle proof. * refactor: use CommitmentSetDigest directly instead of Option for init commitment root Address PR #546 review feedback: the circuit now accepts CommitmentSetDigest directly on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit), with callers providing DUMMY_COMMITMENT_HASH as the default. Also fixes duplicate resolve_external_seed from rebase and rebuilds artifacts. * style: run cargo +nightly fmt
2026-07-01 10:14:32 -04:00
Ok(Self {
states,
pin,
dummy_commitment_root,
})
}
pub fn pre_states(&self) -> Vec<AccountWithMetadata> {
self.states
.iter()
.map(|state| match state {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
State::Public { account, .. } | State::PublicKeycard { account, .. } => {
account.clone()
}
2025-12-11 20:59:37 -03:00
State::Private(pre) => pre.pre_state.clone(),
})
.collect()
}
pub fn public_account_nonces(&self) -> Vec<Nonce> {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
// Must match the signature order produced by sign_message(): local accounts first,
// keycard accounts second.
let local = self.states.iter().filter_map(|state| match state {
State::Public { account, sk } => sk.as_ref().map(|_| account.account.nonce),
State::PublicKeycard { .. } | State::Private(_) => None,
});
let keycard = self.states.iter().filter_map(|state| match state {
State::PublicKeycard { account, .. } => Some(account.account.nonce),
State::Public { .. } | State::Private(_) => None,
});
local.chain(keycard).collect()
}
pub fn private_account_keys(&self) -> Vec<PrivateAccountKeys> {
self.states
.iter()
.filter_map(|state| match state {
2026-06-19 22:37:36 +04:00
State::Private(pre) => Some(pre),
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
State::Public { .. } | State::PublicKeycard { .. } => None,
})
.map(|pre| {
let nonce = if pre.proof.is_some() {
pre.pre_state.account.nonce.private_account_nonce_increment(
pre.nsk.as_ref().expect("update variant must have nsk"),
)
} else {
lee_core::account::Nonce::private_account_nonce_init(&pre.pre_state.account_id)
};
let esk = lee_core::EphemeralSecretKey::new(
&pre.pre_state.account_id,
&pre.random_seed,
&nonce,
);
PrivateAccountKeys {
ssk: SharedSecretKey::encapsulate_deterministic(&pre.vpk, &esk).0,
}
2026-06-19 22:37:36 +04:00
})
.collect()
}
/// Given a count, generate that many dummy inputs with randomized seeds and notes.
/// Uses the given commitment root from the account.
pub fn dummy_inputs(&self, count: usize) -> Vec<DummyInput> {
std::iter::repeat_with(|| DummyInput {
nullifier_seed: random_bytes(),
commitment_seed: random_bytes(),
note: random_dummy_note(),
commitment_root: self.dummy_commitment_root,
})
.take(count)
.collect()
}
/// Build the per-account input vec for the privacy-preserving circuit. Each variant carries
/// exactly the fields the circuit's code path for that account needs, with the ephemeral
/// keys (`ssk`) drawn from the cached values that `private_account_keys` and the message
/// construction also use, so all three views agree on the same ephemeral key.
pub fn account_identities(&self) -> Vec<InputAccountIdentity> {
self.states
.iter()
.map(|state| match state {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
State::Public { .. } | State::PublicKeycard { .. } => InputAccountIdentity::Public,
2026-05-07 01:41:35 -03:00
State::Private(pre) if pre.is_pda => match (pre.nsk, pre.proof.clone()) {
(Some(nsk), Some(membership_proof)) => InputAccountIdentity::PrivatePdaUpdate {
2026-06-19 22:37:36 +04:00
vpk: pre.vpk.clone(),
random_seed: pre.random_seed,
view_tag: random_view_tag(),
2026-05-07 01:41:35 -03:00
nsk,
membership_proof,
identifier: pre.identifier,
seed: None,
2026-05-07 01:41:35 -03:00
},
_ => InputAccountIdentity::PrivatePdaInit {
2026-06-19 22:37:36 +04:00
vpk: pre.vpk.clone(),
random_seed: pre.random_seed,
2026-05-07 01:41:35 -03:00
npk: pre.npk,
identifier: pre.identifier,
refactor(privacy_preserving_circuit): introduce helper functions to shorten long functions (#545) * refactor(privacy_preserving_circuit): extract functions for readability * refactor(privacy_preserving_circuit): address PR review comments Bundle shared handle_* arguments into PrivateOutputHandler struct in output.rs and fix misplaced docstring on resolve_external_seed in execution_state.rs. * feat: update commitment mechanism for new private account (#546) * refactor(privacy_preserving_circuit): extract functions for readability * feat: update commitment mechanism for new private accounts Allow init accounts to optionally use a real membership proof for DUMMY_COMMITMENT instead of hardcoding DUMMY_COMMITMENT_HASH as the CommitmentSetDigest. The wallet fetches the proof from the sequencer and passes it through the circuit. * fix: address clippy lints and fix integration test visibility * add tests * refactor: removed duplicated code * refactor: simplify init nullifier mechanism Replace Option<MembershipProof> with Option<CommitmentSetDigest> on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit). The circuit now receives the commitment tree root directly instead of recomputing it from a Merkle proof. * refactor: use CommitmentSetDigest directly instead of Option for init commitment root Address PR #546 review feedback: the circuit now accepts CommitmentSetDigest directly on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit), with callers providing DUMMY_COMMITMENT_HASH as the default. Also fixes duplicate resolve_external_seed from rebase and rebuilds artifacts. * style: run cargo +nightly fmt
2026-07-01 10:14:32 -04:00
commitment_root: self.dummy_commitment_root,
seed: None,
2026-05-07 01:41:35 -03:00
},
},
State::Private(pre) => match (pre.nsk, pre.proof.clone()) {
(Some(nsk), Some(membership_proof)) => {
InputAccountIdentity::PrivateAuthorizedUpdate {
2026-06-19 22:37:36 +04:00
vpk: pre.vpk.clone(),
random_seed: pre.random_seed,
view_tag: random_view_tag(),
nsk,
membership_proof,
identifier: pre.identifier,
}
}
(Some(nsk), None) => InputAccountIdentity::PrivateAuthorizedInit {
2026-06-19 22:37:36 +04:00
vpk: pre.vpk.clone(),
random_seed: pre.random_seed,
nsk,
identifier: pre.identifier,
refactor(privacy_preserving_circuit): introduce helper functions to shorten long functions (#545) * refactor(privacy_preserving_circuit): extract functions for readability * refactor(privacy_preserving_circuit): address PR review comments Bundle shared handle_* arguments into PrivateOutputHandler struct in output.rs and fix misplaced docstring on resolve_external_seed in execution_state.rs. * feat: update commitment mechanism for new private account (#546) * refactor(privacy_preserving_circuit): extract functions for readability * feat: update commitment mechanism for new private accounts Allow init accounts to optionally use a real membership proof for DUMMY_COMMITMENT instead of hardcoding DUMMY_COMMITMENT_HASH as the CommitmentSetDigest. The wallet fetches the proof from the sequencer and passes it through the circuit. * fix: address clippy lints and fix integration test visibility * add tests * refactor: removed duplicated code * refactor: simplify init nullifier mechanism Replace Option<MembershipProof> with Option<CommitmentSetDigest> on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit). The circuit now receives the commitment tree root directly instead of recomputing it from a Merkle proof. * refactor: use CommitmentSetDigest directly instead of Option for init commitment root Address PR #546 review feedback: the circuit now accepts CommitmentSetDigest directly on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit), with callers providing DUMMY_COMMITMENT_HASH as the default. Also fixes duplicate resolve_external_seed from rebase and rebuilds artifacts. * style: run cargo +nightly fmt
2026-07-01 10:14:32 -04:00
commitment_root: self.dummy_commitment_root,
},
(None, _) => InputAccountIdentity::PrivateUnauthorized {
2026-06-19 22:37:36 +04:00
vpk: pre.vpk.clone(),
random_seed: pre.random_seed,
npk: pre.npk,
identifier: pre.identifier,
refactor(privacy_preserving_circuit): introduce helper functions to shorten long functions (#545) * refactor(privacy_preserving_circuit): extract functions for readability * refactor(privacy_preserving_circuit): address PR review comments Bundle shared handle_* arguments into PrivateOutputHandler struct in output.rs and fix misplaced docstring on resolve_external_seed in execution_state.rs. * feat: update commitment mechanism for new private account (#546) * refactor(privacy_preserving_circuit): extract functions for readability * feat: update commitment mechanism for new private accounts Allow init accounts to optionally use a real membership proof for DUMMY_COMMITMENT instead of hardcoding DUMMY_COMMITMENT_HASH as the CommitmentSetDigest. The wallet fetches the proof from the sequencer and passes it through the circuit. * fix: address clippy lints and fix integration test visibility * add tests * refactor: removed duplicated code * refactor: simplify init nullifier mechanism Replace Option<MembershipProof> with Option<CommitmentSetDigest> on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit). The circuit now receives the commitment tree root directly instead of recomputing it from a Merkle proof. * refactor: use CommitmentSetDigest directly instead of Option for init commitment root Address PR #546 review feedback: the circuit now accepts CommitmentSetDigest directly on init variants (PrivateAuthorizedInit, PrivateUnauthorized, PrivatePdaInit), with callers providing DUMMY_COMMITMENT_HASH as the default. Also fixes duplicate resolve_external_seed from rebase and rebuilds artifacts. * style: run cargo +nightly fmt
2026-07-01 10:14:32 -04:00
commitment_root: self.dummy_commitment_root,
},
},
})
.collect()
}
pub fn public_account_ids(&self) -> Vec<AccountId> {
self.states
.iter()
.filter_map(|state| match state {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
State::Public { account, .. } | State::PublicKeycard { account, .. } => {
Some(account.account_id)
}
2026-03-03 23:21:08 +03:00
State::Private(_) => None,
})
.collect()
}
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
pub fn public_non_keycard_account_auth(&self) -> Vec<&PrivateKey> {
self.states
.iter()
.filter_map(|state| match state {
State::Public { sk, .. } => sk.as_ref(),
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
State::PublicKeycard { .. } | State::Private(_) => None,
})
.collect()
}
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
pub fn sign_message(&self, message_hash: [u8; 32]) -> Result<Vec<(Signature, PublicKey)>> {
let mut sigs: Vec<(Signature, PublicKey)> = self
.public_non_keycard_account_auth()
.into_iter()
.map(|key| {
(
Signature::new(key, &message_hash),
PublicKey::new_from_private_key(key),
)
})
.collect();
let keycard_paths: Vec<&str> = self
.states
.iter()
.filter_map(|state| match state {
State::PublicKeycard { key_path, .. } => Some(key_path.as_str()),
State::Private(_) | State::Public { .. } => None,
})
.collect();
if let Some(pin) = self.pin.clone() {
2026-06-12 14:25:37 +04:00
pyo3::Python::attach(|py| -> pyo3::PyResult<()> {
feat(wallet): add keycard support for public accounts for public/privacy txs for program facades (#461) * feat: add basic commands for communicating with keycard * initialize changes * reorganization * add script file for easier wallet access * update commands * fixes * fixed load for non continuous run * Updates for signatures with keycard * fix BIP-340 signatures for fixed sized messages * fmt * refactor and add pin support to program facades * fix unit test * fixes * Revert "fixes" This reverts commit 41f34f4ff4145b7abb60fd9bec168ae4b60f23b4. * fixes * fixes * Removed privacy keycard calls * Revert "Removed privacy keycard calls" This reverts commit d70ef505a1f40b87159099761f5fce5a31e3f17b. * Add domain separators * Removed privacy txs for keycard * CI fixes * CI fixes * addressed some comments * fix ci * initialize branch * ci fixes * fix integration test issue and updated keycard firmware * addressed more comments * fixed deny * remove keycard-py * fixed from earlier merge * add hash_message tests * add test * fix deny * CI fixes * fixed integration tests * Update public.rs * update artifacts * privacy command fixes * ci and comments * addressed comments * comment fixes * fixes from merging main * adding support to other programs * expanded support * ci fixes * ci and add private account keys test * some fixes and setup notes * Ci fixes * ci fixes * update key paths to avoid collisions in tests * added separated files for keycard_tests_2.sh * first round of comments * Revert "Merge branch 'main' into marvin/keycard-commands" This reverts commit 3fce53f663a3996938dddf77680854570063ca21, reversing changes made to e7b42a5177641455a8917bd2e29db20afd9690e5. * python comments * addressed comments * compile error fixed * fix artifacts * fix main merge error * adjust signer logic workflow * updating logic * fmt * refactored * clippy fix * minor fix * addressing comments * minor fix * ci fix * addressed deferred comments * clean up * minor cleanup * ci fixes * fmt fix * feat!(wallet): Merged `SigningGroup` with `AccountManager` (#500) * feat: account manager extension * feat(wallet): added unified way of sending public transactions to all facades * fix(wallet): no sign option added * fix(deny): deny fix * fix(wallet): suggestion 1 * fix(wallet): suggestion fix 1 * feat!: Add new path for externally provided seed to the circuit. BREAKING CHANGE: add identity variants to the circuit and change semantics for `Claim::Authorized` for private PDAs * feat(ci): use separate job per each integration tests module * feat(ci): cache rust artifacts * feat(ci): build integration tests binary once and reuse it * fix(wallet): fmt * ci: add bench-regression workflow with criterion-compare for crypto_primitives_bench * fix(wallet): merge postfix * feat!(wallet): SigningGroup merged with AccountManager * fix(ci): deny and artifacts fix * fix(deny): deny fix * fix keycard and lint --------- Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com> Co-authored-by: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> * addressed comments * minor comments * Rebase to main * CI fixes --------- Co-authored-by: Pravdyvy <46261001+Pravdyvy@users.noreply.github.com> Co-authored-by: Sergio Chouhy <sergio.chouhy@gmail.com> Co-authored-by: Daniil Polyakov <arjentix@gmail.com> Co-authored-by: Moudy <m.ellaz@hotmail.com> Co-authored-by: Sergio Chouhy <41742639+schouhy@users.noreply.github.com>
2026-06-05 17:35:10 -04:00
python_path::add_python_path(py)?;
let wallet = KeycardWallet::new(py)?;
wallet.connect(py, &pin)?;
for path in keycard_paths {
sigs.push(wallet.sign_message_for_path(py, path, &message_hash)?);
}
let _res = wallet.close_session(py);
Ok(())
})
.map_err(anyhow::Error::from)?;
}
Ok(sigs)
}
}
2025-12-11 21:15:57 -03:00
struct AccountPreparedData {
nsk: Option<NullifierSecretKey>,
npk: NullifierPublicKey,
2026-04-15 01:09:17 -03:00
identifier: Identifier,
2026-01-21 17:27:23 -05:00
vpk: ViewingPublicKey,
2025-12-11 21:15:57 -03:00
pre_state: AccountWithMetadata,
proof: Option<MembershipProof>,
random_seed: [u8; 32],
/// True when this account is a private PDA (owned or foreign). Used by `account_identities()`
/// to select `PrivatePdaInit`/`PrivatePdaUpdate` rather than the standalone private variants.
is_pda: bool,
}
async fn fetch_private_proofs_and_root(
wallet: &WalletCore,
states: &mut [State],
) -> Result<CommitmentSetDigest, ExecutionFailureKind> {
let (mut private, commitments): (Vec<&mut AccountPreparedData>, Vec<Commitment>) = states
.iter_mut()
.filter_map(|state| match state {
State::Private(pre) => {
let commitment = wallet.get_private_account_commitment(pre.pre_state.account_id)?;
Some((pre, commitment))
}
State::Public { .. } | State::PublicKeycard { .. } => None,
})
.unzip();
let (proofs, root) = wallet
.get_proofs_and_root(commitments)
.await
.map_err(ExecutionFailureKind::SequencerError)?;
for (pre, proof) in private.iter_mut().zip(proofs) {
pre.proof = proof;
}
Ok(root)
}
fn private_key_tree_acc_preparation(
wallet: &WalletCore,
account_id: AccountId,
is_pda: bool,
) -> Result<AccountPreparedData, ExecutionFailureKind> {
let Some(from_acc) = wallet.storage.key_chain().private_account(account_id) else {
return Err(ExecutionFailureKind::KeyNotFoundError);
};
let from_identifier = from_acc.kind.identifier();
let from_keys = &from_acc.key_chain;
2026-05-11 20:26:03 -03:00
let nsk = from_keys.private_key_holder.nullifier_secret_key;
let from_npk = from_keys.nullifier_public_key;
let from_vpk = from_keys.viewing_public_key.clone();
2026-05-11 20:26:03 -03:00
// TODO: Technically we could allow unauthorized owned accounts, but currently we don't have
// support from that in the wallet.
let sender_pre = AccountWithMetadata::new(from_acc.account.clone(), true, account_id);
let random_seed = random_bytes();
2026-05-05 12:37:54 +02:00
Ok(AccountPreparedData {
2026-05-11 20:26:03 -03:00
nsk: Some(nsk),
npk: from_npk,
identifier: from_identifier,
vpk: from_vpk,
pre_state: sender_pre,
proof: None,
random_seed,
2026-05-11 20:26:03 -03:00
is_pda,
})
}
fn private_shared_acc_preparation(
wallet: &WalletCore,
2026-05-11 20:26:03 -03:00
account_id: AccountId,
nsk: NullifierSecretKey,
npk: NullifierPublicKey,
vpk: ViewingPublicKey,
identifier: Identifier,
2026-05-11 20:26:03 -03:00
is_pda: bool,
) -> AccountPreparedData {
let acc = wallet
.storage()
.key_chain()
.shared_private_account(account_id)
.map(|e| e.account.clone())
.unwrap_or_default();
2026-05-12 17:17:58 -03:00
let pre_state = AccountWithMetadata::new(acc, true, account_id);
let random_seed = random_bytes();
AccountPreparedData {
2026-05-12 17:17:58 -03:00
nsk: Some(nsk),
npk,
identifier,
vpk,
pre_state,
proof: None,
random_seed,
2026-05-11 20:26:03 -03:00
is_pda,
}
}
/// Generate random byte using OS randomness.
fn random_view_tag() -> ViewTag {
let mut byte: [u8; 1] = [0; 1];
OsRng.fill_bytes(&mut byte);
byte[0]
}
fn random_bytes() -> [u8; 32] {
let mut bytes = [0; 32];
OsRng.fill_bytes(&mut bytes);
bytes
}
fn random_vec(len: usize) -> Vec<u8> {
let mut bytes = vec![0; len];
OsRng.fill_bytes(&mut bytes);
bytes
}
/// Generates a dummy note: random bytes sized to a default-account ciphertext, a real
/// ML-KEM ciphertext epk toward a throwaway key, and a random view tag.
fn random_dummy_note() -> EncryptedAccountData {
// Sized to a default-account ciphertext; matching real data sizes is a separate issue.
let ciphertext_len = PrivateAccountKind::HEADER_LEN
.checked_add(Account::default().to_bytes().len())
.expect("dummy ciphertext length fits in usize");
let throwaway_ek = MlKem768EncapsulationKey::from_seed(&random_bytes(), &random_bytes());
let (_, epk) = SharedSecretKey::encapsulate(&throwaway_ek);
EncryptedAccountData {
ciphertext: Ciphertext::from_inner(random_vec(ciphertext_len)),
epk,
view_tag: random_view_tag(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn private_shared_is_private() {
2026-05-20 18:55:39 +03:00
let acc = AccountIdentity::PrivateShared {
nsk: [0; 32],
npk: NullifierPublicKey([1; 32]),
vpk: ViewingPublicKey::from_seed(&[2_u8; 32], &[3_u8; 32]),
identifier: 42,
};
assert!(acc.is_private());
assert!(!acc.is_public());
}
}