interfaces: typed receive-request APIs #34838

pull MkDev11 wants to merge 1 commits into bitcoin:master from MkDev11:feat/issue-34629-typed-receive-request-api changing 5 files +161 −73
  1. MkDev11 commented at 3:10 am on March 17, 2026: none

    Problem

    The interfaces::Wallet receive-request API uses raw serialized strings, coupling GUI code to the wallet’s internal storage format. The GUI serializes/deserializes RecentRequestEntry objects itself, and crashes if deserialization fails on malformed data. The GUI also owns ID assignment, which should be the wallet’s responsibility.

    Root Cause

    getAddressReceiveRequests() returns vector<string> of opaque serialized blobs, and setAddressReceiveRequest() accepts the same — forcing the GUI to own the serialization format (RecentRequestEntry + SendCoinsRecipient SERIALIZE_METHODS in Qt code). The SpanReader deserialization in RecentRequestsTableModel::addNewRequest(const std::string&) throws on malformed data with no error handling.

    Solution

    Replace the two raw-string methods with three typed methods on interfaces::Wallet:

    • getReceiveRequests() → returns vector<WalletReceiveRequest> with typed fields
    • addReceiveRequest() → wallet assigns ID + timestamp, serializes internally, returns assigned ID
    • eraseReceiveRequest() → deletes by destination + ID

    Serialization moves to wallet/interfaces.cpp using local RecipientData/RequestEntryData structs that are byte-identical to the Qt-side SendCoinsRecipient/RecentRequestEntry format, but have no Qt dependency. Malformed entries are logged and skipped instead of crashing. DB format is unchanged for full backward/forward compatibility.

    Testing

    • Updated existing GUI test (src/qt/test/wallettests.cpp) to verify the new typed API:
      • Round-trip: add request via GUI → getReceiveRequests() returns correct typed fields
      • Erase: remove request → getReceiveRequests() returns empty
    • Existing wallet-layer test (LoadReceiveRequests in wallet_tests.cpp) unchanged — CWallet internals not modified
    • Verify: cmake --build build && build/bin/test_bitcoin-qt

    Before / After

    • Before: GUI deserializes raw strings from wallet. SpanReader throws on malformed data → GUI crash. GUI owns ID assignment. Single method setAddressReceiveRequest overloaded for both save (non-empty value) and delete (empty value).
    • After: Wallet returns typed WalletReceiveRequest structs. Malformed entries are logged and skipped. Wallet assigns IDs and timestamps. Separate addReceiveRequest / eraseReceiveRequest methods.

    Edge Cases Handled

    • Malformed/corrupted DB entries: caught with try/catch, logged via LogWarning, skipped
    • ID=0 entries: skipped on load (matches previous GUI behavior)
    • Invalid destination address on add: returns nullopt
    • ID collision with existing entries: scans all existing IDs to find max, assigns max+1
    • Empty label/message/zero amount: handled correctly (no special-casing needed)
    • Thread safety: all methods hold LOCK(m_wallet->cs_wallet)
    • Legacy BIP70 fields (sPaymentRequest, authenticatedMerchant): preserved in serialization format for DB compatibility

    Closes #34629

  2. interfaces: typed receive-request APIs
    Replace getAddressReceiveRequests() and setAddressReceiveRequest() with
    three typed methods: getReceiveRequests(), addReceiveRequest(), and
    eraseReceiveRequest(). This moves serialization responsibility from the
    GUI to the wallet interface layer, decoupling Qt code from the wallet
    storage format.
    
    Add WalletReceiveRequest struct to interfaces/wallet.h carrying typed
    fields (id, time, address, label, message, amount) instead of opaque
    serialized blobs.
    
    The wallet now:
    - Assigns request IDs (previously done by GUI)
    - Assigns timestamps
    - Handles serialization/deserialization with graceful error recovery
      (malformed entries are logged and skipped instead of crashing the GUI)
    - Uses separate add/erase methods instead of overloading a single setter
    
    DB format is unchanged for full backward/forward compatibility. Local
    serialization-compatible structs (RecipientData, RequestEntryData) in
    wallet/interfaces.cpp mirror the Qt-side format without Qt dependencies.
    
    Closes #34629
    441eeba76f
  3. DrahtBot added the label interfaces on Mar 17, 2026
  4. DrahtBot commented at 3:10 am on March 17, 2026: contributor

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    Reviews

    See the guideline for information on the review process. A summary of reviews will appear here.

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #33034 (wallet: Store transactions in a separate sqlite table by achow101)
    • #32763 (wallet: Replace CWalletTx::mapValue and vOrderForm with explicit class members by achow101)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  5. MkDev11 commented at 7:20 pm on March 17, 2026: none
    @fanquake @hebasto Can you review the PR and let me know your feedback?
  6. hebasto commented at 11:47 am on March 18, 2026: member
  7. sedited added the label Wallet on Mar 20, 2026
  8. MkDev11 commented at 1:45 am on March 24, 2026: none
    @achow101 @johnny9 can you review the PR and let me know your feedback? thanks.

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-03-24 03:12 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me