Auto merge of #4966 - str4d:zcash-script-lib, r=nuttycom

Replace libzcashconsensus with libzcash_script

We inherited `libzcashconsensus` from upstream (we just renamed it before launch to avoid conflicts). However, it has become increasingly inaccurately named; it only covers (Zcash's subset of) the Bitcoin scripting system, and not the myriad of other consensus changes (in particular, the shielded pools).

This PR reworks the library to instead be focused on transparent script verification:
- The script verification APIs are altered to take `amount` and `consensusBranchId` fields.
- Equihash code is removed (the canonical Equihash validator is now the `equihash` Rust crate).
- The library is renamed to `libzcash_script`.

The API changes are backwards-incompatible, but the library rename prevents any issues. Also, `libzcashconsensus` was in fact broken and not compiling for several years and no one complained, suggesting that it was not actually being relied on within the ecosystem. By contrast, this focused library already has a consumer: the `zebrad` full node.

Closes zcash/zcash#4879.
This commit is contained in:
Homu 2021-01-28 19:34:09 +00:00
commit a960e896dd
12 changed files with 72 additions and 61 deletions

2
.gitignore vendored
View File

@ -112,7 +112,7 @@ qa/cache/*
/doc/doxygen/ /doc/doxygen/
libzcashconsensus.pc libzcash_script.pc
contrib/debian/files contrib/debian/files
contrib/debian/substvars contrib/debian/substvars

View File

@ -19,7 +19,7 @@ GZIP_ENV="-9n"
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
pkgconfigdir = $(libdir)/pkgconfig pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libzcashconsensus.pc pkgconfig_DATA = libzcash_script.pc
endif endif
BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT) BITCOIND_BIN=$(top_builddir)/src/$(BITCOIN_DAEMON_NAME)$(EXEEXT)

View File

@ -872,8 +872,8 @@ AC_MSG_RESULT($build_bitcoin_utils)
AC_MSG_CHECKING([whether to build libraries]) AC_MSG_CHECKING([whether to build libraries])
AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes]) AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes])
if test x$build_bitcoin_libs = xyes; then if test x$build_bitcoin_libs = xyes; then
AC_DEFINE(HAVE_CONSENSUS_LIB, 1, [Define this symbol if the consensus lib has been built]) AC_DEFINE(HAVE_SCRIPT_LIB, 1, [Define this symbol if the script lib has been built])
AC_CONFIG_FILES([libzcashconsensus.pc:libzcashconsensus.pc.in]) AC_CONFIG_FILES([libzcash_script.pc:libzcash_script.pc.in])
fi fi
AC_MSG_RESULT($build_bitcoin_libs) AC_MSG_RESULT($build_bitcoin_libs)

10
libzcash_script.pc.in Normal file
View File

@ -0,0 +1,10 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Zcash transparent script verification library
Description: Library for verifying scripts against the Zcash consensus protocol.
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lzcash_script
Cflags: -I${includedir}

View File

@ -1,10 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: Zcash consensus library
Description: Library for the Zcash consensus protocol.
Version: @PACKAGE_VERSION@
Libs: -L${libdir} -lzcashconsensus
Cflags: -I${includedir}

View File

@ -33,7 +33,7 @@ if ENABLE_ZMQ
LIBBITCOIN_ZMQ=libbitcoin_zmq.a LIBBITCOIN_ZMQ=libbitcoin_zmq.a
endif endif
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
LIBZCASH_CONSENSUS=libzcashconsensus.la LIBZCASH_SCRIPT=libzcash_script.la
endif endif
if ENABLE_WALLET if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a LIBBITCOIN_WALLET=libbitcoin_wallet.a
@ -88,7 +88,7 @@ EXTRA_LIBRARIES += \
$(LIBBITCOIN_ZMQ) \ $(LIBBITCOIN_ZMQ) \
$(LIBZCASH) $(LIBZCASH)
lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS) lib_LTLIBRARIES = $(LIBZCASH_SCRIPT)
bin_PROGRAMS = bin_PROGRAMS =
noinst_PROGRAMS = noinst_PROGRAMS =
@ -543,11 +543,10 @@ libzcash_a_CPPFLAGS = $(AM_CPPFLAGS) $(PIC_FLAGS) $(BITCOIN_INCLUDES)
libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libzcash_a_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
libzcash_a_LDFLAGS = $(AM_LDFLAGS) libzcash_a_LDFLAGS = $(AM_LDFLAGS)
# zcashconsensus library # # zcash_script library #
if BUILD_BITCOIN_LIBS if BUILD_BITCOIN_LIBS
include_HEADERS = script/zcashconsensus.h include_HEADERS = script/zcash_script.h
libzcashconsensus_la_SOURCES = \ libzcash_script_la_SOURCES = \
crypto/equihash.cpp \
crypto/hmac_sha512.cpp \ crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \ crypto/ripemd160.cpp \
crypto/sha1.cpp \ crypto/sha1.cpp \
@ -556,20 +555,20 @@ libzcashconsensus_la_SOURCES = \
hash.cpp \ hash.cpp \
primitives/transaction.cpp \ primitives/transaction.cpp \
pubkey.cpp \ pubkey.cpp \
script/zcashconsensus.cpp \ script/zcash_script.cpp \
script/interpreter.cpp \ script/interpreter.cpp \
script/script.cpp \ script/script.cpp \
uint256.cpp \ uint256.cpp \
utilstrencodings.cpp utilstrencodings.cpp
if GLIBC_BACK_COMPAT if GLIBC_BACK_COMPAT
libzcashconsensus_la_SOURCES += compat/glibc_compat.cpp libzcash_script_la_SOURCES += compat/glibc_compat.cpp
endif endif
libzcashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS) libzcash_script_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
libzcashconsensus_la_LIBADD = $(LIBSECP256K1) libzcash_script_la_LIBADD = $(LIBSECP256K1)
libzcashconsensus_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/rust/include -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL libzcash_script_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/rust/include -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libzcashconsensus_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) libzcash_script_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
endif endif
# #

View File

@ -80,7 +80,7 @@ zcash_gtest_LDADD = \
$(LIBSECP256K1) $(LIBSECP256K1)
zcash_gtest_LDADD += \ zcash_gtest_LDADD += \
$(LIBZCASH_CONSENSUS) \ $(LIBZCASH_SCRIPT) \
$(BOOST_LIBS) \ $(BOOST_LIBS) \
$(BOOST_UNIT_TEST_FRAMEWORK_LIB) \ $(BOOST_UNIT_TEST_FRAMEWORK_LIB) \
$(BDB_LIBS) \ $(BDB_LIBS) \

View File

@ -130,7 +130,7 @@ test_test_bitcoin_LDADD += $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_C
$(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS) $(LIBLEVELDB) $(LIBLEVELDB_SSE42) $(LIBMEMENV) $(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_LIBS) $(EVENT_PTHREADS_LIBS)
test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS) test_test_bitcoin_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
test_test_bitcoin_LDADD += $(LIBZCASH_CONSENSUS) $(BDB_LIBS) $(LIBZCASH) $(LIBRUSTZCASH) $(LIBZCASH_LIBS) test_test_bitcoin_LDADD += $(LIBZCASH_SCRIPT) $(BDB_LIBS) $(LIBZCASH) $(LIBRUSTZCASH) $(LIBZCASH_LIBS)
test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static test_test_bitcoin_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS) -static
if ENABLE_ZMQ if ENABLE_ZMQ

View File

@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying // Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php . // file COPYING or https://www.opensource.org/licenses/mit-license.php .
#include "zcashconsensus.h" #include "zcash_script.h"
#include "consensus/upgrades.h" #include "consensus/upgrades.h"
#include "primitives/transaction.h" #include "primitives/transaction.h"
@ -56,7 +56,7 @@ private:
size_t m_remaining; size_t m_remaining;
}; };
inline int set_error(zcashconsensus_error* ret, zcashconsensus_error serror) inline int set_error(zcash_script_error* ret, zcash_script_error serror)
{ {
if (ret) if (ret)
*ret = serror; *ret = serror;
@ -71,38 +71,40 @@ struct ECCryptoClosure
ECCryptoClosure instance_of_eccryptoclosure; ECCryptoClosure instance_of_eccryptoclosure;
} }
int zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, int zcash_script_verify(
const unsigned char *txTo , unsigned int txToLen, const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
unsigned int nIn, unsigned int flags, zcashconsensus_error* err) int64_t amount,
const unsigned char *txTo, unsigned int txToLen,
unsigned int nIn, unsigned int flags,
uint32_t consensusBranchId,
zcash_script_error* err)
{ {
try { try {
TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen); TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen);
CTransaction tx; CTransaction tx;
stream >> tx; stream >> tx;
if (nIn >= tx.vin.size()) if (nIn >= tx.vin.size())
return set_error(err, zcashconsensus_ERR_TX_INDEX); return set_error(err, zcash_script_ERR_TX_INDEX);
if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen) if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
return set_error(err, zcashconsensus_ERR_TX_SIZE_MISMATCH); return set_error(err, zcash_script_ERR_TX_SIZE_MISMATCH);
// Regardless of the verification result, the tx did not error. // Regardless of the verification result, the tx did not error.
set_error(err, zcashconsensus_ERR_OK); set_error(err, zcash_script_ERR_OK);
PrecomputedTransactionData txdata(tx); PrecomputedTransactionData txdata(tx);
CAmount am(0);
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
return VerifyScript( return VerifyScript(
tx.vin[nIn].scriptSig, tx.vin[nIn].scriptSig,
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
flags, flags,
TransactionSignatureChecker(&tx, nIn, am, txdata), TransactionSignatureChecker(&tx, nIn, amount, txdata),
consensusBranchId, consensusBranchId,
NULL); NULL);
} catch (const std::exception&) { } catch (const std::exception&) {
return set_error(err, zcashconsensus_ERR_TX_DESERIALIZE); // Error deserializing return set_error(err, zcash_script_ERR_TX_DESERIALIZE); // Error deserializing
} }
} }
unsigned int zcashconsensus_version() unsigned int zcash_script_version()
{ {
// Just use the API version for now // Just use the API version for now
return ZCASHCONSENSUS_API_VER; return ZCASH_SCRIPT_API_VER;
} }

View File

@ -33,33 +33,37 @@
extern "C" { extern "C" {
#endif #endif
#define ZCASHCONSENSUS_API_VER 0 #define ZCASH_SCRIPT_API_VER 0
typedef enum zcashconsensus_error_t typedef enum zcash_script_error_t
{ {
zcashconsensus_ERR_OK = 0, zcash_script_ERR_OK = 0,
zcashconsensus_ERR_TX_INDEX, zcash_script_ERR_TX_INDEX,
zcashconsensus_ERR_TX_SIZE_MISMATCH, zcash_script_ERR_TX_SIZE_MISMATCH,
zcashconsensus_ERR_TX_DESERIALIZE, zcash_script_ERR_TX_DESERIALIZE,
} zcashconsensus_error; } zcash_script_error;
/** Script verification flags */ /** Script verification flags */
enum enum
{ {
zcashconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0, zcash_script_SCRIPT_FLAGS_VERIFY_NONE = 0,
zcashconsensus_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts zcash_script_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
zcashconsensus_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65) zcash_script_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
}; };
/// Returns 1 if the input nIn of the serialized transaction pointed to by /// Returns 1 if the input nIn of the serialized transaction pointed to by
/// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under /// txTo correctly spends the scriptPubKey pointed to by scriptPubKey under
/// the additional constraints specified by flags. /// the additional constraints specified by flags.
/// If not NULL, err will contain an error/success code for the operation /// If not NULL, err will contain an error/success code for the operation
EXPORT_SYMBOL int zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen, EXPORT_SYMBOL int zcash_script_verify(
const unsigned char *txTo , unsigned int txToLen, const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
unsigned int nIn, unsigned int flags, zcashconsensus_error* err); int64_t amount,
const unsigned char *txTo, unsigned int txToLen,
unsigned int nIn, unsigned int flags,
uint32_t consensusBranchId,
zcash_script_error* err);
EXPORT_SYMBOL unsigned int zcashconsensus_version(); EXPORT_SYMBOL unsigned int zcash_script_version();
#ifdef __cplusplus #ifdef __cplusplus
} // extern "C" } // extern "C"

