Skip to content

Commit

Permalink
create a shared library to make creating wallets easier. (dashpay#1130)
Browse files Browse the repository at this point in the history
* create a shared library whose API presents the complicated or time consuming functions needed for creating and sending transactions
  • Loading branch information
gandrewstone authored and wagerr-builder committed Nov 14, 2022
1 parent 5f3c3f3 commit 283192e
Show file tree
Hide file tree
Showing 4 changed files with 393 additions and 182 deletions.
45 changes: 44 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ LIBBITCOIN_ZMQ=libbitcoin_zmq.a
endif
if BUILD_BITCOIN_LIBS
LIBBITCOINCONSENSUS=libdashconsensus.la
LIBBITCOINCORE=libdashcore.la
endif
if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a
Expand Down Expand Up @@ -92,7 +93,7 @@ EXTRA_LIBRARIES += \
$(LIBBITCOIN_WALLET_TOOL) \
$(LIBBITCOIN_ZMQ)

lib_LTLIBRARIES = $(LIBBITCOINCONSENSUS)
lib_LTLIBRARIES = $(LIBBITCOINCORE) $(LIBBITCOINCONSENSUS)
noinst_LTLIBRARIES =

bin_PROGRAMS =
Expand Down Expand Up @@ -486,6 +487,31 @@ libbitcoin_server_a_SOURCES = \
zwgr/zerocoindb.cpp \
$(BITCOIN_CORE_H)

libdashcore_a_CPPFLAGS = $(AM_CPPFLAGS) $(BITCOIN_INCLUDES)
libdashcore_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)

libdashcore_a_SOURCES = \
wagerrlib/wagerrlib.cpp \
script/sigcommon.cpp \
hash.cpp \
hash.h \
key.cpp \
key.h \
primitives/transaction.cpp \
primitives/transaction.h \
pubkey.cpp \
pubkey.h \
random.cpp \
random.h \
support/cleanse.cpp \
support/cleanse.h \
uint256.cpp \
uint256.h \
util/strencodings.cpp \
util/strencodings.h \
util/time.cpp \
util/time.h

if ENABLE_WALLET
libbitcoin_server_a_SOURCES += wallet/init.cpp
endif
Expand Down Expand Up @@ -689,6 +715,7 @@ libbitcoin_consensus_a_SOURCES = \
script/script.h \
script/script_error.cpp \
script/script_error.h \
script/sigcommon.cpp \
serialize.h \
span.h \
streams.h \
Expand Down Expand Up @@ -898,6 +925,22 @@ dash_wallet_LDADD = \
dash_wallet_LDADD += $(BACKTRACE_LIB) $(BOOST_LIBS) $(BDB_LIBS) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS) $(MINIUPNPC_LIBS) $(NATPMP_LIBS) $(ZMQ_LIBS) $(BLS_LIBS) $(GMP_LIBS)
#

# dashcore library #
if BUILD_BITCOIN_LIBS
libdashcore_la_SOURCES = $(libdashcore_a_SOURCES) $(crypto_libdash_crypto_a_SOURCES)

if GLIBC_BACK_COMPAT
libdashcore_la_SOURCES += compat/glibc_compat.cpp
endif

libdashcore_la_LDFLAGS = $(AM_LDFLAGS) $(SSL_LIBS) $(CRYPTO_LIBS) $(BOOST_LIBS) -no-undefined $(RELDFLAGS)
libdashcore_la_LIBADD = $(LIBSECP256K1)
libdashcore_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(BOOST_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libdashcore_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)

endif
#

# dashconsensus library #
if BUILD_BITCOIN_LIBS
include_HEADERS = script/bitcoinconsensus.h
Expand Down
181 changes: 0 additions & 181 deletions src/script/interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1302,187 +1302,6 @@ bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript&
return set_success(serror);
}

namespace {

/**
* Wrapper that serializes like CTransaction, but with the modifications
* required for the signature hash done in-place
*/
template <class T>
class CTransactionSignatureSerializer
{
private:
const T& txTo; //!< reference to the spending transaction (the one being serialized)
const CScript& scriptCode; //!< output script being consumed
const unsigned int nIn; //!< input index of txTo being signed
const bool fAnyoneCanPay; //!< whether the hashtype has the SIGHASH_ANYONECANPAY flag set
const bool fHashSingle; //!< whether the hashtype is SIGHASH_SINGLE
const bool fHashNone; //!< whether the hashtype is SIGHASH_NONE

public:
CTransactionSignatureSerializer(const T& txToIn, const CScript& scriptCodeIn, unsigned int nInIn, int nHashTypeIn) :
txTo(txToIn), scriptCode(scriptCodeIn), nIn(nInIn),
fAnyoneCanPay(!!(nHashTypeIn & SIGHASH_ANYONECANPAY)),
fHashSingle((nHashTypeIn & 0x1f) == SIGHASH_SINGLE),
fHashNone((nHashTypeIn & 0x1f) == SIGHASH_NONE) {}

/** Serialize the passed scriptCode, skipping OP_CODESEPARATORs */
template<typename S>
void SerializeScriptCode(S &s) const {
CScript::const_iterator it = scriptCode.begin();
CScript::const_iterator itBegin = it;
opcodetype opcode;
unsigned int nCodeSeparators = 0;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR)
nCodeSeparators++;
}
::WriteCompactSize(s, scriptCode.size() - nCodeSeparators);
it = itBegin;
while (scriptCode.GetOp(it, opcode)) {
if (opcode == OP_CODESEPARATOR) {
s.write((char*)&itBegin[0], it-itBegin-1);
itBegin = it;
}
}
if (itBegin != scriptCode.end())
s.write((char*)&itBegin[0], it-itBegin);
}

