Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2021 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #include <script/bitcoinconsensus.h>
# 7 : :
# 8 : : #include <primitives/transaction.h>
# 9 : : #include <pubkey.h>
# 10 : : #include <script/interpreter.h>
# 11 : : #include <version.h>
# 12 : :
# 13 : : namespace {
# 14 : :
# 15 : : /** A class that deserializes a single CTransaction one time. */
# 16 : : class TxInputStream
# 17 : : {
# 18 : : public:
# 19 : : TxInputStream(int nVersionIn, const unsigned char *txTo, size_t txToLen) :
# 20 : : m_version(nVersionIn),
# 21 : : m_data(txTo),
# 22 : : m_remaining(txToLen)
# 23 : 1156 : {}
# 24 : :
# 25 : : void read(Span<std::byte> dst)
# 26 : 13964 : {
# 27 [ + + ]: 13964 : if (dst.size() > m_remaining) {
# 28 : 2 : throw std::ios_base::failure(std::string(__func__) + ": end of data");
# 29 : 2 : }
# 30 : :
# 31 [ - + ]: 13962 : if (dst.data() == nullptr) {
# 32 : 0 : throw std::ios_base::failure(std::string(__func__) + ": bad destination buffer");
# 33 : 0 : }
# 34 : :
# 35 [ - + ]: 13962 : if (m_data == nullptr) {
# 36 : 0 : throw std::ios_base::failure(std::string(__func__) + ": bad source buffer");
# 37 : 0 : }
# 38 : :
# 39 : 13962 : memcpy(dst.data(), m_data, dst.size());
# 40 : 13962 : m_remaining -= dst.size();
# 41 : 13962 : m_data += dst.size();
# 42 : 13962 : }
# 43 : :
# 44 : : template<typename T>
# 45 : : TxInputStream& operator>>(T&& obj)
# 46 : 5232 : {
# 47 : 5232 : ::Unserialize(*this, obj);
# 48 : 5232 : return *this;
# 49 : 5232 : }
# 50 : :
# 51 : 1156 : int GetVersion() const { return m_version; }
# 52 : : private:
# 53 : : const int m_version;
# 54 : : const unsigned char* m_data;
# 55 : : size_t m_remaining;
# 56 : : };
# 57 : :
# 58 : : inline int set_error(bitcoinconsensus_error* ret, bitcoinconsensus_error serror)
# 59 : 1160 : {
# 60 [ + + ]: 1160 : if (ret)
# 61 : 12 : *ret = serror;
# 62 : 1160 : return 0;
# 63 : 1160 : }
# 64 : :
# 65 : : struct ECCryptoClosure
# 66 : : {
# 67 : : ECCVerifyHandle handle;
# 68 : : };
# 69 : :
# 70 : : ECCryptoClosure instance_of_eccryptoclosure;
# 71 : : } // namespace
# 72 : :
# 73 : : /** Check that all specified flags are part of the libconsensus interface. */
# 74 : : static bool verify_flags(unsigned int flags)
# 75 : 1158 : {
# 76 : 1158 : return (flags & ~(bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL)) == 0;
# 77 : 1158 : }
# 78 : :
# 79 : : static int verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, CAmount amount,
# 80 : : const unsigned char *txTo , unsigned int txToLen,
# 81 : : unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
# 82 : 1158 : {
# 83 [ + + ]: 1158 : if (!verify_flags(flags)) {
# 84 : 2 : return set_error(err, bitcoinconsensus_ERR_INVALID_FLAGS);
# 85 : 2 : }
# 86 : 1156 : try {
# 87 : 1156 : TxInputStream stream(PROTOCOL_VERSION, txTo, txToLen);
# 88 : 1156 : CTransaction tx(deserialize, stream);
# 89 [ + + ]: 1156 : if (nIn >= tx.vin.size())
# 90 : 2 : return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
# 91 [ + + ]: 1154 : if (GetSerializeSize(tx, PROTOCOL_VERSION) != txToLen)
# 92 : 2 : return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
# 93 : :
# 94 : : // Regardless of the verification result, the tx did not error.
# 95 : 1152 : set_error(err, bitcoinconsensus_ERR_OK);
# 96 : :
# 97 : 1152 : PrecomputedTransactionData txdata(tx);
# 98 : 1152 : return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), &tx.vin[nIn].scriptWitness, flags, TransactionSignatureChecker(&tx, nIn, amount, txdata, MissingDataBehavior::FAIL), nullptr);
# 99 : 1154 : } catch (const std::exception&) {
# 100 : 2 : return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
# 101 : 2 : }
# 102 : 1156 : }
# 103 : :
# 104 : : int bitcoinconsensus_verify_script_with_amount(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int64_t amount,
# 105 : : const unsigned char *txTo , unsigned int txToLen,
# 106 : : unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
# 107 : 658 : {
# 108 : 658 : CAmount am(amount);
# 109 : 658 : return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
# 110 : 658 : }
# 111 : :
# 112 : :
# 113 : : int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
# 114 : : const unsigned char *txTo , unsigned int txToLen,
# 115 : : unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
# 116 : 502 : {
# 117 [ + + ]: 502 : if (flags & bitcoinconsensus_SCRIPT_FLAGS_VERIFY_WITNESS) {
# 118 : 2 : return set_error(err, bitcoinconsensus_ERR_AMOUNT_REQUIRED);
# 119 : 2 : }
# 120 : :
# 121 : 500 : CAmount am(0);
# 122 : 500 : return ::verify_script(scriptPubKey, scriptPubKeyLen, am, txTo, txToLen, nIn, flags, err);
# 123 : 502 : }
# 124 : :
# 125 : : unsigned int bitcoinconsensus_version()
# 126 : 0 : {
# 127 : : // Just use the API version for now
# 128 : 0 : return BITCOINCONSENSUS_API_VER;
# 129 : 0 : }
|