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 486 : TxInputStream(int nVersionIn, const unsigned char *txTo, size_t txToLen) : 20 243 : m_version(nVersionIn), 21 243 : m_data(txTo), 22 243 : m_remaining(txToLen) 23 486 : {} 24 : 25 2660 : void read(Span<std::byte> dst) 26 : { 27 2660 : if (dst.size() > m_remaining) { 28 1 : throw std::ios_base::failure(std::string(__func__) + ": end of data"); 29 : } 30 : 31 2659 : if (dst.data() == nullptr) { 32 0 : throw std::ios_base::failure(std::string(__func__) + ": bad destination buffer"); 33 : } 34 : 35 2659 : if (m_data == nullptr) { 36 0 : throw std::ios_base::failure(std::string(__func__) + ": bad source buffer"); 37 : } 38 : 39 2659 : memcpy(dst.data(), m_data, dst.size()); 40 2659 : m_remaining -= dst.size(); 41 2659 : m_data += dst.size(); 42 2660 : } 43 : 44 : template<typename T> 45 : TxInputStream& operator>>(T&& obj) 46 : { 47 : ::Unserialize(*this, obj); 48 : return *this; 49 : } 50 : 51 : [[maybe_unused]] 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 244 : inline int set_error(dashconsensus_error* ret, dashconsensus_error serror) 59 : { 60 244 : if (ret) 61 5 : *ret = serror; 62 244 : return 0; 63 : } 64 : 65 : } // namespace 66 : 67 : /** Check that all specified flags are part of the libconsensus interface. */ 68 244 : static bool verify_flags(unsigned int flags) 69 : { 70 244 : return (flags & ~(dashconsensus_SCRIPT_FLAGS_VERIFY_ALL)) == 0; 71 : } 72 : 73 244 : int dashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, 74 : const unsigned char *txTo , unsigned int txToLen, 75 : unsigned int nIn, unsigned int flags, dashconsensus_error* err) 76 : { 77 244 : if (!verify_flags(flags)) { 78 1 : return set_error(err, dashconsensus_ERR_INVALID_FLAGS); 79 : } 80 : try { 81 243 : TxInputStream stream(PROTOCOL_VERSION, txTo, txToLen); 82 243 : CTransaction tx(deserialize, stream); 83 242 : if (nIn >= tx.vin.size()) 84 1 : return set_error(err, dashconsensus_ERR_TX_INDEX); 85 241 : if (GetSerializeSize(tx, PROTOCOL_VERSION) != txToLen) 86 1 : return set_error(err, dashconsensus_ERR_TX_SIZE_MISMATCH); 87 : 88 : // Regardless of the verification result, the tx did not error. 89 240 : set_error(err, dashconsensus_ERR_OK); 90 : 91 240 : PrecomputedTransactionData txdata(tx); 92 240 : CAmount am(0); 93 240 : return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn, am, txdata, MissingDataBehavior::FAIL), nullptr); 94 243 : } catch (const std::exception&) { 95 1 : return set_error(err, dashconsensus_ERR_TX_DESERIALIZE); // Error deserializing 96 1 : } 97 245 : } 98 : 99 0 : unsigned int dashconsensus_version() 100 : { 101 : // Just use the API version for now 102 0 : return BITCOINCONSENSUS_API_VER; 103 : }