Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/script/descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,7 @@ class BIP32PubkeyProvider final : public PubkeyProvider
{
if (m_derive == DeriveType::HARDENED) {
out = ToString(/*normalized=*/true);

return true;
}
// Step backwards to find the last hardened step in the path
Expand Down
2 changes: 1 addition & 1 deletion src/wallet/scriptpubkeyman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2023,7 +2023,7 @@ std::optional<MigrationData> LegacyScriptPubKeyMan::MigrateToDescriptor()
const std::string xpub_str = EncodeExtPubKey(master_key.Neuter());
for (int i = 0; i < 2; ++i) {
const uint32_t chain_counter = (i == 1) ? acc.nInternalChainCounter : acc.nExternalChainCounter;
const std::string desc_str = strprintf("combo(%s/%d'/%d'/0'/%d/*)",
const std::string desc_str = strprintf("combo(%s/%dh/%dh/0h/%d/*)",
xpub_str, BIP32_PURPOSE_STANDARD, Params().ExtCoinType(), i);
FlatSigningProvider keys;
std::string error;
Expand Down
1 change: 0 additions & 1 deletion test/functional/wallet_descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@ def run_test(self):
addr_info = self.nodes[0].getaddressinfo(addr)
assert addr_info['desc'].startswith('pkh(')
assert_equal(addr_info['hdkeypath'], 'm/44h/1h/0h/1/0')

# Make a wallet to receive coins at
self.nodes[0].createwallet(wallet_name="desc2", descriptors=True)
recv_wrpc = self.nodes[0].get_wallet_rpc("desc2")
Expand Down
14 changes: 7 additions & 7 deletions test/functional/wallet_migration.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def assert_addr_info_equal(self, addr_info, addr_info_old):
assert_equal(addr_info["address"], addr_info_old["address"])
assert_equal(addr_info["scriptPubKey"], addr_info_old["scriptPubKey"])
assert_equal(addr_info["ismine"], addr_info_old["ismine"])
assert_equal(addr_info["hdkeypath"], addr_info_old["hdkeypath"])
assert_equal(addr_info["hdkeypath"], addr_info_old["hdkeypath"].replace("'","h"))
assert_equal(addr_info["solvable"], addr_info_old["solvable"])
assert_equal(addr_info["ischange"], addr_info_old["ischange"])
assert_equal(addr_info["hdmasterfingerprint"], addr_info_old["hdmasterfingerprint"])
Expand Down Expand Up @@ -90,8 +90,8 @@ def test_basic(self):
self.assert_is_sqlite("basic0")

# The wallet should create the following descriptors:
# * BIP44 descriptors in the form of "44'/1'/0'/0/*" and "44'/1'/0'/1/*" (2 descriptors)
# * Inactive DIP0009 CoinJoin: pkh(xpub/9'/1'/4'/0'/0/*) (1 descriptor)
# * BIP44 descriptors in the form of "44h/1h/0h/0/*" and "44h/1h/0h/1/*" (2 descriptors)
# * Inactive DIP0009 CoinJoin: pkh(xpub/9h/1h/4h/0h/0/*) (1 descriptor)
# * Inactive Migration descriptors for the legacy HD keys (2 combo descriptors)
# Dash uses the same BIP44 paths for both legacy and descriptor wallets, but
# combo descriptor can not be active
Expand All @@ -113,10 +113,10 @@ def test_basic(self):
new_change = basic0.getrawchangeaddress()
assert not new_addr == addr
assert not new_change == change
assert_equal(addr_info["hdkeypath"], "m/44'/1'/0'/0/0")
assert_equal(change_addr_info["hdkeypath"], "m/44'/1'/0'/1/0")
assert_equal(basic0.getaddressinfo(new_addr)["hdkeypath"], "m/44'/1'/0'/0/2")
assert_equal(basic0.getaddressinfo(new_change)["hdkeypath"], "m/44'/1'/0'/1/2")
assert_equal(addr_info["hdkeypath"], "m/44h/1h/0h/0/0")
assert_equal(change_addr_info["hdkeypath"], "m/44h/1h/0h/1/0")
assert_equal(basic0.getaddressinfo(new_addr)["hdkeypath"], "m/44h/1h/0h/0/2")
assert_equal(basic0.getaddressinfo(new_change)["hdkeypath"], "m/44h/1h/0h/1/2")

self.log.info("Test migration of a basic keys only wallet with a balance")
basic1 = self.create_legacy_wallet("basic1")
Expand Down
8 changes: 4 additions & 4 deletions test/functional/wallet_signer.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,14 @@ def test_valid_signer(self):
assert mock_wallet.getwalletinfo()['private_keys_enabled']

result = mock_wallet.importdescriptors([{
"desc": "pkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0/*)#6k3x80k9",
"desc": "pkh([00000001/84h/1h/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/0/*)#ta5h29a8",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Complete the hardened-marker migration in descriptor origins.

These descriptors still use mixed notation (84h/1h/0'). For this migration, the origin path should be fully h-suffixed (84h/1h/0h) in both active imports and commented examples, and descriptor checksums must be recalculated after the edit.

Proposed update pattern
- "desc": "pkh([00000001/84h/1h/0']... )#<old_checksum>",
+ "desc": "pkh([00000001/84h/1h/0h]... )#<recomputed_checksum>",

- #     "desc": "wpkh([00000001/84h/1h/0']... )#<old_checksum>",
+ #     "desc": "wpkh([00000001/84h/1h/0h]... )#<recomputed_checksum>",

Also applies to: 139-139, 161-161, 169-169

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/wallet_signer.py` at line 132, The descriptor origin strings
in test/functional/wallet_signer.py use mixed hardened notation like "84h/1h/0'"
and must be migrated to fully-hardened notation "84h/1h/0h"; update each
descriptor occurrence (the shown descriptor value and the other instances noted
at the same file) replacing 0' with 0h in both active test data and commented
examples, then recompute and replace the descriptor checksums for each edited
descriptor so the tests remain valid.

"timestamp": 0,
"range": [0,1],
"internal": False,
"active": True
},
{

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Verify indentation of the continuation line.

Flake8 flagged this line for missing or incorrect indentation (E122). Ensure the opening brace aligns properly with the first descriptor object in the list.

🧰 Tools
🪛 Flake8 (7.3.0)

[error] 138-138: continuation line missing indentation or outdented

(E122)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/functional/wallet_signer.py` at line 138, Adjust the indentation of the
continuation line that contains a lone "{" so it aligns with the first
descriptor object in the surrounding list literal in
test/functional/wallet_signer.py; locate the list of descriptor objects (the
multi-line list where the brace starts) and move the "{" to the same column as
the first descriptor entry to satisfy E122 (ensure opening brace lines up with
the first item in the list).

"desc": "pkh([00000001/84'/1'/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/*)#tz5866xa",
"desc": "pkh([00000001/84h/1h/0']tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/*)#6f3khsdl",
"timestamp": 0,
"range": [0, 0],
"internal": True,
Expand All @@ -158,15 +158,15 @@ def test_valid_signer(self):
# hww4 = self.nodes[1].get_wallet_rpc("hww4")
#
# descriptors = [{
# "desc": "wpkh([00000001/84'/1'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/0/*)#x30uthjs",
# "desc": "wpkh([00000001/84h/1h/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/0/*)#x30uthjs",
# "timestamp": "now",
# "range": [0, 1],
# "internal": False,
# "watchonly": True,
# "active": True
# },
# {
# "desc": "wpkh([00000001/84'/1'/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/*)#h92akzzg",
# "desc": "wpkh([00000001/84h/1h/0']tpubD6NzVbkrYhZ4WaWSyoBvQwbpLkojyoTZPRsgXELWz3Popb3qkjcJyJUGLnL4qHHoQvao8ESaAstxYSnhyswJ76uZPStJRJCTKvosUCJZL5B/1/*)#h92akzzg",
# "timestamp": "now",
# "range": [0, 0],
# "internal": True,
Expand Down
Loading