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
2 changes: 1 addition & 1 deletion src/node/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -580,7 +580,7 @@ class NodeImpl : public Node
}
return result;
#else
// This result is undistinguisable from a succesful call that returns
// This result is indistinguishable from a successful call that returns
// no signers. For the current GUI this doesn't matter, because the wallet
// creation dialog disables the external signer checkbox in both
// cases. The return type could be changed to std::optional<std::vector>
Expand Down
4 changes: 2 additions & 2 deletions src/script/interpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,10 @@ using MutableTransactionSignatureChecker = GenericTransactionSignatureChecker<CM
class DeferringSignatureChecker : public BaseSignatureChecker
{
protected:
BaseSignatureChecker& m_checker;
const BaseSignatureChecker& m_checker;

public:
DeferringSignatureChecker(BaseSignatureChecker& checker) : m_checker(checker) {}
DeferringSignatureChecker(const BaseSignatureChecker& checker) : m_checker(checker) {}

bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override
{
Expand Down
5 changes: 4 additions & 1 deletion src/script/sign.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -350,8 +350,11 @@ class DummySignatureChecker final : public BaseSignatureChecker
DummySignatureChecker() = default;
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
};
const DummySignatureChecker DUMMY_CHECKER;
}

const BaseSignatureChecker& DUMMY_CHECKER = DummySignatureChecker();

namespace {
class DummySignatureCreator final : public BaseSignatureCreator {
private:
char m_r_len = 32;
Expand Down
2 changes: 2 additions & 0 deletions src/script/sign.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ class MutableTransactionSignatureCreator : public BaseSignatureCreator
bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;
};

/** A signature checker that accepts all signatures */
extern const BaseSignatureChecker& DUMMY_CHECKER;
/** A signature creator that just produces 71-byte empty signatures. */
extern const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR;
/** A signature creator that just produces 72-byte empty signatures. */
Expand Down
8 changes: 6 additions & 2 deletions src/wallet/rpc/addresses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -506,7 +506,12 @@ RPCHelpMan getaddressinfo()
ret.pushKV("desc", InferDescriptor(scriptPubKey, *provider)->ToString());
}

DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(pwallet->GetScriptPubKeyMan(scriptPubKey));
const auto& spk_mans = pwallet->GetScriptPubKeyMans(scriptPubKey);
// In most cases there is only one matching ScriptPubKey manager and we can't resolve ambiguity in a better way
ScriptPubKeyMan* spk_man{nullptr};
if (spk_mans.size()) spk_man = *spk_mans.begin();

DescriptorScriptPubKeyMan* desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
if (desc_spk_man) {
std::string desc_str;
if (desc_spk_man->GetDescriptorString(desc_str, /*priv=*/false)) {
Expand All @@ -521,7 +526,6 @@ RPCHelpMan getaddressinfo()

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

ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan(scriptPubKey);
if (spk_man) {
if (const std::unique_ptr<CKeyMetadata> meta = spk_man->GetMetadata(dest)) {
ret.pushKV("timestamp", meta->nCreateTime);
Expand Down
88 changes: 61 additions & 27 deletions src/wallet/rpc/backup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1987,7 +1987,7 @@ RPCHelpMan listdescriptors()
},
RPCResult{RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::STR, "wallet_name", "Name of wallet this operation was performed on"},
{RPCResult::Type::ARR, "descriptors", "Array of descriptor objects",
{RPCResult::Type::ARR, "descriptors", "Array of descriptor objects (sorted by descriptor string representation)",
{
{RPCResult::Type::OBJ, "", "", {
{RPCResult::Type::STR, "desc", "Descriptor string representation"},
Expand Down Expand Up @@ -2026,51 +2026,85 @@ RPCHelpMan listdescriptors()

LOCK(wallet->cs_wallet);

UniValue descriptors(UniValue::VARR);
const auto active_spk_mans = wallet->GetActiveScriptPubKeyMans();

struct WalletDescInfo {
std::string descriptor;
uint64_t creation_time;
bool active;
std::optional<bool> internal;
std::optional<std::pair<int64_t,int64_t>> range;
int64_t next_index;
bool is_coinjoin;
SecureString mnemonic;
SecureString mnemonic_passphrase;
};

std::vector<WalletDescInfo> wallet_descriptors;
for (const auto& spk_man : wallet->GetAllScriptPubKeyMans()) {
const auto desc_spk_man = dynamic_cast<DescriptorScriptPubKeyMan*>(spk_man);
if (!desc_spk_man) {
throw JSONRPCError(RPC_WALLET_ERROR, "Unexpected ScriptPubKey manager type.");
}
UniValue spk(UniValue::VOBJ);
LOCK(desc_spk_man->cs_desc_man);
const auto& wallet_descriptor = desc_spk_man->GetWalletDescriptor();
std::string descriptor;

if (!desc_spk_man->GetDescriptorString(descriptor, priv)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Can't get descriptor string.");
}
SecureString mnemonic;
SecureString mnemonic_passphrase;
if (priv) {
SecureString mnemonic;
SecureString mnemonic_passphrase;
if (desc_spk_man->GetMnemonicString(mnemonic, mnemonic_passphrase) && !mnemonic.empty()) {
spk.pushKV("mnemonic", mnemonic);
spk.pushKV("mnemonicpassphrase", mnemonic_passphrase);
if (!desc_spk_man->GetMnemonicString(mnemonic, mnemonic_passphrase)) {
mnemonic.clear();
mnemonic_passphrase.clear();
}
}
spk.pushKV("desc", descriptor);
spk.pushKV("timestamp", wallet_descriptor.creation_time);
const bool active = active_spk_mans.count(desc_spk_man) != 0;
spk.pushKV("active", active);
const auto& type = wallet_descriptor.descriptor->GetOutputType();
if (active && type != std::nullopt) {
spk.pushKV("internal", wallet->GetScriptPubKeyMan(true) == desc_spk_man);
}
if (type != std::nullopt) {
std::string match = strprintf("/%d'/%s'/4'/0'", BIP32_PURPOSE_FEATURE, Params().ExtCoinType());
bool is_cj = descriptor.find(match) != std::string::npos;
if (is_cj) {
spk.pushKV("coinjoin", is_cj);
}
std::string match = strprintf("/%d'/%s'/4'/0'", BIP32_PURPOSE_FEATURE, Params().ExtCoinType());
bool is_cj = type != std::nullopt && descriptor.find(match) != std::string::npos;

const bool is_range = wallet_descriptor.descriptor->IsRange();
wallet_descriptors.push_back({
descriptor,
wallet_descriptor.creation_time,
active_spk_mans.count(desc_spk_man) != 0,
wallet->IsInternalScriptPubKeyMan(desc_spk_man),
is_range ? std::optional(std::make_pair(wallet_descriptor.range_start, wallet_descriptor.range_end)) : std::nullopt,
wallet_descriptor.next_index,
is_cj,
mnemonic,
mnemonic_passphrase,
});
}

std::sort(wallet_descriptors.begin(), wallet_descriptors.end(), [](const auto& a, const auto& b) {
return a.descriptor < b.descriptor;
});

UniValue descriptors(UniValue::VARR);
for (const WalletDescInfo& info : wallet_descriptors) {
UniValue spk(UniValue::VOBJ);
spk.pushKV("desc", info.descriptor);
if (!info.mnemonic.empty()) {
spk.pushKV("mnemonic", info.mnemonic);
spk.pushKV("mnemonicpassphrase", info.mnemonic_passphrase);
}
if (wallet_descriptor.descriptor->IsRange()) {
spk.pushKV("timestamp", info.creation_time);
spk.pushKV("active", info.active);
if (info.internal.has_value()) {
spk.pushKV("internal", info.internal.value());
}
if (info.range.has_value()) {
UniValue range(UniValue::VARR);
range.push_back(wallet_descriptor.range_start);
range.push_back(wallet_descriptor.range_end - 1);
range.push_back(info.range->first);
range.push_back(info.range->second - 1);
if (info.is_coinjoin) {
spk.pushKV("coinjoin", info.is_coinjoin);
}
spk.pushKV("range", range);
spk.pushKV("next", wallet_descriptor.next_index);
spk.pushKV("next_index", wallet_descriptor.next_index);
spk.pushKV("next", info.next_index);
spk.pushKV("next_index", info.next_index);
}
descriptors.push_back(spk);
}
Expand Down
Loading
Loading