mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
Merge a0c73846aa
into c5e44a0435
This commit is contained in:
commit
a83096c7c9
2 changed files with 75 additions and 7 deletions
|
@ -642,13 +642,26 @@ public:
|
||||||
virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const
|
virtual bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const
|
||||||
{
|
{
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
bool has_any_priv = false;
|
||||||
for (const auto& scriptarg : m_subdescriptor_args) {
|
for (const auto& scriptarg : m_subdescriptor_args) {
|
||||||
if (pos++) ret += ",";
|
if (pos++) ret += ",";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if (!scriptarg->ToStringHelper(arg, tmp, type, cache)) return false;
|
bool success = scriptarg->ToStringHelper(arg, tmp, type, cache);
|
||||||
|
if (type == StringType::PRIVATE) {
|
||||||
|
if (success) {
|
||||||
|
has_any_priv = true;
|
||||||
|
} else {
|
||||||
|
tmp = "";
|
||||||
|
if (!scriptarg->ToStringHelper(arg, tmp, StringType::PUBLIC, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ret += tmp;
|
ret += tmp;
|
||||||
}
|
}
|
||||||
return true;
|
return (type == StringType::PRIVATE) ? has_any_priv : true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(misc-no-recursion)
|
// NOLINTNEXTLINE(misc-no-recursion)
|
||||||
|
@ -657,6 +670,7 @@ public:
|
||||||
std::string extra = ToStringExtra();
|
std::string extra = ToStringExtra();
|
||||||
size_t pos = extra.size() > 0 ? 1 : 0;
|
size_t pos = extra.size() > 0 ? 1 : 0;
|
||||||
std::string ret = m_name + "(" + extra;
|
std::string ret = m_name + "(" + extra;
|
||||||
|
bool has_any_priv = false;
|
||||||
for (const auto& pubkey : m_pubkey_args) {
|
for (const auto& pubkey : m_pubkey_args) {
|
||||||
if (pos++) ret += ",";
|
if (pos++) ret += ",";
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
|
@ -665,7 +679,11 @@ public:
|
||||||
if (!pubkey->ToNormalizedString(*arg, tmp, cache)) return false;
|
if (!pubkey->ToNormalizedString(*arg, tmp, cache)) return false;
|
||||||
break;
|
break;
|
||||||
case StringType::PRIVATE:
|
case StringType::PRIVATE:
|
||||||
if (!pubkey->ToPrivateString(*arg, tmp)) return false;
|
if (!pubkey->ToPrivateString(*arg, tmp)) {
|
||||||
|
tmp = pubkey->ToString();
|
||||||
|
} else {
|
||||||
|
has_any_priv = true;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case StringType::PUBLIC:
|
case StringType::PUBLIC:
|
||||||
tmp = pubkey->ToString();
|
tmp = pubkey->ToString();
|
||||||
|
@ -677,7 +695,21 @@ public:
|
||||||
ret += tmp;
|
ret += tmp;
|
||||||
}
|
}
|
||||||
std::string subscript;
|
std::string subscript;
|
||||||
if (!ToStringSubScriptHelper(arg, subscript, type, cache)) return false;
|
bool is_subscript_successful = ToStringSubScriptHelper(arg, subscript, type, cache);
|
||||||
|
|
||||||
|
if (type == StringType::PRIVATE) {
|
||||||
|
if (!has_any_priv) {
|
||||||
|
if (subscript.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!is_subscript_successful) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!is_subscript_successful) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (pos && subscript.size()) ret += ',';
|
if (pos && subscript.size()) ret += ',';
|
||||||
out = std::move(ret) + std::move(subscript) + ")";
|
out = std::move(ret) + std::move(subscript) + ")";
|
||||||
return true;
|
return true;
|
||||||
|
@ -1186,6 +1218,7 @@ protected:
|
||||||
bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const override
|
bool ToStringSubScriptHelper(const SigningProvider* arg, std::string& ret, const StringType type, const DescriptorCache* cache = nullptr) const override
|
||||||
{
|
{
|
||||||
if (m_depths.empty()) return true;
|
if (m_depths.empty()) return true;
|
||||||
|
bool has_any_subscript_key = false;
|
||||||
std::vector<bool> path;
|
std::vector<bool> path;
|
||||||
for (size_t pos = 0; pos < m_depths.size(); ++pos) {
|
for (size_t pos = 0; pos < m_depths.size(); ++pos) {
|
||||||
if (pos) ret += ',';
|
if (pos) ret += ',';
|
||||||
|
@ -1194,7 +1227,19 @@ protected:
|
||||||
path.push_back(false);
|
path.push_back(false);
|
||||||
}
|
}
|
||||||
std::string tmp;
|
std::string tmp;
|
||||||
if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache)) return false;
|
bool is_subdescriptor_successful = m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, type, cache);
|
||||||
|
if (type == StringType::PRIVATE) {
|
||||||
|
if (is_subdescriptor_successful) {
|
||||||
|
has_any_subscript_key = true;
|
||||||
|
} else {
|
||||||
|
tmp = "";
|
||||||
|
if (!m_subdescriptor_args[pos]->ToStringHelper(arg, tmp, StringType::PUBLIC, cache)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!is_subdescriptor_successful) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ret += tmp;
|
ret += tmp;
|
||||||
while (!path.empty() && path.back()) {
|
while (!path.empty() && path.back()) {
|
||||||
if (path.size() > 1) ret += '}';
|
if (path.size() > 1) ret += '}';
|
||||||
|
@ -1202,7 +1247,7 @@ protected:
|
||||||
}
|
}
|
||||||
if (!path.empty()) path.back() = true;
|
if (!path.empty()) path.back() = true;
|
||||||
}
|
}
|
||||||
return true;
|
return (type == StringType::PRIVATE) ? has_any_subscript_key : true;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
|
TRDescriptor(std::unique_ptr<PubkeyProvider> internal_key, std::vector<std::unique_ptr<DescriptorImpl>> descs, std::vector<int> depths) :
|
||||||
|
@ -1296,7 +1341,9 @@ public:
|
||||||
{
|
{
|
||||||
std::string ret;
|
std::string ret;
|
||||||
if (m_private) {
|
if (m_private) {
|
||||||
if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) return {};
|
if (!m_pubkeys[key]->ToPrivateString(*m_arg, ret)) {
|
||||||
|
ret = m_pubkeys[key]->ToString();
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ret = m_pubkeys[key]->ToString();
|
ret = m_pubkeys[key]->ToString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,26 @@ class ListDescriptorsTest(BitcoinTestFramework):
|
||||||
def init_wallet(self, *, node):
|
def init_wallet(self, *, node):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
def test_listdescriptors_with_partial_privkeys(self):
|
||||||
|
self.nodes[0].createwallet(wallet_name="partialkeys_descs", blank=True)
|
||||||
|
wallet = self.nodes[0].get_wallet_rpc("partialkeys_descs")
|
||||||
|
|
||||||
|
self.log.info("Test listdescriptors(private=true) with descriptors containing partial private keys")
|
||||||
|
descs = [
|
||||||
|
descsum_create("wsh(multi(2,tprv8ZgxMBicQKsPdzuc344mDaeUk5zseMcRK9Hst8xodskNu3YbQG5NxLa2X17PUU5yXQhptiBE7F5W5cgEmsfQg4Y21Y18w4DJhLxSb8CurDf,tpubD6NzVbkrYhZ4YiCvExLvH4yh1k3jFGf5irm6TsrArY8GYdEhYVdztQTBtTirmRc6XfSJpH9tayUdnngaJZKDaa2zbqEY29DfcGZW8iRVGUY))"),
|
||||||
|
descsum_create("wsh(thresh(2,pk(tprv8ZgxMBicQKsPdzuc344mDaeUk5zseMcRK9Hst8xodskNu3YbQG5NxLa2X17PUU5yXQhptiBE7F5W5cgEmsfQg4Y21Y18w4DJhLxSb8CurDf),s:pk(tpubD6NzVbkrYhZ4YiCvExLvH4yh1k3jFGf5irm6TsrArY8GYdEhYVdztQTBtTirmRc6XfSJpH9tayUdnngaJZKDaa2zbqEY29DfcGZW8iRVGUY),sln:older(2)))"),
|
||||||
|
descsum_create("tr(03d1d1110030000000000120000000000000000000000000001370010912cd08cc,pk(cNKAo2ZRsaWKcP481cEfj3astPyBrfq56JBtLeRhHUvTSuk2z4MR))"),
|
||||||
|
descsum_create("tr(cNKAo2ZRsaWKcP481cEfj3astPyBrfq56JBtLeRhHUvTSuk2z4MR,pk(03d1d1110030000000000120000000000000000000000000001370010912cd08cc))")
|
||||||
|
]
|
||||||
|
importdescriptors_request = list(map(lambda desc: {"desc": desc, "timestamp": "now"}, descs))
|
||||||
|
res = wallet.importdescriptors(importdescriptors_request)
|
||||||
|
for imported_desc in res:
|
||||||
|
assert_equal(imported_desc["success"], True)
|
||||||
|
res = wallet.listdescriptors(private=True)
|
||||||
|
for listed_desc in res["descriptors"]:
|
||||||
|
# descriptors are not returned in the order they were present in the import request
|
||||||
|
assert_equal(listed_desc["desc"], next(desc for desc in descs if listed_desc["desc"] == desc))
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
assert_raises_rpc_error(-18, 'No wallet is loaded.', node.listdescriptors)
|
assert_raises_rpc_error(-18, 'No wallet is loaded.', node.listdescriptors)
|
||||||
|
@ -125,6 +145,7 @@ class ListDescriptorsTest(BitcoinTestFramework):
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
assert_equal(expected, wallet.listdescriptors())
|
assert_equal(expected, wallet.listdescriptors())
|
||||||
|
self.test_listdescriptors_with_partial_privkeys()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Add table
Reference in a new issue