Skip to content

Conversation

@kwvg
Copy link
Collaborator

@kwvg kwvg commented Jan 11, 2025

Additional Information

  • Dependent on backport: merge bitcoin#25497, #17331, #22155 (wallet backports: part 1) #6517

  • Dependent on refactor: polish CoinJoin interface, use WalletLoader in Dash wallet initialization code, introduce new RPC coinjoin status #6594

  • bitcoin#19101 has been split into two due to it performing two refactors in one commit, the first half deals with utilizing interfaces and managers as defined in WalletContext (as opposed to either passing them in separately as arguments or accessing them through globals) and the second half deals with deglobalizing wallet variables like ::vpwallets and cs_wallets.

    • WalletContext still needs to be initialized with a constructor as it stores a const-ref std::unique_ptr of interfaces::CoinJoin::Loader. This requirement hasn't been done away with. Tests that don't have access to coinjoin_loader will still need to pass nullptr.

    • Bitcoin registers wallet RPCs through WalletClient::registerRpcs() (source), which a part of the ChainClient interface (source). They are enumerated (source) differently from non-wallet RPCs (source).

      Wallet RPCs aren't supposed to have knowledge of NodeContext and likewise non-wallet RPCs aren't supposed to have knowledge of WalletContext. So far, Bitcoin has reworked their RPCs to maintain this separation and upstream RPCs are a part of the libbitcoin_wallet library.

      This isn't the case for some Dash RPCs, many of which reside in libbitcoin_server, some of which fit into two categories.

      • Requires knowledge of both NodeContext and WalletContext

        • Knowledge of WalletContext wasn't mandatory before deglobalization as wallet information could be accessed through the global context courtesy of ::vpwallets and friends but now that it is, many RPCs need to be able to access WalletContext when otherwise they wouldn't need to.
        • Due to the mutual exclusivity mentioned above, RPCs that access WalletContext cannot access NodeContext as their RPC registration logic doesn't give them access to NodeContext (source, m_context here is WalletContext) but in order to give those RPCs WalletContext, we need to register them as wallet RPCs, which prevent us from accessing NodeContext.
        • This has been tentatively worked around by including a pointer to NodeContext in WalletContext (source) and modifying EnsureAnyNodeContext() to fetch from WalletContext if regular behavior doesn't yield a NodeContext (source).
      • Are RPCs that possess both wallet and non-wallet functionality (i.e. have "reduced" capabilities if wallet support isn't compiled in as opposed to being absent altogether).

        • To enable wallet functionality, the RPCs need to be registered as wallet RPCs. If wallet functionality is disabled, those RPCs are not registered. Simple enough, unless you have an RPC that can partially work if wallet functionality as disabled, as the lack of registration would mean those RPCs are entirely inaccessible.
        • This is also tentatively worked around by registering them as non-wallet RPCs in the cases where wallet RPCs aren't registered (i.e. if wallet support isn't compiled in or if wallet support is disabled at runtime).
          • Bitcoin doesn't use #ifndef ENABLE_WALLET for checking if support is absent, we're expected to use !g_wallet_init_interface.HasWalletSupport() (which will always evaluate false if support isn't compiled in, source, as the stub wallet would be utilized to initialize the global in those cases, source). This has been done in the PR.

          • A notable change in this PR is that a lot of behavior that would be enabled if support was compiled in but disabled at runtime would now be disabled if support was disabled at runtime as wallet_loader won't be initialized if runtime disablement occurs (source), which in turns means that anything that relies on wallet_loader wouldn't work either, such as coinjoin_loader.

            This means that we also need to register the RPC as a non-wallet RPC if support is compiled in but disabled at runtime (source).

    • To register RPCs as wallet RPCs, generally they're done through WalletClient::registerRpcs(), which iterates through GetWalletRPCCommands(). This is perfectly fine as both reside in libbitcoin_wallet. Unfortunately, our Dash RPCs reside in libbitcoin_server and registerRpcs() cannot be extended to enumerate through RPCs not included in its library.

      We cannot simply move the Dash RPCs either (at least in its current state) as they rely on non-wallet logic, so moving the source files for those RPCs into libbitcoin_wallet would pull more or less, all of libbitcoin_server along with it.

      • To tentatively get around this, a new method has been defined, WalletLoader::registerOtherRpcs(), which will accept any set of RPCs for registration (source) and we use it in RPC init logic (source).
    • Some usage of CoreContext had to be removed (source) as without those removals, the test suite would crash.

      Crash:
      dash@01fd4f6cfa52:/src/dash$ lldb ./src/test/test_dash
      (lldb) target create "./src/test/test_dash"
      Current executable set to '/src/dash/src/test/test_dash' (x86_64).
      (lldb) r -t wallet_tests
      Process 653232 launched: '/src/dash/src/test/test_dash' (x86_64)
      Running 17 test cases...
      unknown location(0): fatal error: in "wallet_tests/CreateTransactionTest": unknown type
      wallet/test/wallet_tests.cpp(1052): last checkpoint
      
      *** 1 failure is detected in the test module "Dash Core Test Suite"
      Process 653232 exited with status = 201 (0x000000c9)
      
  • The assertion introduced in bitcoin#22686 (source) has not been backported as this assertion is downgraded to an error in bitcoin#26611 and then further modified in bitcoin#26643 (source), portions of which are already included in dash#6517 (source).

  • bitcoin#23288 finished what e3687f7 (dash#6078) started and coinselection_tests has now been realigned with upstream.

    • Dash-specific tests in wallet_tests (as introduced in dash#3367) have not been moved over to descriptor wallets and are still based on legacy wallets (to this effect, the old AddKey logic has been retained as AddLegacyKey, source).

      • To prevent merge conflicts, Dash-specific tests have been moved to the end of the source file and demarcated by a comment (source).

How Has This Been Tested?

6813863 was tested on Debian 12 (bookworm) mixing ~1 tDASH on default settings.

CoinJoin run

Breaking Changes

  • The RPCs coinjoin, coinjoinsalt, getpoolinfo, gobject list-prepared, gobject prepare, gobject vote-alias, gobject vote-many, masternode outputs, protx update*, protx register* and protx revoke will no longer be available if wallet support is disabled at runtime. This is not a change in functionality as they were already inoperative with disabled wallets but is a change in reporting as they would not be available at all.

Checklist

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have made corresponding changes to the documentation (note: N/A)
  • I have assigned this pull request to a milestone (for repository code-owners and collaborators only)

@kwvg kwvg added this to the 23 milestone Jan 11, 2025
@kwvg kwvg force-pushed the wbps_p2 branch 3 times, most recently from e622444 to eea8e42 Compare January 13, 2025 01:08
@kwvg kwvg requested a review from UdjinM6 January 14, 2025 08:02
@github-actions
Copy link

This pull request has conflicts, please rebase.

@github-actions
Copy link

This pull request has conflicts, please rebase.

PastaPastaPasta added a commit that referenced this pull request Feb 6, 2025
…tcoin#22155 (wallet refactoring)

2c3d9cf merge bitcoin#21207: CWallet transaction code out of wallet.cpp/.h (Kittywhiskers Van Gogh)
a21691a partial bitcoin#22155: Add test for subtract fee from recipient behavior (Kittywhiskers Van Gogh)
829510c merge bitcoin#15596: Ignore sendmany::minconf as dummy value (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  As [dash#6517](#6517) and [dash#6529](#6529) both introduce behavior changes and workarounds that, changes from both PRs that do not affect behavior have been extracted and spun-off into this PR and they will be subsequently rebased on this PR upon merger into `develop`. This should let us at least get some of the larger (mostly move-only) diffs merged in and ease review for the aforementioned PRs.

  [bitcoin#21207](bitcoin#21207) can be reviewed using `git log -p -n1 --color-moved=dimmed_zebra`

  ## Breaking Changes

  None expected, no changes in behavior.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas **(note: N/A)**
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 2c3d9cf
  PastaPastaPasta:
    utACK 2c3d9cf

Tree-SHA512: 3e5bb5869793b389aefbe0e97b1cedd13d06abce2ad06d1c16c0f8ecd4e0fa7f148fa5d89653c76ac97171787b35525ec20ece1ea753fb97eebec95a456411e2
PastaPastaPasta added a commit that referenced this pull request Feb 12, 2025
 (wallet backports: part 1)

153bdc2 merge bitcoin#22155: Add test for subtract fee from recipient behavior (Kittywhiskers Van Gogh)
0185847 fix: correct fee calculations in `CreateTransactionInternal` (Kittywhiskers Van Gogh)
445f489 merge bitcoin#17331: Use effective values throughout coin selection (Kittywhiskers Van Gogh)
7e54bd9 wallet: copy and sort `vecSend` if BIP69 sorting enabled, enable sorting (Kittywhiskers Van Gogh)
9e9e66f partial bitcoin#17331: Use effective values throughout coin selection (Kittywhiskers Van Gogh)
66fe2d4 merge bitcoin#25497: more accurate target for large transactions (Kittywhiskers Van Gogh)
6e4d789 wallet: add back missing `CoinSelectionParams` assignments (Kittywhiskers Van Gogh)
bd35042 wallet: move `CoinSelectionParams` to positions expected upstream (Kittywhiskers Van Gogh)
0711e67 wallet: shuffle transaction inputs if we aren't using BIP69 (Kittywhiskers Van Gogh)
1cf1c58 refactor: move selected coin and txin sorting to the end of the scope (Kittywhiskers Van Gogh)
ab756ba wallet: Fail if maximum weight is too large (Kittywhiskers Van Gogh)
05c319e refactor: move oversized transaction check to tail end of scope (Kittywhiskers Van Gogh)
6ca51df wallet: Use existing feerate instead of getting a new one (Kittywhiskers Van Gogh)

Pull request description:

  ## Additional Information

  * Dependent on #6543

  * Dependency for #6529

  * [bitcoin#17331](bitcoin#17331) logically partially reverts [dash#3368](#3668) as Dash Core implemented a calculate-before approach (compared to _then_ Bitcoin Core's calculate-and-adjust approach) and it is being replaced  with the current upstream calculate-after approach done in a single-pass instead of iteratively (like the former two).
    * As the changes are non-trivial, they have been split into a "partial" and a "merge" commit, the first half dedicated just to the logical partial revert and the latter half dedicated to using effective values in coin selection.
      * BIP69 sorting is disabled in the former half to allow the fix to be in a separate commit while allowing validation of the remaining set of changes. The fix re-enables BIP69 sorting.
    * Due to the changes introduced in [dash#3368](#3668), a lot of then-redundant code was removed and changes to it upstream were not mirrored in Dash Core. To allow [bitcoin#17331](bitcoin#17331) to work properly, a lot of that unmirrored code was reintroduced and existing code readjusted to match upstream.

  * `coin_selection_params.tx_noinputs_size` is said to have a size (sans output count) of `9` instead of `10` as we don't have a SegWit field (referred to as `1 witness overhead (dummy, flag, stack size)` in a code comment) on account of not having SegWit.

  * To allow for backporting [bitcoin#17331](bitcoin#17331), portions of [bitcoin#21083](bitcoin#21083) (1a6a0b0) and [bitcoin#20536](bitcoin@51e2cd3) (3e69939) were backported.

  * [bitcoin#17331](bitcoin#17331) seems to have silently broken `CreateTransactionInternal` as functional tests fail (see below) despite the backport not intending to change behavior. This was caught due to unit tests introduced in [dash#3667](#3667).

    The aberration seems be remedied by portions of [bitcoin#25647](bitcoin#25647) and [bitcoin#26643](bitcoin#26643) and they have been incorporated into this pull request in a separate commit.

    **Special thanks to UdjinM6 for figuring this out!** 🎉

    <details>

    <summary>Error log:</summary>

    ```
     dash@479e0aa4ebbf:/src/dash$ ./src/test/test_dash -t coinselector_tests,wallet_tests
     Running 21 test cases...
     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 2 - 5

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 4 - 4

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 4 - 5

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 6 - 0

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 6 - 2

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 6 - 4

     wallet/test/wallet_tests.cpp(749): error: in "wallet_tests/CreateTransactionTest": check expected == actual has failed [false != true]
     CreateTransactionTest failed at: 6 - 5

     *** 7 failures are detected in the test module "Dash Core Test Suite"
    ```

    </details>

  ## How Has This Been Tested?

  153bdc2 was tested on Debian 12 (`bookworm`) mixing ~2 tDASH on default settings.

  ![CoinJoin run](https://github.com/user-attachments/assets/da1f13e7-dd83-4211-8d42-0cd4c770bbf1)

  ## Breaking Changes

  * If a transaction isn't shuffled using BIP69 (i.e. if an explicit position for the change txout is specified), it will be randomly shuffled (mirroring upstream behavior, [source](https://github.com/bitcoin/bitcoin/blob/51a3ac242c92e69b59df26f8f9e287b31e5c3b0f/src/wallet/wallet.cpp#L3048)). This deviates from earlier behavior where no shuffling would be done at all if BIP69 isn't applied.

  ## Checklist

  - [x] I have performed a self-review of my own code
  - [x] I have commented my code, particularly in hard-to-understand areas
  - [x] I have added or updated relevant unit/integration/functional/e2e tests
  - [x] I have made corresponding changes to the documentation **(note: N/A)**
  - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  UdjinM6:
    utACK 153bdc2
  PastaPastaPasta:
    utACK 153bdc2

Tree-SHA512: 709b77dce3cea2bbf09eab42c7e70171c3bc6527ff4c387a4db75994da5c0d59025b641d90f734b87a62cdfa8e422d09513697a6e875635de2765a1c9141233e
@github-actions
Copy link

This pull request has conflicts, please rebase.

Comment on lines +776 to +781
/** When the actual feerate is less than the consolidate feerate, we will tend to make transactions which
* consolidate inputs. When the actual feerate is greater than the consolidate feerate, we will tend to make
* transactions which have the lowest fees.
*/
CFeeRate m_consolidate_feerate{DEFAULT_CONSOLIDATE_FEERATE};
Copy link
Member

Choose a reason for hiding this comment

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

we don't really need any of this; at least we should set DEFAULT_CONSOLIDATE_FEERATE to 0 or something to basically disable this logic?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Not sure if this is the best idea since m_consolidate_feerate is used to define coin_selection_params.m_long_term_feerate in CreateTransactionInternal (source) though I did find that the old code generated a fee-per-KB of 1000 and the commit changes it to a fee-per-KB of 10000.

This has been corrected in latest push.

@kwvg kwvg marked this pull request as ready for review February 14, 2025 15:04
@kwvg kwvg requested review from PastaPastaPasta, UdjinM6 and knst and removed request for UdjinM6 February 14, 2025 15:04
@coderabbitai
Copy link

coderabbitai bot commented Feb 14, 2025

Walkthrough

The changes refactor various components of the wallet and RPC systems. Multiple coin selection functions have been updated by renaming and enhancing their logic, including the renaming of SelectCoinsMinConf to AttemptSelection and the introduction of waste calculation. Legacy wallet behaviors such as the setup of legacy script public key management and address import methods have been removed in favor of descriptor-based setups. RPC command registration for features like CoinJoin, Evo, governance, and masternode functionalities has been reorganized so that wallet-specific commands are now grouped into dedicated functions returning spans of RPC commands. Across wallet interfaces, initialization, transaction creation, and test cases, function signatures have been updated to include new context objects (WalletContext and NodeContext) and new parameters (such as -consolidatefeerate) to better manage state. These modifications are consistently applied across benchmarks, wallet methods, RPC utilities, and test suites.

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ 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.
    • Generate unit testing code for this file.
    • 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 generate unit testing code for this file.
    • @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 generate unit testing code.
    • @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.

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. (Beta)
  • @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

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

🔭 Outside diff range comments (3)
src/wallet/wallet.cpp (1)

412-412: ⚠️ Potential issue

Duplicate definition of AddWallet detected

A second bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet) function appears to be defined here, with nearly identical logic to the one at lines [112-126], risking a merge conflict or ODR violation. Remove or merge the extra definition to restore clarity and compilation safety:

-// Potential removal of the duplicate function starting at line 412:
-bool AddWallet(WalletContext& context, const std::shared_ptr<CWallet>& wallet)
-{
-    // ...
-    return true;
-}

Failure to address this duplication will likely break builds or cause runtime conflicts.

src/rpc/evo.cpp (1)

1-1: ⚠️ Potential issue

Resolve conflicts with other PRs.

The pipeline indicates potential conflicts with other pull requests. Please rebase your branch on the latest main branch and resolve any conflicts.

🧰 Tools
🪛 GitHub Actions: Check Potential Conflicts

[error] 1-1: Conflict detected with multiple pull requests.

src/init.cpp (1)

1-2460: ⚠️ Potential issue

Warning: Potential merge conflicts detected.

The pipeline failure indicates conflicts with other PRs. Please resolve the conflicts before merging.

🧰 Tools
🪛 Cppcheck (2.10-2)

[error] 830-830: syntax error

(syntaxError)

🪛 GitHub Actions: Check Potential Conflicts

[error] 1-1: Conflict detected with multiple pull requests.

🧹 Nitpick comments (28)
src/wallet/load.cpp (3)

58-58: Loading default (unnamed) wallet conditionally is clear.
If additional wallet constraints (like encryption or custom options) arise, review that this logic gracefully handles them.


125-131: Creation of wallet with CWallet::Create and immediate addition via AddWallet is well-sequenced.
Make sure that over time, if more wallet configuration steps are added, they occur before usage.


164-166: StopWallets approach
Closing wallets in a loop is straightforward. Ensure that any new potential concurrency with the scheduler is addressed (e.g., ensure tasks are not referencing closed wallets).

src/qt/test/wallettests.cpp (1)

118-127: Descriptor-based setup logic
Properly setting up scriptPubKey managers and adding the descriptor within the locked wallet is a clear workflow. Test coverage on these steps is recommended to validate descriptor function.

src/wallet/interfaces.cpp (1)

568-580: New RegisterRPCs method
Declares a local request object with context = m_context. This approach isolates wallet-specific RPCs. Encourage further decoupling of non-wallet RPC logic if needed.

src/wallet/test/coinselector_tests.cpp (3)

130-139: Assess code reuse for KnapsackGroupOutputs.
This helper function duplicates logic from existing grouping methods but imposes zero-based fees (CFeeRate(0)) for testing. If additional scenarios require different fee rates, consider parameterizing them to avoid code duplication.


271-271: Improve inline comment clarity.
The comment referencing effective value for AttemptSelection is fairly brief. Consider expanding it to clarify why BnB must handle negative effective values carefully.


300-300: Clarify block scope.
A new block is opened at line 300 without an explanatory comment. Consider adding a short note describing the test scope or using a separate test function for clarity.

src/wallet/wallet.h (3)

52-52: Context parameter injection.
Introducing WalletContext& as the first parameter in wallet management functions centralizes context usage. This is a good pattern to reduce global dependencies but may need updates in unit tests or legacy code that previously used static references.


63-70: Unified wallet load/unload functions.
Replacing separate calls with AddWallet, RemoveWallet, LoadWallet, CreateWallet, etc. that accept a WalletContext& clarifies the relationship between wallets and the node context. This enforces better scoping but watch for potential initialization order issues if called too early.


1090-1091: MaybeResendWalletTxs consolidation.
Global function now requires WalletContext&, ensuring that no global wallet lists are used. This is consistent with deglobalization efforts. Confirm older code uses the new pattern.

src/wallet/test/wallet_tests.cpp (1)

93-102: AddKey now leverages descriptor-based approach
Transitioning to descriptors is correct. However, relying on assert(false) for error handling can abruptly terminate tests. Consider throwing an exception or returning an error to facilitate robust handling.

src/wallet/wallet.cpp (6)

112-126: Check return values for downstream calls

While adding the wallet to the global list is carefully protected by a scoped mutex lock, note that some subsequent helper calls (ConnectScriptPubKeyManNotifiers, coinjoin_loader().AddWallet, etc.) do not have their return values checked. It might be beneficial to verify their success or at least log potential failures.


128-150: Consider error handling after RemoveWallet

This function properly locks the wallet list and removes the wallet. However, similar to the counterpart in AddWallet, the downstream call wallet->coinjoin_loader().RemoveWallet(name) is not checked for errors. Consider adding logging or conditional handling to help diagnose unexpected failures or partial states.


152-156: Delegate function could be consolidated

This overload simply delegates to the version accepting a std::vector<bilingual_str>& warnings. If there’s no compelling usage outside of simplifying calls, you could consider consolidating them to reduce maintenance overhead.


158-162: Linear lookup of wallets

The function locks the wallet vector and then returns it. For systems expected to carry many wallets, consider using a more direct data structure (e.g., an unordered container) if lookups or enumerations become performance-critical. Currently, this is fine for smaller sets of wallet contexts.


283-367: Streamline creation & initialization

This large block effectively orchestrates wallet creation, optional HD usage, essential calls to AddWallet, and UpdateWalletSetting. A few suggestions:

  1. Repeated initMessage: The chain’s initMessage("Loading wallet…") is called in multiple places. Consider centralizing or deduplicating these progress messages if they appear in multiple flows.
  2. Error propagation: Similar to AddWallet, error returns from calls like coinjoin_loader().AddWallet (if any) could be handled or at least logged to clarify partial failures.
  3. -usehd logic: The HD-related branch at line 313 might be more self-documenting if you add logs clarifying whether the existing wallet is updated or remains as-is.

Overall, these refinements can make the creation process more robust and maintainable.


391-391: Missing null-check after LoadWallet

After calling LoadWallet(...), consider explicitly checking if wallet is null to log or handle the error path more verbosely, especially if status or error indicates a partial failure or ongoing conflict.

src/wallet/rpcwallet.cpp (2)

2956-2959: Refine reporting of database operation outcomes.

Storing the outcomes in status, error, and warnings is good practice. However, consider logging or returning partial diagnostic data to help pinpoint root causes when RestoreWallet fails or returns warnings. This extra insight can speed up debugging in production.

Also applies to: 2961-2961


3013-3013: Incorporate warning details during removal failure.

If RemoveWallet(...) fails, returning the collected warnings in the thrown error message can aid troubleshooting. This will give end users and developers more context into why the removal might have failed.

src/wallet/context.h (1)

47-52:

❓ Verification inconclusive

Plan removal of NodeContext dependency.

The temporary node_context member allows wallet RPCs to access non-wallet capabilities. While pragmatic for now, this should be removed to maintain proper separation of concerns.

Let's identify wallet RPCs that depend on NodeContext:


🏁 Script executed:

#!/bin/bash
# Search for wallet RPC implementations accessing NodeContext
rg "node_context->" src/wallet/rpc/

Length of output: 37


Plan to Remove NodeContext Dependency – Please Verify Indirect Usage

The temporary node_context member in src/wallet/context.h (lines 47–52) currently enables wallet RPCs to access non-wallet capabilities. An initial search for direct references (using node_context-> in src/wallet/rpc/) produced no hits. However, please manually verify that wallet RPCs or related code do not access NodeContext indirectly before proceeding with removal:

  • Location: src/wallet/context.h (lines 47–52)
  • Action: Confirm that no wallet RPC implementation (or other wallet-related modules) relies on node_context to access non-wallet features.
  • Next Step: Once verified, plan for the complete removal of the node_context member to ensure a proper separation of concerns.
src/bench/wallet_balance.cpp (1)

47-50: Consider documenting the epoch iteration values.

While the epoch iteration values (2500, 8000, 16000) seem reasonable, it would be helpful to document why these specific values were chosen.

Add comments explaining the rationale:

-static void WalletBalanceDirty(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ true, /* add_mine */ true, 2500); }
-static void WalletBalanceClean(benchmark::Bench& bench) {WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 8000); }
-static void WalletBalanceMine(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 16000); }
-static void WalletBalanceWatch(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ false, 8000); }
+// Lower iterations for dirty benchmarks as they're slower
+static void WalletBalanceDirty(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ true, /* add_mine */ true, 2500); }
+// Clean operations can handle more iterations
+static void WalletBalanceClean(benchmark::Bench& bench) {WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 8000); }
+// Mining operations need more iterations for accurate measurements
+static void WalletBalanceMine(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ true, 16000); }
+// Watch-only operations use moderate iterations
+static void WalletBalanceWatch(benchmark::Bench& bench) { WalletBalance(bench, /* set_dirty */ false, /* add_mine */ false, 8000); }
src/dummywallet.cpp (1)

36-36: Document the consolidatefeerate parameter format.

The new hidden argument needs documentation for its expected format and valid range.

Add a comment explaining the parameter:

-        "-consolidatefeerate=<amt>",
+        // Fee rate (in DASH/kB) for consolidation transactions
+        "-consolidatefeerate=<amt>",
src/coinjoin/interfaces.cpp (1)

69-74: Consider initializing order and member initialization list style.

While the initialization is correct, the style could be improved for consistency.

Consider this style:

-    explicit CoinJoinLoaderImpl(CoinJoinWalletManager& walletman, interfaces::WalletLoader& wallet_loader) :
-        m_walletman{walletman},
-        m_wallet_loader{wallet_loader}
-    {
-        g_wallet_init_interface.InitCoinJoinSettings(m_wallet_loader, m_walletman);
-    }
+    explicit CoinJoinLoaderImpl(
+        CoinJoinWalletManager& walletman,
+        interfaces::WalletLoader& wallet_loader)
+        : m_walletman(walletman)
+        , m_wallet_loader(wallet_loader)
+    {
+        g_wallet_init_interface.InitCoinJoinSettings(m_wallet_loader, m_walletman);
+    }
src/rpc/server_util.cpp (1)

29-33: Document the workaround's limitations and risks.

The TODO comment indicates this is a temporary solution. Consider documenting potential issues and limitations.

Add detailed documentation:

-    // We're now going to try our luck with WalletContext on the off chance
-    // we're being called by a wallet RPC that's trying to access NodeContext
-    // See comment on WalletContext::node_context for more information.
-    // TODO: Find a solution that removes the need for this workaround
+    // WORKAROUND: Attempt to retrieve NodeContext from WalletContext
+    // This is a temporary solution for wallet RPCs that need NodeContext access.
+    // 
+    // Limitations:
+    // 1. Creates implicit dependency between wallet and node contexts
+    // 2. May hide architectural issues in RPC design
+    // 3. Could lead to subtle bugs if context ownership changes
+    // 
+    // TODO: Implement proper context management system that:
+    // - Maintains clear separation of concerns
+    // - Provides explicit context access patterns
+    // - Eliminates need for context fallback logic
src/wallet/coinselection.cpp (1)

406-431: LGTM: New waste calculation function.

The GetSelectionWaste function is well-implemented with:

  • Proper input validation using assert
  • Clear waste calculation logic
  • Appropriate handling of change costs
  • Good documentation of the calculation process

However, consider adding a test case to verify the waste calculation logic.

Would you like me to generate a test case for the GetSelectionWaste function?

test/functional/rpc_fundrawtransaction.py (1)

957-959: Rename unused loop variable.

The loop control variable i is not used within the loop body. Consider renaming it to _ or _i to indicate it's intentionally unused.

-        for i in range(0, 3):
+        for _ in range(0, 3):
🧰 Tools
🪛 Ruff (0.8.2)

957-957: Loop control variable i not used within loop body

Rename unused i to _i

(B007)

src/rpc/evo.cpp (1)

1811-1848: Consider future refactoring of hybrid RPCs.

The current implementation includes a well-documented workaround for handling wallet-disabled scenarios. As noted in the TODO comment, consider splitting these hybrid RPCs into dedicated wallet-only and wallet-free RPCs in the future to eliminate this workaround.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 265d9b5 and 6813863.

📒 Files selected for processing (44)
  • src/bench/coin_selection.cpp (1 hunks)
  • src/bench/wallet_balance.cpp (2 hunks)
  • src/bitcoin-cli.cpp (1 hunks)
  • src/coinjoin/client.cpp (2 hunks)
  • src/coinjoin/interfaces.cpp (3 hunks)
  • src/dummywallet.cpp (2 hunks)
  • src/init.cpp (4 hunks)
  • src/interfaces/coinjoin.h (2 hunks)
  • src/interfaces/wallet.h (5 hunks)
  • src/node/blockstorage.cpp (0 hunks)
  • src/qt/test/addressbooktests.cpp (2 hunks)
  • src/qt/test/wallettests.cpp (3 hunks)
  • src/rpc/coinjoin.cpp (3 hunks)
  • src/rpc/evo.cpp (3 hunks)
  • src/rpc/governance.cpp (1 hunks)
  • src/rpc/masternode.cpp (1 hunks)
  • src/rpc/register.h (2 hunks)
  • src/rpc/server_util.cpp (1 hunks)
  • src/test/util/setup_common.cpp (1 hunks)
  • src/test/util/wallet.cpp (0 hunks)
  • src/wallet/coinselection.cpp (3 hunks)
  • src/wallet/coinselection.h (1 hunks)
  • src/wallet/context.cpp (1 hunks)
  • src/wallet/context.h (2 hunks)
  • src/wallet/init.cpp (3 hunks)
  • src/wallet/interfaces.cpp (8 hunks)
  • src/wallet/load.cpp (7 hunks)
  • src/wallet/load.h (2 hunks)
  • src/wallet/rpc/util.cpp (1 hunks)
  • src/wallet/rpcwallet.cpp (6 hunks)
  • src/wallet/spend.cpp (5 hunks)
  • src/wallet/test/coinjoin_tests.cpp (3 hunks)
  • src/wallet/test/coinselector_tests.cpp (21 hunks)
  • src/wallet/test/init_test_fixture.cpp (1 hunks)
  • src/wallet/test/psbt_wallet_tests.cpp (3 hunks)
  • src/wallet/test/util.cpp (2 hunks)
  • src/wallet/test/wallet_test_fixture.cpp (1 hunks)
  • src/wallet/test/wallet_tests.cpp (15 hunks)
  • src/wallet/wallet.cpp (23 hunks)
  • src/wallet/wallet.h (8 hunks)
  • src/wallet/walletdb.cpp (1 hunks)
  • src/wallet/walletdb.h (2 hunks)
  • src/walletinitinterface.h (2 hunks)
  • test/functional/rpc_fundrawtransaction.py (2 hunks)
💤 Files with no reviewable changes (2)
  • src/test/util/wallet.cpp
  • src/node/blockstorage.cpp
✅ Files skipped from review due to trivial changes (2)
  • src/coinjoin/client.cpp
  • src/bitcoin-cli.cpp
🧰 Additional context used
🪛 GitHub Actions: Check Potential Conflicts
src/init.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/test/util/setup_common.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/rpc/evo.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/rpc/masternode.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/wallet/rpcwallet.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/rpc/governance.cpp

[error] 1-1: Conflict detected with multiple pull requests.

src/wallet/wallet.h

[error] 1-1: Conflict detected with multiple pull requests.

src/wallet/wallet.cpp

[error] 1-1: Conflict detected with multiple pull requests.

🪛 GitHub Actions: Clang Diff Format Check
src/rpc/evo.cpp

[warning] 1805-1805: Clang format differences found. Please format the code according to Clang standards.

src/rpc/masternode.cpp

[warning] 740-740: Clang format differences found. Please format the code according to Clang standards.

src/rpc/coinjoin.cpp

[warning] 486-486: Clang format differences found. Please format the code according to Clang standards.

src/rpc/governance.cpp

[warning] 1075-1075: Clang format differences found. Please format the code according to Clang standards.

🪛 Ruff (0.8.2)
test/functional/rpc_fundrawtransaction.py

957-957: Loop control variable i not used within loop body

Rename unused i to _i

(B007)

🔇 Additional comments (159)
src/wallet/load.h (2)

15-15: Forward declaration is clear and standard.
This forward declaration avoids unnecessary includes and circular dependencies. No issues found.


25-40:

✅ Verification successful

Verify that all calling sites have been updated to use the new WalletContext& parameter.
Switching from multiple parameters (e.g., interfaces::Chain) to a consolidated WalletContext& is a good design for maintainability. However, please confirm that any surrounding code and all function call sites have been updated accordingly, to avoid build or runtime errors.


🏁 Script executed:

#!/bin/bash
# Description: Verify that no outdated calls remain
rg -A2 "VerifyWallets\(interfaces::Chain" 
rg -A2 "LoadWallets\(interfaces::Chain" 
rg -A2 "StartWallets\(interfaces::Chain"
rg -A2 "FlushWallets()"
rg -A2 "StopWallets()"
rg -A2 "UnloadWallets()"

Length of output: 1783


All calling sites correctly use the new WalletContext parameter
The searches confirmed that there are no outdated calls remaining that reference interfaces::Chain—all invocations now correctly pass the consolidated WalletContext&. No further modifications are necessary based on the current state of the code.

src/wallet/rpc/util.cpp (3)

56-57: Ensure request.context is valid.
Acquiring the wallet context with EnsureWalletContext(request.context) is appropriate. If request.context is ever null or uninitialized, EnsureWalletContext will correctly throw an error, preventing undefined behavior.


60-60: Context-based wallet retrieval.
Switching from a global or direct approach to using GetWallet(context, wallet_name) clarifies ownership and scope of wallet objects. The error handling for nonexistent wallets is also correct.


65-65: Context-based wallet enumeration.
Using GetWallets(context) ensures that all loaded wallets are retrieved in a context-aware manner, aligning with the updated wallet design.

src/qt/test/addressbooktests.cpp (2)

69-73: Switch to descriptor-based wallets with proper locking.
Enabling WALLET_FLAG_DESCRIPTORS and then calling SetupDescriptorScriptPubKeyMans() within a locked wallet context is a solid approach for modern descriptor wallets. This ensures thread safety during wallet setup.


117-120: Context-based wallet lifecycle management.
Acquiring the wallet context from node.walletLoader() and using AddWallet/RemoveWallet reflects a consistent, modular approach. This helps prevent concurrency issues and keeps wallet state transitions clear.

src/wallet/load.cpp (7)

14-14: No issues with adding these includes.
They provide necessary references for assertion checks and wallet context usage.

Also applies to: 18-18


26-29: Encapsulation of chain and args in WalletContext is a clean approach.
Consolidating these references into a single context object simplifies function signatures and increases maintainability.


31-49: Check for edge cases when forcing -walletdir.
Ensuring the canonical path is valid and absolute is good. However, if args.ForceSetArg is called repeatedly or under different contexts, consider verifying that subsequent wallet logic still behaves as intended.


104-106: Refactoring LoadWallets to accept WalletContext& aligns well with your new architecture.
This helps ensure all necessary objects (chain, args, etc.) are consistently accessible.


140-150: Scheduler captures context by reference.
Verify that context outlives all scheduled tasks to avoid dangling references if the scheduler outlives the main scope.


153-155: FlushWallets usage
Flushing wallets here maintains consistency with existing design. No additional concerns.


171-178: Cautious unload approach
Removing from the context prior to unloading ensures the wallet is no longer tracked. This is a standard pattern and looks correct.

src/qt/test/wallettests.cpp (3)

112-116: Initialization with WalletContext and immediate descriptor flag
Good transition to descriptor-based wallets. This ensures the new wallet is recognized from the start.


147-147: Constructing WalletModel with MakeWallet(context, wallet)
The updated approach is consistent and ensures the wallet's context is properly injected.


259-259: Removal of wallet from test environment
A direct call to RemoveWallet(context, wallet, std::nullopt) is correct for test teardown. No issues found.

src/wallet/interfaces.cpp (7)

130-131: WalletImpl constructor uses a WalletContext&
This centralizes context-dependent logic. Good step towards modularizing wallet functions.


150-150: autoLockMasternodeCollaterals() bridging function
Straightforward delegate call. Ensure any future masternode-collateral changes remain in sync.


515-515: Removing wallet with stored m_context
Using RemoveWallet(m_context, m_wallet, false) is consistent with the new architecture. Verify that this doesn’t conflict with any dynamic load/unload.


582-590: WalletLoaderImpl constructor
Initializing m_context with coinjoin loader, args, chain, and node context is a cohesive approach. The destructor call to UnloadWallets(m_context) ensures resources are freed.


593-604: ChainClient life-cycle methods
Delegating to VerifyWallets, LoadWallets, StartWallets, etc., keeps the code flows uniform. No immediate issues.


605-659: Other wallet loader methods
The consistent usage of m_context to create, load, or restore wallets fosters a stable code flow. Adding assert(m_context.coinjoin_loader) ensures the loader is always valid.


669-673: MakeWallet and MakeWalletLoader
Factories now require WalletContext& which unifies context usage. This simplifies code that previously had to juggle multiple references.

src/wallet/test/coinselector_tests.cpp (45)

44-54: Add checks for negative effective_value.
The logic for subtracting the fee from nValue could result in a negative effective_value if fee is unexpectedly larger than nValue. Consider adding a safety check or assertion to ensure that effective_value doesn't go negative and is handled gracefully.


125-128: Confirm correctness of KnapsackSolver overload.
This inline overload effectively forwards to the main KnapsackSolver. Ensure that the default arguments (fFulyMixedOnly=false, maxTxFee=DEFAULT_TRANSACTION_MAXFEE) are appropriate for all uses, especially in tests covering corner cases with high transaction fees.


289-289: Validate negative effective value rejection.
This test checks that a negative effective value triggers selection failure as expected. Good coverage of this edge case. No issues found.


296-296: Confirm fee subtraction behavior in test.
The test sets m_subtract_fee_outputs = true before selection, ensuring BnB can still succeed. Confirm that changes in upstream test logic won't break the scenario.


305-306: Descriptor wallet flag usage.
Enabling WALLET_FLAG_DESCRIPTORS and calling SetupDescriptorScriptPubKeyMans() is correct for descriptor-based testing. Confirm that the wallet can gracefully handle non-descriptor scenarios if tested side by side.


322-322: Knapsack solver test initialization.
This new test block is well-structured. Ensure coverage includes typical and corner cases (very large inputs, dust outputs, etc.).


338-338: Check repeated test runs.
Line 338 resets the coin list. This ensures consistent test permutations. No immediate issues; the logic is clear and isolated.


340-340: Validate filter_standard usage.
Test ensures that an immature coin isn't selected by standard filtering. This is correct. Keep an eye on future changes to default filter parameters.


344-344: Multiple consecutive checks.
Repeated BOOST_CHECK calls help verify the transition from no solution to a valid solution. Tests are well-structured.


346-346: Coverage for newly added 1-cent coin.
This ensures new, but immature coin selection still fails under standard constraints. Good negative test.


348-348: Enabling filter_confirmed for partial coverage.
Switching to filter_confirmed to allow maturity is consistent. The flow from no selection to successful selection is validated. Looks fine.


354-354: Insufficient mature coins scenario.
Ensures there’s no solution with only standard-eligible coins for 3 CENT. Good boundary coverage.


357-357: Confirm selection with newly added coins.
Switching to filter_confirmed to enable picking up the newly added 2 CENT coin is appropriate. Test logic is consistent.


367-367: Disallow new coins for large target.
Demonstrates that we cannot raise enough from old coins alone. Succeeds in showing standard extra filter failing. Looks correct.


369-369: Extra constraints test.
Using filter_standard_extra (6 confirmations for coins from external sources) clarifies a scenario with restricted coin usage. The negative check is valid.


371-371: Positive test with partial new coins.
Now allowing new coins from our own wallet demonstrates a successful selection. This progressive testing approach is good.


374-374: Full new coin acceptance test.
Confirms that if we accept all new coins, large sums like 38 CENT are reachable. No changes recommended.


378-378: Exact subset edge case.
Covers behavior when an exact solution is unavailable but a near subset is found. The test is well-defined and clarifies fallback strategy.


383-383: Smaller coin usage scenario.
Choosing combination of smaller coins for 7 CENT. The test verifies correct subset selection. No negative findings.


388-388: Exact match with multiple small coins.
Verifies successful 8-cent selection with three smaller coins. Good demonstration of knapsack’s subset approach.


394-394: Nearest coin fallback.
Selecting 9 CENT from a 10-cent coin tests fallback if smaller subsets can’t match exactly. Logical coverage is robust.


406-407: Testing boundary of total wallet amount.
Lines 406-407 confirm that 71 CENT is possible, but 72 is not. Thorough boundary coverage. No issues found.


411-411: One-coin preference.
Check that for 16 CENT, the solver picks the next largest single coin (20 CENT) if smaller subsets exceed. Good demonstration of knapsack preference logic.


418-419: Refine logic for smaller coin combos.
Demonstrates a scenario where multiple smaller coins produce a better fit than a single large coin. Good edge test.


425-426: Tie-breaking rule demonstration.
When multiple solutions match the target but differ in subset size, the test ensures the biggest coin wins in a tie.


430-430: Summation check for 11-cent target.
Multi-coin approach (5 + 6). Straightforward. Verified logic with no concerns.


439-439: Confirm smaller coin preference for 95 CENT.
Checks that a single 1 BTC coin is chosen if it meets or just exceeds the target. Behaves as expected.


443-444: 195-cent scenario.
Similarly ensures 2 BTC coin is chosen. No issues found.


495-496: Exact subset fallback test.
With small coins, one scenario will pick a bigger coin if no exact subset is found. Another scenario tries an exact subset. Clear coverage.


534-535: Repetitive test loop clarity.
These nested loops test multiple scenarios. The approach systematically checks partial sets. Looks good for coverage.


561-562: Mid-range target selection.
Selecting 50 BTC from 100 identical coins ensures that the solver picks half the coins. The random shuffle test is correct.


571-572: Random single-coin picks.
Ensures that selecting 1 BTC from 100 identical coins shows randomness in solver picks. Good stress scenario.


593-594: Choice among multiple “smallest bigger” coins.
Tests 90-cent target with multiple near-fitting coins. The solver picks among them randomly. Good to confirm.


672-673: Introduction of waste_test.
This newly added test block specifically checks GetSelectionWaste. It’s a valuable addition for validating advanced coin selection heuristics.


674-680: Basic fee parameters initialization.
Initial definitions (fee, change_cost, fee_diff, …) are straightforward and clarify test input for subsequent checks.


681-687: Waste with change scenario.
Validates if the correct waste is computed (change_cost + difference in fees). Good to confirm correct formula usage.


689-695: Waste without change scenario.
Checks that the computed waste includes leftover coin value (excess) plus fee differences. Implementation is consistent with coin selection logic.


696-702: Zero difference between fee and long-term fee (with change).
Confirms that when fees align, the waste equals just change_cost. Clear demonstration of formula.


703-707: Zero difference between fee and long-term fee (no change).
Here, waste matches the excess. The test reaffirms correct portion of the formula.


708-714: Higher short-term fee test.
By doubling the fee with the same long-term fee, we expect a larger waste. Confirm the test captures an expected bigger difference.


715-723: Long-term fee higher than short-term fee (with change).
Checks that the waste is lowered by a negative difference in fees. Demonstrates thorough coverage.


724-732: Long-term fee higher than short-term fee (no change).
Compares negative fee diffs plus excess. The logic ensures that the test covers symmetrical scenarios.


733-739: Verify no waste for exact target when fees match.
Confirms that if we expend exactly in_amt - fee*2, the waste is zero. This is correct.


740-746: Correlate change cost offset to fee difference.
Demonstrates that if (fee - long_term_fee) equals negative change_cost, the waste is zero again.


747-752: No waste with different target offset.
Another scenario ensuring zero-waste alignment if (fee - long_term_fee) balances out excess.

src/wallet/spend.cpp (3)

362-405: Combined BnB and Knapsack strategy with waste comparison.
The new AttemptSelection merges results from both BnB and Knapsack, then picks the least waste. This is a robust approach but introduces complexity:

  • Ensure any future algorithm (e.g., randomization or Single Random Draw) merges consistently.
  • Verify that comparing waste metrics is stable across edge cases (like negative effective values, huge fees, or large coin sets).

541-544: Optional long-chain acceptance.
Allowing infinite ancestors/descendants if -walletrejectlongchains=0 is correct but can lead to unexpected user experiences in large mempool scenarios. Keep an eye out for user confusion or large chain transaction rejections by the network.


550-557: Preset coin integration.
Merging coin_control preset inputs with the newly selected coins is done after AttemptSelection. This ensures these preset UTXOs remain forcibly included, as intended. Implementation looks consistent with the coin selection logic.

src/wallet/wallet.h (5)

82-83: DEFAULT_CONSOLIDATE_FEERATE usage.
Defining a default consolidate fee rate (10 sat/vbyte) is helpful for input consolidation strategies. Confirm it doesn’t conflict with the main usage or overshadow the user’s custom fee if they override it.


362-362: Redundant note on AttemptSelection rename.
The header references SelectCoinsMinConfAttemptSelection. Confirm that all references are updated, and no stale references remain in documentation or inline comments.


553-553: New AttemptSelection function signature.
The extra parameters for CoinEligibilityFilter, std::vector<COutput> coins, and CoinSelectionParams align with the flexible selection workflow. This is consistent with the approach taken in spend.cpp.


777-780: Added consolidate feerate member.
CFeeRate m_consolidate_feerate{DEFAULT_CONSOLIDATE_FEERATE}; helps streamline consolidation. Evaluate whether “consolidation mode” is toggled or if partial usage might cause confusion in everyday transactions.


919-920: Static Create method referencing WalletContext.
Replacing older code that used global references with Create(WalletContext&, ...) is a clear improvement for testability. Just ensure that required context fields (e.g., chain pointer, settings) are available before creation.

src/wallet/test/wallet_tests.cpp (31)

29-29: Add WalletContext header
No issues. This include is necessary for the new WalletContext usage.


51-68: Refactored TestLoadWallet to accept a WalletContext
Switching from separate chain and coinjoin loader parameters to a single context promotes better modularity and maintainability. This approach cleanly aggregates wallet dependencies. Implementation appears correct.


70-77: TestUnloadWallet with WalletContext
Properly removes the wallet from the context and unloads it. The sync step is a good precaution to ensure pending notifications are cleared.


118-118: SetWalletFlag(WALLET_FLAG_DESCRIPTORS)
Enabling descriptor-based wallet flags aligns with the overall descriptor migration.


138-138: Again setting DESCRIPTORS flag
Consistent usage of descriptor wallets.


167-167: Another DESCRIPTORS flag setting
No concerns; follows the same pattern.


354-356: Enable descriptor usage in coin_mark_dirty_immature_credit test
Locking the wallet, setting the descriptor flag, and initializing descriptor-based managers is appropriate.


370-370: AddKey call
Uses the new AddKey function to add the coinbase key post-dirtying the wallet transaction. Logic and flow look coherent.


233-235: Construct and populate WalletContext
Assigning coinjoin_loader and args ensures the wallet has full context when added.


267-267: RemoveWallet call
Cleanly detaches the wallet from the context after the test completes.


294-295: New local WalletContext
These lines instantiate a context object for subsequent wallet operations. Straightforward.


303-303: AddWallet invocation
Adds the newly created wallet into the context. No issues encountered.


312-312: RemoveWallet invocation
Proper removal of the wallet from the context, restoring a clean test state.


322-324: Initialize another WalletContext
Correctly sets up the context with coinjoin loader and argument references.


325-325: Assign request.context
Ensures that RPC requests run against the correct wallet context.


328-328: AddWallet
No issues. This matches the descriptor-based pattern from earlier additions.


331-331: RemoveWallet
Clean removal of the wallet from the context.


625-647: wallet_disableprivkeys test
This test confirms that a wallet with disabled private keys cannot generate new addresses or top up its key pool. The checks for TopUpKeyPool and GetNewDestination both failing are correct.


649-684: CalculateNestedKeyhashInputSize
Methodically computes the serialized size of a nested P2PKH input with optional maximum signatures. The logic is sound.


685-689: dummy_input_size_test
Checks that the computed dummy input size is as expected. Straightforward verification.


691-695: malformed_descriptor check
Filters out descriptors without checksums, throwing an I/O error appropriately. Implementation is fine.


697-710: wallet_descriptor_test
Probes loading of an invalid descriptor and expects an exception. The failure condition is validated as intended.


712-821: CreateWallet test
Simulates race conditions when loading a wallet with pending mempool and block notifications. Coverage is thorough, ensuring the wallet detects transactions regardless of notification timing.


823-830: CreateWalletWithoutChain
Demonstrates correct wallet creation without an active chain client. Straightforward logic.


832-866: ZapSelectTx test
Validates selective removal of transactions from the wallet, verifying that locked coins and spends are updated. Effective for ensuring correctness of partial wallet “zaps.”


868-872: Dash-specific fallback fee
Introduces a fallback fee for subsequent tests. No issues noted.


873-879: AddLegacyKey function
Extends the legacy script pubkey manager with a new key. Useful for remaining legacy-based scenarios.


881-957: rpc_getaddressinfo test
Covers P2PKH and P2SH multisig addresses, verifying the fields in the JSON response for ownership, watchonly status, and multisig properties. Implementation is correct.


959-1116: CreateTransactionTestSetup
Sets up a wallet with coin control and scanning logic for thorough transaction creation tests. Provides a good foundation for verifying fee handling, coin selection, and recipient requests.


1118-1403: CreateTransactionTest
Comprehensive set of test cases inspecting fee rates, change outputs, transaction sizes, and error scenarios. The coverage is extensive and robust.


1405-1466: select_coins_grouped_by_addresses test
Ensures coins are grouped correctly by address and tests conflict resolution. Logic is consistent with expected wallet behaviors.

src/wallet/wallet.cpp (5)

43-43: Header inclusion looks good

Including <wallet/context.h> is necessary for referencing WalletContext. No issues found here.


164-171: Clear and straightforward retrieval

The loop-based retrieval by name is simple and effective. No major concerns here.


173-178: Handler registration pattern looks solid

Storing the functor and returning a scoped remover via MakeHandler is a neat approach to event registration. The concurrency guards appear correct.


228-257: Consider checking AddWallet(...) success

AddWallet(context, wallet) is invoked but its return status isn’t used. If it fails (e.g., the wallet is already tracked), subsequent logic could proceed under incorrect assumptions. You might want to verify and handle this scenario properly to avoid subtle issues.


260-271: Synchronized loading logic

The method is well-structured: it checks for a duplicate loading process and properly erases from g_loading_wallet_set after the operation. Minor suggestion: if LoadWalletInternal fails, also consider logging that fact (beyond setting the error message) for easier debugging.

src/wallet/rpcwallet.cpp (2)

2582-2583: Validate wallet context usage.

These lines introduce a context dependency for retrieving loaded wallets. Ensure there's proper error handling if the returned WalletContext is invalid or unavailable. This helps prevent null references in subsequent operations.


2951-2951: Add robustness to backup file path creation.

Before converting request.params[1].get_str() to a filesystem path, consider guarding against empty or invalid inputs. This helps safeguard against unexpected runtime errors or user mistakes.

src/wallet/context.cpp (1)

7-8: LGTM! Naming convention update.

The change from m_coinjoin_loader to coinjoin_loader aligns with the project's move away from Hungarian notation prefixes, improving code readability while maintaining functionality.

src/wallet/test/wallet_test_fixture.cpp (1)

11-11: LGTM! Updated wallet loader initialization.

The change adds m_node as a parameter to MakeWalletLoader, aligning with the broader changes in wallet context management. The parameter order is correct and matches the interface requirements.

src/walletinitinterface.h (2)

12-14: LGTM! Added WalletLoader forward declaration.

Clean addition of the interfaces namespace and WalletLoader forward declaration.


28-29:

✅ Verification successful

Verify implementation of updated method signatures.

The methods now require a WalletLoader parameter, which is part of the wallet context restructuring. This change improves encapsulation but requires verification of all implementing classes.


🏁 Script executed:

#!/bin/bash
# Search for classes implementing WalletInitInterface
rg -l "class.*:.*public.*WalletInitInterface"

# Search for implementations of the updated methods
rg "void.*AutoLockMasternodeCollaterals.*\(.*WalletLoader.*\)" -A 5
rg "void.*InitCoinJoinSettings.*\(.*WalletLoader.*\)" -A 5

Length of output: 3627


Implementation Verified: Updated method signatures are consistent across implementations.

  • Confirmed that both AutoLockMasternodeCollaterals and InitCoinJoinSettings now correctly include the interfaces::WalletLoader& parameter as declared in src/walletinitinterface.h.
  • Verified implementations in both src/wallet/init.cpp and src/dummywallet.cpp adhere to the updated signatures.
src/interfaces/coinjoin.h (2)

13-15: LGTM! Added WalletLoader forward declaration.

Clean addition of the WalletLoader forward declaration in the interfaces namespace.


48-48:

✅ Verification successful

Verify implementation of updated MakeCoinJoinLoader function.

The function signature now includes WalletLoader parameter, which is part of the wallet context restructuring. This change requires verification of the implementation and all call sites.


🏁 Script executed:

#!/bin/bash
# Search for MakeCoinJoinLoader implementation
rg "MakeCoinJoinLoader.*\(.*WalletLoader.*\)" -A 5

# Search for MakeCoinJoinLoader call sites
rg "MakeCoinJoinLoader\(" -A 2

Length of output: 1324


Action: The updated MakeCoinJoinLoader signature has been correctly applied.

The declaration in src/interfaces/coinjoin.h now includes the additional interfaces::WalletLoader& wallet_loader parameter, and the implementation in src/coinjoin/interfaces.cpp reflects this change. All call sites (seen in src/test/util/setup_common.cpp and src/init.cpp) are updated accordingly.

No further changes are required.

src/wallet/test/init_test_fixture.cpp (1)

17-17:

✅ Verification successful

LGTM! Parameter reordering aligns with wallet context changes.

The updated MakeWalletLoader call correctly includes the node context parameter, which is consistent with the broader changes in wallet management.

Let's verify that this signature matches other MakeWalletLoader calls:


🏁 Script executed:

#!/bin/bash
# Search for other MakeWalletLoader calls to verify parameter consistency
rg "MakeWalletLoader\(" -A 2

Length of output: 1600


LGTM! Parameter reordering verified across the codebase.
The updated MakeWalletLoader call in src/wallet/test/init_test_fixture.cpp now correctly uses the node context parameter, just as defined in src/interfaces/wallet.h and used consistently in other parts of the code (e.g., in src/wallet/init.cpp and src/wallet/test/wallet_test_fixture.cpp). No additional changes are necessary.

src/wallet/test/util.cpp (2)

9-9: LGTM! Required import for key encoding.

The addition of key_io.h is necessary for EncodeSecret used in the descriptor setup.


27-37: LGTM! Modernized wallet setup with descriptors.

The changes properly implement descriptor-based wallet setup:

  1. Sets descriptor wallet flag
  2. Initializes descriptor script public key managers
  3. Creates and adds a wallet descriptor using the combo format
  4. Properly handles the signing provider

This modernization improves wallet management by using the more robust descriptor-based approach.

src/rpc/register.h (2)

10-14: LGTM! Clean forward declarations.

The forward declarations for CRPCCommand and Span template are properly placed and minimize header dependencies.


31-37: LGTM! Well-organized wallet-specific RPC command getters.

The new functions are:

  1. Properly guarded by ENABLE_WALLET
  2. Follow a consistent pattern returning Span<const CRPCCommand>
  3. Logically grouped by functionality (CoinJoin, Evo, Governance, Masternode)
src/wallet/context.h (1)

41-43: LGTM! Thread-safe wallet management.

The implementation properly ensures thread safety:

  1. Uses Mutex for synchronization
  2. Guards both containers with GUARDED_BY annotation
  3. Uses appropriate container types (vector for wallets, list for load functions)
src/bench/wallet_balance.cpp (1)

23-25: LGTM! Proper locking and descriptor setup.

The changes correctly implement thread-safe wallet initialization with descriptors, which is the recommended approach.

src/dummywallet.cpp (1)

27-28: LGTM! Updated method signatures for wallet loader integration.

The changes correctly integrate the wallet loader parameter into the interface methods.

src/coinjoin/interfaces.cpp (1)

76-85: Consider error handling for InitCoinJoinSettings.

The InitCoinJoinSettings calls after wallet operations should handle potential failures.

Consider adding error handling:

     void AddWallet(const std::shared_ptr<CWallet>& wallet) override
     {
         m_walletman.Add(wallet);
-        g_wallet_init_interface.InitCoinJoinSettings(m_wallet_loader, m_walletman);
+        try {
+            g_wallet_init_interface.InitCoinJoinSettings(m_wallet_loader, m_walletman);
+        } catch (const std::exception& e) {
+            // Log error but don't prevent wallet addition
+            LogPrintf("Failed to initialize CoinJoin settings: %s\n", e.what());
+        }
     }
src/bench/coin_selection.cpp (2)

53-53: LGTM!

The parameter name change improves naming consistency.


57-57: LGTM!

The method name change from SelectCoinsMinConf to AttemptSelection is more descriptive and aligns with the broader changes in the wallet management system.

src/wallet/test/psbt_wallet_tests.cpp (3)

17-26: LGTM!

The new helper function import_descriptor is well-structured, handles errors appropriately, and follows good practices:

  • Uses proper locking mechanism
  • Uses descriptive variable names
  • Follows single responsibility principle

30-31: LGTM!

The changes properly initialize the wallet for descriptor support:

  • Adds necessary locking for thread safety
  • Sets the required wallet flag

74-74: LGTM!

The updated FillPSBT call properly includes the required parameters for signing and BIP32 derivation paths.

src/wallet/coinselection.h (1)

167-180: LGTM!

The new GetSelectionWaste method is well-designed:

  • Comprehensive documentation explaining the waste calculation formula
  • Proper use of [[nodiscard]] attribute to prevent accidental ignoring of return value
  • Clear parameter names with appropriate default values
src/wallet/walletdb.h (2)

33-33: LGTM!

The forward declaration for WalletContext is properly placed and necessary for the updated method signature.


258-258: LGTM!

The updated MaybeCompactWalletDB signature properly accepts a WalletContext reference, aligning with the broader changes in wallet context management.

src/wallet/test/coinjoin_tests.cpp (2)

132-138: LGTM: Constructor initialization and context setup looks correct.

The constructor properly initializes the context member with m_node.coinjoin_loader and sets up the required context attributes (args and chain).


141-141: LGTM: Wallet management calls updated correctly.

The AddWallet and RemoveWallet calls have been properly updated to include the context parameter, maintaining consistency with the new wallet management interface.

Also applies to: 155-155

src/interfaces/wallet.h (4)

31-45: LGTM: Forward declarations added correctly.

The new forward declarations for CRPCCommand, NodeContext, and template class Span are properly added to support the new functionality.


93-94: LGTM: New method for masternode collateral management.

The autoLockMasternodeCollaterals method is appropriately added to the Wallet interface to support masternode functionality.


348-349: LGTM: New method for RPC registration.

The registerOtherRpcs method is correctly added to the WalletLoader interface to support registration of non-core wallet RPCs.


460-465: LGTM: Function signatures updated for context awareness.

The MakeWallet and MakeWalletLoader function signatures have been properly updated to include context parameters, enhancing the context-aware design.

src/wallet/init.cpp (3)

191-193: LGTM: Wallet loader initialization updated correctly.

The MakeWalletLoader call is properly updated to include all required parameters: chain, args, node context, and coinjoin loader.


197-203: LGTM: Masternode collateral locking updated.

The AutoLockMasternodeCollaterals method correctly uses the wallet loader to iterate through wallets and call the new interface method.


205-228: LGTM: CoinJoin settings initialization updated.

The InitCoinJoinSettings method properly:

  • Uses wallet loader to get wallets
  • Checks wallet lock status using the interface method
  • Initializes CoinJoin settings with appropriate logging
src/wallet/coinselection.cpp (1)

202-202: LGTM: Consistent use of GetSelectionAmount.

The ApproximateBestSubset function now correctly uses GetSelectionAmount() instead of directly accessing m_value, maintaining consistency in value calculations.

Also applies to: 214-214

src/rpc/coinjoin.cpp (2)

468-490: LGTM! Clean separation of wallet-specific RPC commands.

The new GetWalletCoinJoinRPCCommands() function effectively encapsulates wallet-specific CoinJoin RPC commands, improving code organization and modularity.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[warning] 486-486: Clang format differences found. Please format the code according to Clang standards.


492-515: LGTM! Robust handling of wallet-disabled scenarios.

The modified RegisterCoinJoinRPCCommands() function properly handles cases where:

  1. Wallet support is not compiled in
  2. Wallet support is compiled but disabled at runtime
src/test/util/setup_common.cpp (1)

127-127: LGTM! Updated CoinJoin loader initialization.

The change correctly passes the wallet loader to MakeCoinJoinLoader(), aligning with the enhanced wallet context management.

src/rpc/masternode.cpp (1)

739-751: LGTM! Clean separation of wallet-specific masternode RPC commands.

The new GetWalletMasternodeRPCCommands() function effectively encapsulates wallet-specific masternode RPC commands, following the same pattern as CoinJoin RPC commands.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[warning] 740-740: Clang format differences found. Please format the code according to Clang standards.

src/wallet/walletdb.cpp (2)

1023-1048: LGTM! Enhanced wallet context management.

The MaybeCompactWalletDB() function now properly accepts a WalletContext parameter, enabling better context-aware wallet operations.


1050-1053: LGTM! Clean implementation of destination data operations.

The new WriteDestData() and EraseDestData() functions provide a clean interface for managing destination data in the wallet database.

Also applies to: 1055-1058

test/functional/rpc_fundrawtransaction.py (1)

936-990: LGTM! Well-structured test for issue bitcoin#22670.

The test thoroughly verifies that transaction fees are correctly calculated when using ApproximateBestSubset for coin selection. The implementation includes:

  • Setting up test conditions with a high minimum relay fee
  • Creating transactions to calculate fee bounds
  • Testing both lower and upper bounds of the target value
🧰 Tools
🪛 Ruff (0.8.2)

957-957: Loop control variable i not used within loop body

Rename unused i to _i

(B007)

src/rpc/evo.cpp (1)

1781-1809: LGTM! Clean separation of wallet-specific RPC commands.

The new GetWalletEvoRPCCommands() function effectively encapsulates wallet-specific RPC commands, improving modularity and maintainability. This aligns well with the PR's objective of better wallet context management.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[warning] 1805-1805: Clang format differences found. Please format the code according to Clang standards.

src/init.cpp (3)

31-33: LGTM! Header file changes look good.

The addition of interfaces/wallet.h is consistent with the PR objectives to backport wallet-related changes.


2232-2235: LGTM! Wallet loader initialization is properly guarded.

The initialization of wallet loader and auto-locking of masternode collaterals is correctly guarded by the -disablewallet check.


1519-1534:

✅ Verification successful

Verify the wallet RPC registration changes.

The conditional registration of non-core wallet-only RPC commands looks correct, but let's verify that all required wallet RPC commands are properly registered.


🏁 Script executed:

#!/bin/bash
# Description: Check if all wallet RPC commands are properly registered
# Look for any wallet RPC registration patterns that might have been missed

# Search for wallet RPC registration patterns
rg -A 5 "RegisterWallet.*RPC|GetWallet.*RPC"

# Search for any TODO/FIXME comments related to wallet RPC registration
rg -i "todo|fixme|xxx|hack" -A 3 ".*wallet.*rpc"

Length of output: 39243


Wallet RPC registration confirmed. The investigation verifies that all intended wallet RPC command sets—CoinJoin, Evo, Governance, and Masternode—are correctly registered via node.wallet_loader->registerOtherRpcs in src/init.cpp (lines 1519–1534). The search results also show the expected declarations (e.g., in src/rpc/register.h) and their implementations, confirming there are no missing RPC registrations. The only note is the existing TODO about moving these commands to chain client interfaces, which can be addressed later.

Comment on lines +507 to 529
if (AttemptSelection(value_to_select, CoinEligibilityFilter(1, 6, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) return true;
if (AttemptSelection(value_to_select, CoinEligibilityFilter(1, 1, 0), vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) return true;

// Fall back to using zero confirmation change (but with as few ancestors in the mempool as
// possible) if we cannot fund the transaction otherwise.
if (m_spend_zero_conf_change) {
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) return true;
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
if (AttemptSelection(value_to_select, CoinEligibilityFilter(0, 1, 2), vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) return true;
if (AttemptSelection(value_to_select, CoinEligibilityFilter(0, 1, std::min((size_t)4, max_ancestors/3), std::min((size_t)4, max_descendants/3)),
vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) {
return true;
}
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
if (AttemptSelection(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors/2, max_descendants/2),
vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) {
return true;
}
// If partial groups are allowed, relax the requirement of spending OutputGroups (groups
// of UTXOs sent to the same address, which are obviously controlled by a single wallet)
// in their entirety.
if (SelectCoinsMinConf(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
if (AttemptSelection(value_to_select, CoinEligibilityFilter(0, 1, max_ancestors-1, max_descendants-1, true /* include_partial_groups */),
vCoins, setCoinsRet, nValueRet, coin_selection_params, nCoinType)) {
return true;
}
// Try with unsafe inputs if they are allowed. This may spend unconfirmed outputs
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Coin eligibility fallback expansions.
This block systematically attempts increasingly permissive CoinEligibilityFilter paths (Confirmed-Only, 1-conf, zero-conf with limited ancestors, etc.). It’s well-structured but can get unwieldy if new fallback layers are added. Consider whether any new fallback steps or advanced strategies (like feerate-based selection) might be beneficial to generalize.

Comment on lines +3002 to +3003
WalletContext& context = EnsureWalletContext(request.context);
std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
Copy link

@coderabbitai coderabbitai bot Feb 14, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue

Verify the retrieved wallet handle.

GetWallet(context, wallet_name) may return null if no wallet matches the requested name. Ensure a user-friendly error or fallback if wallet is null, preventing potential dereferences of an invalid pointer.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

But there is a validation check right after...

dash/src/wallet/rpcwallet.cpp

Lines 3001 to 3007 in 6813863

WalletContext& context = EnsureWalletContext(request.context);
std::shared_ptr<CWallet> wallet = GetWallet(context, wallet_name);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_NOT_FOUND, "Requested wallet does not exist or is not loaded");
}

Copy link

Choose a reason for hiding this comment

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

@kwvg You are absolutely right - I apologize for the false warning. The code already has proper null pointer validation with a descriptive error message right after the GetWallet() call.

🐰 Rabbit looks thoughtful after learning something new


✏️ Learnings added
Learnt from: kwvg
PR: dashpay/dash#6529
File: src/wallet/rpcwallet.cpp:3002-3003
Timestamp: 2025-02-14T15:19:17.049Z
Learning: The `GetWallet()` function calls in `src/wallet/rpcwallet.cpp` are properly validated with null checks that throw appropriate RPC errors, making additional validation unnecessary.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +44 to +45
// Import descriptors for keys and scripts
import_descriptor(m_wallet, "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/0h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/1h))");
import_descriptor(m_wallet, "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/2h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/3h))");
import_descriptor(m_wallet, "pkh(xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/*h)");
Copy link

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Verify the test descriptors.

The descriptors look well-formed but let's verify they are valid and use appropriate test keys.

Run the following script to verify the descriptors:


🏁 Script executed:

#!/bin/bash
# Description: Verify the test descriptors are valid and use test keys.

# Test: Check if the descriptors are valid. Expect: Valid descriptors.
python3 -c '
import re

def verify_descriptor(desc):
    # Basic validation of descriptor format
    if not desc.startswith("sh(") or not desc.endswith("))"):
        return False
    # Check for test keys (should start with xprv)
    if not "xprv" in desc:
        return False
    return True

descriptors = [
    "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/0h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/1h))",
    "sh(multi(2,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/2h,xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/3h))",
    "pkh(xprv9s21ZrQH143K2LE7W4Xf3jATf9jECxSb7wj91ZnmY4qEJrS66Qru9RFqq8xbkgT32ya6HqYJweFdJUEDf5Q6JFV7jMiUws7kQfe6Tv4RbfN/0h/0h/*h)"
]

for desc in descriptors:
    print(f"Descriptor: {desc}")
    print(f"Valid: {verify_descriptor(desc)}")
'

Length of output: 1788


Descriptor Verification Update

  • The multi-signature descriptors (lines 44–46 in src/wallet/test/psbt_wallet_tests.cpp) are correctly formatted and pass our basic validity checks.
  • However, the public key hash descriptor on line 47 (pkh(…)) fails the simple validation since it does not follow the expected sh(...)) pattern used by the current validation logic.
  • Please confirm whether the pkh descriptor is intended to be in its current form. If so, consider updating the validation logic to accept pkh descriptors; otherwise, update the descriptor format so that it meets the expected pattern.

Comment on lines +1074 to +1089
#ifdef ENABLE_WALLET
Span<const CRPCCommand> GetWalletGovernanceRPCCommands()
{
// clang-format off
static const CRPCCommand commands[] =
{ // category actor (function)
// --------------------- -----------------------
{ "dash", &gobject_prepare, },
{ "dash", &gobject_list_prepared, },
{ "dash", &gobject_vote_many, },
{ "dash", &gobject_vote_alias, },
};
// clang-format on
return commands;
}
#endif // ENABLE_WALLET
Copy link

@coderabbitai coderabbitai bot Feb 14, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix clang-format issues.

The pipeline reports formatting issues in this section. Please run clang-format to fix the formatting.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[warning] 1075-1075: Clang format differences found. Please format the code according to Clang standards.

Copy link
Collaborator Author

@kwvg kwvg Feb 14, 2025

Choose a reason for hiding this comment

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

We want this code to be excluded from clang-format, hence the comment

// clang-format off

Copy link

Choose a reason for hiding this comment

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

@kwvg I apologize for the incorrect suggestion. You are absolutely right - the // clang-format off directive is intentionally used here to maintain the readable alignment of the command registration array. I will remember this for future reviews.


✏️ Learnings added
Learnt from: kwvg
PR: dashpay/dash#6529
File: src/rpc/governance.cpp:1074-1089
Timestamp: 2025-02-14T15:15:57.974Z
Learning: Code blocks marked with `// clang-format off` and `// clang-format on` directives should be excluded from clang-format suggestions as they are intentionally formatted manually for better readability.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

#endif
{ "evo", &protx_list, },
{ "evo", &protx_info, },
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Fix Clang format issues.

The pipeline indicates formatting issues. Please run clang-format on the code to ensure consistent style.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[warning] 1805-1805: Clang format differences found. Please format the code according to Clang standards.

@kwvg kwvg marked this pull request as ready for review February 25, 2025 16:35
Copy link

@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 (12)
test/functional/rpc_fundrawtransaction.py (1)

936-990: Test case implementation looks good with one minor improvement needed.

This new test specifically targets issue bitcoin#22670, where ApproximateBestSubset might choose enough value to cover the target amount but not enough to cover transaction fees. The test correctly:

  1. Sets a high minimum relay fee (0.1 BTC/kvB) to make the issue more apparent
  2. Creates transactions to test fee calculations under boundary conditions
  3. Verifies transaction validity and mempool acceptance

Per the static analysis suggestion, rename the unused loop variable i to _ at line 957:

-        for i in range(0, 3):
+        for _ in range(0, 3):
🧰 Tools
🪛 Ruff (0.8.2)

957-957: Loop control variable i not used within loop body

Rename unused i to _i

(B007)

src/qt/test/wallettests.cpp (1)

259-259: Parameter name inconsistency in comment.

There's a minor inconsistency between the comment variable name (load_on_start) and the actual parameter name (load_on_startup) used elsewhere in the codebase.

-    RemoveWallet(context, wallet, /*load_on_start=*/std::nullopt);
+    RemoveWallet(context, wallet, /*load_on_startup=*/std::nullopt);
src/wallet/wallet.cpp (10)

113-120: Ensure consistent behavior on adding wallets
Locking context.wallets_mutex before searching and appending the wallet pointer is correct. The return condition avoids duplicates in context.wallets. Consider logging a warning if attempting to add an already-present wallet for better diagnostics.


129-142: Clean wallet removal flow
Removal checks for the wallet’s existence and erases it under the mutex. This sequence is appropriate. As an optional improvement, consider capturing and logging the return value of UpdateWalletSetting for debugging potential storage issues.


153-157: Potential naming confusion
The overload of RemoveWallet that calls another RemoveWallet might be more descriptive if the function names were distinct (e.g., _internal suffix) to reduce confusion.


165-172: GetWallet by name
Looping under lock to find a matching wallet name is straightforward. Potentially, a map of wallet name → wallet pointer could improve performance for large wallet sets, but for typical usage this is sufficient.


229-229: Refactored internal loading
Introducing LoadWalletInternal to accept WalletContext clarifies ownership of chain, load, and wallet management. The method is fairly large, so consider further splitting or adding inline documentation for readability.


239-240: Repeated chain init message
Calling initMessage(_("Loading wallet…")) again may cause redundant UI updates. Consider deduplicating or skipping the second message to prevent flicker in some UIs.


250-250: UpdateWalletSetting
Short and clear. As with the removal path, checking the returned boolean for possible warnings or logging might help diagnose persistence issues.


306-308: Consistent usage of chain initialization
Again, repeating the “Loading wallet…” message. Possibly unify the three calls to “initMessage” in a single place unless different contexts are required.


364-364: Repeating wallet setting update
Same approach as earlier: success/failure for UpdateWalletSetting is not checked. For debugging, a confirmation log line may be beneficial in case of save issues.


392-393: Deferred error handling
When calling LoadWallet(context, …) inside RestoreWallet, consider further logging or user feedback if the returned wallet is null.

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0f7c173 and e2eea71.

📒 Files selected for processing (40)
  • src/bench/coin_selection.cpp (1 hunks)
  • src/bench/wallet_balance.cpp (2 hunks)
  • src/bitcoin-cli.cpp (1 hunks)
  • src/dummywallet.cpp (2 hunks)
  • src/init.cpp (2 hunks)
  • src/init/bitcoin-node.cpp (1 hunks)
  • src/init/bitcoind.cpp (1 hunks)
  • src/interfaces/wallet.h (4 hunks)
  • src/qt/test/addressbooktests.cpp (2 hunks)
  • src/qt/test/wallettests.cpp (3 hunks)
  • src/rpc/coinjoin.cpp (3 hunks)
  • src/rpc/evo.cpp (3 hunks)
  • src/rpc/governance.cpp (1 hunks)
  • src/rpc/masternode.cpp (1 hunks)
  • src/rpc/register.h (2 hunks)
  • src/rpc/server_util.cpp (1 hunks)
  • src/test/util/setup_common.cpp (1 hunks)
  • src/test/util/wallet.cpp (0 hunks)
  • src/wallet/coinselection.cpp (3 hunks)
  • src/wallet/coinselection.h (1 hunks)
  • src/wallet/context.h (2 hunks)
  • src/wallet/init.cpp (1 hunks)
  • src/wallet/interfaces.cpp (6 hunks)
  • src/wallet/load.cpp (7 hunks)
  • src/wallet/load.h (2 hunks)
  • src/wallet/rpc/util.cpp (1 hunks)
  • src/wallet/rpcwallet.cpp (6 hunks)
  • src/wallet/spend.cpp (5 hunks)
  • src/wallet/test/coinjoin_tests.cpp (3 hunks)
  • src/wallet/test/coinselector_tests.cpp (21 hunks)
  • src/wallet/test/init_test_fixture.cpp (1 hunks)
  • src/wallet/test/psbt_wallet_tests.cpp (3 hunks)
  • src/wallet/test/util.cpp (2 hunks)
  • src/wallet/test/wallet_test_fixture.cpp (1 hunks)
  • src/wallet/test/wallet_tests.cpp (15 hunks)
  • src/wallet/wallet.cpp (23 hunks)
  • src/wallet/wallet.h (8 hunks)
  • src/wallet/walletdb.cpp (1 hunks)
  • src/wallet/walletdb.h (2 hunks)
  • test/functional/rpc_fundrawtransaction.py (2 hunks)
💤 Files with no reviewable changes (1)
  • src/test/util/wallet.cpp
🚧 Files skipped from review as they are similar to previous changes (18)
  • src/wallet/init.cpp
  • src/bench/coin_selection.cpp
  • src/wallet/test/init_test_fixture.cpp
  • src/dummywallet.cpp
  • src/bitcoin-cli.cpp
  • src/wallet/test/wallet_test_fixture.cpp
  • src/test/util/setup_common.cpp
  • src/qt/test/addressbooktests.cpp
  • src/wallet/test/coinjoin_tests.cpp
  • src/rpc/server_util.cpp
  • src/rpc/register.h
  • src/wallet/rpc/util.cpp
  • src/wallet/load.h
  • src/wallet/load.cpp
  • src/wallet/test/psbt_wallet_tests.cpp
  • src/interfaces/wallet.h
  • src/init.cpp
  • src/wallet/rpcwallet.cpp
🧰 Additional context used
🪛 GitHub Actions: Clang Diff Format Check
src/rpc/coinjoin.cpp

[error] 505-505: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/rpc/governance.cpp

[error] 1074-1074: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/rpc/masternode.cpp

[error] 674-674: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/rpc/evo.cpp

[error] 1804-1804: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

🪛 Ruff (0.8.2)
test/functional/rpc_fundrawtransaction.py

957-957: Loop control variable i not used within loop body

Rename unused i to _i

(B007)

⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: linux64_multiprocess-build / Build source
🔇 Additional comments (77)
src/wallet/walletdb.h (2)

33-33: LGTM: Added new WalletContext forward declaration.

This forward declaration is necessary to support the function signature change below, enabling the context-based approach for wallet operations.


258-258: LGTM: Updated function signature to use WalletContext.

The function signature update for MaybeCompactWalletDB is part of the wallet context refactoring effort. This change allows the function to access wallet-related state through a centralized context object rather than global variables.

src/init/bitcoin-node.cpp (1)

40-40: LGTM: Updated MakeWalletLoader call to pass node context.

Adding m_node as a parameter to the MakeWalletLoader function call is consistent with the overall PR objective of improving wallet context management. This change allows the wallet loader to access node-specific information without relying on global state.

src/init/bitcoind.cpp (1)

33-36: Added node context parameter to MakeWalletLoader call.

The wallet loader function now receives the node context as an additional parameter, allowing the wallet loader to access node-related functionality directly. This is in line with the PR's goal of improving the interaction between wallets and node context.

src/wallet/coinselection.h (1)

167-180: Well-designed waste calculation function for coin selection.

The new GetSelectionWaste function enhances coin selection by calculating the efficiency of coin choices, considering both change costs and opportunity costs. The [[nodiscard]] attribute appropriately ensures the return value is handled, and the documentation clearly explains the calculation logic.

src/wallet/test/util.cpp (1)

27-37: Migrated to descriptor-based wallet setup in test utility.

This change implements descriptor-based wallet management, replacing the legacy script public key management approach. The implementation correctly:

  • Sets the descriptors wallet flag
  • Sets up the descriptor infrastructure
  • Parses and adds the key descriptor with proper error handling

This aligns with the PR's goal of modernizing wallet functionality.

src/rpc/governance.cpp (1)

1074-1089: Refactored wallet governance RPC commands into a dedicated function.

This change encapsulates wallet-specific governance RPC commands into a separate function, improving code organization by clearly separating wallet and non-wallet functionalities. The conditional compilation with #ifdef ENABLE_WALLET ensures these commands are only available when wallet support is enabled.

Note: The clang-format off/on directives are intentionally used to maintain the readable alignment of the command registration array, as indicated in previous reviews.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 1074-1074: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/rpc/evo.cpp (3)

1781-1809: Modular encapsulation of wallet RPC commands

The new function properly encapsulates wallet-specific Evolution RPC commands into a separate function, improving code organization by clearly separating wallet functionality.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 1804-1804: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.


1811-1847: Improved conditional RPC command registration

This refactoring properly handles wallet command registration based on wallet support availability. The approach ensures that even when wallet support is disabled, hybrid commands with reduced functionality are still registered.


1804-1805: Fix Clang format issues

The pipeline indicates a formatting issue in this line. Please run clang-format to fix it.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 1804-1804: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/rpc/coinjoin.cpp (4)

7-8: Properly organized header includes

The addition of necessary headers (node/context.h, util/check.h, validation.h, and walletinitinterface.h) supports the new functionality while maintaining a logical organization.

Also applies to: 12-12, 14-14, 16-16


489-510: Modular encapsulation of wallet CoinJoin RPC commands

The new function properly encapsulates wallet-specific CoinJoin RPC commands, improving code organization by clearly separating wallet functionality.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 505-505: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.


512-536: Improved conditional RPC command registration

This refactoring properly handles wallet command registration based on wallet support availability. The approach ensures that even when wallet support is disabled, hybrid commands with reduced functionality are still registered.


505-505: Fix Clang format issues

The pipeline indicates a formatting issue in this line. Please run clang-format to fix it.

🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 505-505: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

src/wallet/walletdb.cpp (2)

1023-1048: WalletContext integration improves dependency management

The change to accept a WalletContext parameter improves the architecture by explicitly passing the wallet context rather than relying on global state. This makes the code more testable and the dependencies clearer.


1050-1058: New methods for destination data management

The added WriteDestData and EraseDestData methods provide a clean way to manage destination data in the wallet database, properly leveraging existing WriteIC and EraseIC methods.

src/qt/test/wallettests.cpp (4)

112-112: Good addition of wallet context retrieval.

The retrieval of the WalletContext from node.walletLoader() aligns with the broader refactoring of wallet management across the codebase, facilitating better context awareness.


114-114: Properly updated AddWallet call to include context.

This change correctly modifies the AddWallet call to include the wallet context, consistent with the updated function signature in wallet.cpp.


116-129: Modernized wallet setup with descriptors.

The code now properly sets up the wallet with descriptor support, replacing the legacy approach. The implementation correctly:

  1. Sets the descriptor flag
  2. Sets up descriptor script pubkey managers
  3. Adds the coinbase key using descriptors
  4. Maintains address book functionality

This change aligns with the broader transition to descriptor-based wallet management in the codebase.


147-147: Updated WalletModel creation to use context.

Good update to the WalletModel constructor to utilize interfaces::MakeWallet with the wallet context.

src/wallet/coinselection.cpp (2)

202-202: Improved encapsulation in ApproximateBestSubset.

Changed to use GetSelectionAmount() method instead of directly accessing m_value, which is a good improvement for encapsulation and consistency with the rest of the codebase.

Also applies to: 214-214


406-431: Well-implemented GetSelectionWaste function.

This new function properly calculates the waste metric for coin selection, considering:

  1. Fee differentials between current and long-term fees
  2. Cost of making change when applicable
  3. Excess value when no change is made

The implementation includes appropriate assertions to ensure proper usage, and the logic is clear and well-structured. This enhances the coin selection algorithm by providing a consistent way to evaluate selection quality.

src/wallet/context.h (4)

8-13: Added necessary headers for enhanced functionality.

The additional headers support the new synchronization and container functionality in the WalletContext struct.


26-26: Good type alias for wallet loading functions.

The LoadWalletFn type alias improves code readability by providing a clear type for functions that load wallets.


41-43: Added thread-safe wallet management.

The addition of a mutex and guarded containers (wallets and wallet_load_fns) is a good improvement for thread safety in the wallet context.


45-50: Temporary NodeContext dependency with clear TODO.

The added NodeContext pointer with explanatory comments clearly acknowledges this is a temporary solution that should be removed in the future.

Consider adding a specific tracking issue number to the TODO comment to ensure this technical debt is properly tracked.

src/wallet/test/coinselector_tests.cpp (4)

44-54: Enhanced add_coin function with fee parameters.

The function has been properly extended to include fee and long-term fee parameters, allowing for more detailed testing of coin selection with different fee structures.


125-139: Good helper functions for test encapsulation.

The addition of KnapsackSolver and KnapsackGroupOutputs helper functions improves test code organization by encapsulating common logic used throughout the tests.


271-297: Updated test for effective value in BnB selection.

Test properly verifies that effective value is respected in the Branch and Bound selection algorithm by checking both rejection of negative effective value coins and proper handling when fees are subtracted from outputs.


672-752: Comprehensive waste calculation tests.

The new waste_test function provides thorough testing of the GetSelectionWaste function with various scenarios:

  1. Waste calculation with and without change
  2. Impact of fee versus long-term fee differentials
  3. Edge cases with exact target amounts
  4. Scenarios with zero waste

This ensures the waste calculation logic is robust and behaves as expected across different selection scenarios.

src/bench/wallet_balance.cpp (3)

16-16: Function signature updated to remove watch-only parameter.

The function signature for WalletBalance has been updated to remove the add_watchonly parameter, reflecting the shift towards descriptor-based wallet management and away from legacy watch-only address handling.


23-25: Migrate from legacy to descriptor-based wallet setup.

Changed wallet setup from SetupLegacyScriptPubKeyMan() to a more comprehensive initialization process:

  1. Adding proper locking with LOCK(wallet.cs_wallet)
  2. Setting the descriptor wallet flag with SetWalletFlag(WALLET_FLAG_DESCRIPTORS)
  3. Setting up the descriptor-based script pubkey manager with SetupDescriptorScriptPubKeyMans()

This change aligns with modern Bitcoin wallet architecture, moving away from legacy script management towards the more flexible descriptor-based approach.


47-50: Updated benchmark function signatures to reflect parameter changes.

The benchmark function signatures have been updated to remove the add_watchonly parameter, ensuring consistency with the updated WalletBalance function signature. This reflects the architectural shift in wallet management and properly maintains the test cases.

src/wallet/spend.cpp (5)

362-405: Rename and enhance the coin selection algorithm.

The function SelectCoinsMinConf has been renamed to AttemptSelection with significant enhancements:

  1. Added results vector to track selection outcomes (waste, coins, value)
  2. Implemented waste calculation for different selection algorithms
  3. Improved selection logic to choose the result with least waste

This change significantly improves the coin selection efficiency by selecting inputs that minimize waste, which leads to more optimal fee usage and transaction sizes.


507-529: Coin eligibility fallback expansions.

This block systematically attempts increasingly permissive CoinEligibilityFilter paths (Confirmed-Only, 1-conf, zero-conf with limited ancestors, etc.). It's well-structured but can get unwieldy if new fallback layers are added. Consider whether any new fallback steps or advanced strategies (like feerate-based selection) might be beneficial to generalize.


550-551: Updated coin selection result handling.

The code now properly handles the result from AttemptSelection by adding preset coins to the selection set, ensuring that manually selected inputs are always included in the transaction.


631-910: Comprehensive improvements to transaction creation logic.

The CreateTransactionInternal method has been significantly enhanced with:

  1. Better structure and variable declarations
  2. Improved fee calculation and management
  3. Enhanced change output handling including position tracking
  4. Robust transaction size estimation
  5. More comprehensive error handling
  6. Clearer logic for input selection and output management

These changes make transaction creation more reliable, efficient, and maintainable while handling edge cases better.


957-966: Added critical input validation.

Important validation checks have been added to ensure:

  1. At least one recipient exists
  2. No negative transaction amounts are allowed

This improves robustness by catching invalid transaction parameters early before attempting transaction creation.

src/wallet/test/wallet_tests.cpp (14)

29-29: Added wallet context header.

Added include for the new wallet context header file, which is essential for the context-based wallet management introduced in this PR.


51-67: Refactored TestLoadWallet to use WalletContext.

The TestLoadWallet function has been updated to:

  1. Accept a WalletContext& parameter
  2. Set the WALLET_FLAG_DESCRIPTORS flag to enable descriptor wallets
  3. Use the context when creating and adding the wallet

This change aligns with the broader refactoring to use context-based wallet management, improving organization and modularity.


70-77: Updated TestUnloadWallet to use WalletContext.

The TestUnloadWallet function has been updated to accept and use the WalletContext parameter when removing a wallet, maintaining consistency with the context-based approach.


93-102: Modernized AddKey function to use descriptor-based approach.

The AddKey function has been refactored to:

  1. Properly lock the wallet with LOCK(wallet.cs_wallet)
  2. Use descriptor-based key management instead of legacy script pubkey management
  3. Generate a descriptor from the key and add it to the wallet

This change reflects the architectural shift from legacy to descriptor-based wallet management.


193-206: Updated wallet setup in test case to use descriptor-based approach.

The wallet setup in the scan_for_wallet_transactions test case has been updated to:

  1. Set the WALLET_FLAG_DESCRIPTORS flag
  2. Use the descriptor-based key management

This ensures the test case properly tests the new descriptor-based wallet architecture.


233-268: Updated importmulti test case to use WalletContext.

The importmulti_rescan test case has been modified to:

  1. Create and initialize a WalletContext
  2. Pass the context to wallet functions
  3. Remove the wallet using context-aware methods

This maintains consistency with the context-based approach throughout the tests.


294-313: Updated importwallet test case to use WalletContext.

Similar to the importmulti test, this test case now properly uses WalletContext for wallet operations, ensuring consistent usage of the context-based approach.


354-357: Updated coin_mark_dirty_immature_credit test to use descriptor wallets.

Modified the test to:

  1. Lock the wallet when making changes
  2. Set the descriptor wallet flag
  3. Use descriptor-based setup instead of legacy script pubkey management

This ensures the test properly works with the updated wallet architecture.


625-647: Updated wallet_disableprivkeys test to use modern wallet setup.

This test has been updated to properly test private key disabling in both legacy and descriptor wallet types, ensuring comprehensive test coverage for the feature.


649-690: Added test for nested P2PKH input size calculation.

New test function dummy_input_size_test has been added to verify the behavior of the DUMMY_NESTED_P2PKH_INPUT_SIZE constant, which is important for transaction fee estimation. The test includes:

  1. A helper function CalculateNestedKeyhashInputSize that computes the size
  2. Verification that the constant matches the actual calculated size

This ensures the accuracy of transaction fee estimation for nested P2PKH inputs.


691-710: Added test for malformed descriptor handling.

New test wallet_descriptor_test verifies proper error handling for malformed wallet descriptors, ensuring the wallet gracefully handles incorrect descriptor formats.


712-833: Added comprehensive test for wallet creation race conditions.

The CreateWallet test case thoroughly verifies that no race conditions occur during wallet creation when:

  1. Transactions appear in the mempool or new blocks while the wallet is loading
  2. The wallet needs to properly handle notifications that arrive during startup

This is crucial for ensuring wallet reliability in concurrent environments.


834-869: Added test for wallet creation without chain.

The CreateWalletWithoutChain test verifies that wallets can be created without a blockchain connection, which is important for certain use cases like offline wallet creation.


870-1470: Added extensive Dash-specific wallet tests.

A comprehensive suite of Dash-specific wallet tests has been added, including:

  1. Tests for ZapSelectTx to verify transaction removal
  2. RPC tests for address information
  3. Transaction creation tests with various input/output configurations
  4. Coin selection tests with grouped addresses

These tests ensure that Dash-specific wallet functionality works correctly with the new architecture.

src/wallet/interfaces.cpp (10)

130-130: Updated WalletImpl constructor to use WalletContext.

The WalletImpl constructor now accepts a WalletContext& parameter alongside the existing wallet parameter, allowing the implementation to access the broader context needed for wallet operations.


504-504: Updated remove method to use context.

The remove method now passes the context to RemoveWallet, ensuring proper context-aware wallet removal.


550-550: Added WalletContext member to WalletImpl.

Added a WalletContext& m_context member to store the reference passed in the constructor, making it available for wallet operations that require context.


557-568: Added private RegisterRPCs method to WalletLoaderImpl.

Extracted the RPC registration logic into a dedicated private method to improve code organization and reusability. The method:

  1. Takes a Span of CRPCCommand objects
  2. Creates wrapped commands that inject the wallet context into requests
  3. Registers the commands with the chain interface

This improves modularity and reduces code duplication.


571-577: Updated WalletLoaderImpl constructor to include NodeContext.

The constructor now accepts a NodeContext& parameter and stores it in the wallet context, providing access to node-level functionality that may be needed by wallet operations.


582-597: Refactored RPC registration to use the new helper method.

The registerRpcs and new registerOtherRpcs methods now use the private RegisterRPCs helper, improving code organization and ensuring consistent handling of RPC commands.


586-590: Updated wallet operation methods to use context.

The wallet verification, loading, starting, flushing, and stopping methods now use the context, ensuring consistent context usage across all wallet operations.


606-643: Updated wallet creation and loading methods to use context.

The methods for creating, loading, restoring, and listing wallets now use the context when interacting with wallet functionality, maintaining consistency with the context-based approach.


644-644: Added context accessor method.

Added a context() method to WalletLoaderImpl that returns the wallet context, allowing external code to access the context if needed.


655-660: Updated MakeWallet and MakeWalletLoader interfaces to use context.

The interface factory functions have been updated to:

  1. Accept and use WalletContext for MakeWallet
  2. Accept NodeContext for MakeWalletLoader and pass it to the implementation

This ensures the interfaces align with the context-based architecture changes.

src/wallet/wallet.h (8)

52-52: Good addition of the WalletContext forward declaration.

This is a good step toward deglobalizing wallet variables, aligning with the PR's objective of refactoring the wallet context.


63-71: Properly refactored functions to use WalletContext.

All these wallet-related functions now properly take a WalletContext parameter, which aligns with the PR objective of refactoring wallet context and RPC registration processes. This change:

  • Makes dependencies explicit
  • Reduces reliance on global state
  • Improves testability
  • Enhances modularity

83-83: Appropriate default value for consolidate feerate.

The addition of DEFAULT_CONSOLIDATE_FEERATE with a value of 1000 (10 sat/vbyte) appears correct and aligns with the comments in the PR. This default ensures the functionality is active without being overly aggressive.


407-407: Function signature looks good.

The CreateTransactionInternal function signature includes all necessary parameters including fee calculation.


552-552: Good function rename from SelectCoinsMinConf to AttemptSelection.

This change clarifies the function's purpose - it's making an attempt to select coins that might succeed or fail, rather than implying it only works with minimum confirmations. This aligns with best practices for clear and descriptive naming.


777-781: Appropriate description of consolidate feerate behavior.

The comment accurately describes how the consolidation feerate influences transaction creation behavior. When the actual feerate is less than the consolidate feerate, the wallet will tend to consolidate inputs. When greater, it will prioritize lowest fees.


920-921: Properly updated Create function to use WalletContext.

The static Create function has been correctly refactored to accept a WalletContext parameter, consistent with the other wallet function changes in this PR.


1092-1092: Correctly updated MaybeResendWalletTxs to use WalletContext.

The function signature has been updated to take a WalletContext reference, consistent with the pattern applied throughout this file.

src/wallet/wallet.cpp (7)

44-44: Include statement update looks fine
This new include (<wallet/context.h>) is necessary for the WalletContext usage. No issues found.


159-163: Synchronized wallet list retrieval
The approach of locking context.wallets_mutex before returning context.wallets is correct. This ensures consistency during iteration in calling code.


174-179: Graceful handling of wallet-load callbacks
Emplace the callback into context.wallet_load_fns and return a handler which erases on destructor. This is a neat RAII approach. Looks good.


231-231: Initialization message
Calling context.chain->initMessage is consistent with the updated design of hooking into the chain interface. No issues found.


246-246: Return-value check
AddWallet(context, wallet) could fail if this wallet already exists in context.wallets. Consider checking the boolean return and logging an error if false, to avoid silent failures.


360-360: Consistent addition
Similar to line 246, ensure that the return value from AddWallet(context, wallet) is handled to detect any duplication or errors.


370-371: RestoreWallet signature
Accepting WalletContext& aligns with the new architecture. Implementation is straightforward. Good job ensuring the optional parameter for load_on_start.

Comment on lines +674 to +686
#ifdef ENABLE_WALLET
Span<const CRPCCommand> GetWalletMasternodeRPCCommands()
{
// clang-format off
static const CRPCCommand commands[] =
{ // category actor (function)
// --------------------- -----------------------
{ "dash", &masternode_outputs, },
};
// clang-format on
return commands;
}
#endif // ENABLE_WALLET
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Good separation of wallet-specific RPC commands, but fix formatting issue.

Adding GetWalletMasternodeRPCCommands() function improves code organization by separating wallet-specific masternode RPC commands from core masternode commands. This aligns with the PR's approach of modularizing wallet functionality.

The pipeline failures indicate a formatting issue at line 674. Please run clang-format to fix this:

clang-format -i src/rpc/masternode.cpp
🧰 Tools
🪛 GitHub Actions: Clang Diff Format Check

[error] 674-674: Clang format differences found: Formatting issues detected. Please run 'clang-format' to fix.

Copy link

@UdjinM6 UdjinM6 left a comment

Choose a reason for hiding this comment

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

LGTM, utACK e2eea71

Copy link
Member

@PastaPastaPasta PastaPastaPasta left a comment

Choose a reason for hiding this comment

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

utACK e2eea71

@PastaPastaPasta PastaPastaPasta merged commit d5e3d46 into dashpay:develop Feb 25, 2025
27 of 29 checks passed
@kwvg
Copy link
Collaborator Author

kwvg commented Feb 26, 2025

Post-merge CoinJoin run on Debian 12 (bookworm) mixing ~1 tDASH on default settings

image

@UdjinM6 UdjinM6 changed the title backport: merge bitcoin#21207, #22008, #22686, #22742, #19101, #22183, #22009, #22938, #23288, #24592 (wallet backports: part 2) backport: merge bitcoin#22008, #22686, #22742, #19101, #22183, #22009, #22938, #23288, #24592 (wallet backports: part 2) Mar 5, 2025
PastaPastaPasta added a commit that referenced this pull request Mar 18, 2025
…get early

17b40f9 Merge bitcoin-core/gui#605: Delete splash screen widget early (Hennadii Stepanov)

Pull request description:

  ## Issue being fixed or feature implemented

  Original PR description:

  >  `SplashScreen::deleteLater()` [does not guarantee](https://doc.qt.io/qt-5/qobject.html#deleteLater) deletion of the `m_splash` object prior to the wallet context deletion. If the latter happens first, the [segfault](bitcoin-core/gui#604 (comment)) follows.

  Crash:
  ```
  Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
  ...
  6   libc++abi.dylib               	       0x19012d6b4 std::terminate() + 108
  7   dash-qt                       	       0x1027e5744 SplashScreen::~SplashScreen() + 504 (splashscreen.cpp:142)
  8   dash-qt                       	       0x1027e5974 SplashScreen::~SplashScreen() + 4 (splashscreen.cpp:141) [inlined]
  9   dash-qt                       	       0x1027e5974 SplashScreen::~SplashScreen() + 36 (splashscreen.cpp:141)
  ...
  ```

  The issue was introduced via bitcoin#19101 backport (14aa05d) in #6529.

  ## What was done?
  Backport bitcoin-core/gui#605

  ## How Has This Been Tested?
  Run `./src/qt/dash-qt --regtest` and press `q` while on splash screen to shutdown asap

  develop: crash
  this PR: no crash

  ## Breaking Changes

  ## Checklist:
  - [ ] I have performed a self-review of my own code
  - [ ] I have commented my code, particularly in hard-to-understand areas
  - [ ] I have added or updated relevant unit/integration/functional/e2e tests
  - [ ] I have made corresponding changes to the documentation
  - [ ] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_

ACKs for top commit:
  knst:
    utACK 17b40f9

Tree-SHA512: d7f84d66ceaa499fb8f6874c54a389f5e3a852d4b94dc9ae43d9fd0bcf150e8952714d531b6ffb53903f19c1ed11ec5a1d64502a4027672305799d6061ce04e8
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.

3 participants