From 643eb2e741a170f3861939b6ab264d085b672d77 Mon Sep 17 00:00:00 2001 From: jonesmarvin8 <83104039+jonesmarvin8@users.noreply.github.com> Date: Mon, 18 May 2026 15:33:26 -0400 Subject: [PATCH] addressing comments --- Cargo.toml | 1 + docs/LEZ testnet v0.1 tutorials/keycard.md | 272 +++++++++++++++++- .../src/bin/run_hello_world_private.rs | 2 +- ...n_hello_world_through_tail_call_private.rs | 2 +- .../bin/run_hello_world_with_move_function.rs | 4 +- integration_tests/src/setup.rs | 2 +- integration_tests/tests/private_pda.rs | 4 +- keycard_test_3.sh | 3 + keycard_tests.sh | 37 ++- keycard_tests_2.sh | 60 ++-- keycard_tests_2_1.sh | 229 --------------- keycard_tests_2_2.sh | 107 ------- keycard_tests_2_3.sh | 89 ------ keycard_wallet/Cargo.toml | 2 +- keycard_wallet/python/keycard_wallet.py | 4 +- nssa/core/src/program.rs | 2 +- .../privacy_preserving_transaction/message.rs | 2 +- wallet-ffi/src/transfer.rs | 21 +- wallet-ffi/wallet_ffi.h | 4 - wallet/Cargo.toml | 5 +- wallet/src/cli/keycard.rs | 3 + wallet/src/cli/mod.rs | 5 - wallet/src/cli/programs/amm.rs | 35 ++- wallet/src/cli/programs/ata.rs | 18 +- .../src/cli/programs/native_token_transfer.rs | 7 +- wallet/src/cli/programs/token.rs | 24 +- wallet/src/lib.rs | 13 +- wallet/src/program_facades/amm.rs | 70 +---- wallet/src/program_facades/ata.rs | 12 +- .../native_token_transfer/deshielded.rs | 3 +- .../native_token_transfer/private.rs | 9 +- .../native_token_transfer/public.rs | 10 +- .../native_token_transfer/shielded.rs | 8 +- wallet/src/program_facades/pinata.rs | 2 +- wallet/src/program_facades/token.rs | 50 ++-- wallet/src/signing.rs | 6 +- 36 files changed, 492 insertions(+), 635 deletions(-) delete mode 100644 keycard_tests_2_1.sh delete mode 100644 keycard_tests_2_2.sh delete mode 100644 keycard_tests_2_3.sh diff --git a/Cargo.toml b/Cargo.toml index b3090355..a0b02f81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -155,6 +155,7 @@ actix-web = { version = "4.13.0", default-features = false, features = [ clap = { version = "4.5.42", features = ["derive", "env"] } reqwest = { version = "0.12", features = ["json", "rustls-tls", "stream"] } pyo3 = { version = "0.24", features = ["auto-initialize"] } +zeroize = "1" # Profile for leptos WASM release builds [profile.wasm-release] diff --git a/docs/LEZ testnet v0.1 tutorials/keycard.md b/docs/LEZ testnet v0.1 tutorials/keycard.md index 92224292..508f99f1 100644 --- a/docs/LEZ testnet v0.1 tutorials/keycard.md +++ b/docs/LEZ testnet v0.1 tutorials/keycard.md @@ -64,13 +64,14 @@ unset KEYCARD_PIN ### Keycard -| Command | Description | -|-----------------------------|------------------------------------------------------------| -| `wallet keycard available` | Checks whether a Keycard reader and card are accessible | -| `wallet keycard init` | Initializes a blank Keycard with a PIN and a generated PUK | -| `wallet keycard connect` | Establishes and saves a pairing with the Keycard | -| `wallet keycard disconnect` | Unpairs the Keycard and clears the saved pairing | -| `wallet keycard load` | Loads a mnemonic phrase onto the Keycard | +| Command | Description | +|----------------------------------|-----------------------------------------------------------------------| +| `wallet keycard available` | Checks whether a Keycard reader and card are accessible | +| `wallet keycard init` | Initializes a blank Keycard with a PIN and a generated PUK | +| `wallet keycard connect` | Establishes and saves a pairing with the Keycard | +| `wallet keycard disconnect` | Unpairs the Keycard and clears the saved pairing | +| `wallet keycard load` | Loads a mnemonic phrase onto the Keycard | +| `wallet keycard get-private-keys`| Prints NSK and VSK for a BIP-32 path — **debug builds only** (see below) | 1. Check keycard availability ```bash @@ -122,6 +123,31 @@ Keycard PIN: ✅ Keycard unpaired and pairing cleared. ``` +6. Get private keys for a BIP-32 path (**debug builds only**) + +`get-private-keys` exports the raw NSK and VSK for a derivation path. NSK gates nullifier creation and VSK gates note decryption — either key is sufficient to fully compromise that account's privacy. The command is only available in debug builds and requires `--reveal` to confirm intent. + +First install the wallet with the `keycard-debug` feature: +```bash +cargo install --path wallet --force --features keycard-debug +``` + +Then run the command: +```bash +wallet keycard get-private-keys --key-path "m/44'/60'/0'/0/0" --reveal + +# Output: +WARNING: NSK and VSK are being printed to stdout. Any terminal log, scrollback, or screen recording captures these keys. +Keycard PIN: +NSK: 55e505bf925e536c843a12ebc08c41ca5f4761eeeb7fa33725f0b44e6f1ac2e4 +VSK: 30f798893977a7b7263d1f77abf58e11e014428c92030d6a02fe363cceb41ffa +``` + +To restore the standard build without `keycard-debug` afterwards: +```bash +cargo install --path wallet --force +``` + ### Pinata (testnet) | Command | Description | @@ -211,4 +237,236 @@ wallet auth-transfer send \ # Output: Keycard PIN: Transaction hash is 7d4c1b8e2f903a56fd19084b3c8b25d07e8f243829bc50addf6e2c78b4b09e45 +``` + +### Token program + +`--definition`, `--holder`, `--from`, and `--to` each accept any of: +- A BIP-32 key path — uses Keycard (e.g. `m/44'/60'/0'/0/0`) +- An account ID with privacy prefix (e.g. `Public/9bKm...`) +- An account label (e.g. `my-account`) + +The token program requires both the definition account and the holder/recipient to sign when both are owned. If only one is a Keycard path, only that account signs via the card; the other signs locally or is treated as foreign. + +**Shielded transfers** (public Keycard sender → private recipient) are supported. The Keycard signs the public sender's authorization; the ZK circuit handles the private recipient side. + +| Command | Description | +|--------------------|-------------------------------------------------------| +| `wallet token new` | Creates a new token definition with an initial supply | +| `wallet token send`| Transfers tokens between accounts | +| `wallet token mint`| Mints tokens to a holder account | +| `wallet token burn`| Burns tokens from a holder account | + +1. Create a new token — definition and supply both on Keycard +```bash +wallet token new \ + --definition-account-id "m/44'/60'/0'/0/2" \ + --supply-account-id "m/44'/60'/0'/0/3" \ + --name LEZ \ + --total-supply 100000 + +# Output: +Keycard PIN: +Transaction hash is a3f1c8e2049b7d56fe19084b3c8b25d07e8f243829bc50addf6e2c78b4b09d11 +Transaction data is ... +``` + +2. Transfer tokens between two Keycard accounts (public → public) +```bash +wallet token send \ + --from "m/44'/60'/0'/0/3" \ + --to "m/44'/60'/0'/0/6" \ + --amount 20000 + +# Output: +Keycard PIN: +Transaction hash is b2e4d9f1038c6e45ad28175c4d9c36e18bf9354930cd61beef59f3e89c5a0e22 +Transaction data is ... +``` + +3. Transfer tokens from a Keycard account to a private account (shielded) +```bash +wallet token send \ + --from "m/44'/60'/0'/0/6" \ + --to "Private/CJwKfrb3DFMmFvujQSB5ARcRTAa8EdP6eWm2hmSkF7Rb" \ + --amount 500 + +# Output: +Keycard PIN: +Transaction hash is c5f7e0a2149d8f67be39286d5eaa47f29cg0465041de72cff06a4f9ad6b1f33 +``` + +4. Mint tokens — Keycard definition account mints to a Keycard holder +```bash +wallet token mint \ + --definition "m/44'/60'/0'/0/2" \ + --holder "m/44'/60'/0'/0/6" \ + --amount 2000 + +# Output: +Keycard PIN: +Transaction hash is d6g8f1b3250e9a78cf4a397e6fbb58g3ah1567152ef83dgg17b5g0be7c2g0g44 +Transaction data is ... +``` + +5. Burn tokens — Keycard holder burns from its own account +```bash +wallet token burn \ + --definition "Public/9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" \ + --holder "m/44'/60'/0'/0/6" \ + --amount 500 + +# Output: +Keycard PIN: +Transaction hash is e7h9g2c4361f0b89dg5b408f7gcc69h4bi2678263fg94ehh28c6h1cf8d3h1h55 +Transaction data is ... +``` + +### AMM program + +AMM operations are **public only** — all holdings involved must be public accounts. Keycard accounts can be used for any or all of the holding accounts. + +`--user-holding-a`, `--user-holding-b`, and `--user-holding-lp` each accept any of: +- A BIP-32 key path — uses Keycard (e.g. `m/44'/60'/0'/0/0`) +- An account ID with privacy prefix (e.g. `Public/9bKm...`) +- An account label (e.g. `my-account`) + +For swaps, only the seller's holding signs — the wallet identifies which holding corresponds to the input token and signs only that account. + +| Command | Description | +|----------------------------|-------------------------------------------------------| +| `wallet amm new` | Creates a new AMM liquidity pool | +| `wallet amm swap-exact-input` | Swaps specifying exact input amount | +| `wallet amm swap-exact-output` | Swaps specifying exact output amount | +| `wallet amm add-liquidity` | Adds liquidity to an existing pool | +| `wallet amm remove-liquidity` | Removes liquidity from a pool | + +1. Create a new AMM pool — all holdings on Keycard +```bash +wallet amm new \ + --user-holding-a "m/44'/60'/0'/0/6" \ + --user-holding-b "m/44'/60'/0'/0/7" \ + --user-holding-lp "m/44'/60'/0'/0/8" \ + --balance-a 10000 \ + --balance-b 10000 + +# Output: +Keycard PIN: +Transaction hash is f8i0h3d5472g1c90eh6c519g8hdd70i5cj3789374gh05fii39d7i2dg9e4i2i66 +Transaction data is ... +``` + +2. Swap exact input — Keycard account sells LEE, receives LEZ +```bash +wallet amm swap-exact-input \ + --user-holding-a "m/44'/60'/0'/0/6" \ + --user-holding-b "m/44'/60'/0'/0/7" \ + --amount-in 500 \ + --min-amount-out 1 \ + --token-definition "9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" + +# Output: +Keycard PIN: +Transaction hash is g9j1i4e6583h2d01fi7d620h9iee81j6dk4890485hi16gjj40e8j3eh0f5j3j77 +Transaction data is ... +``` + +3. Add liquidity — all three holdings on Keycard +```bash +wallet amm add-liquidity \ + --user-holding-a "m/44'/60'/0'/0/6" \ + --user-holding-b "m/44'/60'/0'/0/7" \ + --user-holding-lp "m/44'/60'/0'/0/8" \ + --max-amount-a 1000 \ + --max-amount-b 1000 \ + --min-amount-lp 1 + +# Output: +Keycard PIN: +Transaction hash is h0k2j5f7694i3e12gj8e731i0jff92k7el5901596ij27hkk51f9k4fi1g6k4k88 +Transaction data is ... +``` + +4. Remove liquidity — LP holding on Keycard +```bash +wallet amm remove-liquidity \ + --user-holding-a "m/44'/60'/0'/0/6" \ + --user-holding-b "m/44'/60'/0'/0/7" \ + --user-holding-lp "m/44'/60'/0'/0/8" \ + --balance-lp 500 \ + --min-amount-a 1 \ + --min-amount-b 1 + +# Output: +Keycard PIN: +Transaction hash is i1l3k6g8705j4f23hk9f842j1kgg03l8fm6012607jk38ill62g0l5gj2h7l5l99 +Transaction data is ... +``` + +### ATA program + +The Associated Token Account program derives a deterministic token holding address from an owner account and a token definition. Keycard accounts can be used as the owner. + +`--owner` and `--from`/`--holder` accept any of: +- A BIP-32 key path — uses Keycard (e.g. `m/44'/60'/0'/0/0`) +- An account ID with privacy prefix (e.g. `Public/9bKm...`) +- An account label (e.g. `my-account`) + +| Command | Description | +|--------------------|------------------------------------------------------------------| +| `wallet ata address` | Derives and prints the ATA address (local only, no network) | +| `wallet ata create` | Creates the ATA on-chain | +| `wallet ata send` | Sends tokens from the owner's ATA to a recipient | +| `wallet ata burn` | Burns tokens from the owner's ATA | +| `wallet ata list` | Lists ATAs for a given owner across token definitions | + +1. Derive an ATA address for a Keycard account +```bash +# First resolve the Keycard account ID +OWNER_ID=$(wallet account id --account-id "m/44'/60'/0'/0/9") +wallet ata address \ + --owner "$OWNER_ID" \ + --token-definition "9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" + +# Output: +DFMmFvujQSB5ARcRTAa8EdP6eWm2hmSkF7RbCJwKfrb3 +``` + +2. Create an ATA — Keycard account as owner +```bash +wallet ata create \ + --owner "m/44'/60'/0'/0/9" \ + --token-definition "9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" + +# Output: +Keycard PIN: +Transaction hash is j2m4l7h9816k5g34il0g953k2lhh14m9gn7123718kl49jmm73h1m6hk3i8m6m00 +Transaction data is ... +``` + +3. Send tokens from a Keycard ATA to another account +```bash +wallet ata send \ + --from "m/44'/60'/0'/0/9" \ + --token-definition "9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" \ + --to "DFMmFvujQSB5ARcRTAa8EdP6eWm2hmSkF7RbCJwKfrb3" \ + --amount 500 + +# Output: +Keycard PIN: +Transaction hash is k3n5m8i0927l6h45jm1h064l3mii25n0ho8234829lm50knn84i2n7il4j9n7n11 +Transaction data is ... +``` + +4. Burn tokens from a Keycard ATA +```bash +wallet ata burn \ + --holder "m/44'/60'/0'/0/9" \ + --token-definition "9bKmZ4n7PqVRxEtY3dWsQjA2cHrFT5LpDoGXM8wJuNv6" \ + --amount 200 + +# Output: +Keycard PIN: +Transaction hash is l4o6n9j1038m7i56kn2i175m4njj36o1ip9345930mn61loo95j3o8jm5k0o8o22 +Transaction data is ... ``` \ No newline at end of file diff --git a/examples/program_deployment/src/bin/run_hello_world_private.rs b/examples/program_deployment/src/bin/run_hello_world_private.rs index 148addb3..11a6c0f6 100644 --- a/examples/program_deployment/src/bin/run_hello_world_private.rs +++ b/examples/program_deployment/src/bin/run_hello_world_private.rs @@ -52,7 +52,7 @@ async fn main() { accounts, Program::serialize_instruction(greeting).unwrap(), &program.into(), - &None, + None, ) .await .unwrap(); diff --git a/examples/program_deployment/src/bin/run_hello_world_through_tail_call_private.rs b/examples/program_deployment/src/bin/run_hello_world_through_tail_call_private.rs index eb9d3b4c..f01c83e7 100644 --- a/examples/program_deployment/src/bin/run_hello_world_through_tail_call_private.rs +++ b/examples/program_deployment/src/bin/run_hello_world_through_tail_call_private.rs @@ -60,7 +60,7 @@ async fn main() { accounts, Program::serialize_instruction(instruction).unwrap(), &program_with_dependencies, - &None, + None, ) .await .unwrap(); diff --git a/examples/program_deployment/src/bin/run_hello_world_with_move_function.rs b/examples/program_deployment/src/bin/run_hello_world_with_move_function.rs index 81594ac3..7e5fa5d8 100644 --- a/examples/program_deployment/src/bin/run_hello_world_with_move_function.rs +++ b/examples/program_deployment/src/bin/run_hello_world_with_move_function.rs @@ -106,7 +106,7 @@ async fn main() { accounts, Program::serialize_instruction(instruction).unwrap(), &program.into(), - &None, + None, ) .await .unwrap(); @@ -148,7 +148,7 @@ async fn main() { accounts, Program::serialize_instruction(instruction).unwrap(), &program.into(), - &None, + None, ) .await .unwrap(); diff --git a/integration_tests/src/setup.rs b/integration_tests/src/setup.rs index 116f2d96..54bdc493 100644 --- a/integration_tests/src/setup.rs +++ b/integration_tests/src/setup.rs @@ -298,7 +298,7 @@ async fn claim_funds_from_vault_to_private( ], instruction_data, &program_with_dependencies, - &None, + None, ) .await .context("Failed to submit private vault claim transaction")?; diff --git a/integration_tests/tests/private_pda.rs b/integration_tests/tests/private_pda.rs index 208c6c15..d1e79ab3 100644 --- a/integration_tests/tests/private_pda.rs +++ b/integration_tests/tests/private_pda.rs @@ -57,7 +57,7 @@ async fn fund_private_pda( Program::serialize_instruction((seed, amount, auth_transfer_id, true)) .context("failed to serialize pda_fund_spend_proxy fund instruction")?, proxy_program, - &None, + None, ) .await .map_err(|e| anyhow::anyhow!("{e}"))?; @@ -94,7 +94,7 @@ async fn spend_private_pda( Program::serialize_instruction((seed, amount, auth_transfer_id, false)) .context("failed to serialize pda_fund_spend_proxy instruction")?, spend_program, - &None, + None, ) .await .map_err(|e| anyhow::anyhow!("{e}"))?; diff --git a/keycard_test_3.sh b/keycard_test_3.sh index bf13aa0e..5be1a3dd 100644 --- a/keycard_test_3.sh +++ b/keycard_test_3.sh @@ -6,6 +6,9 @@ # 2. Keycard reader inserted with card loaded (wallet keycard load has been run). source venv/bin/activate + +cargo install --path wallet --force --features keycard-debug + export KEYCARD_PIN=111111 echo "=== Test: wallet keycard get-private-keys path 10 ===" diff --git a/keycard_tests.sh b/keycard_tests.sh index 56e4fbc1..d336e5fc 100644 --- a/keycard_tests.sh +++ b/keycard_tests.sh @@ -96,4 +96,39 @@ wallet auth-transfer send --amount 2 \ echo "Shielded auth-transfer sent" sleep 15 -wallet account get --account-id "m/44'/60'/0'/0/0" \ No newline at end of file +wallet account get --account-id "m/44'/60'/0'/0/0" + +# ============================================================================= +# Test (2): Deshielded auth-transfer — private account → keycard recipient +# A fresh private account is funded, then sends native tokens to keycard +# path 1. The private sender is handled by the ZK circuit; the keycard +# recipient does not sign — resolve() derives its account ID from the card. +# ============================================================================= +echo "" +echo "=== Test (2): Deshielded auth-transfer: private account → keycard path 1 ===" + +PRIV_SENDER=$(wallet account new private | grep -o 'Private/[^[:space:]]*' | head -1) +echo "Fresh private sender account: $PRIV_SENDER" + +wallet auth-transfer init --account-id "$PRIV_SENDER" + +echo "Test: wallet pinata claim to private sender" +wallet pinata claim --to "$PRIV_SENDER" + +sleep 15 + +echo "priv-sender state after claim:" +wallet account get --account-id "$PRIV_SENDER" + +wallet auth-transfer send \ + --from "$PRIV_SENDER" \ + --to "m/44'/60'/0'/0/1" \ + --amount 5 +echo "Deshielded transfer of 5: $PRIV_SENDER → keycard path 1" + +sleep 15 + +echo "priv-sender state (balance should have decreased by 5):" +wallet account get --account-id "$PRIV_SENDER" +echo "Keycard path 1 state (balance should have increased by 5):" +wallet account get --account-id "m/44'/60'/0'/0/1" \ No newline at end of file diff --git a/keycard_tests_2.sh b/keycard_tests_2.sh index 1c38f571..9a6450f4 100644 --- a/keycard_tests_2.sh +++ b/keycard_tests_2.sh @@ -220,10 +220,34 @@ echo "priv-receiver state (balance should be 500):" wallet account get --account-id "$PRIV_RECEIVER" # ============================================================================= -# (5) Token mint with keycard — definition signed by keycard path 2 +# (5) Token transfer: private account → keycard path 6 (deshielded) +# Uses priv-receiver from test (4) which holds 500 LEZ. +# The private sender is handled by the ZK circuit; the keycard recipient +# does not sign — resolve() derives its account ID from the card only. # ============================================================================= echo "" -echo "=== (5) Token mint: keycard def path 2 mints 2000 LEZ to keycard path 6 ===" +echo "=== (5) Token transfer: priv-receiver (private) → keycard path 6 (deshielded) ===" + +wallet token send \ + --from "$PRIV_RECEIVER" \ + --to "m/44'/60'/0'/0/6" \ + --amount 300 +echo "Deshielded transfer of 300 LEZ: $PRIV_RECEIVER → keycard path 6" + +wallet account sync-private + +sleep 15 + +echo "priv-receiver state (balance should be 200):" +wallet account get --account-id "$PRIV_RECEIVER" +echo "Keycard path 6 (LEZ) state (balance should be 18800):" +wallet account get --account-id "m/44'/60'/0'/0/6" + +# ============================================================================= +# (6) Token mint with keycard — definition signed by keycard path 2 +# ============================================================================= +echo "" +echo "=== (6) Token mint: keycard def path 2 mints 2000 LEZ to keycard path 6 ===" wallet token mint \ --definition "m/44'/60'/0'/0/2" \ --holder "m/44'/60'/0'/0/6" \ @@ -238,10 +262,10 @@ echo "Keycard path 6 (LEZ holding) state (balance should be 20500):" wallet account get --account-id "m/44'/60'/0'/0/6" # ============================================================================= -# (6) Token burn with keycard — holder is keycard path 6 +# (7) Token burn with keycard — holder is keycard path 6 # ============================================================================= echo "" -echo "=== (6) Token burn: keycard path 6 burns 500 LEZ ===" +echo "=== (7) Token burn: keycard path 6 burns 500 LEZ ===" wallet token burn \ --definition "Public/$LEZ_DEF_ID" \ --holder "m/44'/60'/0'/0/6" \ @@ -256,10 +280,10 @@ echo "Keycard path 6 (LEZ holding) state (balance should be 20000):" wallet account get --account-id "m/44'/60'/0'/0/6" # ============================================================================= -# (7) Create AMM pool for LEZ/LEE — without keycard +# (8) Create AMM pool for LEZ/LEE — without keycard # ============================================================================= echo "" -echo "=== (7) Create AMM pool for LEZ/LEE (without keycard) ===" +echo "=== (8) Create AMM pool for LEZ/LEE (without keycard) ===" wallet amm new \ --user-holding-a amm-lez-fund \ @@ -281,11 +305,11 @@ LP_DEF_ID=$(wallet account get --account-id amm-lp-fund | grep -o '"definition_i echo "LP token definition ID: $LP_DEF_ID" # ============================================================================= -# (8) Swap tokens owned by keycard accounts +# (9) Swap tokens owned by keycard accounts # keycard path 7 (LEE) sells 500 LEE; keycard path 6 (LEZ) receives LEZ # ============================================================================= echo "" -echo "=== (8) Swap: keycard path 7 sells 500 LEE, keycard path 6 receives LEZ ===" +echo "=== (9) Swap: keycard path 7 sells 500 LEE, keycard path 6 receives LEZ ===" wallet amm swap-exact-input \ --user-holding-a "m/44'/60'/0'/0/6" \ --user-holding-b "m/44'/60'/0'/0/7" \ @@ -302,10 +326,10 @@ echo "Keycard path 7 (LEE holding) state (balance should have decreased by 500): wallet account get --account-id "m/44'/60'/0'/0/7" # ============================================================================= -# (9) Add liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) +# (10) Add liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) # ============================================================================= echo "" -echo "=== (9) Add liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" +echo "=== (10) Add liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" wallet amm add-liquidity \ --user-holding-a "m/44'/60'/0'/0/6" \ --user-holding-b "m/44'/60'/0'/0/7" \ @@ -325,10 +349,10 @@ echo "Keycard path 8 (LP holding) state (should have received LP tokens):" wallet account get --account-id "m/44'/60'/0'/0/8" # ============================================================================= -# (10) Remove liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) +# (11) Remove liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) # ============================================================================= echo "" -echo "=== (10) Remove liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" +echo "=== (11) Remove liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" wallet amm remove-liquidity \ --user-holding-a "m/44'/60'/0'/0/6" \ --user-holding-b "m/44'/60'/0'/0/7" \ @@ -348,10 +372,10 @@ echo "Keycard path 8 (LP holding) state (balance should have decreased):" wallet account get --account-id "m/44'/60'/0'/0/8" # ============================================================================= -# (11) ATA create — keycard path 9 as owner for LEZ +# (12) ATA create — keycard path 9 as owner for LEZ # ============================================================================= echo "" -echo "=== (11) ATA create: keycard path 9 as owner, LEZ token ===" +echo "=== (12) ATA create: keycard path 9 as owner, LEZ token ===" ATA_OWNER_ID=$(wallet account id --account-id "m/44'/60'/0'/0/9") echo "ATA owner (keycard path 9): $ATA_OWNER_ID" @@ -380,10 +404,10 @@ echo "ATA state after funding (balance should be 3000):" wallet account get --account-id "Public/$LEZ_ATA_ID" # ============================================================================= -# (12) ATA send — keycard path 9's ATA → pub-receiver's ATA +# (13) ATA send — keycard path 9's ATA → pub-receiver's ATA # ============================================================================= echo "" -echo "=== (12) ATA send: keycard path 9's ATA → pub-receiver's ATA ===" +echo "=== (13) ATA send: keycard path 9's ATA → pub-receiver's ATA ===" PUB_RECEIVER_ID=$(wallet account id --account-id pub-receiver) wallet ata create \ --owner "Public/$PUB_RECEIVER_ID" \ @@ -412,10 +436,10 @@ echo "pub-receiver ATA state (balance should be 500):" wallet account get --account-id "Public/$PUB_RECEIVER_ATA_ID" # ============================================================================= -# (13) ATA burn — keycard path 9's ATA burns 200 LEZ +# (14) ATA burn — keycard path 9's ATA burns 200 LEZ # ============================================================================= echo "" -echo "=== (13) ATA burn: keycard path 9's ATA burns 200 LEZ ===" +echo "=== (14) ATA burn: keycard path 9's ATA burns 200 LEZ ===" wallet ata burn \ --holder "m/44'/60'/0'/0/9" \ --token-definition "$LEZ_DEF_ID" \ diff --git a/keycard_tests_2_1.sh b/keycard_tests_2_1.sh deleted file mode 100644 index 54d7e507..00000000 --- a/keycard_tests_2_1.sh +++ /dev/null @@ -1,229 +0,0 @@ -#!/usr/bin/env bash -# keycard_tests_2.sh — comprehensive token + AMM keycard integration tests. -# -# Prerequisites: -# 1. Run wallet_with_keycard.sh once to install dependencies. -# 2. Reset the local chain so all accounts are uninitialized. -# 3. Keycard reader inserted with card loaded. -# -# Keycard path layout: -# path 2 → LEZ token definition (keycard) -# path 3 → LEZ token supply (keycard) -# path 4 → LEE token definition (keycard) -# path 5 → LEE token supply (keycard) -# path 6 → LEZ holding (keycard — transfers, mint, burn, swap, liquidity) -# path 7 → LEE holding (keycard — swap, add/remove liquidity) -# path 8 → LP holding (keycard — add/remove liquidity) -# path 9 → ATA owner (keycard — ATA create, send, burn) -# -# Non-keycard accounts: -# pub-receiver → public account (target for keycard → public token transfer) -# priv-receiver → private account (target for keycard → private token transfer) -# amm-lez-fund → public LEZ holding used to seed the AMM pool -# amm-lee-fund → public LEE holding used to seed the AMM pool -# (LP holding for amm new is created fresh each run — no persistent label) - -source venv/bin/activate -export KEYCARD_PIN=111111 - -# ============================================================================= -# Create non-keycard wallet accounts -# ============================================================================= -echo "" -echo "=== Create non-keycard accounts ===" -wallet account new public --label pub-receiver 2>/dev/null || true - -wallet account new public --label amm-lez-fund 2>/dev/null || true -wallet account new public --label amm-lee-fund 2>/dev/null || true -wallet account new public --label amm-lp-fund 2>/dev/null || true - -# ============================================================================= -# (1) Create LEZ token — definition AND supply via keycard paths -# ============================================================================= -echo "" -echo "=== (1) Create LEZ token (keycard def=path2, supply=path1) ===" -wallet token new \ - --definition-key-path "m/44'/60'/0'/0/2" \ - --supply-key-path "m/44'/60'/0'/0/3" \ - --name LEZ \ - --total-supply 100000 -echo "LEZ token created" - -# ============================================================================= -# (2) Create LEE token — definition AND supply via keycard paths -# ============================================================================= -echo "" -echo "=== (2) Create LEE token (keycard def=path4, supply=path3) ===" -wallet token new \ - --definition-key-path "m/44'/60'/0'/0/4" \ - --supply-key-path "m/44'/60'/0'/0/5" \ - --name LEE \ - --total-supply 100000 -echo "LEE token created" - -sleep 15 - -LEZ_DEF_ID=$(wallet account id --key-path "m/44'/60'/0'/0/2") -LEE_DEF_ID=$(wallet account id --key-path "m/44'/60'/0'/0/4") -echo "LEZ definition ID: $LEZ_DEF_ID" -echo "LEE definition ID: $LEE_DEF_ID" - -echo "Keycard path 2 (LEZ definition) state:" -wallet account get --key-path "m/44'/60'/0'/0/2" -echo "Keycard path 3 (LEZ supply) state:" -wallet account get --key-path "m/44'/60'/0'/0/3" -echo "Keycard path 4 (LEE definition) state:" -wallet account get --key-path "m/44'/60'/0'/0/4" -echo "Keycard path 5 (LEE supply) state:" -wallet account get --key-path "m/44'/60'/0'/0/5" - -# ============================================================================= -# Initialize token holding accounts -# ============================================================================= -echo "" -echo "=== Initialize token holding accounts ===" - -# Keycard path 6: LEZ holding -wallet token init \ - --definition-account-id "Public/$LEZ_DEF_ID" \ - --holder-key-path "m/44'/60'/0'/0/6" -echo "LEZ holding initialized for keycard path 4" - -# Keycard path 7: LEE holding -wallet token init \ - --definition-account-id "Public/$LEE_DEF_ID" \ - --holder-key-path "m/44'/60'/0'/0/7" -echo "LEE holding initialized for keycard path 5" - -# pub-receiver: public LEZ holding (for token transfer test) -wallet token init \ - --definition-account-id "Public/$LEZ_DEF_ID" \ - --holder-account-label pub-receiver -echo "LEZ holding initialized for pub-receiver" - -# AMM seed accounts -wallet token init \ - --definition-account-id "Public/$LEZ_DEF_ID" \ - --holder-account-label amm-lez-fund -wallet token init \ - --definition-account-id "Public/$LEE_DEF_ID" \ - --holder-account-label amm-lee-fund -echo "AMM seed holdings initialized" - -# ============================================================================= -# Fund keycard holdings and AMM seed accounts from supply -# ============================================================================= -echo "" -echo "=== Fund keycard holdings and AMM seed accounts ===" - -wallet token send \ - --from-key-path "m/44'/60'/0'/0/3" \ - --to-key-path "m/44'/60'/0'/0/6" \ - --amount 20000 -echo "Transferred 20000 LEZ → keycard path 4" - -wallet token send \ - --from-key-path "m/44'/60'/0'/0/5" \ - --to-key-path "m/44'/60'/0'/0/7" \ - --amount 20000 -echo "Transferred 20000 LEE → keycard path 5" - -wallet token send \ - --from-key-path "m/44'/60'/0'/0/3" \ - --to-label amm-lez-fund \ - --amount 10000 -echo "Transferred 10000 LEZ → amm-lez-fund" - -wallet token send \ - --from-key-path "m/44'/60'/0'/0/5" \ - --to-label amm-lee-fund \ - --amount 10000 -echo "Transferred 10000 LEE → amm-lee-fund" - -sleep 15 - -echo "Keycard path 6 (LEZ holding) state (balance should be 20000):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "Keycard path 7 (LEE holding) state (balance should be 20000):" -wallet account get --key-path "m/44'/60'/0'/0/7" -echo "amm-lez-fund state (balance should be 10000):" -wallet account get --account-label amm-lez-fund -echo "amm-lee-fund state (balance should be 10000):" -wallet account get --account-label amm-lee-fund - -# ============================================================================= -# (3) Token transfer: keycard path 6 (LEZ) → public account -# ============================================================================= -echo "" -echo "=== (3) Token transfer: keycard path 6 → pub-receiver (public) ===" -wallet token send \ - --from-key-path "m/44'/60'/0'/0/6" \ - --to-label pub-receiver \ - --amount 1000 -echo "Transferred 1000 LEZ: keycard path 6 → pub-receiver" - -sleep 15 - -echo "Keycard path 6 (LEZ) state (balance should be 19000):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "pub-receiver state (balance should be 1000):" -wallet account get --account-label pub-receiver - -# ============================================================================= -# (4) Token transfer: keycard path 6 (LEZ) → private account (shielded) -# ============================================================================= -echo "" -echo "=== (4) Token transfer: keycard path 6 → priv-receiver (private, shielded) ===" -PRIV_RECEIVER=$(wallet account new private | grep -o 'Private/[^[:space:]]*' | head -1) -echo "Fresh private receiver account: $PRIV_RECEIVER" - -wallet token send \ - --from-key-path "m/44'/60'/0'/0/6" \ - --to "$PRIV_RECEIVER" \ - --amount 500 -echo "Shielded transfer of 500 LEZ: keycard path 6 → $PRIV_RECEIVER" - -wallet account sync-private - -sleep 15 - -echo "Keycard path 6 (LEZ) state (balance should be 18500):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "priv-receiver state (balance should be 500):" -wallet account get --account-id "$PRIV_RECEIVER" - -# ============================================================================= -# (5) Token mint with keycard — definition signed by keycard path 2 -# ============================================================================= -echo "" -echo "=== (5) Token mint: keycard def path 2 mints 2000 LEZ to keycard path 6 ===" -wallet token mint \ - --definition-key-path "m/44'/60'/0'/0/2" \ - --holder-key-path "m/44'/60'/0'/0/6" \ - --amount 2000 -echo "Minted 2000 LEZ to keycard path 4" - -sleep 15 - -echo "Keycard path 2 (LEZ definition) state (total supply should have increased):" -wallet account get --key-path "m/44'/60'/0'/0/2" -echo "Keycard path 6 (LEZ holding) state (balance should be 20500):" -wallet account get --key-path "m/44'/60'/0'/0/6" - -# ============================================================================= -# (6) Token burn with keycard — holder is keycard path 6 -# ============================================================================= -echo "" -echo "=== (6) Token burn: keycard path 6 burns 500 LEZ ===" -wallet token burn \ - --definition "Public/$LEZ_DEF_ID" \ - --holder-key-path "m/44'/60'/0'/0/6" \ - --amount 500 -echo "Burned 500 LEZ from keycard path 4" - -sleep 15 - -echo "Keycard path 2 (LEZ definition) state (total supply should reflect burn):" -wallet account get --key-path "m/44'/60'/0'/0/2" -echo "Keycard path 6 (LEZ holding) state (balance should be 20000):" -wallet account get --key-path "m/44'/60'/0'/0/6" \ No newline at end of file diff --git a/keycard_tests_2_2.sh b/keycard_tests_2_2.sh deleted file mode 100644 index ce6c3bba..00000000 --- a/keycard_tests_2_2.sh +++ /dev/null @@ -1,107 +0,0 @@ -source venv/bin/activate -export KEYCARD_PIN=111111 - - -# ============================================================================= -# (7) Create AMM pool for LEZ/LEE — without keycard -# ============================================================================= -echo "" -echo "=== (7) Create AMM pool for LEZ/LEE (without keycard) ===" - -wallet amm new \ - --user-holding-a-label amm-lez-fund \ - --user-holding-b-label amm-lee-fund \ - --user-holding-lp-label amm-lp-fund \ - --balance-a 10000 \ - --balance-b 10000 -echo "AMM pool created for LEZ/LEE" - -sleep 15 - -echo "amm-lez-fund state (balance should be 0 — contributed to pool):" -wallet account get --account-label amm-lez-fund -echo "amm-lee-fund state (balance should be 0 — contributed to pool):" -wallet account get --account-label amm-lee-fund -echo "Initial LP holding state (should hold initial LP tokens):" -wallet account get --account-label amm-lp-fund -LP_DEF_ID=$(wallet account get --account-label amm-lp-fund | grep -o '"definition_id":"[^"]*"' | awk -F'"' '{print $4}') -echo "LP token definition ID: $LP_DEF_ID" - -# ============================================================================= -# (8) Swap tokens owned by keycard accounts -# keycard path 7 (LEE) sells 500 LEE; keycard path 6 (LEZ) receives LEZ -# ============================================================================= -echo "" -echo "=== (8) Swap: keycard path 7 sells 500 LEE, keycard path 6 receives LEZ ===" -wallet amm swap-exact-input \ - --user-holding-a-key-path "m/44'/60'/0'/0/6" \ - --user-holding-b-key-path "m/44'/60'/0'/0/7" \ - --amount-in 500 \ - --min-amount-out 1 \ - --token-definition "$LEE_DEF_ID" -echo "Swap LEE → LEZ complete via keycard" - -sleep 15 - -echo "Keycard path 6 (LEZ holding) state (balance should have increased):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "Keycard path 7 (LEE holding) state (balance should have decreased by 500):" -wallet account get --key-path "m/44'/60'/0'/0/7" - -# ============================================================================= -# (9) Add liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) -# ============================================================================= -echo "" -echo "=== (9) Initialize LP holding (keycard path 8) before add-liquidity ===" -wallet token init \ - --definition-account-id "Public/$LP_DEF_ID" \ - --holder-key-path "m/44'/60'/0'/0/8" -echo "Keycard path 8 (LP holding) initialized" - -sleep 15 - -echo "Keycard path 8 (LP holding) state (after init):" -wallet account get --key-path "m/44'/60'/0'/0/8" - -echo "" -echo "=== (9) Add liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" -wallet amm add-liquidity \ - --user-holding-a-key-path "m/44'/60'/0'/0/6" \ - --user-holding-b-key-path "m/44'/60'/0'/0/7" \ - --user-holding-lp-key-path "m/44'/60'/0'/0/8" \ - --max-amount-a 1000 \ - --max-amount-b 1000 \ - --min-amount-lp 1 -echo "Add liquidity complete via keycard" - -sleep 15 - -echo "Keycard path 6 (LEZ holding) state (balance should have decreased):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "Keycard path 7 (LEE holding) state (balance should have decreased):" -wallet account get --key-path "m/44'/60'/0'/0/7" -echo "Keycard path 8 (LP holding) state (should have received LP tokens):" -wallet account get --key-path "m/44'/60'/0'/0/8" - -# ============================================================================= -# (10) Remove liquidity — keycard accounts for holding A (path 6), B (path 7), LP (path 8) -# ============================================================================= -echo "" -echo "=== (10) Remove liquidity (keycard path 6=LEZ, path 7=LEE, path 8=LP) ===" -wallet amm remove-liquidity \ - --user-holding-a-key-path "m/44'/60'/0'/0/6" \ - --user-holding-b-key-path "m/44'/60'/0'/0/7" \ - --user-holding-lp-key-path "m/44'/60'/0'/0/8" \ - --balance-lp 500 \ - --min-amount-a 1 \ - --min-amount-b 1 -echo "Remove liquidity complete via keycard" - -sleep 15 - -echo "Keycard path 6 (LEZ holding) state (balance should have increased):" -wallet account get --key-path "m/44'/60'/0'/0/6" -echo "Keycard path 7 (LEE holding) state (balance should have increased):" -wallet account get --key-path "m/44'/60'/0'/0/7" -echo "Keycard path 8 (LP holding) state (balance should have decreased):" -wallet account get --key-path "m/44'/60'/0'/0/8" \ No newline at end of file diff --git a/keycard_tests_2_3.sh b/keycard_tests_2_3.sh deleted file mode 100644 index e6600fc5..00000000 --- a/keycard_tests_2_3.sh +++ /dev/null @@ -1,89 +0,0 @@ -source venv/bin/activate -export KEYCARD_PIN=111111 - - - -# ============================================================================= -# (11) ATA create — keycard path 9 as owner for LEZ -# ============================================================================= -echo "" -echo "=== (11) ATA create: keycard path 9 as owner, LEZ token ===" -ATA_OWNER_ID=$(wallet account id --key-path "m/44'/60'/0'/0/9") -echo "ATA owner (keycard path 9): $ATA_OWNER_ID" - -wallet ata create \ - --key-path "m/44'/60'/0'/0/9" \ - --token-definition "$LEZ_DEF_ID" -echo "ATA created for keycard path 9 / LEZ" - -sleep 15 - -LEZ_ATA_ID=$(wallet ata address --owner "$ATA_OWNER_ID" --token-definition "$LEZ_DEF_ID") -echo "Keycard path 9 LEZ ATA ID: $LEZ_ATA_ID" -echo "ATA state (should be initialized with zero balance):" -wallet account get --account-id "Public/$LEZ_ATA_ID" - -# Fund the ATA from LEZ supply (path 3) — setup for tests 12 and 13 -wallet token send \ - --from-key-path "m/44'/60'/0'/0/3" \ - --to "Public/$LEZ_ATA_ID" \ - --amount 3000 -echo "Funded keycard path 9 ATA with 3000 LEZ" - -sleep 15 - -echo "ATA state after funding (balance should be 3000):" -wallet account get --account-id "Public/$LEZ_ATA_ID" - -# ============================================================================= -# (12) ATA send — keycard path 7's ATA → pub-receiver's ATA -# ============================================================================= -echo "" -echo "=== (12) ATA send: keycard path 7's ATA → pub-receiver's ATA ===" -PUB_RECEIVER_ID=$(wallet account id --account-label pub-receiver) -wallet ata create \ - --owner "Public/$PUB_RECEIVER_ID" \ - --token-definition "$LEZ_DEF_ID" -echo "ATA created for pub-receiver / LEZ" - -sleep 15 - -PUB_RECEIVER_ATA_ID=$(wallet ata address --owner "$PUB_RECEIVER_ID" --token-definition "$LEZ_DEF_ID") -echo "pub-receiver LEZ ATA ID: $PUB_RECEIVER_ATA_ID" -echo "pub-receiver ATA state (should be initialized with zero balance):" -wallet account get --account-id "Public/$PUB_RECEIVER_ATA_ID" - -wallet ata send \ - --from-key-path "m/44'/60'/0'/0/9" \ - --token-definition "$LEZ_DEF_ID" \ - --to "$PUB_RECEIVER_ATA_ID" \ - --amount 500 -echo "Sent 500 LEZ: keycard path 9 ATA → pub-receiver ATA" - -sleep 15 - -echo "Keycard path 9 ATA state (balance should be 2500):" -wallet account get --account-id "Public/$LEZ_ATA_ID" -echo "pub-receiver ATA state (balance should be 500):" -wallet account get --account-id "Public/$PUB_RECEIVER_ATA_ID" - -# ============================================================================= -# (13) ATA burn — keycard path 7's ATA burns 200 LEZ -# ============================================================================= -echo "" -echo "=== (13) ATA burn: keycard path 7's ATA burns 200 LEZ ===" -wallet ata burn \ - --key-path "m/44'/60'/0'/0/9" \ - --token-definition "$LEZ_DEF_ID" \ - --amount 200 -echo "Burned 200 LEZ from keycard path 9 ATA" - -sleep 15 - -echo "Keycard path 9 ATA state (balance should be 2300):" -wallet account get --account-id "Public/$LEZ_ATA_ID" -echo "LEZ definition state (total supply should reflect burn):" -wallet account get --key-path "m/44'/60'/0'/0/2" - -echo "" -echo "=== All keycard token + AMM + ATA tests finished ===" diff --git a/keycard_wallet/Cargo.toml b/keycard_wallet/Cargo.toml index b2addc9d..f95f0223 100644 --- a/keycard_wallet/Cargo.toml +++ b/keycard_wallet/Cargo.toml @@ -14,4 +14,4 @@ pyo3.workspace = true log.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true -zeroize = "1" \ No newline at end of file +zeroize.workspace = true \ No newline at end of file diff --git a/keycard_wallet/python/keycard_wallet.py b/keycard_wallet/python/keycard_wallet.py index 457e6a88..1048ebbc 100644 --- a/keycard_wallet/python/keycard_wallet.py +++ b/keycard_wallet/python/keycard_wallet.py @@ -180,7 +180,5 @@ class KeycardWallet: return (nsk, vsk) except Exception as e: - import traceback - traceback.print_exc() - return None + raise RuntimeError(f"Error getting private keys: {e}") from e diff --git a/nssa/core/src/program.rs b/nssa/core/src/program.rs index 27ad9b8b..5802a40c 100644 --- a/nssa/core/src/program.rs +++ b/nssa/core/src/program.rs @@ -89,7 +89,7 @@ impl PrivateAccountKind { /// Borsh layout (all integers little-endian, variant index is u8): /// /// ```text - /// Regular(ident): 0x00 || ident (16 LE) || [0u8; 64] + /// Regular(ident): 0x00 || ident (16 LE) || [0_u8; 64] /// Pda { program_id, seed, ident }: 0x01 || program_id (32) || seed (32) || ident (16 LE) /// ``` /// diff --git a/nssa/src/privacy_preserving_transaction/message.rs b/nssa/src/privacy_preserving_transaction/message.rs index 60087dd8..4c0221db 100644 --- a/nssa/src/privacy_preserving_transaction/message.rs +++ b/nssa/src/privacy_preserving_transaction/message.rs @@ -208,7 +208,7 @@ pub mod tests { let nonces_bytes: &[u8] = &[1, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; // all remaining vec fields are empty: u32 len=0 let empty_vec_bytes: &[u8] = &[0_u8; 4]; - // validity windows: unbounded = {from: None (0u8), to: None (0_u8)} + // validity windows: unbounded = {from: None (0_u8), to: None (0u8)} let unbounded_window_bytes: &[u8] = &[0_u8; 2]; let expected_borsh_vec: Vec = [ diff --git a/wallet-ffi/src/transfer.rs b/wallet-ffi/src/transfer.rs index 1c532e1b..3b36971b 100644 --- a/wallet-ffi/src/transfer.rs +++ b/wallet-ffi/src/transfer.rs @@ -256,7 +256,6 @@ pub unsafe extern "C" fn wallet_ffi_transfer_deshielded( from: *const FfiBytes32, to: *const FfiBytes32, amount: *const [u8; 16], - key_path: *const c_char, out_result: *mut FfiTransferResult, ) -> WalletFfiError { let wrapper = match get_wallet(handle) { @@ -280,11 +279,9 @@ pub unsafe extern "C" fn wallet_ffi_transfer_deshielded( let from_id = AccountId::new(unsafe { (*from).data }); let to_id = AccountId::new(unsafe { (*to).data }); let amount = u128::from_le_bytes(unsafe { *amount }); - let key_path = optional_c_str(key_path); - let transfer = NativeTokenTransfer(&wallet); - match block_on(transfer.send_deshielded_transfer(from_id, to_id, amount, &key_path)) { + match block_on(transfer.send_deshielded_transfer(from_id, to_id, amount)) { Ok((tx_hash, _shared_key)) => { let tx_hash = CString::new(tx_hash.to_string()) .map_or(ptr::null_mut(), std::ffi::CString::into_raw); @@ -340,7 +337,6 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private( to_keys: *const FfiPrivateAccountKeys, to_identifier: *const FfiU128, amount: *const [u8; 16], - key_path: *const c_char, out_result: *mut FfiTransferResult, ) -> WalletFfiError { let wrapper = match get_wallet(handle) { @@ -377,8 +373,6 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private( }; let to_identifier = u128::from_le_bytes(unsafe { (*to_identifier).data }); let amount = u128::from_le_bytes(unsafe { *amount }); - let key_path = optional_c_str(key_path); - let transfer = NativeTokenTransfer(&wallet); match block_on(transfer.send_private_transfer_to_outer_account( @@ -387,7 +381,6 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private( to_vpk, to_identifier, amount, - &key_path, )) { Ok((tx_hash, _shared_key)) => { let tx_hash = CString::new(tx_hash.to_string()) @@ -533,7 +526,6 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private_owned( from: *const FfiBytes32, to: *const FfiBytes32, amount: *const [u8; 16], - key_path: *const c_char, out_result: *mut FfiTransferResult, ) -> WalletFfiError { let wrapper = match get_wallet(handle) { @@ -557,13 +549,9 @@ pub unsafe extern "C" fn wallet_ffi_transfer_private_owned( let from_id = AccountId::new(unsafe { (*from).data }); let to_id = AccountId::new(unsafe { (*to).data }); let amount = u128::from_le_bytes(unsafe { *amount }); - let key_path = optional_c_str(key_path); - let transfer = NativeTokenTransfer(&wallet); - match block_on( - transfer.send_private_transfer_to_owned_account(from_id, to_id, amount, &key_path), - ) { + match block_on(transfer.send_private_transfer_to_owned_account(from_id, to_id, amount)) { Ok((tx_hash, _shared_keys)) => { let tx_hash = CString::new(tx_hash.to_string()) .map_or(ptr::null_mut(), std::ffi::CString::into_raw); @@ -683,7 +671,6 @@ pub unsafe extern "C" fn wallet_ffi_register_public_account( pub unsafe extern "C" fn wallet_ffi_register_private_account( handle: *mut WalletHandle, account_id: *const FfiBytes32, - key_path: *const c_char, out_result: *mut FfiTransferResult, ) -> WalletFfiError { let wrapper = match get_wallet(handle) { @@ -705,11 +692,9 @@ pub unsafe extern "C" fn wallet_ffi_register_private_account( }; let account_id = AccountId::new(unsafe { (*account_id).data }); - let key_path = optional_c_str(key_path); - let transfer = NativeTokenTransfer(&wallet); - match block_on(transfer.register_account_private(account_id, &key_path)) { + match block_on(transfer.register_account_private(account_id)) { Ok((tx_hash, _secret)) => { let tx_hash = CString::new(tx_hash.to_string()) .map_or(ptr::null_mut(), std::ffi::CString::into_raw); diff --git a/wallet-ffi/wallet_ffi.h b/wallet-ffi/wallet_ffi.h index 23a25e79..693e2d5c 100644 --- a/wallet-ffi/wallet_ffi.h +++ b/wallet-ffi/wallet_ffi.h @@ -822,7 +822,6 @@ enum WalletFfiError wallet_ffi_transfer_deshielded(struct WalletHandle *handle, const struct FfiBytes32 *from, const struct FfiBytes32 *to, const uint8_t (*amount)[16], - const char *key_path, struct FfiTransferResult *out_result); /** @@ -859,7 +858,6 @@ enum WalletFfiError wallet_ffi_transfer_private(struct WalletHandle *handle, const struct FfiPrivateAccountKeys *to_keys, const struct FfiU128 *to_identifier, const uint8_t (*amount)[16], - const char *key_path, struct FfiTransferResult *out_result); /** @@ -935,7 +933,6 @@ enum WalletFfiError wallet_ffi_transfer_private_owned(struct WalletHandle *handl const struct FfiBytes32 *from, const struct FfiBytes32 *to, const uint8_t (*amount)[16], - const char *key_path, struct FfiTransferResult *out_result); /** @@ -990,7 +987,6 @@ enum WalletFfiError wallet_ffi_register_public_account(struct WalletHandle *hand */ enum WalletFfiError wallet_ffi_register_private_account(struct WalletHandle *handle, const struct FfiBytes32 *account_id, - const char *key_path, struct FfiTransferResult *out_result); /** diff --git a/wallet/Cargo.toml b/wallet/Cargo.toml index 3aaa1753..a09010ee 100644 --- a/wallet/Cargo.toml +++ b/wallet/Cargo.toml @@ -21,7 +21,7 @@ ata_core.workspace = true bip39.workspace = true pyo3.workspace = true rpassword = "7" -zeroize = "1" +zeroize.workspace = true keycard_wallet.workspace = true anyhow.workspace = true @@ -46,6 +46,9 @@ optfield = "0.4.0" url.workspace = true derive_more = { workspace = true, features = ["display"] } +[features] +keycard-debug = [] + [dev-dependencies] tempfile.workspace = true key_protocol = { workspace = true, features = ["test_utils"] } diff --git a/wallet/src/cli/keycard.rs b/wallet/src/cli/keycard.rs index 7355afbc..4b666f6f 100644 --- a/wallet/src/cli/keycard.rs +++ b/wallet/src/cli/keycard.rs @@ -20,6 +20,8 @@ pub enum KeycardSubcommand { /// /// Prints raw key material to stdout — intended for debugging only. /// Requires --reveal to confirm intent. + /// Only available when built with the `keycard-debug` feature. + #[cfg(feature = "keycard-debug")] GetPrivateKeys { /// BIP-32 derivation path, e.g. `m/44'/60'/0'/0/0`. #[arg(long)] @@ -143,6 +145,7 @@ impl WalletSubcommand for KeycardSubcommand { Ok(SubcommandReturnValue::Empty) } + #[cfg(feature = "keycard-debug")] Self::GetPrivateKeys { key_path, reveal } => { if !reveal { eprintln!( diff --git a/wallet/src/cli/mod.rs b/wallet/src/cli/mod.rs index 572745b4..30443de9 100644 --- a/wallet/src/cli/mod.rs +++ b/wallet/src/cli/mod.rs @@ -148,11 +148,6 @@ impl CliAccountMention { } } - #[must_use] - pub const fn is_keycard(&self) -> bool { - matches!(self, Self::KeyPath(_)) - } - #[must_use] pub fn key_path(&self) -> Option<&str> { match self { diff --git a/wallet/src/cli/programs/amm.rs b/wallet/src/cli/programs/amm.rs index 47af6f4b..f2d546c6 100644 --- a/wallet/src/cli/programs/amm.rs +++ b/wallet/src/cli/programs/amm.rs @@ -140,7 +140,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { AccountIdWithPrivacy::Public(b), AccountIdWithPrivacy::Public(lp), ) => { - Amm(wallet_core) + let tx_hash = Amm(wallet_core) .send_new_definition( a, b, @@ -152,7 +152,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { &user_holding_lp, ) .await?; - + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } _ => { @@ -172,7 +175,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { let b_id = user_holding_b.resolve(wallet_core.storage())?; match (a_id, b_id) { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { - Amm(wallet_core) + let tx_hash = Amm(wallet_core) .send_swap_exact_input( a, b, @@ -183,7 +186,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { &user_holding_b, ) .await?; - + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } _ => { @@ -203,7 +209,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { let b_id = user_holding_b.resolve(wallet_core.storage())?; match (a_id, b_id) { (AccountIdWithPrivacy::Public(a), AccountIdWithPrivacy::Public(b)) => { - Amm(wallet_core) + let tx_hash = Amm(wallet_core) .send_swap_exact_output( a, b, @@ -214,7 +220,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { &user_holding_b, ) .await?; - + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } _ => { @@ -240,7 +249,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { AccountIdWithPrivacy::Public(b), AccountIdWithPrivacy::Public(lp), ) => { - Amm(wallet_core) + let tx_hash = Amm(wallet_core) .send_add_liquidity( a, b, @@ -253,7 +262,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { &user_holding_lp, ) .await?; - + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } _ => { @@ -279,7 +291,7 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { AccountIdWithPrivacy::Public(b), AccountIdWithPrivacy::Public(lp), ) => { - Amm(wallet_core) + let tx_hash = Amm(wallet_core) .send_remove_liquidity( a, b, @@ -290,7 +302,10 @@ impl WalletSubcommand for AmmProgramAgnosticSubcommand { &user_holding_lp, ) .await?; - + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } _ => { diff --git a/wallet/src/cli/programs/ata.rs b/wallet/src/cli/programs/ata.rs index d7e3b223..c2b96a85 100644 --- a/wallet/src/cli/programs/ata.rs +++ b/wallet/src/cli/programs/ata.rs @@ -96,9 +96,13 @@ impl WalletSubcommand for AtaSubcommand { match owner_resolved { AccountIdWithPrivacy::Public(owner_id) => { - Ata(wallet_core) + let tx_hash = Ata(wallet_core) .send_create(owner_id, definition_id, &owner) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } AccountIdWithPrivacy::Private(owner_id) => { @@ -133,9 +137,13 @@ impl WalletSubcommand for AtaSubcommand { match from_resolved { AccountIdWithPrivacy::Public(from_id) => { - Ata(wallet_core) + let tx_hash = Ata(wallet_core) .send_transfer(from_id, definition_id, to_id, amount, &from) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } AccountIdWithPrivacy::Private(from_id) => { @@ -168,9 +176,13 @@ impl WalletSubcommand for AtaSubcommand { match holder_resolved { AccountIdWithPrivacy::Public(holder_id) => { - Ata(wallet_core) + let tx_hash = Ata(wallet_core) .send_burn(holder_id, definition_id, amount, &holder) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } AccountIdWithPrivacy::Private(holder_id) => { diff --git a/wallet/src/cli/programs/native_token_transfer.rs b/wallet/src/cli/programs/native_token_transfer.rs index ee7962b0..724bcca4 100644 --- a/wallet/src/cli/programs/native_token_transfer.rs +++ b/wallet/src/cli/programs/native_token_transfer.rs @@ -73,7 +73,7 @@ impl WalletSubcommand for AuthTransferSubcommand { } AccountIdWithPrivacy::Private(account_id) => { let (tx_hash, secret) = NativeTokenTransfer(wallet_core) - .register_account_private(account_id, &None) + .register_account_private(account_id) .await?; println!("Transaction hash is {tx_hash}"); @@ -324,7 +324,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate { match self { Self::PrivateOwned { from, to, amount } => { let (tx_hash, [secret_from, secret_to]) = NativeTokenTransfer(wallet_core) - .send_private_transfer_to_owned_account(from, to, amount, &None) + .send_private_transfer_to_owned_account(from, to, amount) .await?; println!("Transaction hash is {tx_hash}"); @@ -369,7 +369,6 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommandPrivate { to_vpk, to_identifier.unwrap_or_else(rand::random), amount, - &None, ) .await?; @@ -481,7 +480,7 @@ impl WalletSubcommand for NativeTokenTransferProgramSubcommand { } Self::Deshielded { from, to, amount } => { let (tx_hash, secret) = NativeTokenTransfer(wallet_core) - .send_deshielded_transfer(from, to, amount, &None) + .send_deshielded_transfer(from, to, amount) .await?; println!("Transaction hash is {tx_hash}"); diff --git a/wallet/src/cli/programs/token.rs b/wallet/src/cli/programs/token.rs index 4f202695..77dae3b5 100644 --- a/wallet/src/cli/programs/token.rs +++ b/wallet/src/cli/programs/token.rs @@ -699,7 +699,7 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { else { anyhow::bail!("Only public accounts supported for token transfer"); }; - Token(wallet_core) + let tx_hash = Token(wallet_core) .send_transfer_transaction( sender_id, recipient_id, @@ -708,6 +708,10 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { &recipient_account_id, ) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } Self::BurnToken { @@ -719,7 +723,7 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { let AccountIdWithPrivacy::Public(holder_id) = holder else { anyhow::bail!("Only public holder account supported for token burn"); }; - Token(wallet_core) + let tx_hash = Token(wallet_core) .send_burn_transaction( definition_account_id, holder_id, @@ -727,6 +731,10 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { &holder_account_id, ) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } Self::MintToken { @@ -741,7 +749,7 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { else { anyhow::bail!("Only public accounts supported for token mint"); }; - Token(wallet_core) + let tx_hash = Token(wallet_core) .send_mint_transaction( def_id, holder_id, @@ -750,6 +758,10 @@ impl WalletSubcommand for TokenProgramSubcommandPublic { &holder_account_id, ) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } } @@ -1361,7 +1373,7 @@ impl WalletSubcommand for CreateNewTokenProgramSubcommand { else { anyhow::bail!("Only public accounts supported for new token definition"); }; - Token(wallet_core) + let tx_hash = Token(wallet_core) .send_new_definition( def_id, sup_id, @@ -1371,6 +1383,10 @@ impl WalletSubcommand for CreateNewTokenProgramSubcommand { &supply_account_id, ) .await?; + println!("Transaction hash is {tx_hash}"); + let transfer_tx = wallet_core.poll_native_token_transfer(tx_hash).await?; + println!("Transaction data is {transfer_tx:?}"); + wallet_core.store_persistent_data()?; Ok(SubcommandReturnValue::Empty) } } diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index 36492c31..36fd1684 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -37,6 +37,7 @@ use tokio::io::AsyncWriteExt as _; use crate::{ account::{AccountIdWithPrivacy, Label}, + cli::CliAccountMention, config::WalletConfigOverrides, poller::TxPoller, signing::SigningGroups, @@ -582,8 +583,8 @@ impl WalletCore { /// Send a public transaction with caller-supplied nonces. /// - /// Use this when nonce fetching requires special handling (e.g. the AMM LP account - /// may not yet exist on-chain and needs a `Nonce(0)` fallback). + /// Use this when the caller needs to assemble or augment nonces before submission + /// (e.g. injecting a keycard account nonce that was fetched separately). pub async fn send_public_tx_with_nonces( &self, program: &Program, @@ -624,14 +625,14 @@ impl WalletCore { accounts: Vec, instruction_data: InstructionData, program: &ProgramWithDependencies, - key_path: &Option, + mention: Option<&CliAccountMention>, ) -> Result<(HashType, Vec), ExecutionFailureKind> { self.send_privacy_preserving_tx_with_pre_check( accounts, instruction_data, program, |_| Ok(()), - key_path, + mention, ) .await } @@ -642,14 +643,14 @@ impl WalletCore { instruction_data: InstructionData, program: &ProgramWithDependencies, tx_pre_check: impl FnOnce(&[&Account]) -> Result<(), ExecutionFailureKind>, - key_path: &Option, + mention: Option<&CliAccountMention>, ) -> Result<(HashType, Vec), ExecutionFailureKind> { let acc_manager = privacy_preserving_tx::AccountManager::new(self, accounts).await?; let mut pre_states = acc_manager.pre_states(); let (keycard_account, keycard_pin, keycard_path) = - if let Some(key_path_str) = key_path.as_deref() { + if let Some(key_path_str) = mention.and_then(CliAccountMention::key_path) { let pin = crate::helperfunctions::read_pin().map_err(|e| { ExecutionFailureKind::KeycardError(pyo3::PyErr::new::< pyo3::exceptions::PyRuntimeError, diff --git a/wallet/src/program_facades/amm.rs b/wallet/src/program_facades/amm.rs index 797169ac..526a35b5 100644 --- a/wallet/src/program_facades/amm.rs +++ b/wallet/src/program_facades/amm.rs @@ -63,37 +63,13 @@ impl Amm<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(a_mention, user_holding_a, self.0) - .and_then(|()| groups.add_sender(b_mention, user_holding_b, self.0)) - .and_then(|()| groups.add_recipient(lp_mention, user_holding_lp, self.0)) + .add_required(a_mention, user_holding_a, self.0) + .and_then(|()| groups.add_required(b_mention, user_holding_b, self.0)) + .and_then(|()| groups.add_optional(lp_mention, user_holding_lp, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; - let mut nonces = self - .0 - .get_accounts_nonces(vec![user_holding_a, user_holding_b]) - .await - .map_err(ExecutionFailureKind::SequencerError)?; - - if groups.signing_ids().contains(&user_holding_lp) { - let lp_nonces = self - .0 - .get_accounts_nonces(vec![user_holding_lp]) - .await - .map_err(ExecutionFailureKind::SequencerError)?; - nonces.push( - lp_nonces - .into_iter() - .next() - .unwrap_or(nssa_core::account::Nonce(0)), - ); - } else { - println!( - "Liquidity pool tokens receiver's account ({user_holding_lp}) private key not found in wallet. Proceeding with only liquidity provider's keys." - ); - } - self.0 - .send_public_tx_with_nonces(&program, account_ids, nonces, instruction, groups) + .send_public_tx(&program, account_ids, instruction, groups) .await } @@ -159,7 +135,7 @@ impl Amm<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(seller_mention, account_id_auth, self.0) + .add_required(seller_mention, account_id_auth, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) @@ -228,7 +204,7 @@ impl Amm<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(seller_mention, account_id_auth, self.0) + .add_required(seller_mention, account_id_auth, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) @@ -292,37 +268,13 @@ impl Amm<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(a_mention, user_holding_a, self.0) - .and_then(|()| groups.add_sender(b_mention, user_holding_b, self.0)) - .and_then(|()| groups.add_recipient(lp_mention, user_holding_lp, self.0)) + .add_required(a_mention, user_holding_a, self.0) + .and_then(|()| groups.add_required(b_mention, user_holding_b, self.0)) + .and_then(|()| groups.add_optional(lp_mention, user_holding_lp, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; - let mut nonces = self - .0 - .get_accounts_nonces(vec![user_holding_a, user_holding_b]) - .await - .map_err(ExecutionFailureKind::SequencerError)?; - - if groups.signing_ids().contains(&user_holding_lp) { - let lp_nonces = self - .0 - .get_accounts_nonces(vec![user_holding_lp]) - .await - .map_err(ExecutionFailureKind::SequencerError)?; - nonces.push( - lp_nonces - .into_iter() - .next() - .unwrap_or(nssa_core::account::Nonce(0)), - ); - } else { - println!( - "LP holder's account ({user_holding_lp}) private key not found in wallet. Proceeding with only liquidity providers' keys." - ); - } - self.0 - .send_public_tx_with_nonces(&program, account_ids, nonces, instruction, groups) + .send_public_tx(&program, account_ids, instruction, groups) .await } @@ -381,7 +333,7 @@ impl Amm<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(lp_mention, user_holding_lp, self.0) + .add_required(lp_mention, user_holding_lp, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) diff --git a/wallet/src/program_facades/ata.rs b/wallet/src/program_facades/ata.rs index 7fc1f145..9b38ca2f 100644 --- a/wallet/src/program_facades/ata.rs +++ b/wallet/src/program_facades/ata.rs @@ -33,7 +33,7 @@ impl Ata<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(owner_mention, owner_id, self.0) + .add_required(owner_mention, owner_id, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) @@ -63,7 +63,7 @@ impl Ata<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(owner_mention, owner_id, self.0) + .add_required(owner_mention, owner_id, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) @@ -92,7 +92,7 @@ impl Ata<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(owner_mention, owner_id, self.0) + .add_required(owner_mention, owner_id, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 .send_public_tx(&program, account_ids, instruction, groups) @@ -127,7 +127,7 @@ impl Ata<'_> { accounts, instruction_data, &ata_with_token_dependency(), - &None, + None, ) .await .map(|(hash, mut secrets)| { @@ -169,7 +169,7 @@ impl Ata<'_> { accounts, instruction_data, &ata_with_token_dependency(), - &None, + None, ) .await .map(|(hash, mut secrets)| { @@ -210,7 +210,7 @@ impl Ata<'_> { accounts, instruction_data, &ata_with_token_dependency(), - &None, + None, ) .await .map(|(hash, mut secrets)| { diff --git a/wallet/src/program_facades/native_token_transfer/deshielded.rs b/wallet/src/program_facades/native_token_transfer/deshielded.rs index b5ea696d..5a941d24 100644 --- a/wallet/src/program_facades/native_token_transfer/deshielded.rs +++ b/wallet/src/program_facades/native_token_transfer/deshielded.rs @@ -10,7 +10,6 @@ impl NativeTokenTransfer<'_> { from: AccountId, to: AccountId, balance_to_move: u128, - key_path: &Option, ) -> Result<(HashType, nssa_core::SharedSecretKey), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); @@ -25,7 +24,7 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, - key_path, + None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/native_token_transfer/private.rs b/wallet/src/program_facades/native_token_transfer/private.rs index 450ab917..c940dfb6 100644 --- a/wallet/src/program_facades/native_token_transfer/private.rs +++ b/wallet/src/program_facades/native_token_transfer/private.rs @@ -11,7 +11,6 @@ impl NativeTokenTransfer<'_> { pub async fn register_account_private( &self, from: AccountId, - key_path: &Option, ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { let instruction = authenticated_transfer_core::Instruction::Initialize; @@ -25,7 +24,7 @@ impl NativeTokenTransfer<'_> { vec![account], Program::serialize_instruction(instruction).unwrap(), &Program::authenticated_transfer_program().into(), - key_path, + None, ) .await .map(|(resp, secrets)| { @@ -42,7 +41,6 @@ impl NativeTokenTransfer<'_> { to_vpk: ViewingPublicKey, to_identifier: Identifier, balance_to_move: u128, - key_path: &Option, ) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); @@ -61,7 +59,7 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, - key_path, + None, ) .await .map(|(resp, secrets)| { @@ -77,7 +75,6 @@ impl NativeTokenTransfer<'_> { from: AccountId, to: AccountId, balance_to_move: u128, - key_path: &Option, ) -> Result<(HashType, [SharedSecretKey; 2]), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); @@ -96,7 +93,7 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, - key_path, + None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/native_token_transfer/public.rs b/wallet/src/program_facades/native_token_transfer/public.rs index 89af5a2d..b33104cc 100644 --- a/wallet/src/program_facades/native_token_transfer/public.rs +++ b/wallet/src/program_facades/native_token_transfer/public.rs @@ -3,9 +3,7 @@ use common::HashType; use nssa::{AccountId, program::Program}; use super::NativeTokenTransfer; -use crate::{ - ExecutionFailureKind, cli::CliAccountMention, signing::SigningGroups, -}; +use crate::{ExecutionFailureKind, cli::CliAccountMention, signing::SigningGroups}; impl NativeTokenTransfer<'_> { pub async fn send_public_transfer( @@ -18,8 +16,8 @@ impl NativeTokenTransfer<'_> { ) -> Result { let mut groups = SigningGroups::new(); groups - .add_sender(from_mention, from, self.0) - .and_then(|()| groups.add_recipient(to_mention, to, self.0)) + .add_required(from_mention, from, self.0) + .and_then(|()| groups.add_optional(to_mention, to, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 @@ -41,7 +39,7 @@ impl NativeTokenTransfer<'_> { ) -> Result { let mut groups = SigningGroups::new(); groups - .add_sender(account_mention, from, self.0) + .add_required(account_mention, from, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 diff --git a/wallet/src/program_facades/native_token_transfer/shielded.rs b/wallet/src/program_facades/native_token_transfer/shielded.rs index 03015a63..e221e87e 100644 --- a/wallet/src/program_facades/native_token_transfer/shielded.rs +++ b/wallet/src/program_facades/native_token_transfer/shielded.rs @@ -14,8 +14,6 @@ impl NativeTokenTransfer<'_> { from_mention: &CliAccountMention, ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); - let key_path = from_mention.key_path().map(str::to_owned); - self.0 .send_privacy_preserving_tx_with_pre_check( vec![ @@ -27,7 +25,7 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, - &key_path, + Some(from_mention), ) .await .map(|(resp, secrets)| { @@ -49,8 +47,6 @@ impl NativeTokenTransfer<'_> { from_mention: &CliAccountMention, ) -> Result<(HashType, SharedSecretKey), ExecutionFailureKind> { let (instruction_data, program, tx_pre_check) = auth_transfer_preparation(balance_to_move); - let key_path = from_mention.key_path().map(str::to_owned); - self.0 .send_privacy_preserving_tx_with_pre_check( vec![ @@ -64,7 +60,7 @@ impl NativeTokenTransfer<'_> { instruction_data, &program.into(), tx_pre_check, - &key_path, + Some(from_mention), ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/pinata.rs b/wallet/src/program_facades/pinata.rs index b9803955..fd37016a 100644 --- a/wallet/src/program_facades/pinata.rs +++ b/wallet/src/program_facades/pinata.rs @@ -62,7 +62,7 @@ impl Pinata<'_> { ], nssa::program::Program::serialize_instruction(solution).unwrap(), &nssa::program::Program::pinata().into(), - &None, + None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/program_facades/token.rs b/wallet/src/program_facades/token.rs index 2cbd9f73..ba6779a9 100644 --- a/wallet/src/program_facades/token.rs +++ b/wallet/src/program_facades/token.rs @@ -25,8 +25,8 @@ impl Token<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(definition_mention, definition_account_id, self.0) - .and_then(|()| groups.add_sender(supply_mention, supply_account_id, self.0)) + .add_required(definition_mention, definition_account_id, self.0) + .and_then(|()| groups.add_required(supply_mention, supply_account_id, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 @@ -55,7 +55,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -88,7 +88,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -123,7 +123,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -149,8 +149,8 @@ impl Token<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(sender_mention, sender_account_id, self.0) - .and_then(|()| groups.add_recipient(recipient_mention, recipient_account_id, self.0)) + .add_required(sender_mention, sender_account_id, self.0) + .and_then(|()| groups.add_optional(recipient_mention, recipient_account_id, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 @@ -182,7 +182,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -221,7 +221,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -254,7 +254,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -278,8 +278,6 @@ impl Token<'_> { }; let instruction_data = Program::serialize_instruction(instruction).expect("Instruction should serialize"); - let key_path = sender_mention.key_path().map(str::to_owned); - self.0 .send_privacy_preserving_tx( vec![ @@ -290,7 +288,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &key_path, + Some(sender_mention), ) .await .map(|(resp, secrets)| { @@ -316,8 +314,6 @@ impl Token<'_> { }; let instruction_data = Program::serialize_instruction(instruction).expect("Instruction should serialize"); - let key_path = sender_mention.key_path().map(str::to_owned); - self.0 .send_privacy_preserving_tx( vec![ @@ -330,7 +326,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &key_path, + Some(sender_mention), ) .await .map(|(resp, secrets)| { @@ -356,7 +352,7 @@ impl Token<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(holder_mention, holder_account_id, self.0) + .add_required(holder_mention, holder_account_id, self.0) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 @@ -388,7 +384,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -421,7 +417,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -455,7 +451,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -482,8 +478,8 @@ impl Token<'_> { let mut groups = SigningGroups::new(); groups - .add_sender(definition_mention, definition_account_id, self.0) - .and_then(|()| groups.add_recipient(holder_mention, holder_account_id, self.0)) + .add_required(definition_mention, definition_account_id, self.0) + .and_then(|()| groups.add_optional(holder_mention, holder_account_id, self.0)) .map_err(ExecutionFailureKind::from_anyhow)?; self.0 @@ -515,7 +511,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -554,7 +550,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -587,7 +583,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -621,7 +617,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { @@ -659,7 +655,7 @@ impl Token<'_> { ], instruction_data, &Program::token().into(), - &None, + None, ) .await .map(|(resp, secrets)| { diff --git a/wallet/src/signing.rs b/wallet/src/signing.rs index 1a710950..cd5e865d 100644 --- a/wallet/src/signing.rs +++ b/wallet/src/signing.rs @@ -23,7 +23,7 @@ impl SigningGroups { /// Add a sender. Keycard paths are queued for the hardware session; local accounts /// have their signing key resolved eagerly. Errors if no key is found. - pub fn add_sender( + pub fn add_required( &mut self, mention: &CliAccountMention, account_id: AccountId, @@ -43,9 +43,9 @@ impl SigningGroups { Ok(()) } - /// Add a recipient. Same as [`add_sender`] but silently skips accounts with no local + /// Add a recipient. Same as [`add_required`] but silently skips accounts with no local /// key and no keycard path — they are foreign and require neither a signature nor a nonce. - pub fn add_recipient( + pub fn add_optional( &mut self, mention: &CliAccountMention, account_id: AccountId,