git / moonbite-core / src/script/sign.h · raw

// Copyright (c) 2009-2010 Satoshi Nakamoto// Copyright (c) 2009-2020 The Bitcoin Core developers// Distributed under the MIT software license, see the accompanying// file COPYING or http://www.opensource.org/licenses/mit-license.php.#ifndef BITCOIN_SCRIPT_SIGN_H#define BITCOIN_SCRIPT_SIGN_H#include <coins.h>#include <hash.h>#include <pubkey.h>#include <script/address.h>#include <script/interpreter.h>#include <script/keyorigin.h>#include <span.h>#include <streams.h>class CKey;class CKeyID;class CScript;class CScriptID;class CTransaction;class SigningProvider;struct CMutableTransaction;/** Interface for signature creators. */class BaseSignatureCreator {public:    virtual ~BaseSignatureCreator() {}    virtual const BaseSignatureChecker& Checker() const =0;    /** Create a singular (non-script) signature. */    virtual bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0;};/** A signature creator for transactions. */class MutableTransactionSignatureCreator : public BaseSignatureCreator {    const CMutableTransaction* txTo;    unsigned int nIn;    int nHashType;    CAmount amount;    const MutableTransactionSignatureChecker checker;public:    MutableTransactionSignatureCreator(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn = SIGHASH_ALL);    const BaseSignatureChecker& Checker() const override { return checker; }    bool CreateSig(const SigningProvider& provider, std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const override;};/** 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. */extern const BaseSignatureCreator& DUMMY_MAXIMUM_SIGNATURE_CREATOR;typedef std::pair<CPubKey, std::vector<unsigned char>> SigPair;// This struct contains information from a transaction input and also contains signatures for that input.// The information contained here can be used to create a signature and is also filled by ProduceSignature// in order to construct final scriptSigs and scriptWitnesses.struct SignatureData {    bool complete = false; ///< Stores whether the scriptSig and scriptWitness are complete    bool witness = false; ///< Stores whether the input this SigData corresponds to is a witness input    CScript scriptSig; ///< The scriptSig of an input. Contains complete signatures or the traditional partial signatures format    CScript redeem_script; ///< The redeemScript (if any) for the input    CScript witness_script; ///< The witnessScript (if any) for the input. witnessScripts are used in P2WSH outputs.    CScriptWitness scriptWitness; ///< The scriptWitness of an input. Contains complete signatures or the traditional partial signatures format. scriptWitness is part of a transaction input per BIP 144.    std::map<CKeyID, SigPair> signatures; ///< BIP 174 style partial signatures for the input. May contain all signatures necessary for producing a final scriptSig or scriptWitness.    std::map<CKeyID, std::pair<CPubKey, KeyOriginInfo>> misc_pubkeys;    std::vector<CKeyID> missing_pubkeys; ///< KeyIDs of pubkeys which could not be found    std::vector<CKeyID> missing_sigs; ///< KeyIDs of pubkeys for signatures which could not be found    uint160 missing_redeem_script; ///< ScriptID of the missing redeemScript (if any)    uint256 missing_witness_script; ///< SHA256 of the missing witnessScript (if any)    SignatureData() {}    explicit SignatureData(const CScript& script) : scriptSig(script) {}    void MergeSignatureData(SignatureData sigdata);};// Takes a stream and multiple arguments and serializes them as if first serialized into a vector and then into the stream// The resulting output into the stream has the total serialized length of all of the objects followed by all objects concatenated with each other.template<typename Stream, typename... X>void SerializeToVector(Stream& s, const X&... args){    WriteCompactSize(s, GetSerializeSizeMany(s.GetVersion(), args...));    SerializeMany(s, args...);}// Takes a stream and multiple arguments and unserializes them first as a vector then each object individually in the order provided in the argumentstemplate<typename Stream, typename... X>void UnserializeFromVector(Stream& s, X&... args){    size_t expected_size = ReadCompactSize(s);    size_t remaining_before = s.size();    UnserializeMany(s, args...);    size_t remaining_after = s.size();    if (remaining_after + expected_size != remaining_before) {        throw std::ios_base::failure("Size of value was not the stated size");    }}// Deserialize HD keypaths into a maptemplate<typename Stream>void DeserializeHDKeypaths(Stream& s, const std::vector<unsigned char>& key, std::map<CPubKey, KeyOriginInfo>& hd_keypaths){    // Make sure that the key is the size of pubkey + 1    if (key.size() != CPubKey::SIZE + 1 && key.size() != CPubKey::COMPRESSED_SIZE + 1) {        throw std::ios_base::failure("Size of key was not the expected size for the type BIP32 keypath");    }    // Read in the pubkey from key    CPubKey pubkey(key.begin() + 1, key.end());    if (!pubkey.IsFullyValid()) {       throw std::ios_base::failure("Invalid pubkey");    }    if (hd_keypaths.count(pubkey) > 0) {        throw std::ios_base::failure("Duplicate Key, pubkey derivation path already provided");    }    // Read in key path    uint64_t value_len = ReadCompactSize(s);    if (value_len % 4 || value_len == 0) {        throw std::ios_base::failure("Invalid length for HD key path");    }    KeyOriginInfo keypath;    s >> keypath.fingerprint;    for (unsigned int i = 4; i < value_len; i += sizeof(uint32_t)) {        uint32_t index;        s >> index;        keypath.path.push_back(index);    }    // Add to map    hd_keypaths.emplace(pubkey, std::move(keypath));}// Serialize HD keypaths to a stream from a maptemplate<typename Stream>void SerializeHDKeypaths(Stream& s, const std::map<CPubKey, KeyOriginInfo>& hd_keypaths, uint8_t type){    for (auto keypath_pair : hd_keypaths) {        if (!keypath_pair.first.IsValid()) {            throw std::ios_base::failure("Invalid CPubKey being serialized");        }        SerializeToVector(s, type, MakeSpan(keypath_pair.first));        WriteCompactSize(s, (keypath_pair.second.path.size() + 1) * sizeof(uint32_t));        s << keypath_pair.second.fingerprint;        for (const auto& path : keypath_pair.second.path) {            s << path;        }    }}/** Produce a script signature using a generic signature creator. */bool ProduceSignature(const SigningProvider& provider, const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);/** Produce a script signature for a transaction. */bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);bool SignSignature(const SigningProvider &provider, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);/** Extract signature data from a transaction input, and insert it. */SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn, const CTxOut& txout);void UpdateInput(CTxIn& input, const SignatureData& data);/* Check whether we know how to sign for an output like this, assuming we * 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 DestinationAddr& dest_addr);/** Check whether a scriptPubKey is known to be segwit. */bool IsSegWitOutput(const SigningProvider& provider, const CScript& script);/** Sign the CMutableTransaction */bool SignTransaction(CMutableTransaction& mtx, const SigningProvider* provider, const std::map<COutPoint, Coin>& coins, int sighash, std::map<int, std::string>& input_errors);#endif // BITCOIN_SCRIPT_SIGN_H