Skip to content

Commit

Permalink
Add private key derivation functions to descriptors
Browse files Browse the repository at this point in the history
  • Loading branch information
meshcollider committed Jun 6, 2019
1 parent 03858b2 commit ca039db
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 0 deletions.
37 changes: 37 additions & 0 deletions src/script/descriptor.cpp
Expand Up @@ -164,6 +164,9 @@ struct PubkeyProvider

/** Get the descriptor string form including private data (if available in arg). */
virtual bool ToPrivateString(const SigningProvider& arg, std::string& out) const = 0;

/** Derive a private key, if private data is available in arg. */
virtual bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const = 0;
};

class OriginPubkeyProvider final : public PubkeyProvider
Expand Down Expand Up @@ -195,6 +198,10 @@ class OriginPubkeyProvider final : public PubkeyProvider
ret = "[" + OriginString() + "]" + std::move(sub);
return true;
}
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
{
return m_provider->GetPrivKey(pos, arg, key);
}
};

/** An object representing a parsed constant public key in a descriptor. */
Expand Down Expand Up @@ -222,6 +229,10 @@ class ConstPubkeyProvider final : public PubkeyProvider
ret = EncodeSecret(key);
return true;
}
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
{
return arg.GetKey(m_pubkey.GetID(), key);
}
};

enum class DeriveType {
Expand Down Expand Up @@ -312,6 +323,18 @@ class BIP32PubkeyProvider final : public PubkeyProvider
}
return true;
}
bool GetPrivKey(int pos, const SigningProvider& arg, CKey& key) const override
{
CExtKey extkey;
if (!GetExtKey(arg, extkey)) return false;
for (auto entry : m_path) {
extkey.Derive(extkey, entry);
}
if (m_derive == DeriveType::UNHARDENED) extkey.Derive(extkey, pos);
if (m_derive == DeriveType::HARDENED) extkey.Derive(extkey, pos | 0x80000000UL);
key = extkey.key;
return true;
}
};

/** Base class for all Descriptor implementations. */
Expand Down Expand Up @@ -462,6 +485,20 @@ class DescriptorImpl : public Descriptor
Span<const unsigned char> span = MakeSpan(cache);
return ExpandHelper(pos, DUMMY_SIGNING_PROVIDER, &span, output_scripts, out, nullptr) && span.size() == 0;
}

void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const final
{
for (const auto& p : m_pubkey_args) {
CKey key;
if (!p->GetPrivKey(pos, provider, key)) continue;
out.keys.emplace(key.GetPubKey().GetID(), key);
}
if (m_script_arg) {
FlatSigningProvider subprovider;
m_script_arg->ExpandPrivate(pos, provider, subprovider);
out = Merge(out, subprovider);
}
}
};

/** Construct a vector with one element, which is moved into it. */
Expand Down
8 changes: 8 additions & 0 deletions src/script/descriptor.h
Expand Up @@ -60,6 +60,14 @@ struct Descriptor {
* out: scripts and public keys necessary for solving the expanded scriptPubKeys will be put here (may be equal to provider).
*/
virtual bool ExpandFromCache(int pos, const std::vector<unsigned char>& cache, std::vector<CScript>& output_scripts, FlatSigningProvider& out) const = 0;

/** Expand the private key for a descriptor at a specified position, if possible.
*
* pos: the position at which to expand the descriptor. If IsRange() is false, this is ignored.
* provider: the provider to query for the private keys.
* out: any private keys available for the specified pos will be placed here.
*/
virtual void ExpandPrivate(int pos, const SigningProvider& provider, FlatSigningProvider& out) const = 0;
};

/** Parse a descriptor string. Included private keys are put in out.
Expand Down

0 comments on commit ca039db

Please sign in to comment.