Skip to content

feat!: ensure payref persists during recovery#7225

Merged
SWvheerden merged 5 commits intotari-project:developmentfrom
SWvheerden:sw_payref_payment_id
Jun 18, 2025
Merged

feat!: ensure payref persists during recovery#7225
SWvheerden merged 5 commits intotari-project:developmentfrom
SWvheerden:sw_payref_payment_id

Conversation

@SWvheerden
Copy link
Copy Markdown
Collaborator

@SWvheerden SWvheerden commented Jun 17, 2025

Description

Ensures that payrefs are persisted across recovery of the wallet
Adds two new paymentid fields to ensure fields are properly serialized
Fixed a bug where its possible to deserilize a Tari address wrongly
Fixed a bug where a received tx would not show the correct amount
Added legacy payment id types to ensure correct deseriasation of old types

Breaking Changes

Old wallets will not properly show the transaction details of newly received transactions. A fix would be to rescan the wallet.

Summary by CodeRabbit

  • New Features

    • Introduced a robust and backward-compatible implementation for Payment ID handling, supporting advanced metadata, serialization, and utility methods for transactions.
  • Refactor

    • Reorganized Payment ID and transaction type components into a dedicated module, improving code structure and maintainability.
    • Updated all references to Payment ID and transaction type to use the new module across the codebase.
    • Enhanced transaction protocol to explicitly track and handle change outputs alongside finalized transactions.
  • Bug Fixes

    • Improved handling and explicit confirmation of change outputs during transaction finalization, ensuring accurate wallet state and record-keeping.
  • Database

    • Removed the change_output_hashes column from transaction tables and updated migration scripts accordingly.
    • Enhanced output confirmation logic to support updating metadata and encrypted data for change outputs.
  • Tests

    • Updated tests to reflect new module paths and removed obsolete or unused fields.
    • Marked specific tests to be skipped by default for improved test management.
  • Chores

    • Cleaned up imports and removed legacy code related to Payment ID from deprecated locations.

add payref support in payment id
@SWvheerden SWvheerden requested a review from a team as a code owner June 17, 2025 21:41
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Jun 17, 2025

Walkthrough

This change moves the PaymentId and TxType types from the encrypted_data module to a new payment_id module within the transaction_components namespace. It updates all related imports, removes the old implementation from encrypted_data.rs, introduces a comprehensive new payment_id.rs, and refactors transaction, output, and database logic to explicitly handle change outputs and payment references.

Changes

Files/Groups Change Summary
Most files importing PaymentId/TxType Import paths updated: encrypted_data::{PaymentId, TxType}payment_id::{PaymentId, TxType}. No logic changes.
base_layer/core/src/transactions/transaction_components/encrypted_data.rs Removed all PaymentId and TxType enums, helpers, methods, and tests from this file. Only encrypted data handling remains.
base_layer/core/src/transactions/transaction_components/mod.rs Added new public module: pub mod payment_id;.
base_layer/core/src/transactions/transaction_components/payment_id.rs New file: comprehensive implementation of PaymentId and TxType enums, serialization, deserialization, utilities, metadata packing, display, and extensive unit tests.
base_layer/core/src/transactions/transaction_protocol/sender.rs Refactored SenderState::FinalizedTransaction to a struct containing both transaction and optional change output. Updated all related methods and matches. Changed transaction building/finalization to return change output. Updated test code accordingly.
base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs Updated PaymentId::TransactionInfo construction to initialize sent_output_hashes as empty vector.
base_layer/core/src/transactions/test_helpers.rs Changed mutable handling of outputs/change output: now spend_utxos appends finalized change output, not create_stx_protocol. Updated import path.
base_layer/core/src/transactions/transaction_components/wallet_output.rs Added async method change_encrypted_data to update encrypted data and metadata signature for a wallet output.
base_layer/wallet/src/output_manager_service/handle.rs ConfirmPendingTransaction now takes an optional vector of change outputs. Method signature and Display updated.
base_layer/wallet/src/output_manager_service/service.rs confirm_encumberance is now async and takes change outputs; all calls updated to pass finalized change outputs. Transaction finalization and change output handling refactored to be explicit and asynchronous.
base_layer/wallet/src/output_manager_service/storage/database/backend.rs Trait method confirm_encumbered_outputs now takes a slice of change outputs.
base_layer/wallet/src/output_manager_service/storage/database/mod.rs Database method confirm_encumbered_outputs now takes a vector of change outputs and passes them to the backend.
base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs Backend implementation now updates encrypted data and metadata signature fields for each change output during confirmation. UpdateOutput and UpdateOutputSql structs extended with encrypted_data field.
base_layer/wallet/src/schema.rs Removed change_output_hashes column from outbound_transactions table.
base_layer/wallet/src/transaction_service/storage/models.rs Removed change_output_hashes field from OutboundTransaction. Refactored conversions and methods to require explicit change output hashes. Added WalletTransaction::source_address() helper.
base_layer/wallet/src/transaction_service/storage/sqlite_db.rs Removed all references to change_output_hashes in OutboundTransactionSql and conversion logic.
base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs Moved change output hash handling to after transaction finalization; confirm pending transaction now passes change outputs explicitly.
base_layer/wallet/src/transaction_service/service.rs All calls to confirm_pending_transaction updated to pass finalized change outputs. Change output handling now uses finalized outputs. Minor refactorings for clarity and correctness.
base_layer/wallet_ffi/src/lib.rs, base_layer/wallet_ffi/src/callback_handler.rs Construction of CompletedTransaction from outbound now uses from_outbound(tx, Vec::new()). Updated imports.
base_layer/wallet_ffi/src/callback_handler_tests.rs Updated import paths for PaymentId and TxType.
base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/up.sql Migration: removes change_output_hashes column from outbound_transactions table.
base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/down.sql Migration: adds change_output_hashes column back to outbound_transactions table.
Test files (tests/, integration_tests/, etc.) Updated imports for PaymentId/TxType, removed change_output_hashes from test data, adjusted method calls to match new signatures. Added/removed #[ignore] attribute on one test.

