Skip to content

fix(wallet)!: improved input selection algo - #1637

Merged
sdbondi merged 2 commits into
tari-project:developmentfrom
sdbondi:wallet-input-selection-strategies
Nov 10, 2025
Merged

fix(wallet)!: improved input selection algo#1637
sdbondi merged 2 commits into
tari-project:developmentfrom
sdbondi:wallet-input-selection-strategies

Conversation

@sdbondi

@sdbondi sdbondi commented Nov 10, 2025

Copy link
Copy Markdown
Member

Description

feat: implement a simplified branch-and-bound algorithm for spend input selection.
fix: use u64 for all single utxo values, and Amount for when the upper bound exceeds u64::MAX (e.g sum of funds)
fix: account for and respect the upper input limit (currently 1000)

Motivation and Context

Branch-and-Bound is potentially very good at minimising waste, change & fragmentation when selecting inputs. This is a simplified version of what is used in Bitcoin Core. The simplifications are due to not accounting for input weight (since all inputs have equal weights) and target fees.

The input limit is not respected.

How Has This Been Tested?

New unit tests, partially manually although not with a wallet that has many thousands of UTXOs to spend

What process can a PR reviewer use to test or verify this change?

Breaking Changes

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

Summary by CodeRabbit

  • New Features

    • Added branch-and-bound input selection for improved transaction input selection.
    • Stealth outputs now expose richer output info for spending and selection.
  • Bug Fixes

    • Improved handling and filtering of zero/positive confidential outputs and related proof flows.
  • Breaking Changes

    • Proof/transfer payloads renamed/typed (amount → confidential_amount) and several blinded/confidential amount fields changed to primitive integer/bigint types.
    • Removed a wallet-daemon RPC method previously exposing a pay-ref address.

@coderabbitai

coderabbitai Bot commented Nov 10, 2025

Copy link
Copy Markdown
Contributor

Walkthrough

Refactors numeric amount types across the wallet codebase: replaces Amount wrappers with primitive u64/bigint in APIs, storage, crypto and tests; introduces a branch-and-bound input selection module; updates storage schema and batch locking APIs; and removes one ApplicationErrorCode variant.

Changes

