diff --git a/.gitignore b/.gitignore index c97432df9..7343e722d 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,7 @@ src/qt/test/moc*.cpp .deps .dirstamp +.libs .*.swp *.*~* *.bak @@ -66,6 +67,10 @@ src/qt/test/moc*.cpp *.json.h *.raw.h +#libtool object files +*.lo +*.la + # Compilation and Qt preprocessor part *.qm Makefile diff --git a/src/Makefile.am b/src/Makefile.am index 83dcaeed7..63f2375c8 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -49,6 +49,8 @@ BITCOIN_INCLUDES += $(BDB_CPPFLAGS) noinst_LIBRARIES += libbitcoin_wallet.a endif +lib_LTLIBRARIES = libbitcoinconsensus.la + bin_PROGRAMS = TESTS = @@ -331,6 +333,35 @@ bitcoin_cli_SOURCES += bitcoin-cli-res.rc endif bitcoin_cli_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +if BUILD_BITCOIN_LIBS +include_HEADERS = script/bitcoinconsensus.h +libbitcoinconsensus_la_SOURCES = \ + core/transaction.cpp \ + crypto/sha1.cpp \ + crypto/sha2.cpp \ + crypto/ripemd160.cpp \ + eccryptoverify.cpp \ + ecwrapper.cpp \ + hash.cpp \ + pubkey.cpp \ + script/script.cpp \ + script/interpreter.cpp \ + script/bitcoinconsensus.cpp \ + uint256.cpp \ + utilstrencodings.cpp + +if GLIBC_BACK_COMPAT + libbitcoinconsensus_la_SOURCES += compat/glibc_compat.cpp + libbitcoinconsensus_la_SOURCES += compat/glibcxx_compat.cpp +endif + +libbitcoinconsensus_la_LDFLAGS = -no-undefined $(RELDFLAGS) +libbitcoinconsensus_la_LIBADD = $(CRYPTO_LIBS) +libbitcoinconsensus_la_CPPFLAGS = $(CRYPTO_CFLAGS) -I$(builddir)/obj -DBUILD_BITCOIN_INTERNAL +if USE_LIBSECP256K1 +libbitcoinconsensus_la_LIBADD += secp256k1/libsecp256k1.la +endif + CLEANFILES = leveldb/libleveldb.a leveldb/libmemenv.a *.gcda *.gcno DISTCLEANFILES = obj/build.h diff --git a/src/Makefile.test.include b/src/Makefile.test.include index c3cd7db14..f8711f038 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -86,7 +86,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_WALLET) endif test_test_bitcoin_LDADD += $(BDB_LIBS) $(SSL_LIBS) $(CRYPTO_LIBS) $(MINIUPNPC_LIBS) -test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) +test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static-libtool-libs nodist_test_test_bitcoin_SOURCES = $(GENERATED_TEST_FILES) diff --git a/src/script/bitcoinconsensus.cpp b/src/script/bitcoinconsensus.cpp new file mode 100644 index 000000000..4faa760ad --- /dev/null +++ b/src/script/bitcoinconsensus.cpp @@ -0,0 +1,91 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin 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 "core/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) + {} + + TxInputStream& 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; + return *this; + } + + template + TxInputStream& operator>>(T& obj) + { + ::Unserialize(*this, obj, m_type, m_version); + return *this; + } + +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; +} + +} // 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 (tx.GetSerializeSize(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, SignatureChecker(tx, nIn), NULL); + } catch (std::exception &e) { + 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; +} diff --git a/src/script/bitcoinconsensus.h b/src/script/bitcoinconsensus.h new file mode 100644 index 000000000..15e3337a8 --- /dev/null +++ b/src/script/bitcoinconsensus.h @@ -0,0 +1,67 @@ +// Copyright (c) 2009-2010 Satoshi Nakamoto +// Copyright (c) 2009-2014 The Bitcoin developers +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef BITCOIN_BITCOINCONSENSUS_H +#define BITCOIN_BITCOINCONSENSUS_H + +#if defined(BUILD_BITCOIN_INTERNAL) && defined(HAVE_CONFIG_H) +#include "config/bitcoin-config.h" + #if defined(_WIN32) + #if defined(DLL_EXPORT) + #if defined(HAVE_FUNC_ATTRIBUTE_DLLEXPORT) + #define EXPORT_SYMBOL __declspec(dllexport) + #else + #define EXPORT_SYMBOL + #endif + #endif + #elif defined(HAVE_FUNC_ATTRIBUTE_VISIBILITY) + #define EXPORT_SYMBOL __attribute__ ((visibility ("default"))) + #endif +#elif defined(MSC_VER) && !defined(STATIC_LIBBITCOINCONSENSUS) + #define EXPORT_SYMBOL __declspec(dllimport) +#endif + +#ifndef EXPORT_SYMBOL + #define EXPORT_SYMBOL +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BITCOINCONSENSUS_API_VER 0 + +typedef enum bitcoinconsensus_error_t +{ + bitcoinconsensus_ERR_OK = 0, + bitcoinconsensus_ERR_TX_INDEX, + bitcoinconsensus_ERR_TX_SIZE_MISMATCH, + bitcoinconsensus_ERR_TX_DESERIALIZE, +} bitcoinconsensus_error; + +/** Script verification flags */ +enum +{ + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0, + bitcoinconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts +}; + +/// Returns 1 if the input nIn of the serialized transaction pointed to by +/// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under +/// the additional constraints specified by flags. +/// If not NULL, err will contain an error/success code for the operation +EXPORT_SYMBOL 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); + +EXPORT_SYMBOL unsigned int bitcoinconsensus_version(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#undef EXPORT_SYMBOL + +#endif // BITCOIN_BITCOINCONSENSUS_H