Sequence Diagram(s)

sequenceDiagram
    participant Wallet as Wallet Service
    participant OutputMgr as Output Manager Service
    participant DB as Output Manager DB

    Wallet->>OutputMgr: confirm_pending_transaction(tx_id, Some(change_outputs))
    OutputMgr->>OutputMgr: finalize transaction, get finalized change outputs
    OutputMgr->>DB: confirm_encumbered_outputs(tx_id, change_outputs)
    DB->>DB: update outputs, set encrypted data and metadata signature
    DB-->>OutputMgr: confirmation result
    OutputMgr-->>Wallet: confirmation result
Loading
sequenceDiagram
    participant Protocol as SenderTransactionProtocol
    participant KeyMgr as KeyManager

    Protocol->>KeyMgr: build_transaction(info)
    KeyMgr-->>Protocol: (transaction, Option<change_output>)
    Protocol->>Protocol: store FinalizedTransaction { final_transaction, change_output }
    Protocol->>Protocol: get_finalized_change_output()
Loading

Possibly related PRs

  • tari-project/tari#7187: Fixes and simplifies PaymentId deserialization logic, which is now included and built upon in this PR's new payment_id module.
  • tari-project/tari#7077: Adds explicit user payment ID fields to gRPC/FFI, which depends on the refactored PaymentId structure and imports introduced here.
  • tari-project/tari#7154: Implements the full Payment Reference (PayRef) system, directly related to the foundational refactor and relocation of PaymentId and TxType in this PR.

Suggested reviewers

  • hansieodendaal

Poem

Hopping through code, I leap with glee,
PaymentId found a new home, you see!
Change outputs now handled with care,
Confirmed and finalized, everywhere.
Refactored and tidy, the carrots align—
This bunny’s code garden is looking divine!
(っ◔◡◔)っ 🥕

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🔭 Outside diff range comments (2)
base_layer/core/src/transactions/transaction_components/encrypted_data.rs (1)

85-97: Cap the size of payment_id before encryption

encrypt_data allocates SIZE_VALUE + SIZE_MASK + payment_id.get_size() without validating that get_size() is within a reasonable bound.
Because PaymentId is externally supplied, a malicious caller could craft a huge payment-id, resulting in an oversized ciphertext and unnecessary memory/database growth.

Verify the maximum length expected for on-chain metadata (e.g. legacy TariAddress size ≤ 65 bytes) and reject anything above that before allocation.

[security]

base_layer/wallet/src/transaction_service/storage/models.rs (1)

326-368: Preserve the real source address when deriving CompletedTransaction

from_outbound sets

source_address: Default::default(),

which later bubbles up via WalletTransaction::source_address().
Down-stream UI/reporting will mis-attribute the transaction (empty address / T::default()).

If the wallet cannot determine the sender’s address yet, consider:

- source_address: Default::default(),
+ source_address: tx.sender_protocol.get_source_address_or_default(),

or pass an Option<TariAddress> to keep the information explicit.

♻️ Duplicate comments (2)
base_layer/wallet/tests/output_manager_service_tests/storage.rs (2)

467-468: Same minor allocation point as above

The comment on lines 182-184 applies here as well.


617-618: Same minor allocation point as above

The comment on lines 182-184 applies here as well.

🧹 Nitpick comments (21)
base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/up.sql (1)

5-5: Ensure reversible migration
You may want to add a corresponding down.sql script to restore the change_output_hashes column for rollback support.

base_layer/core/tests/tests/node_comms_interface.rs (1)

46-46: PaymentId is imported but never used