Cohort / File(s) Summary
Wallet CLI & Proof Generation
applications/tari_wallet_cli/src/command/proof.rs
GenerateArgs.amount changed from i64 to u64; removed numeric conversion when building proof request.
Wallet Daemon Handlers
applications/tari_walletd/src/handlers/accounts.rs, applications/tari_walletd/src/handlers/confidential.rs, applications/tari_walletd/src/handlers/stealth_utxos.rs
Replaced Amount-based checks with u64/Amount conversions where appropriate; switched filters from is_positive()/is_zero() to > 0/== 0; adjusted fee/change arithmetic and encryption call sites.
JRPC Server
applications/tari_walletd/src/jrpc_server.rs
Removed NotImplemented = 501 variant from ApplicationErrorCode.
Web UI & TypeScript Bindings
applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts, bindings/src/types/wallet-daemon-client/...
Changed several fields from Amount to bigint and renamed amountconfidential_amount in ProofsGenerateRequest. Removed an unused Amount import.
JavaScript Client
clients/javascript/wallet_daemon_client/src/index.ts
Removed accountsGetPayRefAddress public API and its type imports.
Rust Wallet Daemon Client Types
clients/wallet_daemon_client/src/types.rs
ProofsGenerateRequest.amountconfidential_amount: Amount; ConfidentialCreateOutputProofRequest.amountu64; StealthTransfer.blinded_output_amountu64.
Commitments & Crypto Helpers
crates/engine_types/src/crypto/helpers.rs, crates/wallet/crypto/*
Added commit_u64_amount(mask, u64); replaced many commit_amount_checked/Option paths with direct u64-based commitments; adjusted related APIs to accept u64.
Unblinded / Encrypted Types
crates/wallet/crypto/src/unblinded_statement.rs, crates/wallet/crypto/src/encrypted_data.rs
MaskAndValue.value, UnblindedOutputWitness.amount, and decrypted value APIs changed to u64; to_commitment() now returns PedersenCommitment (not Option); constructors updated accordingly.
Amount Core Library
crates/template_lib_types/src/amount/amount.rs
sum_from_positive made generic over Into<Self>; saturating_sub_positive returns Self (saturates to zero); saturating_mul signature updated; internal checked_sub logic adjusted; tests extended.
Test Tooling & Tests
crates/template_test_tooling/src/support/*, crates/engine/tests/*, crates/wallet/crypto/tests/*
Many test helpers changed from Into<Amount> generics to u64 arguments; call sites updated to pass literals; filtering and mask logic adapted for u64.
Input Selection (new)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs, .../mod.rs, .../mod.rs
New branch-and-bound selection module with KeyedInput<K>, SelectionResult, and select(...); added InputSelectionAlgorithm enum (SmallestFirst, BranchAndBound).
Stealth Output Models & APIs
crates/wallet/sdk/src/models/stealth_output.rs, .../apis/stealth_outputs.rs
StealthOutputModel.value and InputSpendData.valueu64; new StealthOutputInfo (includes encrypted_data, value: u64); APIs updated to return StealthOutputInfo and InputSpendData; added input selection support and InputSelectionFailed error.
Confidential & Stealth Transfer APIs
crates/wallet/sdk/src/apis/*
Updated amount fields and filters to use u64/Amount conversions; added encrypted_data propagation to confidential outputs; many is_positive()/is_zero()> 0/== 0.
Storage Reader & Writer (SDK)
crates/wallet/sdk/src/storage/reader.rs, .../writer.rs
stealth_outputs_get_unspent_by_account now accepts optional resource_address and returns StealthOutputInfo; added stealth_outputs_get_unspent_for_spending; added stealth_outputs_lock_many to writer trait.
SQLite Storage & Migrations
crates/wallet/storage_sqlite/*
Migration changed stealth_outputs.value column from TEXT → BIGINT; model StealthOutput.value String → i64; implemented TryFrom<StealthOutput> for StealthOutputInfo; added batch lock implementation.
Wallet SDK Cargo / TS features
crates/transaction/Cargo.toml, crates/wallet/sdk/Cargo.toml
Removed tari_bor dev-dep; expanded ts feature to include additional crates for TypeScript bindings.
Integration & Utilities
integration_tests/*, utilities/traffic-sim/src/sim.rs
transfer_stealth parameter changed to u64; call sites updated to pass raw values (removed .into()).

Sequence Diagram(s)

sequenceDiagram
    participant CLI as Wallet CLI
    participant Handler as Proof Handler
    participant Crypto as Crypto Module

    Note over CLI,Handler: Proof generation type change
    CLI->>Handler: GenerateArgs { amount: u64 }
    Handler->>Crypto: create_confidential_output_proof(ConfidentialCreateOutputProofRequest{ amount: u64 })
    Crypto->>Handler: ConfidentialOutputProof
Loading
sequenceDiagram
    participant API as Stealth Output API
    participant Storage as Wallet Storage
    participant Selector as Input Selection

    Note over API,Selector: New input selection flow
    API->>Storage: stealth_outputs_get_unspent_by_account(...)
    Storage->>API: Vec<StealthOutputInfo (u64 values)>
    API->>Selector: select(inputs, target, BranchAndBound, max_inputs)
    Selector->>API: SelectionResult { total_value: Amount, selected_keys }
    API->>Storage: stealth_outputs_lock_many(resource_addr, selected_commitments, lock_id)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Areas requiring extra attention:

  • Type transition surface (Amount ↔ u64/bigint): verify all conversions, overflow checks, and invariants (to_u64_checked) are correct and consistent.
  • Commitment API changes: to_commitment() now returns direct commitments; ensure no invalid/negative amounts can reach these paths.
  • Branch-and-bound algorithm: validate correctness, pruning, and max_inputs handling; review tests and edge cases.
  • Storage migration and TryFrom conversions: confirm migration safety and correct field mappings (value, encrypted_data, commitments).
  • Public API changes: ensure all callers (bindings, JS client, web UI, integration tests) updated to new signatures.

Possibly related PRs

Poem

🐇 I hopped through types from Amount to u64,

Commitments now direct, no Option door,
Branch-and-bound digs for inputs with care,
BigInt in storage, locks batch-locked to share,
Tiny rabbit cheers — changes land on the floor!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.65% 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 PR title 'fix(wallet)!: improved input selection algo' clearly describes the main change—implementation of an improved input selection algorithm for the wallet with a breaking change indicator (!), which aligns with significant type and API updates throughout the codebase.
✨ 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.

@sdbondi
sdbondi force-pushed the wallet-input-selection-strategies branch 2 times, most recently from 7fbce02 to 86e0a62 Compare November 10, 2025 06:50
@sdbondi
sdbondi force-pushed the wallet-input-selection-strategies branch from 86e0a62 to 4376262 Compare November 10, 2025 07:01
@sdbondi
sdbondi marked this pull request as ready for review November 10, 2025 07:09

@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: 7

Caution

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

⚠️ Outside diff range comments (1)
clients/wallet_daemon_client/src/types.rs (1)

493-500: Annotate confidential_amount as bigint for generated TS bindings.

bindings/src/types/ProofsGenerateRequest.ts now emits confidential_amount: bigint, but ts-rs still defaults u64 to number, so downstream TypeScript consumers will see a mismatched type and break at compile/runtime. Please override the generated type to keep the Rust and TS views in sync.

 #[cfg_attr(feature = "ts", derive(ts_rs::TS), ts(export, export_to = "wallet-daemon-client/"))]
 pub struct ProofsGenerateRequest {
+    #[cfg_attr(feature = "ts", ts(type = "bigint"))]
     pub confidential_amount: u64,
🧹 Nitpick comments (3)
crates/wallet/sdk/src/models/input_selection/mod.rs (1)

1-12: LGTM! New input selection module introduced.

The new InputSelectionAlgorithm enum provides configurable input selection strategies as described in the PR objectives. The enum is well-structured with clear variant names and appropriate derives.

For future enhancement, consider adding doc comments explaining when to use each algorithm variant (e.g., "BranchAndBound minimizes waste and fragmentation but may be slower for large UTXO sets").

crates/engine_types/src/crypto/helpers.rs (1)

73-76: LGTM! New u64 commitment helper added.

The commit_u64_amount function provides a clean API for committing u64 amounts directly, complementing the existing commit_amount functions. This aligns well with the PR's migration to native u64 types.

Consider adding documentation similar to the existing commit_amount function to maintain consistency:

+/// Creates a Pedersen commitment to the given u64 amount using the provided mask.
 pub fn commit_u64_amount(mask: &RistrettoSecretKey, amount: u64) -> PedersenCommitment {
     get_commitment_factory().commit_value(mask, amount)
 }
crates/wallet/storage_sqlite/src/writer.rs (1)

1259-1294: Consider adding lock validation for consistency.

The new stealth_outputs_lock_many method correctly implements batch locking with proper error handling. However, it doesn't validate that the lock_id exists, unlike stealth_outputs_lock_smallest_amount (line 1209) which calls self.ensure_lock_exists(lock_id).

For consistency with the existing stealth_outputs_lock_smallest_amount method, consider adding lock validation at the beginning:

 fn stealth_outputs_lock_many(
     &mut self,
     resource_address: &ResourceAddress,
     utxos: &[&PedersenCommitmentBytes],
     lock_id: WalletLockId,
 ) -> Result<(), WalletStorageError> {
     const OPERATION: &str = "stealth_outputs_lock_many";
     use crate::schema::stealth_outputs;
+
+    self.ensure_lock_exists(lock_id)?;

     let num_rows = diesel::update(stealth_outputs::table)

This ensures the lock exists before attempting to lock outputs, providing better error messages if an invalid lock_id is used.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9d105c3 and 4376262.

📒 Files selected for processing (52)
  • applications/tari_wallet_cli/src/command/proof.rs (2 hunks)
  • applications/tari_walletd/src/handlers/accounts.rs (5 hunks)
  • applications/tari_walletd/src/handlers/confidential.rs (7 hunks)
  • applications/tari_walletd/src/handlers/stealth_utxos.rs (1 hunks)
  • applications/tari_walletd/src/jrpc_server.rs (0 hunks)
  • applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (1 hunks)
  • bindings/src/types/wallet-daemon-client/ConfidentialCreateOutputProofRequest.ts (1 hunks)
  • bindings/src/types/wallet-daemon-client/ProofsGenerateRequest.ts (1 hunks)
  • bindings/src/types/wallet-daemon-client/StealthTransfer.ts (1 hunks)
  • bindings/src/types/wallet-daemon-client/TransferOutput.ts (1 hunks)
  • clients/javascript/wallet_daemon_client/src/index.ts (1 hunks)
  • clients/wallet_daemon_client/src/types.rs (4 hunks)
  • crates/engine/tests/burn.rs (1 hunks)
  • crates/engine/tests/confidential.rs (2 hunks)
  • crates/engine/tests/recall.rs (1 hunks)
  • crates/engine/tests/stealth.rs (12 hunks)
  • crates/engine_types/src/crypto/helpers.rs (1 hunks)
  • crates/template_lib_types/src/amount/amount.rs (5 hunks)
  • crates/template_test_tooling/src/support/confidential.rs (3 hunks)
  • crates/template_test_tooling/src/support/stealth.rs (6 hunks)
  • crates/transaction/Cargo.toml (1 hunks)
  • crates/wallet/crypto/src/bullet_proof.rs (1 hunks)
  • crates/wallet/crypto/src/confidential.rs (6 hunks)
  • crates/wallet/crypto/src/encrypted_data.rs (2 hunks)
  • crates/wallet/crypto/src/stealth.rs (4 hunks)
  • crates/wallet/crypto/src/unblinded_statement.rs (5 hunks)
  • crates/wallet/crypto/src/viewable_balance_proof.rs (1 hunks)
  • crates/wallet/crypto/tests/stealth_transfer_statement.rs (1 hunks)
  • crates/wallet/crypto/tests/viewable_balance_proof.rs (4 hunks)
  • crates/wallet/sdk/Cargo.toml (1 hunks)
  • crates/wallet/sdk/src/apis/confidential_crypto.rs (1 hunks)
  • crates/wallet/sdk/src/apis/confidential_outputs.rs (1 hunks)
  • crates/wallet/sdk/src/apis/confidential_transfer.rs (5 hunks)
  • crates/wallet/sdk/src/apis/stealth_crypto.rs (1 hunks)
  • crates/wallet/sdk/src/apis/stealth_outputs.rs (10 hunks)
  • crates/wallet/sdk/src/apis/stealth_transfer/api.rs (10 hunks)
  • crates/wallet/sdk/src/apis/stealth_transfer/params.rs (3 hunks)
  • crates/wallet/sdk/src/apis/stealth_transfer/types.rs (2 hunks)
  • crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1 hunks)
  • crates/wallet/sdk/src/models/input_selection/mod.rs (1 hunks)
  • crates/wallet/sdk/src/models/mod.rs (1 hunks)
  • crates/wallet/sdk/src/models/stealth_output.rs (2 hunks)
  • crates/wallet/sdk/src/storage/reader.rs (2 hunks)
  • crates/wallet/sdk/src/storage/writer.rs (2 hunks)
  • crates/wallet/storage_sqlite/migrations/2023-02-08-122514_initial/up.sql (1 hunks)
  • crates/wallet/storage_sqlite/src/models/stealth_output.rs (4 hunks)
  • crates/wallet/storage_sqlite/src/reader.rs (4 hunks)
  • crates/wallet/storage_sqlite/src/schema.rs (1 hunks)
  • crates/wallet/storage_sqlite/src/writer.rs (3 hunks)
  • integration_tests/src/wallet_daemon_client.rs (1 hunks)
  • integration_tests/tests/steps/wallet_daemon.rs (2 hunks)
  • utilities/traffic-sim/src/sim.rs (2 hunks)
💤 Files with no reviewable changes (1)
  • applications/tari_walletd/src/jrpc_server.rs
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1551
File: applications/tari_indexer/src/storage_sqlite/models/utxo.rs:68-0
Timestamp: 2025-08-26T06:41:43.682Z
Learning: In the Tari codebase, u64/u32 values are stored as i64/i32 in SQLite to satisfy database constraints. Since both types have the same bit width and the data comes from trusted local databases, casting from i64/i32 back to u64/u32 is safe and preserves the original unsigned values.
📚 Learning: 2025-11-04T10:10:24.258Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1629
File: applications/tari_walletd/src/handlers/accounts.rs:1001-1002
Timestamp: 2025-11-04T10:10:24.258Z
Learning: In applications/tari_walletd/src/handlers/accounts.rs, the expect() on Memo::new_pay_ref_and_bytes_truncate at line 1002 is safe and intentional. PayRef is validated to be at most 64 bytes during address decoding (PayRef::MAX_LEN = 64), and the function only returns None if payref exceeds 252 bytes (Memo::MAX_BYTES_LENGTH - 1). Since 64 < 252, None is impossible with a valid PayRef.

Applied to files:

  • applications/tari_walletd/src/handlers/accounts.rs
  • applications/tari_walletd/src/handlers/confidential.rs
  • crates/wallet/crypto/src/bullet_proof.rs
  • crates/wallet/sdk/src/apis/stealth_outputs.rs
📚 Learning: 2025-08-26T06:41:43.682Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1551
File: applications/tari_indexer/src/storage_sqlite/models/utxo.rs:68-0
Timestamp: 2025-08-26T06:41:43.682Z
Learning: In the Tari codebase, u64/u32 values are stored as i64/i32 in SQLite to satisfy database constraints. Since both types have the same bit width and the data comes from trusted local databases, casting from i64/i32 back to u64/u32 is safe and preserves the original unsigned values.

Applied to files:

  • crates/wallet/storage_sqlite/src/models/stealth_output.rs
🧬 Code graph analysis (35)
crates/engine/tests/stealth.rs (2)
crates/template_lib_types/src/amount/amount.rs (1)
  • try_from (433-435)
crates/wallet/sdk/src/apis/stealth_outputs.rs (1)
  • outputs (716-716)
applications/tari_wallet_cli/src/command/proof.rs (1)
bindings/src/types/wallet-daemon-client/ConfidentialCreateOutputProofRequest.ts (1)
  • ConfidentialCreateOutputProofRequest (3-3)
crates/wallet/storage_sqlite/src/schema.rs (4)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • value (60-62)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (1)
  • value (28-30)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1)
  • value (21-23)
bindings/src/helpers/BigAmount.ts (1)
  • value (21-23)
applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (2)
crates/wallet/sdk/src/apis/stealth_outputs.rs (1)
  • params (700-712)
crates/wallet/sdk/src/apis/stealth_transfer/api.rs (1)
  • params (523-527)
crates/wallet/crypto/tests/viewable_balance_proof.rs (6)
crates/wallet/crypto/src/confidential.rs (1)
  • create_output_statement (70-127)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • value (60-62)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (1)
  • value (28-30)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1)
  • value (21-23)
crates/p2p/src/conversions/transaction.rs (2)
  • value (836-840)
  • value (897-901)
crates/engine_types/src/resource.rs (1)
  • view_key (126-128)
crates/engine/tests/recall.rs (3)
crates/template_lib/src/resource/builder/confidential.rs (1)
  • initial_supply (236-243)
crates/template_lib/src/resource/builder/stealth.rs (1)
  • initial_supply (231-238)
crates/template_test_tooling/src/support/confidential.rs (1)
  • generate_confidential_output_statement (17-22)
integration_tests/tests/steps/wallet_daemon.rs (2)
crates/template_lib/src/models/bucket.rs (1)
  • amount (206-214)
crates/template_lib/src/models/proof.rs (1)
  • amount (104-112)
applications/tari_walletd/src/handlers/accounts.rs (2)
crates/wallet/sdk/src/models/stealth_output.rs (1)
  • from (71-79)
applications/tari_walletd/src/handlers/helpers.rs (1)
  • invalid_params (161-172)
crates/engine_types/src/crypto/helpers.rs (1)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • mask (64-66)
crates/wallet/crypto/src/stealth.rs (3)
crates/wallet/crypto/src/confidential.rs (1)
  • create_valid_proof (138-154)
bindings/src/types/StealthOutputsStatement.ts (1)
  • StealthOutputsStatement (9-24)
crates/engine_types/src/stealth/outputs.rs (1)
  • validate_stealth_outputs_statement (32-85)
clients/wallet_daemon_client/src/types.rs (1)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (2)
crates/template_lib_types/src/amount/amount.rs (2)
  • new (52-54)
  • zero (57-59)
crates/wallet/sdk/src/apis/stealth_outputs.rs (2)
  • new (73-85)
  • result (223-232)
crates/wallet/sdk/src/storage/reader.rs (2)
crates/wallet/sdk/src/apis/stealth_transfer/params.rs (1)
  • resource_address (154-161)
crates/wallet/storage_sqlite/src/reader.rs (1)
  • stealth_outputs_get_unspent_for_spending (960-995)
crates/wallet/sdk/src/models/stealth_output.rs (4)
bindings/src/types/ResourceAddress.ts (1)
  • ResourceAddress (6-6)
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)
crates/wallet/sdk/src/apis/stealth_transfer/params.rs (3)
bindings/src/types/wallet-daemon-client/TransferOutput.ts (1)
  • TransferOutput (6-24)
clients/wallet_daemon_client/src/types.rs (2)
  • total_output_amount (1077-1082)
  • from (918-926)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/wallet/storage_sqlite/src/models/stealth_output.rs (2)
crates/template_lib/src/models/vault.rs (1)
  • from_hex (77-80)
crates/template_lib_types/src/encrypted_data.rs (1)
  • len (39-41)
crates/wallet/storage_sqlite/src/writer.rs (3)
crates/wallet/sdk/src/storage/writer.rs (1)
  • stealth_outputs_lock_many (156-161)
applications/tari_walletd/src/handlers/accounts.rs (1)
  • stealth_outputs (294-298)
crates/wallet/storage_sqlite/src/reader.rs (6)
  • stealth_outputs (870-877)
  • stealth_outputs (902-914)
  • stealth_outputs (969-987)
  • stealth_outputs (1004-1006)
  • stealth_outputs (1040-1043)
  • dsl (872-872)
applications/tari_walletd/src/handlers/confidential.rs (2)
applications/tari_walletd/src/handlers/helpers.rs (1)
  • invalid_request (191-196)
crates/wallet/sdk/src/apis/confidential_transfer.rs (1)
  • confidential_amount (499-505)
crates/wallet/crypto/src/encrypted_data.rs (3)
crates/wallet/crypto/src/unblinded_statement.rs (2)
  • value (60-62)
  • mask (64-66)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (1)
  • value (28-30)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1)
  • value (21-23)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (2)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • value (60-62)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1)
  • value (21-23)
crates/wallet/sdk/src/storage/writer.rs (2)
bindings/src/types/PedersenCommitmentBytes.ts (1)
  • PedersenCommitmentBytes (6-6)
crates/wallet/storage_sqlite/src/writer.rs (1)
  • stealth_outputs_lock_many (1259-1294)
crates/engine/tests/confidential.rs (1)
crates/template_test_tooling/src/support/confidential.rs (1)
  • generate_confidential_output_statement (17-22)
crates/wallet/crypto/src/viewable_balance_proof.rs (3)
crates/engine_types/src/crypto/helpers.rs (1)
  • get_commitment_factory (50-52)
bindings/src/types/ViewableBalanceProof.ts (1)
  • ViewableBalanceProof (27-62)
bindings/src/types/Scalar32Bytes.ts (1)
  • Scalar32Bytes (3-3)
crates/wallet/crypto/src/bullet_proof.rs (1)
crates/engine_types/src/stealth/outputs.rs (1)
  • stmt (43-82)
crates/wallet/crypto/src/confidential.rs (3)
crates/engine_types/src/crypto/helpers.rs (1)
  • commit_u64_amount (74-76)
crates/wallet/crypto/src/stealth.rs (1)
  • create_valid_proof (167-185)
crates/engine_types/src/confidential/validation.rs (1)
  • validate_confidential_statement (25-119)
crates/wallet/sdk/src/apis/stealth_transfer/api.rs (3)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (2)
  • total_stealth_input_amount (55-57)
  • value (28-30)
crates/wallet/sdk/src/apis/stealth_outputs.rs (1)
  • params (700-712)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • value (60-62)
crates/wallet/storage_sqlite/src/reader.rs (2)
crates/wallet/storage_sqlite/src/writer.rs (10)
  • stealth_outputs (126-126)
  • stealth_outputs (127-127)
  • stealth_outputs (157-164)
  • stealth_outputs (213-213)
  • stealth_outputs (214-214)
  • stealth_outputs (229-229)
  • stealth_outputs (230-230)
  • stealth_outputs (1217-1233)
  • stealth_outputs (1341-1341)
  • stealth_outputs (1342-1342)
crates/wallet/sdk/src/storage/reader.rs (1)
  • stealth_outputs_get_unspent_for_spending (136-141)
crates/wallet/sdk/src/apis/confidential_transfer.rs (2)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/wallet/sdk/src/models/stealth_output.rs (1)
  • from (71-79)
crates/wallet/sdk/src/apis/confidential_outputs.rs (3)
crates/wallet/crypto/src/unblinded_statement.rs (1)
  • value (60-62)
crates/wallet/sdk/src/apis/stealth_transfer/types.rs (1)
  • value (28-30)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (1)
  • value (21-23)
crates/wallet/sdk/src/apis/stealth_outputs.rs (3)
crates/wallet/sdk/src/apis/confidential_outputs.rs (2)
  • new (32-42)
  • lock_outputs_internal (79-110)
crates/wallet/sdk/src/models/stealth_output.rs (1)
  • from (71-79)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (2)
  • inputs (72-72)
  • select (65-153)
crates/template_test_tooling/src/support/stealth.rs (3)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/template_lib/src/models/stealth.rs (1)
  • revealed_output_amount (116-118)
bindings/src/types/StealthOutputsStatement.ts (1)
  • StealthOutputsStatement (9-24)
crates/wallet/crypto/src/unblinded_statement.rs (1)
crates/engine_types/src/crypto/helpers.rs (1)
  • commit_u64_amount (74-76)
crates/template_test_tooling/src/support/confidential.rs (3)
bindings/src/types/ConfidentialOutputStatement.ts (1)
  • ConfidentialOutputStatement (10-32)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/template_lib_types/src/amount/amount.rs (1)
  • zero (57-59)
crates/engine/tests/burn.rs (2)
crates/template_lib/src/resource/builder/stealth.rs (1)
  • initial_supply (231-238)
crates/template_test_tooling/src/support/confidential.rs (1)
  • generate_confidential_output_statement (17-22)
crates/wallet/crypto/tests/stealth_transfer_statement.rs (2)
crates/template_lib_types/src/amount/amount.rs (1)
  • new (52-54)
crates/wallet/crypto/src/unblinded_statement.rs (2)
  • new (40-42)
  • mask (64-66)
⏰ 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). (3)
  • GitHub Check: test
  • GitHub Check: check nightly
  • GitHub Check: clippy
🔇 Additional comments (51)
crates/transaction/Cargo.toml (2)

28-28: Verify completeness of the provided code snippet.

The AI summary mentions removing a dev-dependency on tari_bor from the [dev-dependencies] section, but the provided code snippet ends at line 28 (the ts feature definition) and does not show the [dev-dependencies] section. Please confirm that the full file, including any dev-dependencies removal, is captured in the review context.


28-28: TypeScript bindings expansion is correctly scoped.

The ts feature now properly enables TypeScript bindings for all dependent crates (tari_engine_types, tari_ootle_common_types, tari_template_lib, tari_bor) that are already declared as dependencies. This aligns with the PR's type system refactoring (u64/bigint vs Amount), ensuring that TypeScript bindings are generated for crates affected by these changes.

crates/wallet/sdk/Cargo.toml (1)

44-55: No issues found. All referenced crates expose a ts feature.

Verification confirms that all 8 crates (tari_ootle_address, tari_bor, tari_engine_types, tari_template_abi, tari_template_lib, tari_transaction, tari_ootle_wallet_crypto, tari_consensus_types) have the ts feature available. The change is safe and ready for merge.

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

296-298: LGTM: Type conversion aligns with PR objectives.

The conversion of o.value to Amount using Amount::from() is consistent with the PR's goal of using u64 for single UTXO values and Amount for aggregations. The filter change (removing owner_account constraint) is appropriate since the outputs are already scoped to the account via get_unspent_outputs_by_account() on line 288.


327-328: LGTM: Consistent type handling for aggregations.

The Amount::from(o.value) conversions are consistent with the earlier changes and follow the PR's design of using Amount for aggregations that may exceed u64::MAX.


476-495: LGTM: Proper u64 arithmetic with appropriate edge case handling.

The changes correctly handle u64 arithmetic:

  • Line 478: checked_sub is appropriate for u64 subtraction with overflow protection
  • Line 481: Zero-check prevents claiming when fees consume the entire amount
  • Line 495: Passing u64 final_amount to encrypt_value_and_mask aligns with the comment on lines 491-493 about u64::MAX limits in confidential encryption

1157-1157: LGTM: Idiomatic numeric comparison.

The change from blinded_amount.is_positive() to blinded_amount > 0 is idiomatic for numeric types and correctly filters out zero-value outputs.

applications/tari_walletd/web_ui/src/services/api/hooks/useAccounts.ts (1)

169-169: Review comment is incorrect — the code is safe from BigInt conversion errors.

The amount passed to BigInt(params.amount) is guaranteed to be an integer. In SendMoney.tsx (lines 196 and 272), the amount is calculated as:

Math.floor((parseFloat(transferFormState.amount) || 0) * Math.pow(10, balanceEntry.divisibility))

The Math.floor() call ensures only integers are passed to TransferParams, eliminating any decimal values that would cause a RangeError in BigInt().

The inconsistency between line 169 (BigInt(params.amount)) and line 170 (params.amount used directly) exists, but both receive the same integer value, so both operations are correct.

Likely an incorrect or invalid review comment.

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

264-264: No issues found — the conversion target type is clearly defined and properly supported.

The .into() call converts value (u64, per PR objective) into Amount via the macro impl_from!(Amount, u64) at line 423 of crates/template_lib_types/src/amount/amount.rs. The type is not ambiguous; ConfidentialOutputModel.value expects Amount, and the conversion is explicitly implemented. The code is correct.


256-256: Original review comment is based on incorrect assumptions about data flow.

The code is safe. Invalid outputs created with the 0 sentinel value (line 256) are stored with OutputStatus::Invalid and are filtered out by the database query before reaching aggregation logic. The confidential_outputs_lock_smallest_amount() query explicitly filters: status.eq(OutputStatus::Unspent.as_key_str()), ensuring only valid outputs are aggregated at line 100. The type conversion using .into() (line 264) correctly converts the u64 to Amount, and this pattern mirrors the identical implementation in stealth_outputs.rs.

Likely an incorrect or invalid review comment.

clients/wallet_daemon_client/src/types.rs (1)

1078-1081: Good call on converting per-output amounts to Amount.

Wrapping each blinded amount in Amount before summing avoids the previous u64 overflow risk and keeps the aggregate accurate.

crates/engine/tests/recall.rs (1)

24-25: Test update matches new helper signature

Switching to the primitive literal keeps the test in sync with the u64-based helper; everything else still lines up.

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

253-254: Column type change looks good

Migrating stealth_outputs.value to BIGINT keeps schema aligned with the new u64-backed model.

bindings/src/types/wallet-daemon-client/TransferOutput.ts (1)

19-19: Bindings update aligns with bigint migration

blinded_amount adopting bigint keeps this generated type consistent with the rest of the wallet-daemon bindings changes.

crates/engine/tests/burn.rs (1)

13-13: LGTM! Type conversion aligns with function signature.

The call site correctly passes a plain u64 literal instead of Amount::from(1000), matching the updated signature of generate_confidential_output_statement(output_amount: u64, ...).

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

10-10: LGTM! New input selection module exposed.

The new input_selection module provides the branch-and-bound algorithm referenced in the PR objectives. This is the expected public API expansion.

utilities/traffic-sim/src/sim.rs (2)

232-232: LGTM! Type conversion removed per API change.

The blinded_output_amount field now accepts u64 directly, eliminating the need for .into() conversion.


460-460: LGTM! Type conversion removed per API change.

The blinded_amount field now accepts u64 directly, eliminating the need for .into() conversion.

clients/javascript/wallet_daemon_client/src/index.ts (1)

20-20: API surface reduction noted.

Per the AI summary, the accountsGetPayRefAddress method and related types (AccountsGetPayRefAddressRequest, AccountsGetPayRefAddressResponse) were removed. While the removal itself isn't visible in the annotated code, this represents a breaking change to the public JavaScript client API.

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

19-29: LGTM! Helper function updated for u64 amounts.

The create_output_statement function signature correctly changed from Amount to u64, and the implementation directly assigns the value parameter to amount field.


47-47: LGTM! Test call sites updated consistently.

All invocations of create_output_statement correctly pass plain u64 literals instead of Amount values.

Also applies to: 66-66, 97-98

bindings/src/types/wallet-daemon-client/StealthTransfer.ts (1)

8-8: LGTM! Breaking change: bigint replaces Amount.

The blinded_output_amount field type changed from Amount to bigint, aligning with the Rust-side shift to u64. This is a breaking change for TypeScript consumers who must now provide bigint values directly.

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

67-67: LGTM! Unnecessary conversion removed.

The MaskAndValue construction now directly uses value instead of value.into(), consistent with the field now being u64.


40-40: Code is correct—to_commitment() returns PedersenCommitment directly, not Option.

The DecryptedData::to_commitment() method in crates/wallet/crypto/src/unblinded_statement.rs (lines 72–74) has a return type of PedersenCommitment, not Option<PedersenCommitment>. The assignment at line 40 is safe with no implicit unwrapping or runtime panic risk.

Likely an incorrect or invalid review comment.

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

156-156: Review comment is factually incorrect regarding the schema change.

The stealth_outputs.value column has been BIGINT since the initial migration (2023-02-08-122514_initial), not changing from Text to BigInt. The schema.rs file is auto-generated by Diesel and simply reflects the existing database structure. No migration is needed because no column type conversion is occurring.

Likely an incorrect or invalid review comment.

integration_tests/src/wallet_daemon_client.rs (1)

106-106: LGTM! Type change aligns with the Amount → u64 migration.

The function signature update from Amount to u64 is consistent with the PR objective to use u64 for individual UTXO values and simplifies the API by removing the need for type conversions at call sites.

integration_tests/tests/steps/wallet_daemon.rs (1)

439-439: LGTM! Call sites correctly updated to match the new signature.

The removal of .into() conversions is appropriate since transfer_stealth now accepts u64 directly instead of Amount.

Also applies to: 464-464

applications/tari_wallet_cli/src/command/proof.rs (2)

38-38: Good change: amounts should be unsigned.

Changing from i64 to u64 is semantically correct for amounts and improves type safety by rejecting negative values at the CLI boundary. Note that this could be a breaking change if users previously (incorrectly) passed negative values.


69-69: LGTM! Conversion removed to match updated API.

The removal of .into() is correct since ConfidentialCreateOutputProofRequest now expects amount: u64 directly.

crates/wallet/sdk/src/apis/stealth_transfer/types.rs (3)

28-30: LGTM! Correctly implements the u64-for-individual-values pattern.

The return type change from Amount to u64 aligns with the PR objective to use u64 for single UTXO values.


36-36: LGTM! Field type updated consistently.

The field type change from Amount to u64 is consistent with the broader migration pattern.


56-56: Excellent overflow safety pattern.

The implementation correctly uses Amount::from(i.value) when summing individual u64 values, which allows the sum to exceed u64::MAX without overflow. This matches the PR's stated design: "use Amount when the upper bound may exceed u64::MAX."

crates/engine/tests/stealth.rs (2)

103-103: LGTM! Test data simplified with direct numeric literals.

The removal of .into() conversions simplifies test data construction now that MaskAndValue.value is u64 directly. The changes correctly adapt to the updated type system.

Also applies to: 141-141, 177-177, 219-219, 223-223, 273-273, 305-305, 343-343, 392-392, 461-461, 505-505, 509-509, 580-580, 584-584, 646-646, 650-650


396-396: Good practice: explicit type conversion.

Using u64::try_from(...).unwrap() makes the type conversion explicit and would catch overflow issues if the division result somehow exceeded u64::MAX. This is better than an implicit conversion.

bindings/src/types/wallet-daemon-client/ConfidentialCreateOutputProofRequest.ts (1)

3-3: LGTM! Consistent type migration in TypeScript bindings.

The type change from Amount to bigint aligns with the broader migration to use native numeric types in the TypeScript bindings. Note this is a breaking change for consumers of this type.

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

62-62: LGTM! Commitment extraction simplified correctly.

The direct call to to_commitment() without error handling aligns with the new u64-based amount system where commitment creation is always valid for any u64 value.

Also applies to: 121-121


167-185: LGTM! Test helper updated to use u64.

The signature change from Amount to u64 is consistent with the broader migration to native numeric types throughout the codebase.


189-189: LGTM! Test calls updated for u64 parameters.

Also applies to: 195-195

crates/engine/tests/confidential.rs (2)

71-71: LGTM! Test updated for u64 parameter.


362-362: LGTM! Tuple values simplified to raw integers.

The removal of .into() conversions aligns with the helper function now accepting raw u64 values.

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

44-44: LGTM! Validation logic updated for u64 type.

The change from is_positive() to > 0 and is_zero() to == 0 correctly adapts the validation logic for the new u64 type.

Also applies to: 63-63


111-111: Verification confirmed: TypeScript bindings correctly match the Rust definition.

The blinded_amount field is properly typed as bigint in the TypeScript bindings, which is the correct representation for Rust's u64 type. The migration is consistent across both Rust and TypeScript codebases.

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

29-36: LGTM! Import updated for enhanced error messages.

The addition of Displayable enables better formatting of UTXO arrays in error messages (line 1288).


1310-1310: LGTM! Value storage optimized to use i64.

The change from value.to_string() to value as i64 improves storage efficiency and aligns with the established pattern of storing u64 values as i64 in SQLite. As per learnings, this cast is safe and preserves the original unsigned value.

Based on learnings

crates/wallet/sdk/src/storage/writer.rs (1)

13-13: LGTM! New trait method for batch locking added.

The stealth_outputs_lock_many method extends the WalletStoreWriter trait to support batch locking of stealth outputs. The signature is well-defined and matches the implementation in storage_sqlite.

Also applies to: 156-161

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

5-5: LGTM! Commitment creation updated to use u64 helper.

The change from commit_amount_checked to commit_u64_amount simplifies the code by removing unnecessary error handling for non-negative amounts, since u64 is inherently non-negative.

Also applies to: 38-38


79-79: LGTM! Commitment extraction simplified.

The removal of .ok_or(...) indicates that to_commitment() now returns PedersenCommitment directly instead of Option<PedersenCommitment>, which is consistent with u64-based commitments always being valid.

Also applies to: 101-101


96-96: LGTM! Unnecessary validation removed.

Since the amount is now u64, the non_negative_checked() call is no longer needed. Using unwrap_or_default() directly is correct and simpler.


134-154: LGTM! Tests updated for u64 parameters.

The test helper signature and calls are correctly updated to use raw u64 values instead of Amount types.

Also applies to: 158-169

crates/wallet/storage_sqlite/src/models/stealth_output.rs (2)

30-30: LGTM! Value storage optimized to i64.

The change from String to i64 for the value field improves storage efficiency and type safety. The cast from i64 to u64 at line 65 is safe and preserves the original unsigned value, as per learnings.

Based on learnings

Also applies to: 65-65


101-137: LGTM! Conversion to StealthOutputInfo added.

The new TryFrom implementation provides a clean conversion path from the database model to StealthOutputInfo. Error handling is comprehensive with specific operation names and detailed error messages for each field.

Comment thread applications/tari_walletd/src/handlers/confidential.rs Outdated
Comment thread bindings/src/types/wallet-daemon-client/ProofsGenerateRequest.ts Outdated
Comment thread clients/wallet_daemon_client/src/types.rs
Comment thread clients/wallet_daemon_client/src/types.rs
Comment thread crates/template_test_tooling/src/support/confidential.rs
Comment thread crates/wallet/sdk/src/apis/stealth_outputs.rs
Comment thread crates/wallet/storage_sqlite/src/reader.rs
@sdbondi
sdbondi force-pushed the wallet-input-selection-strategies branch from 35d8eb1 to 0dc065e Compare November 10, 2025 07:55

@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

♻️ Duplicate comments (1)
bindings/src/types/wallet-daemon-client/ProofsGenerateRequest.ts (1)

9-9: Breaking change: field renamed (type preserved).

The field was renamed from amount to confidential_amount, which is a breaking API change for TypeScript consumers. However, the type remains Amount (not bigint as claimed in the past review comment). This contradicts the PR description stating "Breaking changes: None."

Note: The past review comment mentioned both a field rename and type change to bigint, but the current code shows only the field name changed while the type Amount was preserved.

🧹 Nitpick comments (1)
crates/wallet/sdk/src/apis/stealth_outputs.rs (1)

225-225: Redundant .take(INPUT_LIMIT) operation.

The branch_and_bound::select function already respects the max_inputs parameter (passed as INPUT_LIMIT on line 216), so it cannot return more than INPUT_LIMIT selected keys. The .take(INPUT_LIMIT) here is defensive but unnecessary.

Apply this diff to remove the redundant operation:

                 let outputs = result
                     .selected_keys()
                     .iter()
-                    .take(INPUT_LIMIT)
                     .map(|selected| {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4376262 and 0dc065e.

📒 Files selected for processing (5)
  • applications/tari_walletd/src/handlers/confidential.rs (7 hunks)
  • bindings/src/types/wallet-daemon-client/ProofsGenerateRequest.ts (1 hunks)
  • clients/wallet_daemon_client/src/types.rs (4 hunks)
  • crates/wallet/sdk/src/apis/stealth_outputs.rs (10 hunks)
  • crates/wallet/storage_sqlite/src/reader.rs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • clients/wallet_daemon_client/src/types.rs
  • applications/tari_walletd/src/handlers/confidential.rs
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-04T10:10:24.258Z
Learnt from: sdbondi
Repo: tari-project/tari-ootle PR: 1629
File: applications/tari_walletd/src/handlers/accounts.rs:1001-1002
Timestamp: 2025-11-04T10:10:24.258Z
Learning: In applications/tari_walletd/src/handlers/accounts.rs, the expect() on Memo::new_pay_ref_and_bytes_truncate at line 1002 is safe and intentional. PayRef is validated to be at most 64 bytes during address decoding (PayRef::MAX_LEN = 64), and the function only returns None if payref exceeds 252 bytes (Memo::MAX_BYTES_LENGTH - 1). Since 64 < 252, None is impossible with a valid PayRef.

Applied to files:

  • crates/wallet/sdk/src/apis/stealth_outputs.rs
🧬 Code graph analysis (3)
bindings/src/types/wallet-daemon-client/ProofsGenerateRequest.ts (1)
bindings/src/types/Amount.ts (1)
  • Amount (12-12)
crates/wallet/storage_sqlite/src/reader.rs (2)
crates/wallet/storage_sqlite/src/writer.rs (10)
  • stealth_outputs (126-126)
  • stealth_outputs (127-127)
  • stealth_outputs (157-164)
  • stealth_outputs (213-213)
  • stealth_outputs (214-214)
  • stealth_outputs (229-229)
  • stealth_outputs (230-230)
  • stealth_outputs (1217-1233)
  • stealth_outputs (1341-1341)
  • stealth_outputs (1342-1342)
crates/wallet/sdk/src/storage/reader.rs (1)
  • stealth_outputs_get_unspent_for_spending (136-141)
crates/wallet/sdk/src/apis/stealth_outputs.rs (3)
crates/wallet/sdk/src/apis/confidential_outputs.rs (2)
  • new (32-42)
  • lock_outputs_internal (79-110)
crates/wallet/sdk/src/models/stealth_output.rs (1)
  • from (71-79)
crates/wallet/sdk/src/models/input_selection/branch_and_bound.rs (2)
  • inputs (72-72)
  • select (65-153)
⏰ 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). (6)
  • GitHub Check: check stable
  • GitHub Check: clippy
  • GitHub Check: check nightly
  • GitHub Check: test
  • GitHub Check: machete
  • GitHub Check: fmt
🔇 Additional comments (7)
crates/wallet/storage_sqlite/src/reader.rs (3)

42-42: LGTM: Import addition.

The StealthOutputInfo import is correctly used in the updated method signatures below.


920-958: LGTM: Enhanced method signature and return type.

The addition of the optional resource_address parameter and the return type change to StealthOutputInfo improve the API flexibility. The method appropriately serves general querying purposes, while spending-specific filters are handled by the dedicated stealth_outputs_get_unspent_for_spending method below.


960-998: LGTM: Spendability predicates correctly implemented.

The method now includes all required spendability filters (lines 987-989), resolving the critical issue flagged in the previous review. The implementation correctly:

  • Excludes view-only outputs (owner_key_id.is_not_null())
  • Excludes burnt outputs (is_burnt.eq(false))
  • Excludes frozen outputs (is_frozen.eq(false))
  • Allows outputs created within the transaction (LockedUnconfirmed with matching lock_id)

This ensures only truly spendable outputs are returned for branch-and-bound input selection, preventing downstream signing and locking failures.

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

103-105: Good optimization for zero amount case.

The early return when amount is zero avoids unnecessary processing and database transactions.


168-175: Excellent fix for the INPUT_LIMIT bug!

The INPUT_LIMIT check is now correctly positioned before the locking call, which prevents locking the (limit+1)th UTXO that wouldn't be returned. This addresses the critical issue raised in the previous review.


640-640: Appropriate type change for individual UTXO value.

Changing from Amount to u64 for individual output amounts aligns with the PR's approach of using u64 for single UTXO values and reserving Amount for sums that may exceed u64::MAX.


713-715: Correct use of Amount for summing values.

Converting individual UTXO values to Amount before summing ensures the total can safely exceed u64::MAX, which aligns with the PR's approach of using Amount for aggregate values.

@sdbondi
sdbondi merged commit 1ddedae into tari-project:development Nov 10, 2025
13 checks passed
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