Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: consolidate ProTx wallet UTXO locking logic #6536

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from

Conversation

kwvg
Copy link
Collaborator

@kwvg kwvg commented Jan 23, 2025

Additional Information

  • This pull request consolidates locking ProTx UTXOs in a wallet by splitting them into three steps

    • Scanning transactions for eligible UTXOs and registering them in the wallet UTXO set (AddWalletUTXOs())
    • Going through a UTXO set and finding ProTx transactions (modified ListProTxCoins() to accept supplied sets)
    • Locking all supplied ProTx UTXOs (folded into LockProTxCoins(), which utilizes the previous two steps)
  • These are the behavior changes expected from this PR:

    • AutoLockMasternodeCollaterals() will now add new UTXOs it finds to the wallet UTXO set (setWalletUTXO) (earlier behavior was to only scan and lock).
    • UTXO locks will be consistently stored on disk (persistent locks were introduced in bitcoin#23065 (dash#6530) but weren't consistently used in all applicable LockCoin() calls)
  • The m_chain checks removed from various sections are acceptable as the check is still present in ListProTxCoins() (source) and it will clear the vector if it fails, which will effectively skip subsequent logic (also because it's the only place where listMNCollaterials is called)

    • Though this does not prevent them from being added to the wallet UTXO set as this happens before ListProTxCoins() is called but this isn't undesirable.

Breaking Changes

None expected.

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 (note: N/A)
  • 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 22.1 milestone Jan 23, 2025
@kwvg kwvg requested a review from knst January 23, 2025 15:51
@kwvg kwvg marked this pull request as ready for review January 27, 2025 05:50
Copy link

coderabbitai bot commented Jan 27, 2025

Walkthrough

The pull request introduces modifications to the wallet management functionality in the CWallet class across wallet.cpp and wallet.h files. The primary changes focus on enhancing UTXO (Unspent Transaction Output) handling and management. A new method AddWalletUTXOs is introduced, which allows adding unspent transaction outputs to the wallet while checking for duplicates and wallet ownership.

The modifications include refactoring existing methods like AutoLockMasternodeCollaterals to utilize the new AddWalletUTXOs method, simplifying the logic for managing masternode collateral outputs. Additionally, the ListProTxCoins method has been updated to accept a set of UTXOs as an argument, providing more flexible output handling.

The changes also involve renaming some method parameters for improved clarity and adding a new method LockProTxCoins to support locking specific UTXOs. These modifications aim to improve the wallet's UTXO management capabilities and code readability.

✨ 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: 0

🧹 Nitpick comments (3)
src/wallet/wallet.h (2)

766-771: Enhance documentation for ret_dups parameter.

The documentation should clarify the purpose and behavior of the ret_dups parameter, specifically whether it affects the function's behavior or just the return value.

-    /** Add new UTXOs to the wallet UTXO set
-     *
-     *  @param[in] tx         Transaction to scan eligible UTXOs from
-     *  @param[in] ret_dups   Allow UTXOs already in set to be included in return value
-     *  @returns              Set of all new UTXOs (eligible to be) added to set */
+    /** Add new UTXOs to the wallet UTXO set
+     *
+     *  @param[in] tx         Transaction to scan eligible UTXOs from
+     *  @param[in] ret_dups   When true, includes UTXOs already in set in the return value.
+     *                        When false, only returns newly added UTXOs.
+     *  @returns              Set of UTXOs that were added (if ret_dups=false) or all eligible
+     *                        UTXOs from tx (if ret_dups=true) */

1047-1050: Add documentation for coin management functions.

These functions lack documentation explaining their purpose, behavior, and relationships. Documentation is particularly important for the overloaded ListProTxCoins to explain the difference between the two variants.

+    /** Lists all locked coins in the wallet.
+     *  @param[out] outputs   Vector to be populated with locked coin outpoints */
     void ListLockedCoins(std::vector<COutPoint>& outputs) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+    /** Lists all ProTx coins in the wallet.
+     *  @param[out] outputs   Vector to be populated with ProTx coin outpoints */
     void ListProTxCoins(std::vector<COutPoint>& outputs) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+    /** Lists ProTx coins from a specific set of UTXOs.
+     *  @param[in]  utxos     Set of UTXOs to check for ProTx coins
+     *  @param[out] outputs   Vector to be populated with ProTx coin outpoints */
     void ListProTxCoins(const std::set<COutPoint>& utxos, std::vector<COutPoint>& outputs) const EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
+
+    /** Locks all ProTx coins from a specific set of UTXOs.
+     *  @param[in] utxos      Set of UTXOs to lock if they are ProTx coins
+     *  @param[in] batch      Optional batch to use for writing lock status to database */
     void LockProTxCoins(const std::set<COutPoint>& utxos, WalletBatch* batch = nullptr) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
src/wallet/wallet.cpp (1)

1040-1053: LGTM! Consider adding documentation.

The implementation correctly handles UTXO set management with proper locking and duplicate handling. Consider adding documentation to explain the purpose of the ret_dups parameter and the function's behavior.

Add documentation like:

/**
 * Add unspent transaction outputs from a transaction to the wallet UTXO set.
 * @param[in]  tx       Transaction to add UTXOs from
 * @param[in]  ret_dups Whether to return duplicate UTXOs that are already in the set
 * @return     Set of COutPoints that were added or attempted to be added (if ret_dups=true)
 */
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between 0972dfe and fb6f2e2.

📒 Files selected for processing (2)
  • src/wallet/wallet.cpp (5 hunks)
  • src/wallet/wallet.h (2 hunks)
🔇 Additional comments (8)
src/wallet/wallet.h (1)

766-771: LGTM! The design is clean and consistent.

The new UTXO and ProTx management functions are well-integrated into the CWallet class, following existing patterns and maintaining proper thread safety through consistent use of cs_wallet locks.

Also applies to: 1047-1050

src/wallet/wallet.cpp (7)

917-925: LGTM! Proper UTXO tracking for new transactions.

The code correctly tracks UTXOs from newly inserted transactions, using the new AddWalletUTXOs function with ret_dups=true to get all candidates for ProTx locking.


941-942: LGTM! Proper UTXO tracking for existing transactions.

The code correctly tracks UTXOs from existing transactions, using AddWalletUTXOs with ret_dups=false and properly updates the transaction status if new UTXOs are found.


945-946: LGTM! Proper ProTx locking after UTXO tracking.

The code correctly locks ProTx coins using the candidates collected from UTXO tracking, maintaining transactional consistency by using the same batch.


4496-4513: LGTM! Well-designed ProTx coin listing implementation.

The implementation efficiently handles ProTx coin listing with:

  • Proper chain validation
  • Efficient candidate pair building
  • Clear separation between wallet UTXOs and explicit UTXO sets

4515-4522: LGTM! Proper implementation of ProTx coin locking.

The code correctly identifies and locks ProTx coins while maintaining transactional consistency through proper batch usage.


4050-4056: LGTM! Efficient implementation of automatic masternode collateral locking.

The code efficiently collects and locks masternode collaterals using the new UTXO tracking functionality while maintaining proper transaction batching.


4488-4494: LGTM! Clean implementation of locked coins listing.

The implementation correctly handles locked coins listing with proper locking semantics.

Copy link
Collaborator

@knst knst left a comment

Choose a reason for hiding this comment

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

concept ACK, see comments about:

  • std::set vs std::vector + sort + unique
  • use RVO instead return by argument

if (IsMine(wtx.tx->vout[i]) && !IsSpent(hash, i)) {
setWalletUTXO.insert(COutPoint(hash, i));
outputs.emplace_back(wtx.tx, i);
candidates.emplace(hash, i);
Copy link
Collaborator

Choose a reason for hiding this comment

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

std::vector usually has significantly better performance (10x), RAM usage is also over-headed (due to bunch of small allocation 32bytes per one item somewhere randomly allocated in heap, instead consequence allocation as vector) compare to std::set.

std::set has a great usage when you combine 2 types of actions: "add" and "request". In case if you know all elements, you should use data structure with linear memory inside for better performace.

If it is a know case here to have duplicates, consider using std::vector and remove duplicates by std::sort + std::unique + std::erase.

}
}

void CWallet::ListProTxCoins(std::vector<COutPoint>& vOutpts) const
void CWallet::ListProTxCoins(std::vector<COutPoint>& outputs) const { return ListProTxCoins(setWalletUTXO, outputs); }
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's return it using RVO here

std::vector<COutPoint> CWallet::ListProTxCoins() const {
 return ListProTxCoins(setWalletUTXO);
}

}
}
vOutpts = m_chain->listMNCollaterials(outputs);
outputs = m_chain->listMNCollaterials(candidates);
Copy link
Collaborator

Choose a reason for hiding this comment

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

let's return here also like RVO:

return m_chain->listMNCollaterials(candidates);

Comment on lines 933 to 935
std::vector<COutPoint> protx_utxos;
ListProTxCoins(candidates, /*output=*/protx_utxos);
for (const auto& utxo : protx_utxos) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

can be re-written much shorter (see other comments also):

-        std::vector<COutPoint> protx_utxos;
-        ListProTxCoins(candidates, /*output=*/protx_utxos);
-        for (const auto& utxo : protx_utxos) {
+        for (const auto& utxo : ListProTxCoins(candidates)) {

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants