Rebase to main

This commit is contained in:
jonesmarvin8 2026-06-03 09:32:04 -04:00 committed by Marvin Jones
parent 9317c98a90
commit 071dd94671
10 changed files with 30 additions and 105 deletions

1
Cargo.lock generated
View File

@ -4617,6 +4617,7 @@ dependencies = [
"pyo3",
"serde",
"serde_json",
"zeroize",
]
[[package]]

View File

@ -69,7 +69,10 @@ The default password (`KeycardDefaultPairing`) is [recommended](https://docs.key
To use a custom pairing password, set it before `init`:
```bash
export KEYCARD_PAIRING_PASSWORD=my-custom-password
# Note: Keep the leading space before this command.
# Leading space prevents this command from being stored in shell history
# (when HISTCONTROL=ignorespace is enabled).
export KEYCARD_PAIRING_PASSWORD=my-custom-password
wallet keycard init
```
@ -152,7 +155,7 @@ Keycard PIN:
First install the wallet with the `keycard-debug` feature:
```bash
cargo install --path wallet --force --features keycard-debug
cargo install --path lez/wallet --force --features keycard-debug
```
Then run the command:
@ -168,7 +171,7 @@ VSK: 30f798893977a7b7263d1f77abf58e11e014428c92030d6a02fe363cceb41ffa
To restore the standard build without `keycard-debug` afterwards:
```bash
cargo install --path wallet --force
cargo install --path lez/wallet --force
```
### Pinata (testnet)
@ -496,7 +499,7 @@ Transaction data is ...
## Testing
Tests for Keycard commands are in `keycard_wallet/tests/`.
Tests for Keycard commands are in `lez/keycard_wallet/tests/`.
| Test file | Description |
|---|---|
@ -508,15 +511,15 @@ Tests for Keycard commands are in `keycard_wallet/tests/`.
Run from the repo root with a Keycard connected:
```bash
bash keycard_wallet/tests/keycard_tests.sh
bash keycard_wallet/tests/keycard_tests_2.sh
bash keycard_wallet/tests/keycard_test_3.sh
bash keycard_wallet/tests/keycard_power_recovery_tests.sh
bash lez/keycard_wallet/tests/keycard_tests.sh
bash lez/keycard_wallet/tests/keycard_tests_2.sh
bash lez/keycard_wallet/tests/keycard_test_3.sh
bash lez/keycard_wallet/tests/keycard_power_recovery_tests.sh
```
## SigningGroup
`SigningGroup` (`wallet/src/signing.rs`) partitions a transaction's signers into two buckets — local accounts and Keycard accounts. This ensures that Python GIL is only used at most once per transaction, regardless of how many Keycard accounts are involved.
`SigningGroup` (`lez/wallet/src/signing.rs`) partitions a transaction's signers into two buckets — local accounts and Keycard accounts. This ensures that Python GIL is only used at most once per transaction, regardless of how many Keycard accounts are involved.
Local signers are resolved and signed in pure Rust. Keycard signers store only their BIP32 key path; all of them are signed inside a single Python session (`connect` / `close_session`) when `sign_all` is called. The command calls `needs_pin` to decide whether to prompt for a PIN before signing.

View File

@ -12,8 +12,9 @@ pub fn add_python_path(py: Python<'_>) -> PyResult<()> {
.unwrap_or_else(|| current_dir.clone());
let mut paths_to_add: Vec<PathBuf> = vec![
python_base.join("keycard_wallet").join("python"),
python_base.join("lez").join("keycard_wallet").join("python"),
python_base
.join("lez")
.join("keycard_wallet")
.join("python")
.join("keycard-py"),

View File

@ -7,7 +7,7 @@
source venv/bin/activate
cargo install --path wallet --force --features keycard-debug
cargo install --path lez/wallet --force --features keycard-debug
export KEYCARD_PIN=111111

View File

@ -87,10 +87,16 @@ wallet account get --account-id "Public/7wHg9sbJwc6h3NP1S9bekfAzB8CHifEcxKswCKUt
echo ""
echo "=== Test: Shielded auth-transfer to owned private account ==="
SHIELDED_RECV=$(wallet account new private | grep -o 'Private/[^[:space:]]*' | head -1)
echo "Private recipient: $SHIELDED_RECV"
SHIELDED_KEYS=$(wallet account show-keys --account-id "$SHIELDED_RECV")
SHIELDED_NPK=$(echo "$SHIELDED_KEYS" | head -1)
SHIELDED_VPK=$(echo "$SHIELDED_KEYS" | tail -1)
wallet auth-transfer send --amount 2 \
--from "m/44'/60'/0'/0/0" \
--to-npk "55204e2934045b044f06d8222b454d46b54788f33c7dec4f6733d441703bb0e6" \
--to-vpk "02a8626b0c0ad9383c5678dad48c3969b4174fb377cdb03a6259648032c774cec8"
--to-npk "$SHIELDED_NPK" \
--to-vpk "$SHIELDED_VPK"
echo "Shielded auth-transfer sent"
sleep 15

View File

@ -258,7 +258,7 @@ sleep 15
echo "Keycard path 2 (LEZ definition) state (total supply should have increased):"
wallet account get --account-id "m/44'/60'/0'/0/2"
echo "Keycard path 6 (LEZ holding) state (balance should be 20500):"
echo "Keycard path 6 (LEZ holding) state (balance should be 20800):"
wallet account get --account-id "m/44'/60'/0'/0/6"
# =============================================================================
@ -276,7 +276,7 @@ sleep 15
echo "Keycard path 2 (LEZ definition) state (total supply should reflect burn):"
wallet account get --account-id "m/44'/60'/0'/0/2"
echo "Keycard path 6 (LEZ holding) state (balance should be 20000):"
echo "Keycard path 6 (LEZ holding) state (balance should be 20300):"
wallet account get --account-id "m/44'/60'/0'/0/6"
# =============================================================================

View File

@ -72,7 +72,7 @@ impl AccountIdentity {
/// 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<nssa::AccountId> {
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),

View File

@ -157,7 +157,7 @@ impl CliAccountMention {
}
#[must_use]
pub fn into_public_identity(self, account_id: nssa::AccountId) -> crate::AccountIdentity {
pub fn into_public_identity(self, account_id: lee::AccountId) -> crate::AccountIdentity {
match self {
Self::KeyPath(key_path) => crate::AccountIdentity::PublicKeycard {
account_id,

View File

@ -1,12 +1,6 @@
use authenticated_transfer_core::Instruction as AuthTransferInstruction;
use common::{HashType, transaction::LeeTransaction};
use lee::{
AccountId, PublicTransaction,
program::Program,
public_transaction::{Message, WitnessSet},
};
use pyo3::exceptions::PyRuntimeError;
use sequencer_service_rpc::RpcClient as _;
use common::HashType;
use lee::program::Program;
use super::NativeTokenTransfer;
use crate::{
@ -31,41 +25,6 @@ impl NativeTokenTransfer<'_> {
tx_pre_check,
)
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let message = Message::try_new(
program_id,
vec![from, to],
nonces,
AuthTransferInstruction::Transfer {
amount: balance_to_move,
},
)
.map_err(ExecutionFailureKind::TransactionBuildError)?;
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?
.as_str()
.to_owned()
} else {
String::new()
};
let sigs = groups.sign_all(&message.hash(), &pin).map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string()))
})?;
let tx = PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
Ok(self
.0
.sequencer_client
.send_transaction(LeeTransaction::Public(tx))
.await?)
}
pub async fn register_account(
@ -78,49 +37,5 @@ impl NativeTokenTransfer<'_> {
self.0
.send_pub_tx(vec![account], instruction_data, &program.into())
.await
.map_err(ExecutionFailureKind::SequencerError)?;
let account_ids = vec![from];
let program_id = Program::authenticated_transfer_program().id();
let message = Message::try_new(
program_id,
account_ids,
nonces,
AuthTransferInstruction::Initialize,
)
.map_err(ExecutionFailureKind::TransactionBuildError)?;
let mut groups = SigningGroups::new();
groups
.add_sender(account_mention, from, self.0)
.map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?;
let pin = if groups.needs_pin() {
read_pin()
.map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(
e.to_string(),
))
})?
.as_str()
.to_owned()
} else {
String::new()
};
let sigs = groups.sign_all(&message.hash(), &pin).map_err(|e| {
ExecutionFailureKind::KeycardError(pyo3::PyErr::new::<PyRuntimeError, _>(e.to_string()))
})?;
let tx = PublicTransaction::new(message, WitnessSet::from_raw_parts(sigs));
Ok(self
.0
.sequencer_client
.send_transaction(LeeTransaction::Public(tx))
.await?)
}
}

View File

@ -1,5 +1,4 @@
use keycard_wallet::{KeycardWallet, python_path};
use lee::{AccountId, PrivateKey, PublicKey, Signature};
use pyo3::Python;
/// Lazily opens and reuses a single Keycard session for all keycard signers in one transaction.