Skip to content

fix(wallet/sdk)!: split transfer and transaction signing - #1597

Merged
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:wallet-signer
Oct 14, 2025
Merged

fix(wallet/sdk)!: split transfer and transaction signing#1597
sdbondi merged 1 commit into
tari-project:developmentfrom
sdbondi:wallet-signer

Conversation

@sdbondi

@sdbondi sdbondi commented Oct 13, 2025

Copy link
Copy Markdown
Member

Description

fix(wallet/sdk)!: split transfer and transaction signing
fix!: include input and output statement in balance proof signature message
fix(wallet)!: added minimum value promise to stealth outputs table

Motivation and Context

Allows SDK users to generate unsigned transfer transactions and sign them using a secure offline cryptographic device.

Added transfer statement inputs and outputs to the balance signature message preimage to prevent potential malleability of outputs.

How Has This Been Tested?

Existing tests, manually, in this commit tari-project/ootle-wallet-cli@7c196d9

Breaking Changes

  • None
  • Requires data directory to be deleted
  • Other - Please specify

Summary by CodeRabbit

  • New Features

    • Associate resources to accounts from the wallet daemon and services.
    • Manage revealed funds: lock, release, and finalize operations.
    • Wallet initialization validates/persists network automatically.
  • Improvements

    • Stealth transfers: stronger account validation, account-key signing, better lock handling, and dry-run responses include final hash.
    • More accurate fee estimates across UI (NFTs, tokens, manifests) by removing blanket buffers and applying targeted adjustments only for confidential transfers.
  • Bug Fixes

    • Clearer validation errors for transactions lacking inputs or a main signer.
    • Seed words command provides explicit error messaging when unavailable.

@coderabbitai

coderabbitai Bot commented Oct 13, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Refactors stealth/confidential cryptography to use Witness types, updates balance-proof message domains and signatures, introduces unsigned stealth transfer construction, adjusts SDK APIs (keys, stealth/confidential, transactions), adds account resource association, modifies DB schema for minimum_value_promise, revises UI fee estimations, and changes transaction pre-checks to require inputs.

Changes

Cohort / File(s) Summary
Transaction pre-checks
applications/tari_indexer/src/network_client.rs, applications/tari_validator_node/src/p2p/services/mempool/service.rs, applications/tari_validator_node/src/transaction_validators/is_shard_applicable.rs, crates/transaction/src/transaction.rs
Switch predicate from is_shard_applicable() to has_inputs(); early-return paths updated accordingly; public method renamed to has_inputs().
Validator errors and signature validation
applications/tari_validator_node/src/transaction_validators/error.rs, applications/tari_validator_node/src/transaction_validators/signature.rs
Add TransactionValidationError::NoMainSigner and check for main signer before signature verification.
Wallet daemon handlers
applications/tari_walletd/src/handlers/{accounts.rs,confidential.rs}, applications/tari_walletd/src/lib.rs, applications/tari_walletd/src/main.rs
Migrate to Witness-based statements, add owner key checks and new signing/locking flows; remove initial key creation; enforce SeedWords None as panic in CLI path.
Web UI fee adjustments
applications/tari_walletd/web_ui/src/routes/.../SendNft.tsx, .../Tokens/components/SendMoney.tsx, .../Manifest/Manifest.tsx
Remove blanket fee buffers; apply +100 only for confidential token transfers; dry-run fees use exact totals.
Engine crypto domains and messages
crates/engine_types/src/crypto/{messages.rs,utxo_spend.rs}, crates/engine_types/src/{hashing.rs,stealth/transfer.rs}, crates/template_lib/src/models/stealth.rs
Rename StealthTransfer → StealthBalanceProof domain; update message constructors and verification to use Statements; adjust ownership message to exclude public keys.
Wallet crypto: Witness migration
crates/wallet/crypto/src/{unblinded_statement.rs,bullet_proof.rs,confidential.rs,stealth.rs,balance_proof.rs}, crates/wallet/crypto/tests/{output_statement.rs,viewable_balance_proof.rs}
Rename Statement types to Witness variants; add fields (minimum_value_promise, encrypted_data); update APIs and proofs to consume Witness types; adjust balance/owner proof signatures.
SDK APIs: confidential/stealth/transactions/keys
crates/wallet/sdk/src/apis/{confidential_crypto.rs,confidential_outputs.rs,confidential_transfer.rs,stealth_crypto.rs,stealth_outputs.rs,stealth_transfer.rs,transaction.rs,key_manager.rs}, crates/wallet/sdk/src/{lib.rs,models/{key.rs,stealth_output.rs},sdk.rs}
Replace Statement with Witness in public surfaces; add/rename lock/reveal/finalize methods; introduce TransferStatementParams, OutputToCreate, UnblindedInputToSpend; shift to unsigned transactions; add Key::key_id, network helpers; change load_seed_words to return Option; remove get_or_create_initial; add next_key/next_derived_key_index.
SDK services: account monitor
crates/wallet/sdk_services/src/account_monitor/{handle.rs,monitor.rs}
Add AssociateResource request and handle it by caching/fetching resource and associating with account.
SQLite storage updates
crates/wallet/storage_sqlite/migrations/.../up.sql, crates/wallet/storage_sqlite/src/{schema.rs,models/stealth_output.rs,writer.rs}
Add minimum_value_promise column/index; map field in model and writer.
Daemon process def
applications/tari_swarm_daemon/src/process_definitions/wallet_daemon_create_key.rs
Remove explicit --key 0 from create-account command.
Formatting/await tweaks
crates/wallet/sdk_services/src/transaction_service/service.rs, utilities/tariswap_test_bench/src/runner.rs
Adjust call sites for insert_new_transaction after signature change (sync).

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor UI as UI/Client
  participant SDK as Wallet SDK
  participant SO as StealthOutputsApi
  participant SC as StealthCryptoApi
  participant ST as StealthTransferApi
  participant TX as TransactionApi
  participant NW as Network

  UI->>SDK: request stealth transfer (params)
  SDK->>SO: resolve_input_masks(inputs)
  SO-->>SDK: InputSpendData[]
  SDK->>SO: generate_transfer_statement(TransferStatementParams)
  SO-->>SDK: StealthTransferStatement
  SDK->>ST: generate_transfer_transaction(statement) [unsigned]
  ST-->>SDK: UnsignedTransaction + locks
  Note over SDK,ST: Locks managed via release_lock/finalize_lock
  SDK->>TX: insert_new_transaction(unsigned_tx)
  TX-->>SDK: transaction_id
  SDK->>NW: submit_transaction(signed_tx)
  alt success
    NW-->>SDK: ok
    SDK->>SO: finalize_lock(lock_id)
  else error
    NW-->>SDK: err
    SDK->>SO: release_lock(lock_id)
  end
Loading
sequenceDiagram
  autonumber
  actor WD as Wallet Daemon
  participant AM as AccountMonitorHandle
  participant MON as AccountMonitor
  participant ACC as Accounts API
  participant IDX as Resource Cache

  WD->>AM: associate_resource(account, resource)
  AM->>MON: AssociateResource(account, resource)
  MON->>IDX: fetch_and_cache_resource(resource)
  IDX-->>MON: resource (cached)
  MON->>ACC: associate_resource(account, resource)
  ACC-->>MON: ok
  MON-->>AM: ok
  AM-->>WD: ok
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Suggested labels

P-acks_required, P-reviews_required

Poem

A hare taps keys with whiskered grace,
Witness in paw, new proofs in place.
Domains renamed, the hashes sing,
Unsigned dreams take crypto wing.
Fees unpadded, locks align—
Hop-hop! Transactions, right on time.
(_/) ✨ (•‿•) 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 19.80% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title clearly summarizes the primary change of splitting transfer creation and transaction signing within the wallet SDK, aligns with the PR’s objectives, and uses concise conventional-commit style without extraneous detail.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
applications/tari_validator_node/src/transaction_validators/is_shard_applicable.rs (1)

11-14: Rename IsShardApplicable to match its input-only check
Update the docstring and struct name to reflect that only inputs are validated:

-/// Refuse to process the transaction if it does not apply to any shard (i.e. does not have any inputs or claim burn
-/// tombstones).
+/// Refuse to process the transaction if it does not have any inputs.
 #[derive(Debug, Clone, Default)]
-pub struct IsShardApplicable;
+pub struct HasInputsValidator;

 impl Validator<Transaction> for HasInputsValidator {
     // ...
 }
applications/tari_walletd/src/handlers/confidential.rs (2)

149-156: Change output encryption likely uses the wrong owner secret

You encrypt the change using &change_mask.key as the owner secret. Change outputs should be decryptable by the wallet’s owner key. This looks inconsistent with the main output (uses &account_key.secret) and may render change outputs unviewable.

Apply:

-        let encrypted_data = sdk.confidential_crypto_api().encrypt_value_and_mask(
+        let encrypted_data = sdk.confidential_crypto_api().encrypt_value_and_mask(
             change_amount_u64,
             &change_mask.key,
             &public_nonce,
-            &change_mask.key,
+            &account_key.secret,
             None,
         )?;

Please confirm the intended decryption key for change; if change should be owned by the account, use the account owner secret consistently.


86-89: Prevent locked outputs from remaining stuck on error (add RAII unlock guard)

If any step after locking fails, inputs remain locked. Add a scope guard to auto-release on early returns.

Apply imports:

 use std::fs;
+use scopeguard::{guard, ScopeGuard};

Create the guard right after creating the lock:

-    let lock_id = sdk.confidential_outputs_api().create_lock()?;
+    let lock_id = sdk.confidential_outputs_api().create_lock()?;
+    let unlock_guard = guard(lock_id, |id| {
+        let _ = sdk.confidential_outputs_api().release_revealed_funds(id);
+        let _ = sdk.confidential_outputs_api().release_locked_outputs(id);
+    });

Dismiss on success before returning:

-    Ok(ProofsGenerateResponse {
+    // Success: prevent the guard from releasing
+    let _ = ScopeGuard::into_inner(unlock_guard);
+    Ok(ProofsGenerateResponse {
         proof_id: lock_id,
         proof,
     })

Note: add scopeguard = "1" to Cargo.toml.

Also applies to: 65-66, 198-202

crates/wallet/sdk/src/models/stealth_output.rs (1)

13-33: Include minimum_value_promise in all initializers
storage_sqlite’s try_convert sets minimum_value_promise correctly, but in crates/wallet/sdk/src/apis/stealth_transfer.rs (around line 693) and crates/wallet/sdk/src/apis/stealth_outputs.rs (around line 579) the StealthOutputModel literals omit minimum_value_promise. Also verify TS/FFI bindings and DB migrations add the new column.

crates/wallet/sdk/src/apis/stealth_transfer.rs (1)

253-261: BUG: New lock_id is created and shadows the function parameter, leaking locks and breaking finalize/release.

PreferConfidential branch calls create_lock(), shadowing the passed lock_id. The newly locked outputs are not associated with the caller’s lock_id and won’t be finalized/released correctly.

Apply this diff to use the caller’s lock_id and prevent leaks:

- let lock_id = self.outputs_api.create_lock()?;
- let (inputs, blinded_amount_locked) = self.outputs_api.lock_outputs_until_partial_amount(
+ let (inputs, blinded_amount_locked) = self.outputs_api.lock_outputs_until_partial_amount(
     owner_account.component_address(),
     &resource_address,
     spend_amount,
     lock_id,
 )?;

No other changes needed; subsequent release_lock calls will now use the correct lock_id (the function parameter).

🧹 Nitpick comments (18)
crates/wallet/sdk/src/models/key.rs (1)

95-97: LGTM! Consider returning by value for consistency.

The accessor correctly exposes the key_id field for external usage, aligning with the PR's goals. However, since KeyId implements Copy (line 220), idiomatic Rust typically returns Copy types by value rather than by reference. Additionally, WalletKeyRecord::key_id() at line 22-24 returns KeyId by value, creating a minor inconsistency.

Consider this diff for consistency and idiomaticity:

-    pub fn key_id(&self) -> &KeyId {
-        &self.key_id
+    pub fn key_id(&self) -> KeyId {
+        self.key_id
     }
applications/tari_walletd/web_ui/src/routes/AssetVault/Tokens/components/SendMoney.tsx (1)

205-209: Conditional fee buffer logic looks reasonable, but track the TODO.

The conditional fee buffer (applied only for Confidential resource types) is more thoughtful than the blanket buffer removal in other files. The TODO comment indicates awareness that this is a workaround for variable bullet proof sizes.

However, ensure that:

  1. The 100-unit buffer is adequate for all confidential transaction scenarios
  2. The TODO is tracked in an issue to implement a more robust solution

Do you want me to open a tracking issue for the TODO to implement proper variable-size fee estimation for confidential transactions?

crates/wallet/sdk/src/apis/key_manager.rs (1)

283-297: Consider renaming to reflect side effects.

The method next_derived_key_index both advances the index counter in storage (line 294) and returns the new value, but the name suggests it only retrieves. Consider a name like allocate_next_key_index or advance_and_get_next_index to better convey that it mutates state.

The logic itself is correct: the write transaction ensures atomicity, and insert_or_ignore provides idempotency safeguards.

Apply this diff to clarify the method's purpose:

-    pub fn next_derived_key_index(&self, branch: KeyBranch) -> Result<DerivedKeyIndex, KeyManagerApiError> {
+    pub fn allocate_next_key_index(&self, branch: KeyBranch) -> Result<DerivedKeyIndex, KeyManagerApiError> {
         let mut tx = self.store.create_write_tx()?;
         let next_index = tx
             .key_manager_get_last_index(branch.as_str())

And update the call site at line 278:

     pub fn next_key(&self, branch: KeyBranch) -> Result<DerivedWalletKey, KeyManagerApiError> {
-        let next_key_id = self.next_derived_key_index(branch)?;
+        let next_key_id = self.allocate_next_key_index(branch)?;
         let key = self.derive_key(branch, next_key_id)?;
crates/wallet/sdk/src/lib.rs (1)

20-20: Consider listing explicit re-exports instead of wildcard.

The wildcard re-export pub use tari_ootle_address::*; makes all public items from that crate available through this SDK. While convenient, it can introduce unexpected items into the public API and makes it harder to track what's actually being exposed. Consider explicitly listing the types you want to re-export for better API clarity and maintainability.

Apply this pattern if you want more explicit control:

-pub use tari_ootle_address::*;
+pub use tari_ootle_address::{
+    // List specific types to re-export, e.g.:
+    // OotleAddress, AddressBuilder, etc.
+};
crates/wallet/storage_sqlite/src/models/stealth_output.rs (1)

38-38: LGTM with database integrity assumption.

The addition of minimum_value_promise follows the existing pattern for numeric fields. Line 85 casts i64 to u64, which assumes the database value is non-negative. While a negative value would indicate database corruption (an unlikely scenario given the insertion code ensures non-negative values), you might consider adding an explicit check if you want defense-in-depth:

minimum_value_promise: self.minimum_value_promise.try_into().map_err(|_| {
    WalletStorageError::DecodingError {
        operation: "try_into_output",
        item: "minimum_value_promise",
        details: format!("Corrupt db: negative minimum_value_promise {}", self.minimum_value_promise),
    }
})?,

Also applies to: 85-85

applications/tari_validator_node/src/transaction_validators/signature.rs (1)

20-25: Replace transaction.to_id() with transaction.calculate_id().

In applications/tari_validator_node/src/transaction_validators/signature.rs (line 23), use calculate_id() to align with the rest of the codebase.

applications/tari_validator_node/src/p2p/services/mempool/service.rs (1)

239-244: Consider error variant naming consistency.

The check has_inputs() now triggers TransactionValidationError::NoInvolvedShards. While the change aligns with the broader refactor, the error name "NoInvolvedShards" may be less precise than "NoInputs" for describing the actual condition being checked.

Consider whether using a NoInputs variant (which exists at line 34 in error.rs) would be more semantically accurate than NoInvolvedShards for this check, or clarify the relationship between having no inputs and having no involved shards in the error documentation.

crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (2)

235-256: Avoid editing the initial migration; add a new migration for schema changes

Changing 2023-02-08-122514_initial/up.sql breaks upgrade paths for existing nodes. Even with the “delete data dir” note, keeping migration history append-only avoids confusion and accidental mixed states.

  • Create a new migration that adds minimum_value_promise BIGINT NOT NULL to stealth_outputs.
  • Leave the original initial migration untouched for clean history.

Please confirm whether operators actually need to wipe data. If not strictly required, ship a forward migration instead of modifying the initial file.


258-260: Add a composite index including account_id for common queries

Current index is on (resource_address, status). Wallet lookups typically filter by account + resource + status. Consider:

  • (owner_account_id, status) or
  • (owner_account_id, resource_address, status) as a covering index.

Apply this addition:

 CREATE UNIQUE INDEX stealth_outputs_uniq_resource_addr_commitment ON stealth_outputs (resource_address, commitment);
 CREATE INDEX stealth_outputs_idx_resource_status ON stealth_outputs (resource_address, status);
+CREATE INDEX stealth_outputs_idx_account_resource_status
+  ON stealth_outputs (owner_account_id, resource_address, status);
crates/wallet/sdk_services/src/account_monitor/monitor.rs (1)

137-156: AssociateResource flow looks good; trigger an immediate UTXO scan for the new resource

After successfully associating, kick off a scan so balances update without waiting for the next periodic cycle.

Apply after association:

     async fn associate_resource_with_account(
         &self,
         account_address: &ComponentAddress,
         resource_address: ResourceAddress,
     ) -> Result<(), AccountMonitorError> {
         let accounts_api = self.wallet_sdk.accounts_api();
         self.fetch_and_cache_resource(&resource_address).await?;
         accounts_api.associate_stealth_resource(account_address, resource_address)?;
+        // Optional: proactively scan the newly associated resource
+        self.utxo_scanner_handle.request_scan(*account_address, resource_address);
         Ok(())
     }

Confirm request_scan expects owned addresses (it appears to), and that this aligns with your UX expectations. Based on learnings (tari_template_lib prelude usage best practices).

Also applies to: 158-166

applications/tari_walletd/src/handlers/confidential.rs (1)

256-264: Output proof lacks resource view key; extend request to include resource address

resource_view_key: None is a TODO. Without it, verifiers lacking the resource view key cannot validate commitments consistently.

  • Add resource_address to ConfidentialCreateOutputProofRequest.
  • Fetch and pass the view key as in transfer proof:
    let vk = sdk.substate_api().fetch_resource(resource_address).await?.to_view_key_public_key()?;
  • Set resource_view_key: Some(vk).

I can submit a patch for the request/handler and TypeScript bindings if desired.

crates/transaction/src/transaction.rs (1)

179-181: Provide a deprecated alias for has_inputs()
Add a temporary deprecated alias for is_shard_applicable() to preserve upstream compatibility (internal search shows no remaining calls):

 pub fn has_inputs(&self) -> bool {
     !self.inputs().is_empty()
 }
 
 #[deprecated(note = "Use has_inputs(). This will be removed in a future release.")]
 pub fn is_shard_applicable(&self) -> bool {
     self.has_inputs()
 }
applications/tari_walletd/src/handlers/accounts.rs (1)

995-1002: Redundant lock release is safe but could be clearer.

The dry-run flow releases the lock immediately at line 996, then attempts to release it again on error at line 1009. The second release will only succeed if the first failed, making it a safe but redundant fallback.

Consider tracking whether the first release succeeded to avoid the redundant attempt, or add a comment explaining the fallback pattern:

// Release the lock immediately as dry run does not submit the transaction
// If release fails here, we'll attempt again on error
if let Err(err) = sdk.stealth_outputs_api().release_lock(transfer.lock_id) {
    error!(/* ... */);
}

Also applies to: 1009-1009

crates/wallet/crypto/src/balance_proof.rs (2)

4-4: Unify RNG import to avoid rand_core trait mismatches.

Using OsRng re-exported from other crates can lead to trait conflicts. Prefer rand_core::OsRng across the workspace.

Apply this diff:

- use chacha20poly1305::aead::OsRng;
+ use rand_core::OsRng;

34-35: Avoid bare unwraps on signature generation.

Replace unwrap with expect(...) for debugging context or handle errors if feasible.

Example:

- let sig = EngineSchnorrSignature::sign_raw_uniform(&secret_excess, nonce, &message).unwrap();
+ let sig = EngineSchnorrSignature::sign_raw_uniform(&secret_excess, nonce, &message)
+     .expect("sign_raw_uniform failed for confidential balance proof");

Similarly for other unwraps in this file.

Also applies to: 49-50, 59-61

crates/wallet/crypto/src/stealth.rs (1)

81-86: Eliminate unnecessary clones and duplicate statement construction.

Reuse inputs_statement instead of cloning inputs_to_spend and reconstructing later.

Apply this diff:

- let agg_output_mask = output_statements
-     .clone()
-     .into_iter()
-     .map(|stmt| &stmt.witness.mask)
-     .fold(RistrettoSecretKey::default(), |agg, mask| agg + mask);
+ let agg_output_mask = output_statements
+     .clone()
+     .into_iter()
+     .map(|stmt| &stmt.witness.mask)
+     .fold(RistrettoSecretKey::default(), |agg, mask| agg + mask);

- let inputs_statement = StealthInputsStatement {
-     inputs: inputs_to_spend.clone(),
-     revealed_amount: revealed_input_amount,
- };
+ let inputs_statement = StealthInputsStatement {
+     inputs: inputs_to_spend.clone(),
+     revealed_amount: revealed_input_amount,
+ };

  let outputs_statement = create_outputs_statement(output_statements, revealed_output_amount)?;
  let balance_proof = generate_stealth_balance_proof_signature(
      &agg_input_mask,
      &agg_output_mask,
      &inputs_statement,
      &outputs_statement,
  );

- Ok(StealthTransferStatement {
-     inputs_statement: StealthInputsStatement {
-         inputs: inputs_to_spend,
-         revealed_amount: revealed_input_amount,
-     },
-     outputs_statement,
-     balance_proof,
- })
+ Ok(StealthTransferStatement {
+     inputs_statement,
+     outputs_statement,
+     balance_proof,
+ })

Also applies to: 87-92, 100-107

crates/wallet/sdk/src/apis/stealth_outputs.rs (2)

4-4: Use rand_core::OsRng to avoid trait version conflicts.

Importing OsRng via digest::crypto_common can mismatch trait versions with tari_crypto.

Apply this diff:

- use digest::crypto_common::rand_core::OsRng;
+ use rand_core::OsRng;

221-231: Deduplicate lock_revealed_funds and lock_funds_in_vault.

Both perform the same action. Keep one API to reduce surface area and confusion.

Also applies to: 179-188

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a343c57 and ea592b6.

📒 Files selected for processing (48)
  • applications/tari_indexer/src/network_client.rs (1 hunks)
  • applications/tari_swarm_daemon/src/process_definitions/wallet_daemon_create_key.rs (0 hunks)
  • applications/tari_validator_node/src/p2p/services/mempool/service.rs (1 hunks)
  • applications/tari_validator_node/src/transaction_validators/error.rs (1 hunks)
  • applications/tari_validator_node/src/transaction_validators/is_shard_applicable.rs (1 hunks)
  • applications/tari_validator_node/src/transaction_validators/signature.rs (2 hunks)
  • applications/tari_walletd/src/handlers/accounts.rs (7 hunks)
  • applications/tari_walletd/src/handlers/confidential.rs (4 hunks)
  • applications/tari_walletd/src/lib.rs (1 hunks)
  • applications/tari_walletd/src/main.rs (1 hunks)
  • applications/tari_walletd/web_ui/src/routes/AssetVault/NFTs/components/SendNft.tsx (2 hunks)
  • applications/tari_walletd/web_ui/src/routes/AssetVault/Tokens/components/SendMoney.tsx (1 hunks)
  • applications/tari_walletd/web_ui/src/routes/Manifest/Manifest.tsx (1 hunks)
  • crates/engine_types/src/crypto/messages.rs (2 hunks)
  • crates/engine_types/src/crypto/utxo_spend.rs (1 hunks)
  • crates/engine_types/src/hashing.rs (2 hunks)
  • crates/engine_types/src/stealth/transfer.rs (1 hunks)
  • crates/template_lib/src/models/stealth.rs (0 hunks)
  • crates/template_test_tooling/src/support/confidential.rs (4 hunks)
  • crates/template_test_tooling/src/support/stealth.rs (6 hunks)
  • crates/transaction/src/transaction.rs (1 hunks)
  • crates/wallet/crypto/src/balance_proof.rs (2 hunks)
  • crates/wallet/crypto/src/bullet_proof.rs (1 hunks)
  • crates/wallet/crypto/src/confidential.rs (3 hunks)
  • crates/wallet/crypto/src/stealth.rs (8 hunks)
  • crates/wallet/crypto/src/unblinded_statement.rs (3 hunks)
  • crates/wallet/crypto/tests/output_statement.rs (5 hunks)
  • crates/wallet/crypto/tests/viewable_balance_proof.rs (1 hunks)
  • crates/wallet/sdk/src/apis/confidential_crypto.rs (3 hunks)
  • crates/wallet/sdk/src/apis/confidential_outputs.rs (2 hunks)
  • crates/wallet/sdk/src/apis/confidential_transfer.rs (3 hunks)
  • crates/wallet/sdk/src/apis/key_manager.rs (1 hunks)
  • crates/wallet/sdk/src/apis/stealth_crypto.rs (3 hunks)
  • crates/wallet/sdk/src/apis/stealth_outputs.rs (7 hunks)
  • crates/wallet/sdk/src/apis/stealth_transfer.rs (21 hunks)
  • crates/wallet/sdk/src/apis/transaction.rs (2 hunks)
  • crates/wallet/sdk/src/lib.rs (1 hunks)
  • crates/wallet/sdk/src/models/key.rs (1 hunks)
  • crates/wallet/sdk/src/models/stealth_output.rs (2 hunks)
  • crates/wallet/sdk/src/sdk.rs (3 hunks)
  • crates/wallet/sdk_services/src/account_monitor/handle.rs (3 hunks)
  • crates/wallet/sdk_services/src/account_monitor/monitor.rs (3 hunks)
  • crates/wallet/sdk_services/src/transaction_service/service.rs (1 hunks)
  • crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (1 hunks)
  • crates/wallet/storage_sqlite/src/models/stealth_output.rs (2 hunks)
  • crates/wallet/storage_sqlite/src/schema.rs (1 hunks)
  • crates/wallet/storage_sqlite/src/writer.rs (1 hunks)
  • utilities/tariswap_test_bench/src/runner.rs (1 hunks)
💤 Files with no reviewable changes (2)
  • crates/template_lib/src/models/stealth.rs
  • applications/tari_swarm_daemon/src/process_definitions/wallet_daemon_create_key.rs
🧰 Additional context used
🧬 Code graph analysis (23)
crates/wallet/sdk/src/models/stealth_output.rs (4)
bindings/src/types/PedersenCommitmentBytes.ts (1)
  • PedersenCommitmentBytes (6-6)
bindings/src/types/RistrettoPublicKeyBytes.ts (1)
  • RistrettoPublicKeyBytes (6-6)
bindings/src/types/EncryptedData.ts (1)
  • EncryptedData (7-7)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
applications/tari_validator_node/src/transaction_validators/error.rs (1)
bindings/src/types/TransactionId.ts (1)
  • TransactionId (3-3)
crates/engine_types/src/crypto/utxo_spend.rs (2)
crates/engine_types/src/crypto/messages.rs (1)
  • stealth_ownership64 (53-61)
crates/engine_types/src/byte_types.rs (5)
  • convert_from_byte_type (30-31)
  • convert_from_byte_type (62-64)
  • convert_from_byte_type (79-81)
  • convert_from_byte_type (101-105)
  • convert_from_byte_type (124-129)
crates/engine_types/src/stealth/transfer.rs (1)
crates/engine_types/src/crypto/messages.rs (1)
  • stealth_balance_proof64 (39-51)
crates/wallet/crypto/tests/viewable_balance_proof.rs (1)
crates/wallet/crypto/src/confidential.rs (1)
  • create_output_statement (74-136)
crates/template_test_tooling/src/support/confidential.rs (1)
crates/template_lib_types/src/encrypted_data.rs (1)
  • min_size (26-28)
crates/wallet/crypto/src/unblinded_statement.rs (1)
crates/engine_types/src/crypto/helpers.rs (1)
  • commit_amount_checked (68-71)
applications/tari_walletd/src/handlers/accounts.rs (3)
crates/wallet/sdk/src/models/account.rs (3)
  • owner_key_id (33-35)
  • owner_key_id (91-93)
  • account (71-73)
crates/wallet/sdk/src/apis/confidential_transfer.rs (1)
  • transfer (212-426)
crates/wallet/sdk/src/apis/stealth_transfer.rs (1)
  • transfer (302-611)
applications/tari_validator_node/src/p2p/services/mempool/service.rs (2)
applications/tari_indexer/src/network_client.rs (1)
  • transaction (55-55)
crates/wallet/storage_sqlite/src/writer.rs (2)
  • transaction (359-362)
  • transaction (363-368)
crates/wallet/crypto/tests/output_statement.rs (1)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • mask (64-66)
crates/wallet/sdk_services/src/account_monitor/monitor.rs (4)
bindings/src/types/Resource.ts (1)
  • Resource (9-22)
bindings/src/types/ResourceAddress.ts (1)
  • ResourceAddress (6-6)
bindings/src/types/ComponentAddress.ts (1)
  • ComponentAddress (6-6)
crates/wallet/sdk/src/sdk.rs (1)
  • accounts_api (180-187)
crates/wallet/sdk/src/models/key.rs (1)
bindings/src/types/wallet-daemon-client/KeyId.ts (1)
  • KeyId (3-3)
crates/wallet/sdk/src/sdk.rs (2)
crates/wallet/sdk/src/apis/stealth_transfer.rs (1)
  • new (61-73)
crates/wallet/sdk/src/apis/config.rs (1)
  • new (18-23)
crates/wallet/sdk/src/lib.rs (1)
bindings/src/types/Network.ts (1)
  • Network (6-6)
crates/wallet/sdk_services/src/account_monitor/handle.rs (2)
bindings/src/types/ComponentAddress.ts (1)
  • ComponentAddress (6-6)
bindings/src/types/ResourceAddress.ts (1)
  • ResourceAddress (6-6)
crates/wallet/sdk/src/apis/key_manager.rs (1)
bindings/src/types/wallet-daemon-client/KeyBranch.ts (1)
  • KeyBranch (3-10)
crates/wallet/crypto/src/stealth.rs (4)
crates/engine_types/src/stealth/outputs.rs (1)
  • stmt (43-82)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • mask (64-66)
crates/wallet/crypto/src/balance_proof.rs (1)
  • generate_stealth_balance_proof_signature (38-51)
crates/wallet/crypto/src/bullet_proof.rs (1)
  • generate_extended_bullet_proof (20-73)
crates/wallet/sdk_services/src/transaction_service/service.rs (1)
crates/wallet/sdk/src/sdk.rs (1)
  • transaction_api (172-174)
crates/wallet/crypto/src/balance_proof.rs (7)
bindings/src/types/StealthInputsStatement.ts (1)
  • StealthInputsStatement (8-17)
bindings/src/types/StealthOutputsStatement.ts (1)
  • StealthOutputsStatement (9-24)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
bindings/src/types/PedersenCommitmentBytes.ts (1)
  • PedersenCommitmentBytes (6-6)
bindings/src/types/RistrettoPublicKeyBytes.ts (1)
  • RistrettoPublicKeyBytes (6-6)
bindings/src/types/SchnorrSignatureBytes.ts (1)
  • SchnorrSignatureBytes (5-5)
crates/engine_types/src/crypto/messages.rs (2)
  • stealth_balance_proof64 (39-51)
  • stealth_ownership64 (53-61)
crates/wallet/sdk/src/apis/stealth_transfer.rs (3)
crates/wallet/sdk/src/apis/stealth_outputs.rs (2)
  • params (676-688)
  • new (67-79)
crates/template_test_tooling/src/support/stealth.rs (1)
  • inputs (195-206)
crates/wallet/sdk/src/models/account.rs (3)
  • owner_key_id (33-35)
  • owner_key_id (91-93)
  • account (71-73)
crates/template_test_tooling/src/support/stealth.rs (2)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • mask (64-66)
crates/wallet/sdk/src/apis/stealth_outputs.rs (1)
  • outputs (692-692)
crates/engine_types/src/crypto/messages.rs (3)
bindings/src/types/StealthInputsStatement.ts (1)
  • StealthInputsStatement (8-17)
bindings/src/types/StealthOutputsStatement.ts (1)
  • StealthOutputsStatement (9-24)
crates/engine_types/src/hashing.rs (1)
  • engine_hasher64 (35-37)
crates/wallet/sdk/src/apis/stealth_outputs.rs (3)
crates/wallet/sdk/src/models/account.rs (4)
  • owner_key_id (33-35)
  • owner_key_id (91-93)
  • view_only_key_id (29-31)
  • view_only_key_id (87-89)
crates/ootle_address/src/ootle_address.rs (2)
  • network (40-42)
  • network (224-226)
crates/wallet/sdk/src/apis/stealth_crypto.rs (1)
  • generate_transfer_statement (48-73)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: test
  • GitHub Check: check stable
  • GitHub Check: check nightly
  • GitHub Check: clippy
  • GitHub Check: machete
🔇 Additional comments (56)
applications/tari_walletd/web_ui/src/routes/AssetVault/NFTs/components/SendNft.tsx (1)

209-210: Verify fee accuracy for NFT transfers and alignment with confidential transfer handling.

The fee buffer has been completely removed for NFT transfers in both estimateFeeWithTargetAccount and estimateFee (lines 209-210 and 234-235). However, in SendMoney.tsx (lines 205-209), a 100-unit buffer is still applied for Confidential resource types.

Confirm that:

  1. Backend fee estimation is now accurate enough for NFTs to avoid insufficient fee errors
  2. The difference in handling between NFT transfers (no buffer) and Confidential token transfers (buffer retained) is intentional and justified
applications/tari_walletd/web_ui/src/routes/Manifest/Manifest.tsx (1)

83-83: Confirm backend dry-run fee accuracy

  • The UI change in applications/tari_walletd/web_ui/src/routes/Manifest/Manifest.tsx L83 removes the 100n buffer from the fee estimate. Verify that the backend’s dry-run endpoint now returns sufficiently accurate fees to avoid transaction failures due to underpayment.
applications/tari_walletd/src/main.rs (1)

147-150: LGTM! Explicit panic provides clear error context.

The defensive expect call with a descriptive message is appropriate here. Since seed words are initialized immediately before this call (lines 140-146), a None result indicates a logic bug that should halt execution with a clear diagnostic.

crates/wallet/sdk/src/apis/key_manager.rs (1)

277-281: LGTM! Clean separation of index management and key derivation.

The refactored next_key method now properly delegates index advancement to next_derived_key_index before deriving the key. This separation of concerns improves maintainability and makes the key generation flow more explicit.

applications/tari_walletd/src/lib.rs (1)

76-88: Verify all downstream account key usages handle lazy initialization. The removal of get_or_create_initial(KeyBranch::Account) can leave owner_key_id unset, causing calls like get_account_owner_key (e.g., in handlers/nfts.rs, handlers/transaction.rs) to panic or error. Ensure each path initializes or derives the account key before use.

crates/engine_types/src/hashing.rs (1)

129-129: LGTM!

The domain label renaming from StealthTransfer to StealthBalanceProof is consistent between the enum variant and its string representation. This aligns with the broader balance-proof refactor described in the PR objectives.

Also applies to: 156-156

utilities/tariswap_test_bench/src/runner.rs (1)

52-52: LGTM!

The removal of .await correctly reflects the API change where insert_new_transaction was converted from async to sync. The error propagation with ? is appropriate for the new synchronous signature.

crates/wallet/storage_sqlite/src/writer.rs (1)

1128-1128: LGTM with existing limitation noted.

The cast from u64 to i64 follows the existing pattern in this file for persisting large numeric values (see similar casts with TODO comments at lines 736-741). While this could overflow for values exceeding i64::MAX, it's a known limitation already present in the codebase for handling amounts in SQLite.

crates/wallet/sdk_services/src/transaction_service/service.rs (1)

154-154: LGTM!

The removal of .await and formatting change correctly reflect the API refactor where insert_new_transaction became synchronous. The error propagation remains correct.

crates/wallet/sdk/src/apis/transaction.rs (2)

53-65: LGTM! Async removal aligns with synchronous storage operations.

The change from async fn to fn is appropriate since the implementation uses self.store.with_write_tx(), which appears to be a synchronous operation. The added documentation clearly describes the behavior and return semantics.


67-72: Well-documented async method.

The documentation clearly describes the submission behavior, status transitions, and return semantics. The method correctly remains async as it performs network operations.

crates/wallet/storage_sqlite/src/schema.rs (1)

164-164: LGTM! Schema change aligns with PR objectives.

The addition of minimum_value_promise column to the stealth_outputs table is consistent with the PR's goal to add minimum value promise tracking. As noted in the PR objectives, this requires the data directory to be deleted, which is expected for a breaking schema change.

applications/tari_indexer/src/network_client.rs (1)

41-43: LGTM! Pre-check condition aligned with input validation.

The change from is_shard_applicable() to has_inputs() provides a more direct validation of the transaction's input presence. The error NoInputsProvided accurately reflects the check being performed.

crates/engine_types/src/stealth/transfer.rs (1)

116-121: LGTM! Enhanced security through statement-based message construction.

The change to use stealth_balance_proof64 with complete inputs_statement and outputs_statement (instead of individual revealed amounts) strengthens the balance proof by preventing potential output malleability, as stated in the PR objectives. This is a well-considered cryptographic improvement.

crates/engine_types/src/crypto/utxo_spend.rs (2)

25-25: LGTM! Simplified ownership message construction.

The message construction now uses stealth_ownership64(&input.commitment, &utxo.output.public_nonce), which is a cleaner approach consistent with the broader cryptographic refactor in this PR.


32-36: Signature verification method is correct
.verify invokes the domain-aware Verifiable trait for ownership proofs (used elsewhere for knowledge proofs), whereas verify_raw_uniform is reserved for balance proofs. The 64-byte message array auto-borrows to &[u8], matching fn verify(&self, …, message: &[u8]).

crates/template_test_tooling/src/support/confidential.rs (5)

11-11: LGTM! Type import updated to use Witness pattern.

The import change from UnblindedOutputStatement to UnblindedOutputWitness aligns with the broader refactor to use Witness-based types throughout the codebase.


38-45: LGTM! Witness construction with appropriate test values.

The UnblindedOutputWitness is correctly constructed with all required fields. The use of default/zero values for sender_public_nonce, minimum_value_promise, and minimal encrypted_data is appropriate for test scaffolding.


48-55: LGTM! Change statement construction mirrors output pattern.

The change statement construction follows the same pattern as the output statement, ensuring consistency in the test tooling.


152-159: LGTM! Withdraw proof output witness construction.

The output witness construction in the withdraw proof follows the established pattern with appropriate test values.


160-167: LGTM! Withdraw proof change witness construction.

The change witness construction in the withdraw proof is consistent with the output witness pattern.

applications/tari_validator_node/src/transaction_validators/error.rs (1)

39-40: LGTM! Clear error variant for missing signer.

The new NoMainSigner error variant provides clear semantics and includes the transaction_id for debugging. This supports the enhanced signature validation introduced in this PR.

crates/wallet/sdk_services/src/account_monitor/handle.rs (2)

16-20: LGTM!

The new AssociateResource variant follows the established request/response pattern consistently with the existing RefreshAccount variant.


57-72: LGTM!

The associate_resource method correctly implements the request/response pattern, matching the structure and error handling of the existing methods.

crates/wallet/crypto/src/bullet_proof.rs (1)

18-22: LGTM!

The type rename from UnblindedOutputStatement to UnblindedOutputWitness is a straightforward refactor. The function logic remains unchanged and continues to access the same struct fields (mask, amount, minimum_value_promise).

crates/wallet/sdk/src/apis/confidential_transfer.rs (1)

13-13: LGTM!

The type rename from UnblindedOutputStatement to UnblindedOutputWitness is consistent with the broader refactoring effort. The method logic and field assignments remain unchanged.

Also applies to: 428-468

crates/wallet/crypto/tests/viewable_balance_proof.rs (1)

12-12: LGTM!

The test helper has been correctly updated to use UnblindedOutputWitness instead of UnblindedOutputStatement. The field assignments remain consistent with the previous structure.

Also applies to: 19-29

crates/wallet/sdk/src/apis/confidential_outputs.rs (2)

144-150: LGTM!

The release_revealed_funds method correctly follows the established transaction pattern: create write transaction, perform the operation, and commit.


160-166: LGTM!

The finalize_locked_revealed_funds method correctly follows the established transaction pattern, consistent with similar methods in this API.

crates/wallet/sdk/src/apis/stealth_crypto.rs (1)

19-22: LGTM!

The type renames from UnblindedOutputStatement, UnblindedStealthInputStatement, and UnblindedStealthOutputStatement to their Witness counterparts are straightforward refactors. The method implementations remain unchanged and correctly delegate to the underlying crypto functions.

Also applies to: 48-73, 116-128

crates/wallet/sdk/src/sdk.rs (4)

72-83: LGTM!

The network validation logic correctly prevents database/config network mismatches by:

  1. Reading the stored network (if present)
  2. Validating it matches the config network
  3. Initializing the stored network if absent

This ensures consistency but note that existing wallets without a stored network will have one written automatically.


93-97: LGTM!

The new get_store_network helper method correctly retrieves the network from storage and returns None if not found, following the .optional() pattern used elsewhere in the codebase.


217-222: Verify StealthTransferApi constructor signature matches.

The StealthTransferApi::new call was updated to remove key_manager_api and stealth_crypto_api parameters. Ensure the constructor signature in crates/wallet/sdk/src/apis/stealth_transfer.rs matches this usage.

Based on the relevant code snippet from crates/wallet/sdk/src/apis/stealth_transfer.rs (lines 60-72), the constructor signature appears correct and matches the call site.


288-293: LGTM!

The change to return Option<SeedWords> instead of requiring a seed to exist is a good improvement. The implementation correctly uses map and transpose to convert from Option<&CipherSeed> to Result<Option<SeedWords>>.

crates/wallet/crypto/tests/output_statement.rs (2)

15-17: LGTM!

The test helper make_input_statements has been correctly updated to construct and return Vec<UnblindedStealthInputWitness> instead of the previous Statement type. The field assignments remain consistent.

Also applies to: 92-104


106-139: LGTM!

The test helper make_output_statements has been correctly updated to use the new Witness types. Note the structural change at lines 119-136 where UnblindedStealthOutputWitness now contains a nested witness field of type UnblindedOutputWitness, reflecting the new witness-based structure.

crates/wallet/crypto/src/confidential.rs (1)

17-17: LGTM! Type rename is consistent.

The rename from UnblindedOutputStatement to UnblindedOutputWitness aligns with the broader refactor across the codebase to use Witness-based structures.

Also applies to: 24-26, 75-77

crates/wallet/sdk/src/apis/confidential_crypto.rs (1)

14-14: LGTM! Public API updated consistently.

The public API signatures are correctly updated to use UnblindedOutputWitness, maintaining consistency with the internal implementation changes.

Also applies to: 42-44, 93-93

crates/wallet/crypto/src/unblinded_statement.rs (2)

11-18: LGTM! Structural changes align with PR objectives.

The addition of minimum_value_promise and encrypted_data fields to UnblindedOutputWitness supports the PR's goal of adding minimum value promise tracking to stealth outputs. The rename from Statement to Witness clarifies the semantic role of these structures.


27-31: LGTM! Field rename improves semantic clarity.

The field rename from statement to witness in UnblindedStealthOutputWitness better reflects the nature of this data structure as witness information for outputs.

applications/tari_walletd/src/handlers/accounts.rs (4)

949-954: Verify necessity of early owner_key_id requirement.

The handler requires owner_key_id to be present upfront, but the signing logic (lines 977-984) may use a throwaway nonce instead of the account key when there are no revealed amounts. This creates a situation where an owner key is required but might not be used.

Consider clarifying the design intent: Is the owner_key_id required for account creation/validation purposes even if stealth transfers with no revealed amounts don't need it for signing?

Based on the relevant code snippet from crates/wallet/sdk/src/apis/stealth_transfer.rs, the transfer API also validates owner_key_id presence, so this appears to be an intentional API constraint.


977-990: LGTM! Signing logic correctly handles revealed vs. fully confidential transfers.

The conditional signing approach is correct:

  • For transfers with revealed amounts (fee or transfer inputs), the account owner key is required for authorization.
  • For fully confidential stealth transfers with no revealed amounts, a throwaway nonce suffices as no account-level authorization is needed.

1022-1024: LGTM! Transaction ID association improves lock tracking.

Associating the lock with the transaction ID before submission enables proper cleanup if the transaction fails or is aborted later.


1070-1073: LGTM! Resource association delegated to account monitor.

The change from local cache population to delegating resource association to the account monitor improves separation of concerns and ensures consistent state management.

crates/template_test_tooling/src/support/stealth.rs (1)

16-18: LGTM! Test tooling updated consistently with Witness refactor.

All type imports, construction sites, and field access patterns are correctly updated to use the new Witness-based structures and the renamed witness field (previously statement).

Also applies to: 89-100, 177-191, 199-199, 217-217

crates/engine_types/src/crypto/messages.rs (2)

39-51: LGTM! Balance proof signature improved for anti-malleability.

The changes to include full StealthInputsStatement and StealthOutputsStatement objects in the balance proof signature (instead of just amounts) align with the PR objective to prevent potential output malleability. This provides cryptographic binding to the complete input/output structure, not just the amounts.

The function rename to stealth_balance_proof64 and domain label update to StealthBalanceProof improve semantic clarity.


53-61: Verify security implications of reduced signature.

The stealth_ownership64 signature was reduced from including (public_key, public_nonce, commitment, public_output_nonce) to only (commitment, public_output_nonce). Removing the public key and nonce from the message preimage changes the cryptographic binding.

Verify that the ownership proof remains secure with the reduced signature. Specifically:

  1. Does the proof still adequately bind the owner to the commitment?
  2. Could removing these fields enable any malleability or replay attacks?
  3. Was this change intentional as part of the signature refactor?

Given that the PR description mentions security improvements and manual testing was performed, this is likely intentional, but explicit verification would provide confidence.

crates/wallet/crypto/src/balance_proof.rs (3)

47-50: Correct switch to the new domain-separated message (stealth_balance_proof64).

Message includes public_excess, public_nonce, and both statements; aligns with engine_types/messages.rs.


58-60: Owner proof message domain updated and signing path looks correct.

Using stealth_ownership64(commitment, public_output_nonce) with EngineSchnorrSignature::sign is consistent with engine message format.


44-51: Zero secret_excess behavior — verify intent.

If agg_input_mask == agg_output_mask, secret_excess == 0. Do we require a non-zero signature (vs. zero/empty proof) in the stealth case? Confirm engine validation expectations.

crates/wallet/crypto/src/stealth.rs (1)

110-153: Outputs statement from witnesses looks solid.

Range proof aggregation and viewable balance proof construction align with witness fields and engine validators.

crates/wallet/sdk/src/apis/stealth_transfer.rs (2)

432-462: Fee change calculation and balancing — looks consistent with statement validation.

fee_stealth_change_amt = stealth_inputs - max_fee, and the revealed component is balanced via input_revealed_amount/output_revealed_amount.


596-603: Consider linking locks to the transaction id once available.

To aid recovery/observability, call outputs_api.locks_set_transaction_id(lock_id, tx_id) when you have a stable id (signed or unsigned if available).

Do we have an UnsignedTransaction id accessor, or is this only available post-signing? If post-signing, ensure the caller updates the lock with the final TransactionId.

crates/wallet/sdk/src/apis/stealth_outputs.rs (3)

195-202: release_lock now also releases vault locks — good.

This avoids stranded revealed-funds locks when releasing stealth UTXO locks.


604-665: Output witness creation flow looks right.

Key derivation, encryption, tag derivation, and owner public key generation align with the witness model.


667-710: Transfer statement generation performs a strict balance check — good guardrail.

Witness resolution and statement creation integrate cleanly with the crypto API.

@github-actions

Copy link
Copy Markdown

Test Results (CI)

472 tests  +27   464 ✅ +19   1h 38m 13s ⏱️ + 47m 2s
 78 suites +15     0 💤 ± 0 
  2 files   + 1     8 ❌ + 8 

For more details on these failures, see this check.

Results for commit ea592b6. ± Comparison against base commit a343c57.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants