text: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2014 The Bitcoin developers
  // Copyright (c) 2018-2019 The PIVX developers
  // Copyright (C) 2019-2020 The ucacoin developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #include "bitcoinconsensus.h"
  
  #include "primitives/transaction.h"
  #include "script/interpreter.h"
  #include "version.h"
  
  namespace {
  
  /** A class that deserializes a single CTransaction one time. */
  class TxInputStream
  {
  public:
      TxInputStream(int nTypeIn, int nVersionIn, const unsigned char *txTo, size_t txToLen) :
      m_type(nTypeIn),
      m_version(nVersionIn),
      m_data(txTo),
      m_remaining(txToLen)
      {}
  
      void read(char* pch, size_t nSize)
      {
          if (nSize > m_remaining)
              throw std::ios_base::failure(std::string(__func__) + ": end of data");
  
          if (pch == NULL)
              throw std::ios_base::failure(std::string(__func__) + ": bad destination buffer");
  
          if (m_data == NULL)
              throw std::ios_base::failure(std::string(__func__) + ": bad source buffer");
  
          memcpy(pch, m_data, nSize);
          m_remaining -= nSize;
          m_data += nSize;
      }
  
      template<typename T>
      TxInputStream& operator>>(T& obj)
      {
          ::Unserialize(*this, obj);
          return *this;
      }
  
      int GetVersion() const { return m_version; }
      int GetType() const { return m_type; }
  
  private:
      const int m_type;
      const int m_version;
      const unsigned char* m_data;
      size_t m_remaining;
  };
  
  inline int set_error(bitcoinconsensus_error* ret, bitcoinconsensus_error serror)
  {
      if (ret)
          *ret = serror;
      return 0;
  }
  
  struct ECCryptoClosure
  {
      ECCVerifyHandle handle;
  };
  
  ECCryptoClosure instance_of_eccryptoclosure;
  
  } // anon namespace
  
  int bitcoinconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
                                      const unsigned char *txTo        , unsigned int txToLen,
                                      unsigned int nIn, unsigned int flags, bitcoinconsensus_error* err)
  {
      try {
          TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen);
          CTransaction tx;
          stream >> tx;
          if (nIn >= tx.vin.size())
              return set_error(err, bitcoinconsensus_ERR_TX_INDEX);
          if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
              return set_error(err, bitcoinconsensus_ERR_TX_SIZE_MISMATCH);
  
           // Regardless of the verification result, the tx did not error.
           set_error(err, bitcoinconsensus_ERR_OK);
  
          return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn), NULL);
      } catch (const std::exception&) {
          return set_error(err, bitcoinconsensus_ERR_TX_DESERIALIZE); // Error deserializing
      }
  }
  
  unsigned int bitcoinconsensus_version()
  {
      // Just use the API version for now
      return BITCOINCONSENSUS_API_VER;
  }
  