View File

@ -17,8 +17,8 @@
#include "test/test_bitcoin.h" #include "test/test_bitcoin.h"
#include "test/test_util.h" #include "test/test_util.h"
#if defined(HAVE_CONSENSUS_LIB) #if defined(HAVE_SCRIPT_LIB)
#include "script/zcashconsensus.h" #include "script/zcash_script.h"
#endif #endif
#include <fstream> #include <fstream>
@ -81,10 +81,16 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, ui
CMutableTransaction tx2 = tx; CMutableTransaction tx2 = tx;
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), consensusBranchId, &err) == expect, message); BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), consensusBranchId, &err) == expect, message);
BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message); BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
#if defined(HAVE_CONSENSUS_LIB) #if defined(HAVE_SCRIPT_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION); CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
stream << tx2; stream << tx2;
BOOST_CHECK_MESSAGE(zcashconsensus_verify_script(begin_ptr(scriptPubKey), scriptPubKey.size(), (const unsigned char*)&stream[0], stream.size(), 0, flags, NULL) == expect,message); BOOST_CHECK_MESSAGE(zcash_script_verify(
begin_ptr(scriptPubKey), scriptPubKey.size(),
txCredit.vout[0].nValue,
(const unsigned char*)&stream[0], stream.size(),
0, flags,
consensusBranchId,
NULL) == expect,message);
#endif #endif
} }

View File

@ -276,7 +276,7 @@ def build():
'Staging zeromq...', 'Staging zeromq...',
'Staging libsodium...', 'Staging libsodium...',
"Leaving directory '%s'" % depends_dir, "Leaving directory '%s'" % depends_dir,
'config.status: creating libzcashconsensus.pc', 'config.status: creating libzcash_script.pc',
"Entering directory '%s'" % src_dir, "Entering directory '%s'" % src_dir,
'httpserver.cpp', 'httpserver.cpp',
'torcontrol.cpp', 'torcontrol.cpp',