/** Serialize an input of txTo */
template<typename S>
void SerializeInput(S &s, unsigned int nInput) const {
// In case of SIGHASH_ANYONECANPAY, only the input being signed is serialized
if (fAnyoneCanPay)
nInput = nIn;
// Serialize the prevout
::Serialize(s, txTo.vin[nInput].prevout);
// Serialize the script
if (nInput != nIn)
// Blank out other inputs' signatures
::Serialize(s, CScript());
else
SerializeScriptCode(s);
// Serialize the nSequence
if (nInput != nIn && (fHashSingle || fHashNone))
// let the others update at will
::Serialize(s, (int)0);
else
::Serialize(s, txTo.vin[nInput].nSequence);
}

/** Serialize an output of txTo */
template<typename S>
void SerializeOutput(S &s, unsigned int nOutput) const {
if (fHashSingle && nOutput != nIn)
// Do not lock-in the txout payee at other indices as txin
::Serialize(s, CTxOut());
else
::Serialize(s, txTo.vout[nOutput]);
}

/** Serialize txTo */
template<typename S>
void Serialize(S &s) const {
// Serialize nVersion
int32_t n32bitVersion = txTo.nVersion | (txTo.nType << 16);
::Serialize(s, n32bitVersion);
// Serialize vin
unsigned int nInputs = fAnyoneCanPay ? 1 : txTo.vin.size();
::WriteCompactSize(s, nInputs);
for (unsigned int nInput = 0; nInput < nInputs; nInput++)
SerializeInput(s, nInput);
// Serialize vout
unsigned int nOutputs = fHashNone ? 0 : (fHashSingle ? nIn+1 : txTo.vout.size());
::WriteCompactSize(s, nOutputs);
for (unsigned int nOutput = 0; nOutput < nOutputs; nOutput++)
SerializeOutput(s, nOutput);
// Serialize nLockTime
::Serialize(s, txTo.nLockTime);
if (txTo.nVersion == 3 && txTo.nType != TRANSACTION_NORMAL)
::Serialize(s, txTo.vExtraPayload);
}
};

/** Compute the (single) SHA256 of the concatenation of all prevouts of a tx. */
template <class T>
uint256 GetPrevoutsSHA256(const T& txTo)
{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.prevout;
}
return ss.GetSHA256();
}

/** Compute the (single) SHA256 of the concatenation of all nSequences of a tx. */
template <class T>
uint256 GetSequencesSHA256(const T& txTo)
{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txin : txTo.vin) {
ss << txin.nSequence;
}
return ss.GetSHA256();
}

/** Compute the (single) SHA256 of the concatenation of all txouts of a tx. */
template <class T>
uint256 GetOutputsSHA256(const T& txTo)
{
CHashWriter ss(SER_GETHASH, 0);
for (const auto& txout : txTo.vout) {
ss << txout;
}
return ss.GetSHA256();
}

} // namespace

template <class T>
void PrecomputedTransactionData::Init(const T& txTo, std::vector<CTxOut>&& spent_outputs)
{
assert(!m_ready);

m_spent_outputs = std::move(spent_outputs);

m_ready = true;
}

template <class T>
PrecomputedTransactionData::PrecomputedTransactionData(const T& txTo)
{
Init(txTo, {});
}

// explicit instantiation
template PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo);
template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo);
template void PrecomputedTransactionData::Init(const CTransaction& txTo, std::vector<CTxOut>&& spent_outputs);
template void PrecomputedTransactionData::Init(const CMutableTransaction& txTo, std::vector<CTxOut>&& spent_outputs);

template <class T>
uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
{
assert(nIn < txTo.vin.size());

// Check for invalid use of SIGHASH_SINGLE
if ((nHashType & 0x1f) == SIGHASH_SINGLE) {
if (nIn >= txTo.vout.size()) {
// nOut out of range
return uint256::ONE;
}
}

// Wrapper to serialize only the necessary parts of the transaction being signed
CTransactionSignatureSerializer<T> txTmp(txTo, scriptCode, nIn, nHashType);

// Serialize and hash
CHashWriter ss(SER_GETHASH, 0);
ss << txTmp << nHashType;
return ss.GetHash();
}

template uint256 SignatureHash<CMutableTransaction>(const CScript& scriptCode, const CMutableTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache);
template uint256 SignatureHash<CTransaction>(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache);

Expand Down
Loading

0 comments on commit 283192e

Please sign in to comment.