PaymentId is not referenced anywhere in this test file, which will raise an unused_imports warning (or an error if the CI uses #![deny(unused_imports)]).
Consider dropping the import:

-            payment_id::PaymentId,
+            /* PaymentId no longer required */
base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs (1)

433-434: sent_output_hashes is initialised but never populated

A new sent_output_hashes: Vec::new() field is added to the PaymentId::TransactionInfo instance, yet the vector is not subsequently updated in this builder.
If the intention is to persist the hashes of the outputs once they are known, ensure they are pushed later in the transaction-building flow; otherwise the field will always remain empty and provide no value.

If the information will be added elsewhere, please confirm; if not, consider removing the field or wiring it up here.

base_layer/core/src/transactions/transaction_components/mod.rs (1)

61-61: Publicly exposing the new payment_id module

Declaring pub mod payment_id; is necessary, but you might also want to re-export the key types to preserve the previous ergonomic path:

 pub mod payment_id;
+pub use payment_id::{PaymentId, TxType};

That way downstream code can continue to do use transaction_components::PaymentId if desired.

base_layer/wallet/tests/utxo_scanner/mod.rs (1)

861-863: Add rationale for ignoring the one-sided payments test

Please include a comment explaining why test_utxo_scanner_one_sided_payments is marked #[ignore], and add a TODO or issue reference to re-enable it once one-sided payment reference persistence is fully supported.

Would you like help drafting the ignore rationale or linking this to an issue?

base_layer/wallet/src/transaction_service/storage/database.rs (2)

748-756: Minor: make the intent explicit when extracting fee and hashes

Using unwrap_or_default() is fine, but it silently treats a missing field as zero fee / empty sent-hash list.
Explicit fall-back makes the behaviour clearer and prevents accidental masking of malformed PaymentIds:

-let fee = payment_id.get_fee().unwrap_or_default();
-let sent_hashes = payment_id.get_sent_hashes().unwrap_or_default();
+let fee = payment_id
+    .get_fee()
+    .unwrap_or_else(|| {
+        debug!(target: LOG_TARGET, "No fee embedded in PaymentId – defaulting to 0");
+        MicroMinotari::from(0)
+    });
+
+let sent_hashes = payment_id
+    .get_sent_hashes()
+    .unwrap_or_else(|| {
+        debug!(target: LOG_TARGET, "No sent hashes in PaymentId – using empty vec");
+        Vec::new()
+    });

Not critical, but it improves debuggability.


769-770: Avoid double allocation of sent_hashes

You already have the vector in sent_hashes; re-using it avoids a second allocation:

-            sent_hashes,
-            vec![hash],
+            sent_hashes,            // provided by PaymentId
+            vec![hash],             // received hash (imported output)
base_layer/wallet/tests/output_manager_service_tests/storage.rs (1)

182-184: Avoid per-iteration allocation of an empty vector

Vec::new() creates a new allocation every time the loop runs.
Although this is only a test and the cost is negligible, passing a static empty slice (if the API permits) or reusing a single const EMPTY: Vec<DbWalletOutput> = Vec::new(); would be marginally more efficient and makes the intention explicit.

base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (1)

2535-2536: Minor: keep test-only imports shallow

The deep path transaction_components::payment_id::{PaymentId, TxType} works, but pulling from the crate’s public re-export (if one exists) keeps the test decoupled from internal layout shifts.

No action required if a public re-export is not (yet) available.

base_layer/wallet/src/output_manager_service/storage/database/backend.rs (1)

67-74: Doc-comment out of date with new parameter

The sentence preceding this method still reads “This method confirms that a transaction negotiation is complete and outputs can be fully encumbered.”
Now that we also update change-output metadata, it would be clearer to mention that the supplied slice contains the finalized change outputs that must have their encrypted data / metadata updated.

/// This method confirms that a transaction negotiation is complete, fully encumbers the outputs
/// against the pending transaction, and updates the encrypted data/metadata of the provided
/// finalized change outputs.

Minor but helps future maintainers.

base_layer/wallet_ffi/src/lib.rs (1)

12818-12822: Test data aligned with new struct, but consider covering non-empty cases

The addition of sent_output_hashes: vec![] satisfies the new field, yet the test only exercises the empty path. Adding at least one hash would give stronger coverage of the serialization path introduced in this PR.

base_layer/wallet/src/transaction_service/storage/models.rs (1)

449-457: source_address() may return None for outbound tx – clarify intent

Returning None for PendingOutbound while always Some for the other variants makes the API asymmetric.
Consider documenting the behaviour (“None when the wallet itself is the sender”) or return the wallet’s own address instead to avoid Option juggling by callers.

base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs (2)

855-873: Comment/code mismatch – ensure we update only necessary fields

The comment states “Only the ephemeral_pubkey and u_y portion needs to be updated”, yet the UpdateOutput includes five metadata fields plus encrypted_data and hash.

Either:

  1. Expand the comment to reflect reality, or
  2. Trim the update to the minimal required subset to prevent unintended overwrites.

Consistency here avoids future maintenance errors.


1321-1339: Storing full encrypted_data blobs – watch SQLite row size

encrypted_data can be up to 256 + STATIC size (~300 B).
With many change outputs this may enlarge the outputs table significantly and approach SQLite’s 1 GB-row or page-size limits.

Confirm that this blob column is configured as BLOB (not TEXT) and consider compression or a separate table if growth becomes an issue.

base_layer/wallet/src/transaction_service/service.rs (1)

1765-1778: Change-output handling assumes a single output

get_finalized_change_output() returns one TransactionOutput; if future protocol revisions allow multiple change outputs, only the first will be confirmed and hashed.
Consider iterating over all change outputs (or renaming the method to make single-output semantics explicit) to future-proof this block.

base_layer/wallet/src/output_manager_service/service.rs (2)

410-415: Tiny optimisation opportunity

unwrap_or(Vec::new()) allocates every time.
unwrap_or_default() (or just pattern-match) avoids the extra allocation and reads a little clearer.

-let change_outputs = change.unwrap_or(Vec::new());
+let change_outputs = change.unwrap_or_default();

2136-2156: Tag change outputs with the correct source & avoid extra alloc

  1. OutputSource::default() will mark these as “Unknown”. A dedicated OutputSource::Change (if it exists) makes later analytics simpler.
  2. You can pre-allocate the vector:
-let mut change = Vec::new();
-for output in change_outputs {
+let mut change = Vec::with_capacity(change_outputs.len());
+for output in change_outputs {

Both are minor but improve clarity & efficiency.

base_layer/core/src/transactions/transaction_components/payment_id.rs (1)

424-435: Potential overflow: counts stored in a single byte

address_bytes.len(), user_data.len() and sent_output_hashes.len() are all cast to u8.
If any exceed 255 the cast will panic.
Consider validating lengths and returning a descriptive error before the cast.

base_layer/core/src/transactions/transaction_protocol/sender.rs (3)

326-334: Simplify Option + Box access

change_output.as_ref().as_ref() is hard to read.
change_output.as_deref() (or change_output.as_ref().flatten()) achieves the same without the
double call:

change_output.as_deref().map(|o| o.output.value)

340-366: Duplicate helpers – consider merging

get_pre_finalized_change_output and get_finalized_change_output differ only in the match
arms. A single method that takes a flag (or returns Option<Option<...>>) would remove
nearly-identical code and cut maintenance overhead.


870-875: Unnecessary Box around Option

FinalizedTransaction { change_output: Box<Option<OutputPair>> } allocates even when
None.
Storing Option<Box<OutputPair>> (or just Option<OutputPair>) avoids an extra heap
allocation and simplifies access.

-        change_output: Box<Option<OutputPair>>,
+        change_output: Option<Box<OutputPair>>,

(Propagate the type change to the rest of the file.)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e0ab8d1 and 20bd52f.

📒 Files selected for processing (67)
  • applications/minotari_console_wallet/src/automation/commands.rs (1 hunks)
  • applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (1 hunks)
  • applications/minotari_console_wallet/src/ui/components/burn_tab.rs (1 hunks)
  • applications/minotari_console_wallet/src/ui/components/send_tab.rs (1 hunks)
  • applications/minotari_console_wallet/src/ui/components/transactions_tab.rs (1 hunks)
  • applications/minotari_console_wallet/src/ui/state/app_state.rs (2 hunks)
  • applications/minotari_console_wallet/src/ui/state/tasks.rs (1 hunks)
  • applications/minotari_merge_mining_proxy/src/block_template_manager.rs (1 hunks)
  • applications/minotari_miner/src/run_miner.rs (1 hunks)
  • applications/minotari_node/src/grpc/base_node_grpc_server.rs (1 hunks)
  • base_layer/core/src/blocks/pre_mine/mod.rs (1 hunks)
  • base_layer/core/src/test_helpers/mod.rs (1 hunks)
  • base_layer/core/src/transactions/coinbase_builder.rs (2 hunks)
  • base_layer/core/src/transactions/test_helpers.rs (2 hunks)
  • base_layer/core/src/transactions/transaction_components/encrypted_data.rs (4 hunks)
  • base_layer/core/src/transactions/transaction_components/mod.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_components/payment_id.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_components/test.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_components/unblinded_output.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_components/wallet_output.rs (2 hunks)
  • base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_key_manager/inner.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_key_manager/interface.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_key_manager/wrapper.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_protocol/recipient.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_protocol/sender.rs (21 hunks)
  • base_layer/core/src/transactions/transaction_protocol/single_receiver.rs (1 hunks)
  • base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs (2 hunks)
  • base_layer/core/src/validation/block_body/test.rs (1 hunks)
  • base_layer/core/tests/tests/block_validation.rs (1 hunks)
  • base_layer/core/tests/tests/node_comms_interface.rs (1 hunks)
  • base_layer/tari_mining_helper_ffi/src/lib.rs (1 hunks)
  • base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/down.sql (1 hunks)
  • base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/up.sql (1 hunks)
  • base_layer/wallet/src/output_manager_service/handle.rs (4 hunks)
  • base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs (1 hunks)
  • base_layer/wallet/src/output_manager_service/service.rs (14 hunks)
  • base_layer/wallet/src/output_manager_service/storage/database/backend.rs (1 hunks)
  • base_layer/wallet/src/output_manager_service/storage/database/mod.rs (1 hunks)
  • base_layer/wallet/src/output_manager_service/storage/models.rs (1 hunks)
  • base_layer/wallet/src/output_manager_service/storage/sqlite_db/mod.rs (5 hunks)
  • base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs (1 hunks)
  • base_layer/wallet/src/schema.rs (0 hunks)
  • base_layer/wallet/src/transaction_service/handle.rs (1 hunks)
  • base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs (3 hunks)
  • base_layer/wallet/src/transaction_service/service.rs (15 hunks)
  • base_layer/wallet/src/transaction_service/storage/database.rs (3 hunks)
  • base_layer/wallet/src/transaction_service/storage/models.rs (4 hunks)
  • base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (2 hunks)
  • base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs (1 hunks)
  • base_layer/wallet/src/wallet.rs (1 hunks)
  • base_layer/wallet/tests/output_manager_service_tests/service.rs (2 hunks)
  • base_layer/wallet/tests/output_manager_service_tests/storage.rs (3 hunks)
  • base_layer/wallet/tests/support/utils.rs (1 hunks)
  • base_layer/wallet/tests/transaction_service_tests/service.rs (1 hunks)
  • base_layer/wallet/tests/transaction_service_tests/storage.rs (1 hunks)
  • base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs (1 hunks)
  • base_layer/wallet/tests/utxo_scanner/mod.rs (1 hunks)
  • base_layer/wallet_ffi/src/callback_handler.rs (1 hunks)
  • base_layer/wallet_ffi/src/callback_handler_tests.rs (1 hunks)
  • base_layer/wallet_ffi/src/lib.rs (4 hunks)
  • integration_tests/src/ffi/wallet.rs (1 hunks)
  • integration_tests/src/miner.rs (1 hunks)
  • integration_tests/src/wallet_ffi.rs (1 hunks)
  • integration_tests/tests/steps/wallet_ffi_steps.rs (1 hunks)
  • integration_tests/tests/steps/wallet_steps.rs (1 hunks)
💤 Files with no reviewable changes (1)
  • base_layer/wallet/src/schema.rs
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: Cucumber tests / Base Layer
  • GitHub Check: Cucumber tests / FFI
  • GitHub Check: cargo check with stable
  • GitHub Check: test (mainnet, stagenet)
  • GitHub Check: test (nextnet, nextnet)
  • GitHub Check: test (testnet, esmeralda)
  • GitHub Check: ci
🔇 Additional comments (65)
base_layer/core/src/transactions/transaction_components/test.rs (1)

44-44: Updated import path for PaymentId
Import correctly references the new payment_id::PaymentId module.

base_layer/core/src/transactions/transaction_components/wallet_output_builder.rs (1)

35-35: Updated import path for PaymentId
Import correctly references the new payment_id::PaymentId module.

base_layer/wallet/src/output_manager_service/storage/models.rs (1)

32-32: Updated import path for PaymentId
Import correctly references the new payment_id::PaymentId module.

base_layer/core/src/transactions/transaction_components/unblinded_output.rs (1)

44-44: Updated import path for PaymentId
Import correctly references the new payment_id::PaymentId module.

integration_tests/src/ffi/wallet.rs (1)

34-34: Updated import path for PaymentId
Import correctly references the new payment_id::PaymentId module.

base_layer/wallet/src/output_manager_service/storage/sqlite_db/output_sql.rs (1)

41-41: Update PaymentId import path
Import path updated to payment_id::PaymentId aligns with the new module structure.

base_layer/core/src/transactions/transaction_key_manager/wrapper.rs (1)

41-41: Align PaymentId import
Using payment_id::PaymentId is consistent with the refactored module.

base_layer/wallet/tests/support/utils.rs (1)

30-30: Refresh PaymentId import path in tests
Test utility correctly references payment_id::PaymentId following the refactor.

integration_tests/src/miner.rs (1)

41-41: Update payment_id and TxType import paths
Importing both PaymentId and TxType from the new payment_id module is correct.

base_layer/core/src/transactions/transaction_protocol/single_receiver.rs (1)

162-162: Import path updated correctly
The PaymentId type is now imported from the new payment_id module under transaction_components, reflecting the refactor and ensuring consistency.

applications/minotari_console_wallet/src/grpc/wallet_grpc_server.rs (1)

122-122: Consistent import for PaymentId and TxType
Importing both PaymentId and TxType from payment_id under transaction_components aligns with the standardized module structure.

applications/minotari_merge_mining_proxy/src/block_template_manager.rs (1)

37-37: PaymentId and TxType module path corrected
The payment_id::{PaymentId, TxType} import replaces the old location, keeping the codebase coherent after moving these types out of encrypted_data.

base_layer/core/src/transactions/transaction_key_manager/interface.rs (1)

47-47: Validate updated PaymentId import path.

The PaymentId import has been correctly moved from encrypted_data to the new payment_id module. Confirm there are no lingering references to the old path and that serialization/deserialization behavior remains unchanged.

base_layer/wallet/src/wallet.rs (1)

66-66: Verify PaymentId and TxType imports reflect refactor.

The imports for PaymentId and TxType now point to transaction_components::payment_id. Ensure all wallet flows handling payment IDs and transaction types operate correctly with the new module.

base_layer/core/src/blocks/pre_mine/mod.rs (1)

47-48: Import path update looks correct

payment_id::PaymentId matches the new module layout introduced in the PR.
No additional code changes required in this file.

applications/minotari_console_wallet/src/ui/components/transactions_tab.rs (1)

13-14: Confirm enum variants still compile

Only the import path changed, but later code pattern-matches on
PaymentId::{Open, AddressAndData, TransactionInfo} and uses
PaymentId::user_data_as_string().
Please ensure those variants and methods remain unchanged in the new
payment_id module; otherwise this will be a compile-time break.

If any variant names or method signatures changed, update the match
arms accordingly.

base_layer/core/src/transactions/transaction_protocol/proto/transaction_sender.rs (1)

36-37: Verify API parity for PaymentId::{from_bytes,to_bytes}

SingleRoundSenderData still depends on the static helper
PaymentId::from_bytes / to_bytes.
Double-check that these associated fns are re-exported unchanged in the
new module; otherwise serialization/deserialization of sender data will
fail.

No other issues spotted.

base_layer/core/src/transactions/transaction_protocol/recipient.rs (1)

179-179: Correct import path update for PaymentId.

The module path has been accurately changed to transaction_components::payment_id::PaymentId, and the test usage (PaymentId::Empty) aligns with the new enum location. No further adjustments needed here.

base_layer/core/src/transactions/transaction_key_manager/inner.rs (1)

103-103: Correct import path update for PaymentId.

The import of PaymentId from the new payment_id module is consistent with the refactor, and all downstream uses in encryption/decryption functions align with this change.

base_layer/core/src/test_helpers/mod.rs (1)

63-63: Correct import path update for PaymentId and TxType.

The test helper now imports both PaymentId and TxType from the payment_id module as intended, and the subsequent uses (PaymentId::Open { tx_type: TxType::Coinbase }) are correctly referenced.

base_layer/wallet/src/transaction_service/handle.rs (1)

42-45: Import path correctly updated

PaymentId is now pulled from transaction_components::payment_id, which matches the new module location introduced in this PR. No further changes are required in this file.

applications/minotari_console_wallet/src/ui/components/send_tab.rs (1)

7-10: Consistent refactor – OK

Both PaymentId and TxType are imported from the new payment_id module. This keeps the UI layer in sync with the core refactor. Looks good.

applications/minotari_console_wallet/src/ui/state/tasks.rs (1)

38-44: Import path realigned

The task runner now references payment_id::PaymentId. Change is correct and compiles cleanly given the upstream move.

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

25-30: Integration tests updated

Test step file now uses the relocated PaymentId/TxType definitions. Update is accurate; no additional adjustments needed.

applications/minotari_console_wallet/src/ui/components/burn_tab.rs (1)

8-11: Import path update looks correct

The module has been migrated to payment_id; the new path compiles and keeps the local usages of PaymentId and TxType intact. No further action required.

base_layer/wallet/src/utxo_scanner_service/utxo_scanner_task.rs (1)

49-53: Consistent path refactor acknowledged

The import change to transaction_components::payment_id::PaymentId aligns the scanner with the new module structure. ✅

applications/minotari_console_wallet/src/automation/commands.rs (1)

93-95: Import PaymentId and TxType from the new payment_id module
The updated path correctly reflects the refactor moving these types out of encrypted_data.rs. Please verify that there are no remaining imports or references to the old encrypted_data::{PaymentId, TxType} elsewhere in this file or in related modules.

base_layer/wallet/tests/transaction_service_tests/transaction_protocols.rs (1)

85-85: Import PaymentId and TxType from new payment_id module
The import path has been correctly updated to reflect the migration of these types out of encrypted_data.rs.

Please run the following script to verify that there are no remaining imports from the old module:

#!/bin/bash
# Verify no stale imports of PaymentId or TxType from encrypted_data
rg -n "encrypted_data::(PaymentId|TxType)" 
applications/minotari_miner/src/run_miner.rs (1)

66-66: Import PaymentId and TxType from new payment_id module
This aligns with the refactor moving these enums into payment_id.rs.

Ensure no legacy imports remain:

#!/bin/bash
rg -n "encrypted_data::(PaymentId|TxType)" 
integration_tests/src/wallet_ffi.rs (1)

33-33: Import PaymentId from payment_id module
The import path update matches the core migration and is correctly scoped.

Run a check for any leftover encrypted_data references:

#!/bin/bash
rg -n "encrypted_data::PaymentId"
base_layer/tari_mining_helper_ffi/src/lib.rs (1)

46-46: To ensure there are absolutely no leftover references to the old encrypted_data module, let’s search for any stray imports or paths:

#!/bin/bash
# Check for any residual references to the old module path
rg -n 'transaction_components::encrypted_data'
rg -n 'encrypted_data::'

# Check for any lingering imports of PaymentId and TxType
rg -n 'use\s.*PaymentId'
rg -n 'use\s.*TxType'
base_layer/wallet/tests/transaction_service_tests/storage.rs (1)

56-56: Import path update looks good

The switch to transaction_components::payment_id::{PaymentId, TxType} aligns with the new module split.
No further action needed here.

base_layer/core/src/transactions/transaction_protocol/transaction_initializer.rs (1)

43-50: Import path update acknowledged

The refactor to payment_id::{PaymentId, TxType} is consistent with the new module structure.
No issues spotted.

base_layer/core/tests/tests/block_validation.rs (1)

940-947: Update expected block weight after consensus changes.

The actual block weight assertion has been adjusted from 405 to 414 to reflect the new weight calculation. This update aligns the test with the current consensus constants.

base_layer/wallet/migrations/2025-06-17-120000_remove_change_hashes/down.sql (1)

1-3: Restore change_output_hashes column in down migration.

Reintroduces the change_output_hashes column as BLOB NULL, matching the original schema before the up.sql removal.

base_layer/wallet_ffi/src/callback_handler_tests.rs (1)

52-54: Update import path for PaymentId and TxType.

The test now imports these enums from transaction_components::payment_id, consistent with the module relocation.

applications/minotari_node/src/grpc/base_node_grpc_server.rs (1)

70-70: Import path update for PaymentId and TxType is correct.

The refactor moving these enums into transaction_components::payment_id is applied properly. No other references to the old encrypted_data path remain in this file.

base_layer/core/src/transactions/coinbase_builder.rs (2)

801-801: Update test imports to new payment_id module
The test module’s import has been updated to reference payment_id::{PaymentId, TxType}, matching the new structure.


44-44: Update imports to new payment_id module
The import path for PaymentId and TxType has been correctly updated from encrypted_data to the new payment_id module, aligning with the refactoring.

Run this script to ensure there are no remaining references to the old path:

#!/bin/bash
# Verify removal of old PaymentId/TxType imports
rg -n "encrypted_data::\{PaymentId, TxType\}" || echo "No stale imports found"
base_layer/wallet/tests/output_manager_service_tests/service.rs (2)

69-69: Align import path for PaymentId with new module location
The import of PaymentId from the payment_id module correctly reflects the refactoring of payment ID types.


1209-1209: Update confirm_pending_transaction call to match new signature
Including the explicit None for optional change outputs aligns with the extended method signature.

base_layer/core/src/validation/block_body/test.rs (1)

42-43: Correct import paths for encrypted data and PaymentId
Separating STATIC_ENCRYPTED_DATA_SIZE_TOTAL and importing PaymentId from the new payment_id module aligns with the recent modularization of payment ID handling.

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

51-51: Align import paths with new payment_id module
The import has been correctly updated from the old encrypted_data location to the new transaction_components::payment_id module. No logic changes are needed here.

base_layer/wallet/src/output_manager_service/recovery/standard_outputs_recoverer.rs (1)

32-32: Import path corrected for PaymentId
PaymentId is now correctly sourced from transaction_components::payment_id, matching the module extraction.

base_layer/wallet/tests/transaction_service_tests/service.rs (1)

129-129: Import paths updated correctly.

The PaymentId and TxType types are now imported from transaction_components::payment_id, which aligns with the refactor. No lingering references to the old encrypted_data module remain.

base_layer/wallet_ffi/src/callback_handler.rs (1)

554-556: Potential loss of change-output metadata

CompletedTransaction::from_outbound(tx, Vec::new()) intentionally discards every change-output hash.
Down-stream code (e.g. pay-ref generation or balance reconciliation) may rely on sent_output_hashes / change_output_hashes being present once the transaction is surfaced to the UI or persisted.

If the hashes are still available on tx (or can be recomputed from its transaction.body.outputs()), consider passing them through instead of an empty vector:

-let mut outbound_tx = CompletedTransaction::from_outbound(tx, Vec::new());
+let change_hashes = tx
+    .transaction
+    .body
+    .outputs()
+    .iter()
+    .filter(|o| o.is_change())        // pseudo-code – adjust predicate
+    .map(|o| o.hash())
+    .collect();
+
+let mut outbound_tx = CompletedTransaction::from_outbound(tx, change_hashes);

Otherwise, please confirm that no component expects these hashes after a cancellation path.

applications/minotari_console_wallet/src/ui/state/app_state.rs (2)

64-66: Import path update looks good

The switch to transaction_components::payment_id::{PaymentId, TxType} cleanly follows the module refactor.


739-741: Empty sent_output_hashes may hinder PayRef generation for pending outbound TXs

For pending outbound transactions we now build:

CompletedTransaction::from_outbound(t.clone(), Vec::new())

Later, once mined, PayRef calculation (lines 815-819) expects sent_output_hashes.first().
Because this vector is initialised empty, the PayRef for a TX that stays in the UI as “pending” until it is mined could remain None.

If the hash list truly cannot be known at this stage, document the limitation; otherwise populate it similarly to the suggestion in the FFI handler.

base_layer/wallet/src/transaction_service/storage/sqlite_db.rs (1)

59-59: Import path update looks correct – verify remaining crates are migrated

The switch to transaction_components::payment_id::PaymentId is in line with the new module split.
Please confirm there are no lingering references to the former path (encrypted_data::PaymentId) elsewhere in the workspace.

#!/usr/bin/env bash
# Find any remaining occurrences of the obsolete import
rg --count --fixed-strings 'encrypted_data::PaymentId'
base_layer/wallet_ffi/src/lib.rs (3)

152-154: Import path change is correct and matches the new module layout

PaymentId and TxType are now re-exported from transaction_components::payment_id; the updated path compiles against the refactor and keeps the outward FFI surface unchanged.


9024-9027: Make sure we don’t silently drop sent_output_hashes

CompletedTransaction::from_outbound(tx.clone(), Vec::new()) hard-codes an empty list.
If the outbound transaction ever carries change / sent-output hashes, they will be lost and the FFI caller will receive incomplete data.

-let mut outbound_tx = CompletedTransaction::from_outbound(tx.clone(), Vec::new());
+let mut outbound_tx = CompletedTransaction::from_outbound(
+    tx.clone(),
+    tx.sent_output_hashes.clone(), // preserve any hashes that exist
+);

Please double-check that OutboundTransaction no longer contains these hashes, or propagate them as shown.


9321-9324: Same concern as above for single-transaction retrieval

The per-transaction branch replicates the empty‐vector issue. Consider the same fix to avoid losing data:

-let mut outbound_tx = CompletedTransaction::from_outbound(tx.clone(), Vec::new());
+let mut outbound_tx = CompletedTransaction::from_outbound(
+    tx.clone(),
+    tx.sent_output_hashes.clone(),
+);
base_layer/core/src/transactions/transaction_components/wallet_output.rs (2)

43-43: LGTM!

Import path update aligns with the module restructuring.


402-431: Well-implemented method for updating encrypted data.

The method correctly updates the metadata signature when encrypted data changes, which is essential for maintaining the cryptographic integrity of the wallet output.

base_layer/core/src/transactions/test_helpers.rs (1)

46-46: LGTM!

Import path update is consistent with the module restructuring.

base_layer/wallet/src/output_manager_service/handle.rs (2)

35-35: LGTM!

Import path update is consistent with the module restructuring.


69-69: API enhancement for explicit change output handling.

The addition of optional change outputs to the confirmation request improves the explicit handling of change outputs during transaction confirmation, aligning with the PR's goal of ensuring payment references persist during recovery.

Also applies to: 615-622

base_layer/wallet/src/transaction_service/protocols/transaction_send_protocol.rs (3)

41-41: LGTM!

Import path update is consistent with the module restructuring.


340-340: Correct handling of unfinalized transaction state.

Passing None for change outputs at this stage is appropriate since the transaction hasn't been finalized yet.


601-622: Excellent implementation of finalized change output handling.

The logic correctly retrieves the finalized change output after transaction finalization and ensures it's properly confirmed with the output manager service. This aligns perfectly with the PR's objective of ensuring payment references persist during recovery.

base_layer/wallet/src/transaction_service/service.rs (1)

3342-3346: Wildcard arm may hide important PaymentId variants

The fallback _ captures any new/legacy PaymentId variants, but unlike the explicit arms it leaves source_address/destination_address unset, causing them to default to TariAddress::default().
This can mis-classify recovered transactions and break payref look-ups.

Add explicit matches for the legacy variants or at minimum log a warning when hitting the fallback so that address derivation can be revisited.

base_layer/wallet/src/output_manager_service/service.rs (3)

58-59: Import update looks correct – new payment_id path matches the refactor, nothing else to flag here.


1145-1161: Possible duplicate-row hazard with change outputs

You insert a pre-finalised change output via encumber_outputs and later pass the finalised version here.
If confirm_encumbered_outputs treats the incoming vector as new rows rather than updates, a unique-constraint violation (or silent duplicate) is possible.

Please confirm the DB layer performs an upsert/update keyed on output hash/commitment before merging this final record.


2098-2102: Order of operations LGTM

Finalising before reading the change output guarantees the metadata signature is complete; fee is already captured.
No issues spotted.

base_layer/core/src/transactions/transaction_components/payment_id.rs (1)

684-719: Change output’s PaymentId never written back – causes stale metadata

payment_id is cloned, mutated (hash list added) and passed to encrypt_data_for_recovery, but
change_output.payment_id itself is left unchanged.
Down-stream code that inspects WalletOutput.payment_id (without decrypting) will see the
pre-mutation value.

Add the assignment after change_encrypted_data:

-            let mut change_output = change.output.clone();
+            let mut change_output = change.output.clone();
+            change_output.payment_id = payment_id.clone();

Likely an incorrect or invalid review comment.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jun 17, 2025

Test Results (CI)

    3 files    126 suites   42m 23s ⏱️
1 343 tests 1 342 ✅ 0 💤 1 ❌
4 027 runs  4 026 ✅ 0 💤 1 ❌

For more details on these failures, see this check.

Results for commit 7636c4d.

♻️ This comment has been updated with latest results.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Jun 17, 2025

Test Results (Integration tests)

 2 files  + 2  1 errors  1 suites  +1   24m 43s ⏱️ + 24m 43s
 8 tests + 8  7 ✅ +7  0 💤 ±0  1 ❌ +1 
10 runs  +10  7 ✅ +7  0 💤 ±0  3 ❌ +3 

For more details on these parsing errors and failures, see this check.

Results for commit cc148b5. ± Comparison against base commit e0ab8d1.

♻️ This comment has been updated with latest results.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
base_layer/core/src/transactions/transaction_components/payment_id.rs (1)

428-430: Avoid unnecessary allocation

address_bytes is already a Vec<u8>.
extend_from_slice(&address_bytes.to_vec()) copies it into a new buffer just to copy again. Use the slice directly:

-bytes.extend_from_slice(&address_bytes.to_vec());
+bytes.extend_from_slice(&address_bytes);

Saves one allocation and a memcpy per serialization.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 20bd52f and cc148b5.

📒 Files selected for processing (2)
  • base_layer/core/src/transactions/transaction_components/payment_id.rs (1 hunks)
  • base_layer/wallet/src/transaction_service/service.rs (14 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • base_layer/wallet/src/transaction_service/service.rs
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: test (mainnet, stagenet)
  • GitHub Check: test (nextnet, nextnet)
  • GitHub Check: test (testnet, esmeralda)
  • GitHub Check: cargo check with stable
  • GitHub Check: ci
  • GitHub Check: Cucumber tests / Base Layer
  • GitHub Check: Cucumber tests / FFI

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (1)
base_layer/core/src/transactions/transaction_components/payment_id.rs (1)

400-407: Still panics on oversize inputs – replace expect on u8::try_from

The earlier review pointed out that u8::try_from(..).expect(..) will panic for lengths ≥ 256.
These calls are unchanged and can still crash a node/wallet when serialising large user-data, atypical addresses or many sent_output_hashes.

- bytes.push(u8::try_from(address_bytes.len()).expect("Address length must fit in u8"));
+ let len = u8::try_from(address_bytes.len())
+     .map_err(|_| PaymentIdError::ValueTooLarge)?;        // define an error & bubble up
+ bytes.push(len);

- bytes.push(u8::try_from(user_data.len()).expect("User data length should fit in a u8"));
+ let len = u8::try_from(user_data.len())
+     .map_err(|_| PaymentIdError::ValueTooLarge)?;
+ bytes.push(len);

- bytes.push(u8::try_from(sent_output_hashes.len()).expect("Sent output hashes length should fit in a u8"));
+ let len = u8::try_from(sent_output_hashes.len())
+     .map_err(|_| PaymentIdError::ValueTooLarge)?;
+ bytes.push(len);

Consider making to_bytes() fallible (-> Result<Vec<u8>, PaymentIdError>) or upgrading to a wider prefix (u16 / varint).
Untrusted data paths must never rely on expect.

Also applies to: 421-427

🧹 Nitpick comments (2)
base_layer/wallet/src/output_manager_service/service.rs (2)

410-415: Prefer unwrap_or_default() to avoid an unnecessary Vec allocation

unwrap_or(Vec::new()) allocates every time the branch is taken. Option<Vec<T>>::unwrap_or_default() is shorter, avoids the allocation, and is more idiomatic.

-                let change_outputs = change.unwrap_or(Vec::new());
+                let change_outputs = change.unwrap_or_default();

2133-2154: Minor: pre-allocate and preserve OutputSource when converting change outputs

let mut change = Vec::with_capacity(change_outputs.len());
for output in change_outputs {
    change.push(
        DbWalletOutput::from_wallet_output(
            output,
            &self.resources.key_manager,
            None,
-           OutputSource::default(),
+           // Preserve original source if available
+           OutputSource::default(), // <— consider exposing source on WalletOutput
            ...
  1. Vec::with_capacity avoids reallocations.
  2. If the caller knew the OutputSource (e.g. OutputSource::Change), we lose that information here. Either expose it on WalletOutput or accept it as a parameter so the DB keeps accurate provenance.

Both are low-impact tweaks but improve clarity and performance.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cc148b5 and 6597d35.

📒 Files selected for processing (4)
  • base_layer/core/src/transactions/transaction_components/payment_id.rs (1 hunks)
  • base_layer/wallet/src/output_manager_service/service.rs (14 hunks)
  • base_layer/wallet/src/transaction_service/service.rs (14 hunks)
  • base_layer/wallet_ffi/src/lib.rs (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • base_layer/wallet_ffi/src/lib.rs
  • base_layer/wallet/src/transaction_service/service.rs
⏰ Context from checks skipped due to timeout of 90000ms (7)
  • GitHub Check: test (nextnet, nextnet)
  • GitHub Check: test (testnet, esmeralda)
  • GitHub Check: test (mainnet, stagenet)
  • GitHub Check: cargo check with stable
  • GitHub Check: ci
  • GitHub Check: Cucumber tests / Base Layer
  • GitHub Check: Cucumber tests / FFI
🔇 Additional comments (2)
base_layer/wallet/src/output_manager_service/service.rs (1)

58-60: Imports look correct – update aligns the file with the new payment_id module path.

base_layer/core/src/transactions/transaction_components/payment_id.rs (1)

190-196: Pattern-match now compiles – good catch

Replacing PaymentId::Raw { .. } with the tuple pattern PaymentId::Raw(_) resolves the compilation error flagged earlier.
No further changes required here.

Comment on lines 1544 to 1546

self.confirm_encumberance(tx_id)?;
self.confirm_encumberance(tx_id, Vec::new()).await?;

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.

⚠️ Potential issue

Calling confirm_encumberance before stp.finalize() drops change-output metadata

Here confirm_encumberance is invoked before the protocol is finalised, and before any change output is available.
Because confirm_encumberance is the only place where confirm_encumbered_outputs can update the DB with the final encrypted-data / metadata-signature fields, this ordering means:

  1. The DB entry for the change output (added later by finalize) is never updated.
  2. Wallet recovery will still miss the pay-ref data this PR intends to preserve.

Move the call after stp.finalize(&self.resources.key_manager).await? and pass the finalised change output:

-        self.confirm_encumberance(tx_id, Vec::new()).await?;
-
-        // Prepare receiver part of the transaction
+        stp.finalize(&self.resources.key_manager).await?;
+        if let Some(co) = stp.get_finalized_change_output()? {
+            self.confirm_encumberance(tx_id, vec![co]).await?;
+        } else {
+            self.confirm_encumberance(tx_id, Vec::new()).await?;
+        }
+
+        // Prepare receiver part of the transaction

The same pattern appears in create_coin_split_even, spend_backup_pre_mine_utxo, create_coin_split, create_coin_join, create_claim_sha_atomic_swap_transaction, and create_htlc_refund_transaction. Please audit all call-sites to ensure confirm_encumberance runs after finalisation with the actual change outputs supplied.

Copy link
Copy Markdown
Contributor

@hansieodendaal hansieodendaal left a comment

Choose a reason for hiding this comment

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

Looking good, just some comments below.

Not tested at system-level

@SWvheerden SWvheerden merged commit 2737a14 into tari-project:development Jun 18, 2025
10 of 12 checks passed
@SWvheerden SWvheerden deleted the sw_payref_payment_id branch June 18, 2025 10:14
sdbondi added a commit to sdbondi/tari that referenced this pull request Jun 18, 2025
* development:
  chore: new release v4.5.0-pre.0 (tari-project#7228)
  chore: better logging (tari-project#7226)
  feat!: ensure payref persists during recovery (tari-project#7225)
  chore(ci): split out amd64 and arm64 docker builds into native runners (tari-project#7206)
  fix: fix scanner service when connectivity offline (tari-project#7223)
  feat: add payref to grpc outputs (tari-project#7216)
@coderabbitai coderabbitai bot mentioned this pull request Jun 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants