Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow ext keys #3

Merged
merged 7 commits into from
Aug 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
27 changes: 11 additions & 16 deletions src/script/descriptor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,10 @@ class SilentPubkeyProvider final : public PubkeyProvider
std::copy(keyid.begin(), keyid.begin() + sizeof(info.fingerprint), info.fingerprint);
pubkey = m_sppk.scanKey.GetPubKey();
}
void SetSpendPubKey(const CPubKey pubkey)
{
m_sppk.spendKey = pubkey;
}
};

/** Base class for all Descriptor implementations. */
Expand Down Expand Up @@ -1537,13 +1541,11 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S

if (ctx == ParseScriptContext::SP_ONLY) {
if (spkey.IsValid()) {
out.keys.emplace(spkey.scanKey.GetPubKey().GetID(), spkey.scanKey);
out.keys.emplace(spkey.spendKey.GetPubKey().GetID(), spkey.spendKey);
return std::make_unique<SilentPubkeyProvider>(key_exp_index, spkey.Neuter());
}

if (sppubkey.IsValid()) {
out.keys.emplace(sppubkey.scanKey.GetPubKey().GetID(), sppubkey.scanKey);
return std::make_unique<SilentPubkeyProvider>(key_exp_index, sppubkey);
}

Expand Down Expand Up @@ -1596,8 +1598,7 @@ std::unique_ptr<PubkeyProvider> ParsePubkeyInner(uint32_t key_exp_index, const S

// Derive sp scan key from extkey
CKey scan_key = derivedKey.key.IsValid() ? derivedKey.key : extkey.key;
out.keys.emplace(scan_key.GetPubKey().GetID(), scan_key);
return std::make_unique<ConstPubkeyProvider>(key_exp_index, scan_key.GetPubKey(), false);
return std::make_unique<SilentPubkeyProvider>(key_exp_index, SpPubKey(scan_key));
}

if (extkey.key.IsValid()) {
Expand Down Expand Up @@ -1825,24 +1826,18 @@ std::unique_ptr<DescriptorImpl> ParseScript(uint32_t& key_exp_index, Span<const
error = strprintf("sp(): %s", error);
return nullptr;
}
auto scanPubKey = scanKey->GetRootPubKey();
auto spendPubKey = spendKey->GetRootPubKey();
if (!scanPubKey.has_value()) {
error = "sp(): could not get scan pubkey";
return nullptr;
}
if (!spendPubKey.has_value()) {
error = "sp(): could not get spend pubkey";
return nullptr;
}
auto it = out.keys.find(scanPubKey->GetID());
if (it == out.keys.end()) {
error = "sp(): requires the scan priv key";
return nullptr;
}
auto sppk = std::make_unique<SilentPubkeyProvider>(key_exp_index, SpPubKey(it->second, *spendPubKey));

SilentPubkeyProvider* sppubKey = dynamic_cast<SilentPubkeyProvider*>(scanKey.get());
assert(sppubKey != nullptr);
sppubKey->SetSpendPubKey(*spendPubKey);

++key_exp_index;
return std::make_unique<SpDescriptor>(std::move(sppk));
return std::make_unique<SpDescriptor>(std::move(scanKey));
} else if (Func("sp", expr)) {
error = "Can only have sp() at top level";
return nullptr;
Expand Down
12 changes: 12 additions & 0 deletions src/silentpaymentkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,18 @@ struct SpPubKey {

SpPubKey() = default;

/**
* Creates an incomplete SpPubKey.
*/
SpPubKey(CKey scan_key) : scanKey(scan_key)
{
memset(version, 0, sizeof(version));
memset(vchFingerprint, 0, sizeof(vchFingerprint));
maximumNumberOfLabels = 0;
CPubKey dummySpendPubKey;
spendKey = dummySpendPubKey;
}

SpPubKey(CKey scan_key, CPubKey spend_key) : scanKey(scan_key), spendKey(spend_key)
{
memset(version, 0, sizeof(version));
Expand Down
4 changes: 2 additions & 2 deletions src/wallet/walletutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,9 @@ WalletDescriptor GenerateWalletDescriptor(const CExtKey& master_key, const Outpu
}
}

// Add the derived keys
// We only need to save the spend key
// The scan key is preserved in the descriptor
Comment on lines +100 to +101
Copy link
Owner

Choose a reason for hiding this comment

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

in a065b4b:

What would be the harm in persisting the key to the database? I think this is fine, but I am suspicious there might be unintended consequences from not persisting the key. Will need to study this section a bit more, thought, to understand how descriptors are persisted.

Copy link
Author

@Eunovo Eunovo Aug 4, 2024

Choose a reason for hiding this comment

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

No harm that I can think of, It just requires more code. Currently, the wallet does not allow the persistence of private keys when the private keys are disabled. If we don't persist the scan key, this error isn't triggered on watch only wallets.

out_keys.emplace_back(spend_key.key, spend_key.key.GetPubKey());
out_keys.emplace_back(scan_key.key, scan_key.key.GetPubKey());

SpPubKey sppub_key(scan_key.key, spend_key.key.GetPubKey());
std::string sppub = EncodeSpPubKey(sppub_key);
Expand Down