Skip to content

Commit 8f71cc2

Browse files
d59ce85 Merge bitcoin#24083: Revert "Add to spends only transcations from me" (Andrew Chow) 702813f Merge bitcoin#26156: test: check that `listdescriptors` descriptor strings are sorted (MacroFake) 59ce4ca fix: re-order fields of output of RPC listdescriptors accordingly doc (Konstantin Akimov) b50a1f9 Merge bitcoin#25931: rpc: sort listdescriptors result (Andrew Chow) cd07de4 Merge bitcoin#23202: wallet: allow psbtbumpfee to work with txs with external inputs (fanquake) 4e61c42 Merge bitcoin#25679: wallet: Correctly identify external inputs that are also in the wallet (fanquake) a97cc0f Merge bitcoin#23835: test: check for invalid listtransactions RPC parameters (MarcoFalke) 7f66259 Merge bitcoin#23688: test: remove unneeded sync_all() calls in wallet_listtransactions.py (MarcoFalke) 8d760a5 Merge bitcoin#23659: test: fix: remove outdated TestNode.generate calls (fanquake) 0dff162 Merge bitcoin#22929: wallet: Automatically add receiving destinations to the address book (W. J. van der Laan) c19a4b5 Merge bitcoin#23172: doc: Extract FundTxDoc in rpcwallet (fanquake) 9bef4ce partial Merge bitcoin#22323: doc: spelling update (MarcoFalke) Pull request description: ## What was done? More backports to improve support of External signer. This PR have mostly backports related to tests and RPC `listdescriptors` returns descriptors now sorted. It's not a breaking change, because before they has been returned in "undefined" sorting order. ## How Has This Been Tested? Run unit & functional tests ## Breaking Changes N/A ## Checklist: - [x] 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 - [ ] I have made corresponding changes to the documentation - [x] I have assigned this pull request to a milestone _(for repository code-owners and collaborators only)_ ACKs for top commit: UdjinM6: utACK d59ce85 Tree-SHA512: 3ba3fcb07dcb9478ee5eb425e514c3cd3234b51d8b26fd370df65f1cb2f1abd5fe93c5fd6258e221ebee9330f106aaa1442492a6611b4464ebc70ea0a9f4bb64
2 parents 59b2413 + d59ce85 commit 8f71cc2

18 files changed

+385
-190
lines changed

src/node/interfaces.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -580,7 +580,7 @@ class NodeImpl : public Node
580580
}
581581
return result;
582582
#else
583-
// This result is undistinguisable from a succesful call that returns
583+
// This result is indistinguishable from a successful call that returns
584584
// no signers. For the current GUI this doesn't matter, because the wallet
585585
// creation dialog disables the external signer checkbox in both
586586
// cases. The return type could be changed to std::optional<std::vector>

src/script/interpreter.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,10 @@ using MutableTransactionSignatureChecker = GenericTransactionSignatureChecker<CM
192192
class DeferringSignatureChecker : public BaseSignatureChecker
193193
{
194194
protected:
195-
BaseSignatureChecker& m_checker;
195+
const BaseSignatureChecker& m_checker;
196196

197197
public:
198-
DeferringSignatureChecker(BaseSignatureChecker& checker) : m_checker(checker) {}
198+
DeferringSignatureChecker(const BaseSignatureChecker& checker) : m_checker(checker) {}
199199

200200
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
201201
{

src/script/sign.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,8 +350,11 @@ class DummySignatureChecker final : public BaseSignatureChecker
350350
DummySignatureChecker() = default;
351351
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
352352
};
353-
const DummySignatureChecker DUMMY_CHECKER;
353+
}
354+
355+
const BaseSignatureChecker& DUMMY_CHECKER = DummySignatureChecker();
354356

357+
namespace {
355358
class DummySignatureCreator final : public BaseSignatureCreator {
356359
private:
357360
char m_r_len = 32;

src/script/sign.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ class MutableTransactionSignatureCreator : public BaseSignatureCreator
5050
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
5151
};
5252

53+
/** A signature checker that accepts all signatures */
54+
extern const BaseSignatureChecker& DUMMY_CHECKER;
5355
/** A signature creator that just produces 71-byte empty signatures. */
5456
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
5557
/** A signature creator that just produces 72-byte empty signatures. */

src/wallet/rpc/addresses.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -506,7 +506,12 @@ RPCHelpMan getaddressinfo()
506506
ret.pushKV("desc", InferDescriptor(scriptPubKey, *provider)->ToString());
507507
}
508508

509-
DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(pwallet->GetScriptPubKeyMan(scriptPubKey));
509+
const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
510+
// In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
511+
ScriptPubKeyMan* spk_man{nullptr};
512+
if (spk_mans.size()) spk_man = *spk_mans.begin();
513+
514+
DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
510515
if (desc_spk_man) {
511516
std::string desc_str;
512517
if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
@@ -521,7 +526,6 @@ RPCHelpMan getaddressinfo()
521526

522527
ret.pushKV("ischange", ScriptIsChange(*pwallet, scriptPubKey));
523528

524-
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey);
525529
if (spk_man) {
526530
if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
527531
ret.pushKV("timestamp", meta->nCreateTime);

src/wallet/rpc/backup.cpp

Lines changed: 61 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,7 +1987,7 @@ RPCHelpMan listdescriptors()
19871987
},
19881988
RPCResult{RPCResult::Type::OBJ, "", "", {
19891989
{RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
1990-
{RPCResult::Type::ARR, "descriptors", "Array of descriptor objects",
1990+
{RPCResult::Type::ARR, "descriptors", "Array of descriptor objects (sorted by descriptor string representation)",
19911991
{
19921992
{RPCResult::Type::OBJ, "", "", {
19931993
{RPCResult::Type::STR, "desc", "Descriptor string representation"},
@@ -2026,51 +2026,85 @@ RPCHelpMan listdescriptors()
20262026

20272027
LOCK(wallet->cs_wallet);
20282028

2029-
UniValue descriptors(UniValue::VARR);
20302029
const auto active_spk_mans = wallet->GetActiveScriptPubKeyMans();
2030+
2031+
struct WalletDescInfo {
2032+
std::string descriptor;
2033+
uint64_t creation_time;
2034+
bool active;
2035+
std::optional<bool> internal;
2036+
std::optional<std::pair<int64_t,int64_t>> range;
2037+
int64_t next_index;
2038+
bool is_coinjoin;
2039+
SecureString mnemonic;
2040+
SecureString mnemonic_passphrase;
2041+
};
2042+
2043+
std::vector<WalletDescInfo> wallet_descriptors;
20312044
for (const auto& spk_man : wallet->GetAllScriptPubKeyMans()) {
20322045
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
20332046
if (!desc_spk_man) {
20342047
throw JSONRPCError(RPC_WALLET_ERROR, "Unexpected ScriptPubKey manager type.");
20352048
}
2036-
UniValue spk(UniValue::VOBJ);
20372049
LOCK(desc_spk_man->cs_desc_man);
20382050
const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
20392051
std::string descriptor;
2040-
20412052
if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
20422053
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get descriptor string.");
20432054
}
2055+
SecureString mnemonic;
2056+
SecureString mnemonic_passphrase;
20442057
if (priv) {
2045-
SecureString mnemonic;
2046-
SecureString mnemonic_passphrase;
2047-
if (desc_spk_man->GetMnemonicString(mnemonic, mnemonic_passphrase) && !mnemonic.empty()) {
2048-
spk.pushKV("mnemonic", mnemonic);
2049-
spk.pushKV("mnemonicpassphrase", mnemonic_passphrase);
2058+
if (!desc_spk_man->GetMnemonicString(mnemonic, mnemonic_passphrase)) {
2059+
mnemonic.clear();
2060+
mnemonic_passphrase.clear();
20502061
}
20512062
}
2052-
spk.pushKV("desc", descriptor);
2053-
spk.pushKV("timestamp", wallet_descriptor.creation_time);
2054-
const bool active = active_spk_mans.count(desc_spk_man) != 0;
2055-
spk.pushKV("active", active);
20562063
const auto& type = wallet_descriptor.descriptor->GetOutputType();
2057-
if (active && type != std::nullopt) {
2058-
spk.pushKV("internal", wallet->GetScriptPubKeyMan(true) == desc_spk_man);
2059-
}
2060-
if (type != std::nullopt) {
2061-
std::string match = strprintf("/%d'/%s'/4'/0'", BIP32_PURPOSE_FEATURE, Params().ExtCoinType());
2062-
bool is_cj = descriptor.find(match) != std::string::npos;
2063-
if (is_cj) {
2064-
spk.pushKV("coinjoin", is_cj);
2065-
}
2064+
std::string match = strprintf("/%d'/%s'/4'/0'", BIP32_PURPOSE_FEATURE, Params().ExtCoinType());
2065+
bool is_cj = type != std::nullopt && descriptor.find(match) != std::string::npos;
2066+
2067+
const bool is_range = wallet_descriptor.descriptor->IsRange();
2068+
wallet_descriptors.push_back({
2069+
descriptor,
2070+
wallet_descriptor.creation_time,
2071+
active_spk_mans.count(desc_spk_man) != 0,
2072+
wallet->IsInternalScriptPubKeyMan(desc_spk_man),
2073+
is_range ? std::optional(std::make_pair(wallet_descriptor.range_start, wallet_descriptor.range_end)) : std::nullopt,
2074+
wallet_descriptor.next_index,
2075+
is_cj,
2076+
mnemonic,
2077+
mnemonic_passphrase,
2078+
});
2079+
}
2080+
2081+
std::sort(wallet_descriptors.begin(), wallet_descriptors.end(), [](const auto& a, const auto& b) {
2082+
return a.descriptor < b.descriptor;
2083+
});
2084+
2085+
UniValue descriptors(UniValue::VARR);
2086+
for (const WalletDescInfo& info : wallet_descriptors) {
2087+
UniValue spk(UniValue::VOBJ);
2088+
spk.pushKV("desc", info.descriptor);
2089+
if (!info.mnemonic.empty()) {
2090+
spk.pushKV("mnemonic", info.mnemonic);
2091+
spk.pushKV("mnemonicpassphrase", info.mnemonic_passphrase);
20662092
}
2067-
if (wallet_descriptor.descriptor->IsRange()) {
2093+
spk.pushKV("timestamp", info.creation_time);
2094+
spk.pushKV("active", info.active);
2095+
if (info.internal.has_value()) {
2096+
spk.pushKV("internal", info.internal.value());
2097+
}
2098+
if (info.range.has_value()) {
20682099
UniValue range(UniValue::VARR);
2069-
range.push_back(wallet_descriptor.range_start);
2070-
range.push_back(wallet_descriptor.range_end - 1);
2100+
range.push_back(info.range->first);
2101+
range.push_back(info.range->second - 1);
2102+
if (info.is_coinjoin) {
2103+
spk.pushKV("coinjoin", info.is_coinjoin);
2104+
}
20712105
spk.pushKV("range", range);
2072-
spk.pushKV("next", wallet_descriptor.next_index);
2073-
spk.pushKV("next_index", wallet_descriptor.next_index);
2106+
spk.pushKV("next", info.next_index);
2107+
spk.pushKV("next_index", info.next_index);
20742108
}
20752109
descriptors.push_back(spk);
20762110
}

0 commit comments

Comments
 (0)