-
Notifications
You must be signed in to change notification settings - Fork 1.2k
feat: create extra spk by default for mobile derivation path of CJ #6836
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
base: develop
Are you sure you want to change the base?
feat: create extra spk by default for mobile derivation path of CJ #6836
Conversation
✅ No Merge Conflicts DetectedThis PR currently has no conflicts with other open PRs. |
WalkthroughAdds an optional boolean coinjoin field to the listdescriptors RPC output for descriptors with a defined output type by detecting a CoinJoin derivation path that includes the dynamic ExtCoinType. Introduces PathDerivationType (BIP44_External, BIP44_Internal, DIP0009_CoinJoin) and changes DescriptorScriptPubKeyMan::SetupDescriptorGeneration to accept this enum. Adds BIP32_PURPOSE_FEATURE (9) and BIP32_PURPOSE_STANDARD (44) constants, updates HD key path formatting and descriptor generation to use purpose constants, updates wallet activation/registration flow (including AddActiveScriptPubKeyMan and adjusted handling for CoinJoin), and updates related tests and release notes. Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests
Warning Tools execution failed with the following error: Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error) Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🧪 Early access (Sonnet 4.5): enabledWe are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience. Note:
Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/wallet/rpc/backup.cpp (1)
1979-1986
: Doc mismatch: coinjoin should not be “only for active descriptors.”CJ descriptors are intentionally inactive by default; the field should be documented as present when the type is known, regardless of activity.
- {RPCResult::Type::BOOL, "coinjoin", /*optional=*/true, "True if this descriptor is used to generate CoinJoin addresses. False if this descriptor is used to generate receiving addresses; defined only for active descriptors"}, + {RPCResult::Type::BOOL, "coinjoin", /*optional=*/true, "True if this descriptor derives CoinJoin addresses (purpose 9'); present when the descriptor output type is known."},
🧹 Nitpick comments (7)
src/wallet/scriptpubkeyman.h (1)
150-155
: Good addition; please document the new key class.Add a short comment explaining semantics (External, Internal, CoinJoin) and intended activation (CJ inactive by default) to aid future readers.
+// Distinguishes descriptor categories: +// - External: receiving addresses (change=0) +// - Internal: change addresses (change=1) +// - CoinJoin: mobile CJ funds (purpose 9'), created by default but kept inactive enum class InternalKey { External, Internal, CoinJoin, };src/wallet/rpc/wallet.cpp (1)
171-172
: Terminology nit: capitalize CoinJoin in help text.- "how many new keys are pre-generated for internal use (used for change outputs and mobile coinjoin, only appears if the wallet is using this feature, otherwise external keys are used)"}, + "how many new keys are pre-generated for internal use (used for change outputs and mobile CoinJoin; appears only if the wallet is using this feature, otherwise external keys are used)"},test/functional/wallet_listdescriptors.py (2)
49-51
: Safe dict access in assertions; drop noisy logging.Use dict.get to avoid KeyError if schema changes, and remove debug log.
- assert_equal(3, len(result['descriptors'])) - assert_equal(2, len([d for d in result['descriptors'] if d['active']])) - self.log.info(f"result: {result['descriptors']}") + assert_equal(3, len(result['descriptors'])) + assert_equal(2, len([d for d in result['descriptors'] if d.get('active')]))
52-54
: Use.get
and simplify coinjoin check (RUF019).- assert_equal(1, len([d for d in result['descriptors'] if d['internal']])) - assert_equal(1, len([d for d in result['descriptors'] if 'coinjoin' in d and d['coinjoin']])) + assert_equal(1, len([d for d in result['descriptors'] if d.get('internal')])) + assert_equal(1, len([d for d in result['descriptors'] if d.get('coinjoin')]))test/functional/wallet_mnemonicbits.py (1)
55-58
: Make counts robust; avoid reliance on schema details.Keep counts but tolerate descriptors lacking ‘internal’.
- assert_equal(mnemonic_count, 3) + assert_equal(mnemonic_count, 3) assert_equal(cb_count, 1) - assert_equal(len(descriptors), 4) + assert_equal(len(descriptors), 4)src/wallet/rpc/backup.cpp (1)
1960-2065
: Longer-term: avoid string matching; carry CJ metadata.Prefer tagging CJ at creation (e.g., store a flag alongside WalletDescriptor) and expose it here, rather than parsing strings.
src/wallet/wallet.cpp (1)
3827-3836
: Switch on bool is unconventional; prefer if/else for clarityMinor readability nit; avoids odd switch(true/false).
- switch (internal) { - case true: - m_internal_spk_managers = spk_man; - break; - - case false: - m_external_spk_managers = spk_man; - break; - } + if (internal) { + m_internal_spk_managers = spk_man; + } else { + m_external_spk_managers = spk_man; + }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (7)
src/wallet/rpc/backup.cpp
(2 hunks)src/wallet/rpc/wallet.cpp
(1 hunks)src/wallet/scriptpubkeyman.cpp
(2 hunks)src/wallet/scriptpubkeyman.h
(2 hunks)src/wallet/wallet.cpp
(6 hunks)test/functional/wallet_listdescriptors.py
(1 hunks)test/functional/wallet_mnemonicbits.py
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{cpp,h,cc,cxx,hpp}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{cpp,h,cc,cxx,hpp}
: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction
Files:
src/wallet/rpc/wallet.cpp
src/wallet/scriptpubkeyman.h
src/wallet/rpc/backup.cpp
src/wallet/wallet.cpp
src/wallet/scriptpubkeyman.cpp
test/functional/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Functional tests should be written in Python and placed in test/functional/
Files:
test/functional/wallet_listdescriptors.py
test/functional/wallet_mnemonicbits.py
🧠 Learnings (3)
📓 Common learnings
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.203Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
PR: dashpay/dash#6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.
Applied to files:
src/wallet/rpc/wallet.cpp
📚 Learning: 2025-09-02T07:34:28.203Z
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.203Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
Applied to files:
src/wallet/rpc/backup.cpp
test/functional/wallet_mnemonicbits.py
src/wallet/wallet.cpp
src/wallet/scriptpubkeyman.cpp
🧬 Code graph analysis (4)
test/functional/wallet_listdescriptors.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
src/wallet/scriptpubkeyman.h (1)
src/wallet/scriptpubkeyman.cpp (2)
SetupDescriptorGeneration
(2077-2129)SetupDescriptorGeneration
(2077-2077)
src/wallet/rpc/backup.cpp (1)
src/script/descriptor.cpp (1)
nullopt
(657-657)
test/functional/wallet_mnemonicbits.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
🪛 Ruff (0.12.2)
test/functional/wallet_listdescriptors.py
53-53: Unnecessary key check before dictionary access
Replace with dict.get
(RUF019)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Lint / Run linters
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
🔇 Additional comments (5)
src/wallet/scriptpubkeyman.h (1)
584-586
: Signature change looks right; confirm all callers updated.Given the switch from bool to enum, ensure all invocations now pass InternalKey::{External,Internal,CoinJoin}. Compile will catch most, but please double-check wallet setup paths.
src/wallet/scriptpubkeyman.cpp (1)
2077-2079
: Confirm all calls updated—no remaining boolean overloads
Grep shows only one invocation insrc/wallet/wallet.cpp:3800
, passing the localinternal
variable, which is already of typeInternalKey
(notbool
). No literaltrue/false
or stale overloads remain.src/wallet/wallet.cpp (3)
2357-2369
: Use external SPKM directly for receive addresses — OKStraightforward; no behavior change beyond comment cleanup.
3789-3806
: Creating 3 SPKMs and activating only External/Internal — OKMatches goal: CJ SPKM exists for discovery but is inactive for address issuance.
3838-3844
: De-aliasing active SPKM pointers when reassigning — OKPrevents both pointers referencing the same manager; good defensive state management.
src/wallet/scriptpubkeyman.cpp
Outdated
std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, Params().ExtCoinType()); | ||
std::string desc_suffix = "/*)"; | ||
|
||
std::string internal_path = internal ? "/1" : "/0"; | ||
std::string internal_path = (internal == InternalKey::Internal) ? "/1" : "/0"; | ||
std::string desc_str = desc_prefix + "/0'" + internal_path + desc_suffix; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
CoinJoin derivation path likely mismatched with Android “9'/1'/0'” expectation
Code uses Params().ExtCoinType() for CJ coin type, but RPC/tests reportedly detect CJ via path “/9'/1'/0'”. On mainnet ExtCoinType() != 1 (Dash is 5), so generated CJ descriptor would be “9'/5'/0'…”, breaking visibility with Android CJ funds. Fix by forcing coin type 1 for CJ (or align detection to ExtCoinType()).
Apply:
- std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, Params().ExtCoinType());
+ const int coin_type = (internal == InternalKey::CoinJoin) ? 1 : Params().ExtCoinType();
+ std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, coin_type);
Also confirm listdescriptors’ CJ detection logic matches this choice:
If Android CJ uses a different coin_type per network, wire it explicitly and update tests.
🏁 Script executed:
#!/bin/bash
rg -n "listdescriptors|coinjoin|9'/1'|9'\/1'" -C3
Length of output: 200
🏁 Script executed:
#!/bin/bash
# Confirm CJ descriptor generation uses Params().ExtCoinType()
rg -n "desc_prefix" -C5 src/wallet/scriptpubkeyman.cpp
# Search for listdescriptors RPC command occurrences
rg -n "listdescriptors" -C5 .
# Inspect functional tests for CJ path detection (9'/1)
rg -n "9'/1" -C5 test
Length of output: 25750
Force CJ descriptor coin type to 1
Functional tests (wallet_mnemonicbits.py:50) detect CJ descriptors inactive via the substring "/9'/1"
in the descriptor. On mainnet, Params().ExtCoinType()
returns 5, so CJ descriptors are currently generated with 9'/5…
, breaking both the functional test detection and Android’s “9'/1'/0'” assumption. Update the code as follows:
- std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, Params().ExtCoinType());
+ const int coin_type = internal == InternalKey::CoinJoin ? 1 : Params().ExtCoinType();
+ std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, coin_type);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, Params().ExtCoinType()); | |
std::string desc_suffix = "/*)"; | |
std::string internal_path = internal ? "/1" : "/0"; | |
std::string internal_path = (internal == InternalKey::Internal) ? "/1" : "/0"; | |
std::string desc_str = desc_prefix + "/0'" + internal_path + desc_suffix; | |
const int coin_type = internal == InternalKey::CoinJoin ? 1 : Params().ExtCoinType(); | |
std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? 9 : 44, coin_type); | |
std::string desc_suffix = "/*)"; | |
std::string internal_path = (internal == InternalKey::Internal) ? "/1" : "/0"; | |
std::string desc_str = desc_prefix + "/0'" + internal_path + desc_suffix; |
🤖 Prompt for AI Agents
In src/wallet/scriptpubkeyman.cpp around lines 2102 to 2107, the CJ (CoinJoin)
descriptor uses Params().ExtCoinType() which on mainnet yields 5, causing CJ
descriptors to be generated as "9'/5" and breaking tests and Android
assumptions; change the code to force coin type to 1 when internal ==
InternalKey::CoinJoin (e.g. compute a coinType variable = (internal ==
InternalKey::CoinJoin ? 1 : Params().ExtCoinType()) and use that coinType in the
desc_prefix construction), leaving other path parts unchanged.
5f0fcf9
to
9d7be36
Compare
@coderabbitai help to prepare release notes for this PR See PR description and #6745 for information source UPD: it's a bit too long; see as a reference release notes for v21: https://github.com/dashpay/dash/blob/master/doc/release-notes/dash/release-notes-21.0.0.md It should be just one paragraph of text; maximum 2 |
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chainI'll help you prepare release notes for this PR. Let me first gather some additional information about the issue and PR details. Based on the information gathered and the PR changes, here are the release notes for this feature: Release Notes - Mobile CoinJoin Descriptor SupportNew Feature: Enhanced CoinJoin Compatibility Between Mobile and Desktop WalletsProblem Solved:
Changes:
API Changes:
Technical Details:
User Impact:
For Developers:
This change ensures better interoperability between different Dash wallet implementations while maintaining backward compatibility for existing wallets. 🏁 Script executed:
Length of output: 2098 Perfect! Now I have the complete context. Here are the refined release notes for PR #6836: Release Notes - Mobile CoinJoin Descriptor SupportNew Feature: Enhanced CoinJoin Compatibility Between Mobile and Desktop WalletsProblem Solved:
What Changed:
API Enhancements:
User Benefits:
Technical Implementation:
Compatibility:
This enhancement significantly improves the user experience when using multiple Dash wallet applications, ensuring that CoinJoin privacy features work consistently across the entire ecosystem. 🧠 Learnings used
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain@knst, I'll prepare concise release notes following the v21 format. Let me first check the reference format you mentioned: Based on the v21 release notes format, here are the concise release notes for PR #6836: Mobile CoinJoin CompatibilityFixed an issue where CoinJoin funds mixed in Dash Android wallet were invisible when importing the mnemonic into Dash Core or other desktop wallets. New descriptor wallets now include an additional default descriptor for mobile CoinJoin funds, ensuring seamless wallet migration and complete fund visibility across different Dash wallet implementations. This is a breaking change that increases the default number of descriptors from 2 to 3 on mainnet (internal, external, mobile CoinJoin) for newly created descriptor wallets only - existing wallets are unaffected. 🏁 Script executed:
Length of output: 2241 Perfect! Now I can see the format. Here are the concise release notes following the v21 style: Mobile CoinJoin CompatibilityFixed an issue where CoinJoin funds mixed in Dash Android wallet were invisible when importing the mnemonic into Dash Core or other desktop wallets. New descriptor wallets now include an additional default descriptor for mobile CoinJoin funds, ensuring seamless wallet migration and complete fund visibility across different Dash wallet implementations. This is a breaking change that increases the default number of descriptors from 2 to 3 on mainnet (internal, external, mobile CoinJoin) for newly created descriptor wallets only - existing wallets are unaffected. The 🧠 Learnings used
|
018a42d
to
bdb92b2
Compare
There was a problem hiding this 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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
doc/release-notes-6835.md (1)
1-22
: Fix wrong PR reference and capture regtest delta in breaking-change note
- The reference “(#6835)” appears incorrect for this PR; update to “(#6836)” and optionally include the original issue “(#6745)”.
- The breaking-change paragraph omits the regtest increase (3 → 4); add it for completeness.
Apply:
- - This is a breaking change that increases the default number of descriptors - from 2 to 3 on mainnet (internal, external, mobile CoinJoin) for newly created - descriptor wallets only - existing wallets are unaffected. + - Breaking change (new descriptor wallets only): + - Mainnet: default descriptors increase from 2 to 3 (internal, external, mobile CoinJoin). + - Regtest: default descriptors increase from 3 to 4 (internal, external, mobile CoinJoin, cbtx private key). + Existing wallets are unaffected. @@ -(#6835) +(#6836, #6745)
♻️ Duplicate comments (1)
test/functional/wallet_mnemonicbits.py (1)
50-51
: Prefer dict.get for clarity and to satisfy Ruff RUF019Equivalent and cleaner.
- assert_equal(desc['active'], ("coinjoin" not in desc or not desc['coinjoin'])) + assert_equal(desc['active'], not desc.get('coinjoin', False))
🧹 Nitpick comments (3)
test/functional/wallet_mnemonicbits.py (1)
55-57
: Update adjacent comment to match new expectations (3 mnemonics, 4 descriptors)The comment above Lines 52–54 still describes the pre-change state (“3 descriptors total … Two other should be active”). Please align it with the new assertions (mnemonic_count == 3, len(descriptors) == 4). No code change needed here.
test/functional/wallet_listdescriptors.py (1)
53-53
: Use dict.get to simplify the coinjoin filterShorter and avoids an unnecessary key check.
- assert_equal(1, len([d for d in result['descriptors'] if 'coinjoin' in d and d['coinjoin']])) + assert_equal(1, len([d for d in result['descriptors'] if d.get('coinjoin')]))src/wallet/wallet.cpp (1)
3790-3807
: Minor: avoid “internal” as loop var for the InternalKey enumReduces ambiguity with the existing boolean “internal” semantics elsewhere.
- for (auto internal : {InternalKey::External, InternalKey::Internal, InternalKey::CoinJoin}) { + for (auto ikey : {InternalKey::External, InternalKey::Internal, InternalKey::CoinJoin}) { @@ - spk_manager->SetupDescriptorGeneration(master_key, mnemonic, mnemonic_passphrase, internal); + spk_manager->SetupDescriptorGeneration(master_key, mnemonic, mnemonic_passphrase, ikey); @@ - if (internal != InternalKey::CoinJoin) { - AddActiveScriptPubKeyMan(id, internal == InternalKey::Internal); + if (ikey != InternalKey::CoinJoin) { + AddActiveScriptPubKeyMan(id, ikey == InternalKey::Internal);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (8)
doc/release-notes-6835.md
(1 hunks)src/wallet/rpc/backup.cpp
(3 hunks)src/wallet/rpc/wallet.cpp
(1 hunks)src/wallet/scriptpubkeyman.cpp
(2 hunks)src/wallet/scriptpubkeyman.h
(2 hunks)src/wallet/wallet.cpp
(2 hunks)test/functional/wallet_listdescriptors.py
(1 hunks)test/functional/wallet_mnemonicbits.py
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
- src/wallet/scriptpubkeyman.h
- src/wallet/scriptpubkeyman.cpp
- src/wallet/rpc/wallet.cpp
- src/wallet/rpc/backup.cpp
🧰 Additional context used
📓 Path-based instructions (3)
doc/**
📄 CodeRabbit inference engine (CLAUDE.md)
Unless specifically prompted, avoid making changes to the doc directory (documentation)
Files:
doc/release-notes-6835.md
test/functional/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Functional tests should be written in Python and placed in test/functional/
Files:
test/functional/wallet_mnemonicbits.py
test/functional/wallet_listdescriptors.py
src/**/*.{cpp,h,cc,cxx,hpp}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{cpp,h,cc,cxx,hpp}
: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction
Files:
src/wallet/wallet.cpp
🧠 Learnings (2)
📓 Common learnings
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
📚 Learning: 2025-09-02T07:34:28.226Z
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
Applied to files:
doc/release-notes-6835.md
test/functional/wallet_mnemonicbits.py
src/wallet/wallet.cpp
🧬 Code graph analysis (2)
test/functional/wallet_mnemonicbits.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
test/functional/wallet_listdescriptors.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
🪛 Ruff (0.12.2)
test/functional/wallet_listdescriptors.py
53-53: Unnecessary key check before dictionary access
Replace with dict.get
(RUF019)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: linux64_tsan-test / Test source
🔇 Additional comments (2)
src/wallet/wallet.cpp (2)
3790-3807
: LGTM: create CoinJoin SPKM but keep it inactive by defaultCreating the CJ SPKM and not activating it (only External/Internal active) matches the intended behavior and tests relying on listdescriptors. No functional issues spotted.
3790-3807
: Fetched backup.cpp context for manual verification. No critical issues found: all GetAllScriptPubKeyMans call sites perform non-mutating or safe migrations/reporting (descriptor backup, cache upgrade, signing/fill PSBT across all keyrings, logging, and rescan time determination). Address generation, keypool top-up, and notifications exclusively use GetActiveScriptPubKeyMans.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nits
There was a problem hiding this 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 (1)
src/wallet/hdchain.cpp (1)
206-206
: Fix formatting to comply with Clang format check.The pipeline indicates formatting differences detected by clang-format.
Apply this diff to fix the formatting:
- return strprintf("m/%d'/%d'/%d'/%d/%d", BIP32_PURPOSE_STANDARD, Params().ExtCoinType(), nAccountIndex, nChangeIndex, extPubKey.nChild); + return strprintf("m/%d'/%d'/%d'/%d/%d", BIP32_PURPOSE_STANDARD, Params().ExtCoinType(), nAccountIndex, nChangeIndex, + extPubKey.nChild);
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/wallet/hdchain.cpp
(1 hunks)src/wallet/hdchain.h
(1 hunks)src/wallet/scriptpubkeyman.cpp
(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/**/*.{cpp,h,cc,cxx,hpp}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{cpp,h,cc,cxx,hpp}
: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction
Files:
src/wallet/hdchain.h
src/wallet/hdchain.cpp
src/wallet/scriptpubkeyman.cpp
🧠 Learnings (3)
📓 Common learnings
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
📚 Learning: 2025-08-08T07:01:47.332Z
Learnt from: knst
PR: dashpay/dash#6805
File: src/wallet/rpc/wallet.cpp:357-357
Timestamp: 2025-08-08T07:01:47.332Z
Learning: In src/wallet/rpc/wallet.cpp, the upgradetohd RPC now returns a UniValue string message (RPCResult::Type::STR) instead of a boolean, including guidance about mnemonic backup and null-character passphrase handling; functional tests have been updated to assert returned strings in several cases.
Applied to files:
src/wallet/hdchain.h
src/wallet/hdchain.cpp
📚 Learning: 2025-09-02T07:34:28.226Z
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
Applied to files:
src/wallet/scriptpubkeyman.cpp
🧬 Code graph analysis (2)
src/wallet/hdchain.cpp (2)
src/wallet/hdchain.h (3)
BIP32_PURPOSE_STANDARD
(147-149)nAccountIndex
(131-131)nChangeIndex
(132-132)src/chainparams.cpp (2)
Params
(1354-1357)Params
(1354-1354)
src/wallet/scriptpubkeyman.cpp (2)
src/wallet/hdchain.h (2)
BIP32_PURPOSE_FEATURE
(145-145)BIP32_PURPOSE_STANDARD
(147-149)src/chainparams.cpp (2)
Params
(1354-1357)Params
(1354-1354)
🪛 GitHub Actions: Clang Diff Format Check
src/wallet/hdchain.cpp
[error] 203-208: Clang format differences detected by clang-format-diff.py. Formatting changes applied would modify src/wallet/hdchain.cpp; please run clang-format (or update CI to accept formatted changes).
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (6)
- GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
🔇 Additional comments (5)
src/wallet/hdchain.h (1)
144-148
: LGTM!The new constants
BIP32_PURPOSE_FEATURE
(9) andBIP32_PURPOSE_STANDARD
(44) align with the PR objectives to support mobile CoinJoin with purpose 9 and standard derivation with purpose 44. These constants will replace hardcoded values in descriptor path construction.src/wallet/hdchain.cpp (1)
206-206
: LGTM!The path format change from hardcoded
"m/44'/%d'/%d'/%d/%d"
to dynamic"m/%d'/%d'/%d'/%d/%d"
withBIP32_PURPOSE_STANDARD
is correct. This aligns with the new constants defined inhdchain.h
and supports variable purpose codes for different derivation paths.src/wallet/scriptpubkeyman.cpp (3)
2077-2077
: LGTM!The function signature change from
bool internal
toInternalKey internal
properly aligns with the new three-way categorization (External, Internal, CoinJoin) introduced by this PR.
2105-2105
: LGTM!The conditional logic correctly maps the
InternalKey
enum to the appropriate path component: Internal becomes "/1" and External (including CoinJoin) becomes "/0". This properly differentiates internal change addresses from external receiving addresses.
2102-2102
: **Force CJ descriptor coin type to 1.**Based on the web search results, I can see that Dash uses coin type 5 for BIP44 derivation paths. However, the past review comment indicates that functional tests detect CJ descriptors via the substring "/9'/1" and Android CJ uses "9'/1'/0'". This creates a mismatch sinceParams().ExtCoinType()
returns 5 on mainnet, not 1.Based on the previous review feedback and the retrieved learnings showing that CJ descriptors are detected by matching "/9'/1" patterns, the current code using
Params().ExtCoinType()
would generate "9'/5'" paths on mainnet instead of the expected "9'/1'" paths. This breaks compatibility with both functional tests and Android CJ wallets.Apply this fix to force coin type 1 for CJ descriptors:
- std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? BIP32_PURPOSE_FEATURE : BIP32_PURPOSE_STANDARD, Params().ExtCoinType()); + const int coin_type = (internal == InternalKey::CoinJoin) ? 1 : Params().ExtCoinType(); + std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, internal == InternalKey::CoinJoin ? BIP32_PURPOSE_FEATURE : BIP32_PURPOSE_STANDARD, coin_type);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 1038ad3
src/wallet/rpc/backup.cpp
Outdated
std::string match = strprintf("/9'/%s'/0'", Params().ExtCoinType()); | ||
bool is_cj = descriptor.size() > 5 && descriptor.find(match) != std::string::npos; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's avoid these magic numbers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 78a0979
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
utACK 78a0979
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This differs a lot from the proposed plan #6745 (comment). Why?
src/wallet/scriptpubkeyman.h
Outdated
enum class InternalKey | ||
{ | ||
External, | ||
Internal, | ||
CoinJoin, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: These names are confusing imo. Maybe smth like
enum class InternalKey | |
{ | |
External, | |
Internal, | |
CoinJoin, | |
}; | |
enum class PathDerivationType | |
{ | |
BIP44_External, | |
BIP44_Internal, | |
DIP0009_CoinJoin, | |
}; |
we discussed it on weekly calls, there are several reasons to do. Firstly, I'd like to keep compatibility between Dash Core & 3rd party wallets, include hardware one. If we will have custom derivation path for mixing, same as mobile, it means that these funds won't be easily available at any other 3rd party wallets, it creates "vendor lock" to DCG projects (android wallet, Dash Core). That's why I don't like to use for CJ on Dash Core custom mobile path same as it is done in mobile android wallet. So far as we have mnemonic in Dash Core; it is great if these mnemonic can be easily imported in any 3rd party wallet and it "just works". Though, this PR is aim to add a potentially at least 1 wallet beside Android Wallet that could let user to get access to his "lost" funds if user will mix his funds on mobile and it does. Secondly, Dash Core currently has 2 competing implementation of HD wallets (legacy wallets and descriptor wallets). Both of them them (legacy & descriptor) are backported from bitcoin*(1)(2), but legacy wallets are deprecated in bitcoin and in the latest versions you can't even create legacy wallet anymore. I wish Dash Core with mnemonic for Descriptor wallets (#6570) has been released long time ago, so we could start deprecating legacy wallets; and create descriptor wallets, but we haven't had a major releases for awhile, so, it's a bit slower that it is. (1). legacy wallets have our own implementation HD, not fully backported. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This differs a lot from the proposed plan #6745 (comment). Why?
we discussed it on weekly calls, there are several reasons to do.
Firstly, I'd like to keep compatibility between Dash Core & 3rd party wallets, include hardware one. If we will have custom derivation path for mixing, same as mobile, it means that these funds won't be easily available at any other 3rd party wallets, it creates "vendor lock" to DCG projects (android wallet, Dash Core). That's why I don't like to use for CJ on Dash Core custom mobile path same as it is done in mobile android wallet.
So far as we have mnemonic in Dash Core; it is great if these mnemonic can be easily imported in any 3rd party wallet and it "just works".
Though, this PR is aim to add a potentially at least 1 wallet beside Android Wallet that could let user to get access to his "lost" funds if user will mix his funds on mobile and it does.
Secondly, Dash Core currently has 2 competing implementation of HD wallets (legacy wallets and descriptor wallets). Both of them them (legacy & descriptor) are backported from bitcoin*(1)(2), but legacy wallets are deprecated in bitcoin and in the latest versions you can't even create legacy wallet anymore.
I wish Dash Core with mnemonic for Descriptor wallets (#6570) has been released long time ago, so we could start deprecating legacy wallets; and create descriptor wallets, but we haven't had a major releases for awhile, so, it's a bit slower that it is. Due that I don't really want to add new feature to legacy wallets and complicate implementation as proposed in #6745, instead it's much easier to implement & support just adding +1 extra descriptor in descriptor wallets. The patch minimal (50 lines) but it works just fine.
(1). legacy wallets have our own implementation HD, not fully backported. (2). both descriptor & legacy wallets have our own implementation of mnemonic, it's not backported feature.
Makes sense, thanks!
import mnemonic to Dash Core. Funds (including CJ transactions) expect to visible.
I'm creating an empty descriptor wallet and using "upgradetohd" rpc to import mnemonic I use on mobile. I then do "rescanblockchain" but I see no CJ txes once its done, only "Sent to"... What steps were you using exactly to test this?
Maybe there is a bug, I will re-check. I tested some not the very final version, maybe introduced some new issue. I will re-test and check if it works. |
Probably you did everything right. Implementation has lost Steps to reproduce:
|
There was a problem hiding this 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 (1)
test/functional/wallet_listdescriptors.py (1)
52-53
: Test assertions correctly validate the new CoinJoin descriptor.The assertions properly verify that exactly one descriptor has the
internal
flag and one has thecoinjoin
flag, which aligns with the expected structure (3 total descriptors: external, internal, and CoinJoin). Based on learnings, CoinJoin descriptors are intentionally inactive.For a more concise style, consider using
dict.get()
:- assert_equal(1, len([d for d in result['descriptors'] if 'internal' in d and d['internal']])) - assert_equal(1, len([d for d in result['descriptors'] if 'coinjoin' in d and d['coinjoin']])) + assert_equal(1, len([d for d in result['descriptors'] if d.get('internal')])) + assert_equal(1, len([d for d in result['descriptors'] if d.get('coinjoin')]))
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
src/wallet/rpc/backup.cpp
(3 hunks)test/functional/wallet_listdescriptors.py
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- src/wallet/rpc/backup.cpp
🧰 Additional context used
📓 Path-based instructions (1)
test/functional/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Functional tests should be written in Python and placed in test/functional/
Files:
test/functional/wallet_listdescriptors.py
🧠 Learnings (1)
📓 Common learnings
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
🧬 Code graph analysis (1)
test/functional/wallet_listdescriptors.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
🪛 Ruff (0.13.1)
test/functional/wallet_listdescriptors.py
52-52: Unnecessary key check before dictionary access
Replace with dict.get
(RUF019)
53-53: Unnecessary key check before dictionary access
Replace with dict.get
(RUF019)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: x86_64-w64-mingw32 / Build depends
- GitHub Check: Lint / Run linters
- GitHub Check: x86_64-apple-darwin / Build depends
- GitHub Check: x86_64-pc-linux-gnu_multiprocess / Build depends
- GitHub Check: x86_64-pc-linux-gnu / Build depends
- GitHub Check: arm-linux-gnueabihf / Build depends
- GitHub Check: x86_64-pc-linux-gnu_nowallet / Build depends
🔇 Additional comments (2)
test/functional/wallet_listdescriptors.py (2)
49-49
: LGTM!The descriptor count increase from 2 to 3 correctly reflects the addition of the CoinJoin descriptor alongside the existing external and internal descriptors.
51-51
: LGTM!The debug logging helps verify the descriptor output structure during test execution.
This pull request has conflicts, please rebase. |
It's already checked by find()
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
d846c53
to
6d64b87
Compare
rebased due to conflicts with bitcoin backports PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
♻️ Duplicate comments (1)
src/wallet/scriptpubkeyman.cpp (1)
2102-2108
: CJ path uses wrong coin_type; must be 1 to match Android m/9'/1'/…Current code builds CJ descriptors with
9'/ExtCoinType'/…
(Dash mainnet ExtCoinType=5), which will not match Android’s mobile CoinJoin pathm/9'/1'/…
. Funds mixed on mobile won’t be detected.Apply:
- std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, type == PathDerivationType::DIP0009_CoinJoin ? BIP32_PURPOSE_FEATURE : BIP32_PURPOSE_STANDARD, Params().ExtCoinType()); + const int coin_type = (type == PathDerivationType::DIP0009_CoinJoin) ? 1 : Params().ExtCoinType(); + std::string desc_prefix = strprintf("pkh(%s/%d'/%d'", xpub, type == PathDerivationType::DIP0009_CoinJoin ? BIP32_PURPOSE_FEATURE : BIP32_PURPOSE_STANDARD, coin_type);Also ensure listdescriptors’ CJ detection logic matches this choice.
Based on learnings
🧹 Nitpick comments (4)
test/functional/wallet_mnemonicbits.py (1)
50-50
: Consider simplifying the activity assertion.The current assertion
("coinjoin" not in desc or not desc['coinjoin'])
is logically equivalent tonot desc.get('coinjoin', False)
, which is more concise and idiomatic.Apply this diff for a cleaner assertion:
- assert_equal(desc['active'], ("coinjoin" not in desc or not desc['coinjoin'])) + assert_equal(desc['active'], not desc.get('coinjoin', False))src/wallet/rpc/backup.cpp (1)
1980-1980
: Consider clarifying the field description.The description "defined only if it is True" is technically correct but slightly awkward. Consider rephrasing to match the pattern used for the
internal
field or be more explicit about the detection criteria.For example:
- {RPCResult::Type::BOOL, "coinjoin", /*optional=*/true, "True if this descriptor is used to generate CoinJoin addresses; defined only if it is True."}, + {RPCResult::Type::BOOL, "coinjoin", /*optional=*/true, "True if this descriptor uses the CoinJoin derivation path (m/9'/cointype'/4'/0'). Only present when true."},test/functional/wallet_listdescriptors.py (1)
49-53
: Add a sanity check that CJ descriptor matches the Android path (9'/1')Counting is fine, but we can catch regressions like coin_type drift by asserting the path. Example:
result = node.get_wallet_rpc('w3').listdescriptors() @@ -assert_equal(3, len(result['descriptors'])) +assert_equal(3, len(result['descriptors'])) @@ self.log.info(f"result: {result['descriptors']}") cj = [d for d in result['descriptors'] if d.get('coinjoin')] assert_equal(1, len(cj)) +assert "'/9'/1'/" in cj[0]['desc'], "CJ descriptor should use m/9'/1'/… (Android mobile path)"src/wallet/scriptpubkeyman.h (1)
150-156
: Enum addition looks goodNames are clear and scoped; matches prior naming suggestion. Consider a brief doc comment per value for discoverability.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
doc/release-notes-6835.md
(1 hunks)src/wallet/hdchain.cpp
(1 hunks)src/wallet/hdchain.h
(1 hunks)src/wallet/rpc/backup.cpp
(3 hunks)src/wallet/rpc/wallet.cpp
(1 hunks)src/wallet/scriptpubkeyman.cpp
(2 hunks)src/wallet/scriptpubkeyman.h
(2 hunks)src/wallet/wallet.cpp
(2 hunks)test/functional/wallet_listdescriptors.py
(1 hunks)test/functional/wallet_mnemonicbits.py
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/**/*.{cpp,h,cc,cxx,hpp}
📄 CodeRabbit inference engine (CLAUDE.md)
src/**/*.{cpp,h,cc,cxx,hpp}
: Dash Core C++ codebase must be written in C++20 and require at least Clang 16 or GCC 11.1
Dash uses unordered_lru_cache for efficient caching with LRU eviction
Files:
src/wallet/wallet.cpp
src/wallet/hdchain.cpp
src/wallet/rpc/wallet.cpp
src/wallet/scriptpubkeyman.cpp
src/wallet/rpc/backup.cpp
src/wallet/scriptpubkeyman.h
src/wallet/hdchain.h
doc/**
📄 CodeRabbit inference engine (CLAUDE.md)
Unless specifically prompted, avoid making changes to the doc directory (documentation)
Files:
doc/release-notes-6835.md
test/functional/**/*.py
📄 CodeRabbit inference engine (CLAUDE.md)
Functional tests should be written in Python and placed in test/functional/
Files:
test/functional/wallet_mnemonicbits.py
test/functional/wallet_listdescriptors.py
🧠 Learnings (2)
📓 Common learnings
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
📚 Learning: 2025-09-02T07:34:28.226Z
Learnt from: knst
PR: dashpay/dash#6834
File: test/functional/wallet_mnemonicbits.py:50-51
Timestamp: 2025-09-02T07:34:28.226Z
Learning: CJ (CoinJoin) descriptors with derivation path "9'/1" are intentionally inactive in descriptor wallets, while regular internal/external descriptors with different derivation paths remain active.
Applied to files:
src/wallet/wallet.cpp
doc/release-notes-6835.md
src/wallet/scriptpubkeyman.cpp
src/wallet/rpc/backup.cpp
🧬 Code graph analysis (6)
src/wallet/hdchain.cpp (2)
src/wallet/hdchain.h (3)
BIP32_PURPOSE_STANDARD
(147-149)nAccountIndex
(131-131)nChangeIndex
(132-132)src/chainparams.cpp (2)
Params
(1354-1357)Params
(1354-1354)
src/wallet/scriptpubkeyman.cpp (2)
src/wallet/hdchain.h (2)
BIP32_PURPOSE_FEATURE
(145-145)BIP32_PURPOSE_STANDARD
(147-149)src/chainparams.cpp (2)
Params
(1354-1357)Params
(1354-1354)
src/wallet/rpc/backup.cpp (1)
src/wallet/hdchain.h (1)
BIP32_PURPOSE_FEATURE
(145-145)
test/functional/wallet_mnemonicbits.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
test/functional/wallet_listdescriptors.py (1)
test/functional/test_framework/util.py (1)
assert_equal
(69-74)
src/wallet/scriptpubkeyman.h (1)
src/wallet/scriptpubkeyman.cpp (2)
SetupDescriptorGeneration
(2077-2131)SetupDescriptorGeneration
(2077-2077)
🔇 Additional comments (9)
src/wallet/hdchain.h (1)
144-148
: LGTM! Purpose constants clearly defined.The new constants for BIP32 purpose codes are well-named, correctly valued (9 for DIP9 CoinJoin, 44 for standard BIP44), and appropriately typed. The comments provide clear context for their usage.
src/wallet/rpc/wallet.cpp (1)
171-171
: LGTM! Help text accurately reflects mobile CoinJoin usage.The updated help text for
keypoolsize_hd_internal
correctly documents that the internal keypool serves both change outputs and mobile CoinJoin, improving clarity for users.doc/release-notes-6835.md (2)
21-21
: Verify the PR reference number.The release notes reference "(#6835)" but the PR objectives indicate this is PR #6836. Please confirm the correct PR number.
Based on learnings
1-20
: Release notes are clear and comprehensive.The release notes effectively describe:
- The mobile CoinJoin compatibility issue and fix
- The breaking change scope (new wallets only)
- The RPC updates
The content aligns well with the PR objectives and provides users with the necessary context.
src/wallet/hdchain.cpp (1)
206-207
: Verify that the updated key path format is backward compatible.The key path format changed from an implicit
m/44'/%d'/%d'/%d/%d
to an explicitm/%d'/%d'/%d'/%d/%d
withBIP32_PURPOSE_STANDARD
as the first parameter. While this appears to be a display-only function (returns string), ensure that no code parses or relies on the previous format structure.Run the following script to check for potential parsing or format dependencies:
src/wallet/rpc/backup.cpp (2)
7-7
: LGTM!The include is necessary for accessing
Params().ExtCoinType()
used in the CoinJoin detection logic below.
2041-2047
: Verify the CoinJoin derivation path pattern matches the mobile wallet specification.The detection pattern uses
/%d'/%s'/4'/0'
withBIP32_PURPOSE_FEATURE
(9) andExtCoinType()
. However, the PR objectives state the mobile CoinJoin derivation path is m/9'/1'/0', not m/9'/cointype'/4'/0'.Please verify:
- The correct mobile CJ derivation path specification
- Whether the pattern should include the "4'" component
- The format of
ExtCoinType()
return value (string vs numeric)Run the following script to check how CoinJoin descriptors are created and what path they use:
Based on learnings: CJ descriptors with derivation path "9'/1" are intentionally inactive, which suggests the path might not include all components in the match pattern.
src/wallet/wallet.cpp (1)
3790-3807
: Tri‑descriptor setup with inactive CJ is correctLooping over External, Internal, CoinJoin and activating only the first two matches the intended behavior for new descriptor wallets (CJ inactive by default).
src/wallet/scriptpubkeyman.h (1)
585-585
: API change: confirm all call sites updatedSignature switch to PathDerivationType is good; please verify no remaining uses of the old boolean form.
# there should 3 descriptors in total | ||
# One of them is inactive imported private key for coinbase. It has no mnemonic | ||
# Two other should be active and have mnemonic | ||
assert_equal(mnemonic_count, 2) | ||
assert_equal(mnemonic_count, 3) | ||
assert_equal(cb_count, 1) | ||
assert_equal(len(descriptors), 3) | ||
assert_equal(len(descriptors), 4) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update comment to reflect three mnemonic descriptors.
The comment states "Two other should be active and have mnemonic" but the code now expects 3 mnemonic descriptors (line 55). The comment should be updated to match the new behavior.
Apply this diff to fix the comment:
- # there should 3 descriptors in total
- # One of them is inactive imported private key for coinbase. It has no mnemonic
- # Two other should be active and have mnemonic
+ # There should be 4 descriptors in total
+ # One is an inactive imported private key for coinbase (no mnemonic)
+ # Three others have mnemonics: two active (internal, external) and one inactive (coinjoin)
assert_equal(mnemonic_count, 3)
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
# there should 3 descriptors in total | |
# One of them is inactive imported private key for coinbase. It has no mnemonic | |
# Two other should be active and have mnemonic | |
assert_equal(mnemonic_count, 2) | |
assert_equal(mnemonic_count, 3) | |
assert_equal(cb_count, 1) | |
assert_equal(len(descriptors), 3) | |
assert_equal(len(descriptors), 4) | |
# There should be 4 descriptors in total | |
# One is an inactive imported private key for coinbase (no mnemonic) | |
# Three others have mnemonics: two active (internal, external) and one inactive (coinjoin) | |
assert_equal(mnemonic_count, 3) | |
assert_equal(cb_count, 1) | |
assert_equal(len(descriptors), 4) |
🤖 Prompt for AI Agents
In test/functional/wallet_mnemonicbits.py around lines 52 to 57, the inline
comment incorrectly states "Two other should be active and have mnemonic" while
the assertion expects 3 mnemonic descriptors; update the comment to reflect that
there are three mnemonic descriptors (e.g., "Three other should be active and
have mnemonic") so the comment matches the assertion expectations.
Issue being fixed or feature implemented
#6745
Currently, funds mixed by Coin Join by Android wallet may be invisible to other wallets, including Dash Core.
What was done?
This PR introduces 3rd default descriptor for Descriptor wallets, which makes this funds available in Dash Core.
How Has This Been Tested?
Install Android Dash wallet -> get some funds -> mix them -> import mnemonic to Dash Core. Funds (including CJ transactions) expect to visible.
Without this PR, some of these transactions are shown as "spending", and funds are not available.
Breaking Changes
Amount of descriptors created by default for a new wallet on mainnet is increased from 2 (internal, external) to 3.
Amount of descriptors created by default for a new wallet on regtest is increased from 3 (internal, external, cbtx private key) to 4.
Checklist: