Skip to content

Commit 54798c3

Browse files
committed
Merge #15749: Fix: importmulti only imports origin info for PKH outputs
b5d3987 Take non-importing keys into account for spendability warning in descriptor import (Pieter Wuille) 6e59700 Import all origin info in importmulti; even for non-importing pubkeys (Pieter Wuille) 9a93c91 Keep full pubkeys in FlatSigningProvider::origins (Pieter Wuille) Pull request description: This fixes #15743 and #15742. Since #15263, pubkeys are no longer imported for non-PKH (or WPKH, or any wrapped form of those) outputs, as that would incorrectly mark outputs to single-key versions of multisig policies as watched. As a side effect, this change also caused origin info not to be imported anymore for multisig policies. Fix this by plumbing through the full pubkey information for origins in FlatSigningProvider, and then importing all origin info we have in `importmulti` (knowing more never hurts, and additional origin information has no negative consequences like importing the pubkeys themselves). ACKs for commit b5d398: MeshCollider: utACK bitcoin/bitcoin@b5d3987 Tree-SHA512: 37caa2be8d01b8baa12f70a58eaa7c583f5f0afbe012e02936dd8790dc5dc852f880b77258b34ddb68cae30c029585f2d1c4f5d00015380557a1e8b471e500f3
2 parents db29856 + b5d3987 commit 54798c3

File tree

6 files changed

+21
-12
lines changed

6 files changed

+21
-12
lines changed

src/script/descriptor.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,7 @@ class DescriptorImpl : public Descriptor
436436
pubkeys.reserve(entries.size());
437437
for (auto& entry : entries) {
438438
pubkeys.push_back(entry.first);
439-
out.origins.emplace(entry.first.GetID(), std::move(entry.second));
439+
out.origins.emplace(entry.first.GetID(), std::make_pair<CPubKey, KeyOriginInfo>(CPubKey(entry.first), std::move(entry.second)));
440440
}
441441
if (m_script_arg) {
442442
for (const auto& subscript : subscripts) {

src/script/sign.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -483,7 +483,13 @@ bool HidingSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& inf
483483

484484
bool FlatSigningProvider::GetCScript(const CScriptID& scriptid, CScript& script) const { return LookupHelper(scripts, scriptid, script); }
485485
bool FlatSigningProvider::GetPubKey(const CKeyID& keyid, CPubKey& pubkey) const { return LookupHelper(pubkeys, keyid, pubkey); }
486-
bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const { return LookupHelper(origins, keyid, info); }
486+
bool FlatSigningProvider::GetKeyOrigin(const CKeyID& keyid, KeyOriginInfo& info) const
487+
{
488+
std::pair<CPubKey, KeyOriginInfo> out;
489+
bool ret = LookupHelper(origins, keyid, out);
490+
if (ret) info = std::move(out.second);
491+
return ret;
492+
}
487493
bool FlatSigningProvider::GetKey(const CKeyID& keyid, CKey& key) const { return LookupHelper(keys, keyid, key); }
488494

489495
FlatSigningProvider Merge(const FlatSigningProvider& a, const FlatSigningProvider& b)

src/script/sign.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct FlatSigningProvider final : public SigningProvider
7777
{
7878
std::map<CScriptID, CScript> scripts;
7979
std::map<CKeyID, CPubKey> pubkeys;
80-
std::map<CKeyID, KeyOriginInfo> origins;
80+
std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> origins;
8181
std::map<CKeyID, CKey> keys;
8282

8383
bool GetCScript(const CScriptID& scriptid, CScript& script) const override;

src/test/descriptor_tests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,8 +154,8 @@ void Check(const std::string& prv, const std::string& pub, int flags, const std:
154154
// Test whether the observed key path is present in the 'paths' variable (which contains expected, unobserved paths),
155155
// and then remove it from that set.
156156
for (const auto& origin : script_provider.origins) {
157-
BOOST_CHECK_MESSAGE(paths.count(origin.second.path), "Unexpected key path: " + prv);
158-
left_paths.erase(origin.second.path);
157+
BOOST_CHECK_MESSAGE(paths.count(origin.second.second.path), "Unexpected key path: " + prv);
158+
left_paths.erase(origin.second.second.path);
159159
}
160160
}
161161
}

src/wallet/rpcdump.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -900,7 +900,7 @@ struct ImportData
900900
// Output data
901901
std::set<CScript> import_scripts;
902902
std::map<CKeyID, bool> used_keys; //!< Import these private keys if available (the value indicates whether if the key is required for solvability)
903-
std::map<CKeyID, KeyOriginInfo> key_origins;
903+
std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> key_origins;
904904
};
905905

906906
enum class ScriptContext
@@ -1197,6 +1197,9 @@ static UniValue ProcessImportDescriptor(ImportData& import_data, std::map<CKeyID
11971197
bool spendable = std::all_of(pubkey_map.begin(), pubkey_map.end(),
11981198
[&](const std::pair<CKeyID, CPubKey>& used_key) {
11991199
return privkey_map.count(used_key.first) > 0;
1200+
}) && std::all_of(import_data.key_origins.begin(), import_data.key_origins.end(),
1201+
[&](const std::pair<CKeyID, std::pair<CPubKey, KeyOriginInfo>>& entry) {
1202+
return privkey_map.count(entry.first) > 0;
12001203
});
12011204
if (!watch_only && !spendable) {
12021205
warnings.push_back("Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag.");
@@ -1274,7 +1277,10 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
12741277
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
12751278
}
12761279
pwallet->UpdateTimeFirstKey(timestamp);
1277-
}
1280+
}
1281+
for (const auto& entry : import_data.key_origins) {
1282+
pwallet->AddKeyOrigin(entry.second.first, entry.second.second);
1283+
}
12781284
for (const CKeyID& id : ordered_pubkeys) {
12791285
auto entry = pubkey_map.find(id);
12801286
if (entry == pubkey_map.end()) {
@@ -1285,10 +1291,6 @@ static UniValue ProcessImport(CWallet * const pwallet, const UniValue& data, con
12851291
if (!pwallet->GetPubKey(id, temp) && !pwallet->AddWatchOnly(GetScriptForRawPubKey(pubkey), timestamp)) {
12861292
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding address to wallet");
12871293
}
1288-
const auto& key_orig_it = import_data.key_origins.find(id);
1289-
if (key_orig_it != import_data.key_origins.end()) {
1290-
pwallet->AddKeyOrigin(pubkey, key_orig_it->second);
1291-
}
12921294
pwallet->mapKeyMetadata[id].nCreateTime = timestamp;
12931295

12941296
// Add to keypool only works with pubkeys

test/functional/wallet_importmulti.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,8 @@ def run_test(self):
629629
self.log.info("Should import a 1-of-2 bare multisig from descriptor")
630630
self.test_importmulti({"desc": descsum_create("multi(1," + key1.pubkey + "," + key2.pubkey + ")"),
631631
"timestamp": "now"},
632-
success=True)
632+
success=True,
633+
warnings=["Some private keys are missing, outputs will be considered watchonly. If this is intentional, specify the watchonly flag."])
633634
self.log.info("Should not treat individual keys from the imported bare multisig as watchonly")
634635
test_address(self.nodes[1],
635636
key1.p2pkh_addr,

0 commit comments

Comments
 (0)