MWEB: Add DesitnationAddr wrapper

This commit is contained in:
David Burkett 2022-01-29 15:06:24 -05:00 committed by Loshan T
parent d8e940f301
commit f22b501828
7 changed files with 95 additions and 2 deletions

View File

@ -242,6 +242,7 @@ BITCOIN_CORE_H = \
rpc/server.h \
rpc/util.h \
scheduler.h \
script/address.h \
script/descriptor.h \
script/keyorigin.h \
script/sigcache.h \
@ -557,6 +558,7 @@ libbitcoin_common_a_SOURCES = \
rpc/rawtransaction_util.cpp \
rpc/util.cpp \
scheduler.cpp \
script/address.cpp \
script/descriptor.cpp \
script/sign.cpp \
script/signingprovider.cpp \

42
src/script/address.cpp Normal file
View File

@ -0,0 +1,42 @@
#include <script/address.h>
#include <key_io.h>
DestinationAddr::DestinationAddr(const CTxDestination& dest)
{
if (dest.type() == typeid(StealthAddress)) {
m_script = boost::get<StealthAddress>(dest);
} else {
m_script = ::GetScriptForDestination(dest);
}
}
std::string DestinationAddr::Encode() const
{
CTxDestination dest;
if (ExtractDestination(dest)) {
return ::EncodeDestination(dest);
}
return HexStr(GetScript());
}
const CScript& DestinationAddr::GetScript() const noexcept
{
assert(m_script.type() == typeid(CScript));
return boost::get<CScript>(m_script);
}
const StealthAddress& DestinationAddr::GetMWEBAddress() const noexcept
{
assert(m_script.type() == typeid(StealthAddress));
return boost::get<StealthAddress>(m_script);
}
bool DestinationAddr::ExtractDestination(CTxDestination& dest) const
{
if (IsMWEB()) {
dest = GetMWEBAddress();
return true;
}
return ::ExtractDestination(GetScript(), dest);
}

37
src/script/address.h Normal file
View File

@ -0,0 +1,37 @@
#pragma once
#include <script/standard.h>
#include <boost/variant.hpp>
//
// A wrapper around a boost::variant<CScript, StealthAddress> to deal with cases where
// a raw CScript is passed around as an address, rather than a CTxDestination.
// Since StealthAddresses can't be represented as a CScript, this wrapper should be used
// wherever the address could contain a StealthAddress instead of a CScript
//
class DestinationAddr
{
public:
DestinationAddr() = default;
DestinationAddr(CScript script)
: m_script(std::move(script)) {}
DestinationAddr(StealthAddress address)
: m_script(std::move(address)) {}
DestinationAddr(const CTxDestination& dest);
bool operator==(const DestinationAddr& rhs) const noexcept { return this->m_script == rhs.m_script; }
bool operator<(const DestinationAddr& rhs) const noexcept { return this->m_script < rhs.m_script; }
bool operator<=(const DestinationAddr& rhs) const noexcept { return this->m_script <= rhs.m_script; }
std::string Encode() const;
bool IsMWEB() const noexcept { return m_script.type() == typeid(StealthAddress); }
bool IsEmpty() const noexcept { return !IsMWEB() && GetScript().empty(); }
const CScript& GetScript() const noexcept;
const StealthAddress& GetMWEBAddress() const noexcept;
bool ExtractDestination(CTxDestination& dest) const;
private:
boost::variant<CScript, StealthAddress> m_script;
};

View File

@ -434,8 +434,14 @@ public:
const BaseSignatureCreator& DUMMY_SIGNATURE_CREATOR = DummySignatureCreator(32, 32);
const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR = DummySignatureCreator(33, 32);
bool IsSolvable(const SigningProvider& provider, const CScript& script)
bool IsSolvable(const SigningProvider& provider, const DestinationAddr& dest_addr)
{
if (dest_addr.IsMWEB()) {
CPubKey pubkey(dest_addr.GetMWEBAddress().GetSpendPubKey().vec());
return provider.HaveKey(pubkey.GetID());
}
const CScript& script = dest_addr.GetScript();
// This check is to make sure that the script we created can actually be solved for and signed by us
// if we were to have the private keys. This is just to make sure that the script is valid and that,
// if found in a transaction, we would still accept and relay that transaction. In particular,

View File

@ -9,6 +9,7 @@
#include <coins.h>
#include <hash.h>
#include <pubkey.h>
#include <script/address.h>
#include <script/interpreter.h>
#include <script/keyorigin.h>
#include <span.h>
@ -165,7 +166,7 @@ void UpdateInput(CTxIn& input, const SignatureData& data);
* have all private keys. While this function does not need private keys, the passed
* provider is used to look up public keys and redeemscripts by hash.
* Solvability is unrelated to whether we consider this output to be ours. */
bool IsSolvable(const SigningProvider& provider, const CScript& script);
bool IsSolvable(const SigningProvider& provider, const DestinationAddr& dest_addr);
/** Check whether a scriptPubKey is known to be segwit. */
bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);

View File

@ -195,5 +195,8 @@ CKeyID GetKeyForDestination(const SigningProvider& store, const CTxDestination&
}
}
}
if (auto stealth_address = boost::get<StealthAddress>(&dest)) {
return CPubKey(stealth_address->B().vec()).GetID();
}
return CKeyID();
}

View File

@ -273,4 +273,6 @@ bool IsPegInOutput(const CTxOutput& output);
CScript GetScriptForPegin(const mw::Hash& kernel_id);
#include <script/address.h>
#endif // BITCOIN_SCRIPT_STANDARD_H