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/
libzcashconsensus.pc
libzcash_script.pc
contrib/debian/files
contrib/debian/substvars

View File

@ -19,7 +19,7 @@ GZIP_ENV="-9n"
if BUILD_BITCOIN_LIBS
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libzcashconsensus.pc
pkgconfig_DATA = libzcash_script.pc
endif
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])
AM_CONDITIONAL([BUILD_BITCOIN_LIBS], [test x$build_bitcoin_libs = xyes])
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_CONFIG_FILES([libzcashconsensus.pc:libzcashconsensus.pc.in])
AC_DEFINE(HAVE_SCRIPT_LIB, 1, [Define this symbol if the script lib has been built])
AC_CONFIG_FILES([libzcash_script.pc:libzcash_script.pc.in])
fi
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
endif
if BUILD_BITCOIN_LIBS
LIBZCASH_CONSENSUS=libzcashconsensus.la
LIBZCASH_SCRIPT=libzcash_script.la
endif
if ENABLE_WALLET
LIBBITCOIN_WALLET=libbitcoin_wallet.a
@ -88,7 +88,7 @@ EXTRA_LIBRARIES += \
$(LIBBITCOIN_ZMQ) \
$(LIBZCASH)
lib_LTLIBRARIES = $(LIBZCASH_CONSENSUS)
lib_LTLIBRARIES = $(LIBZCASH_SCRIPT)
bin_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_LDFLAGS = $(AM_LDFLAGS)
# zcashconsensus library #
# zcash_script library #
if BUILD_BITCOIN_LIBS
include_HEADERS = script/zcashconsensus.h
libzcashconsensus_la_SOURCES = \
crypto/equihash.cpp \
include_HEADERS = script/zcash_script.h
libzcash_script_la_SOURCES = \
crypto/hmac_sha512.cpp \
crypto/ripemd160.cpp \
crypto/sha1.cpp \
@ -556,20 +555,20 @@ libzcashconsensus_la_SOURCES = \
hash.cpp \
primitives/transaction.cpp \
pubkey.cpp \
script/zcashconsensus.cpp \
script/zcash_script.cpp \
script/interpreter.cpp \
script/script.cpp \
uint256.cpp \
utilstrencodings.cpp
if GLIBC_BACK_COMPAT
libzcashconsensus_la_SOURCES += compat/glibc_compat.cpp
libzcash_script_la_SOURCES += compat/glibc_compat.cpp
endif
libzcashconsensus_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
libzcashconsensus_la_LIBADD = $(LIBSECP256K1)
libzcashconsensus_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_LDFLAGS = $(AM_LDFLAGS) -no-undefined $(RELDFLAGS)
libzcash_script_la_LIBADD = $(LIBSECP256K1)
libzcash_script_la_CPPFLAGS = $(AM_CPPFLAGS) -I$(builddir)/obj -I$(srcdir)/rust/include -I$(srcdir)/secp256k1/include -DBUILD_BITCOIN_INTERNAL
libzcash_script_la_CXXFLAGS = $(AM_CXXFLAGS) $(PIE_FLAGS)
endif
#

View File

@ -80,7 +80,7 @@ zcash_gtest_LDADD = \
$(LIBSECP256K1)
zcash_gtest_LDADD += \
$(LIBZCASH_CONSENSUS) \
$(LIBZCASH_SCRIPT) \
$(BOOST_LIBS) \
$(BOOST_UNIT_TEST_FRAMEWORK_LIB) \
$(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)
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
if ENABLE_ZMQ

View File

@ -3,7 +3,7 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or https://www.opensource.org/licenses/mit-license.php .
#include "zcashconsensus.h"
#include "zcash_script.h"
#include "consensus/upgrades.h"
#include "primitives/transaction.h"
@ -56,7 +56,7 @@ private:
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)
*ret = serror;
@ -71,38 +71,40 @@ struct ECCryptoClosure
ECCryptoClosure instance_of_eccryptoclosure;
}
int zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, zcashconsensus_error* err)
int zcash_script_verify(
const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
int64_t amount,
const unsigned char *txTo, unsigned int txToLen,
unsigned int nIn, unsigned int flags,
uint32_t consensusBranchId,
zcash_script_error* err)
{
try {
TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen);
CTransaction tx;
stream >> tx;
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)
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.
set_error(err, zcashconsensus_ERR_OK);
set_error(err, zcash_script_ERR_OK);
PrecomputedTransactionData txdata(tx);
CAmount am(0);
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
return VerifyScript(
tx.vin[nIn].scriptSig,
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
flags,
TransactionSignatureChecker(&tx, nIn, am, txdata),
TransactionSignatureChecker(&tx, nIn, amount, txdata),
consensusBranchId,
NULL);
} 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
return ZCASHCONSENSUS_API_VER;
return ZCASH_SCRIPT_API_VER;
}

View File

@ -33,33 +33,37 @@
extern "C" {
#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,
zcashconsensus_ERR_TX_INDEX,
zcashconsensus_ERR_TX_SIZE_MISMATCH,
zcashconsensus_ERR_TX_DESERIALIZE,
} zcashconsensus_error;
zcash_script_ERR_OK = 0,
zcash_script_ERR_TX_INDEX,
zcash_script_ERR_TX_SIZE_MISMATCH,
zcash_script_ERR_TX_DESERIALIZE,
} zcash_script_error;
/** Script verification flags */
enum
{
zcashconsensus_SCRIPT_FLAGS_VERIFY_NONE = 0,
zcashconsensus_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_NONE = 0,
zcash_script_SCRIPT_FLAGS_VERIFY_P2SH = (1U << 0), // evaluate P2SH (BIP16) subscripts
zcash_script_SCRIPT_FLAGS_VERIFY_CHECKLOCKTIMEVERIFY = (1U << 9), // enable CHECKLOCKTIMEVERIFY (BIP65)
};
/// 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 zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
const unsigned char *txTo , unsigned int txToLen,
unsigned int nIn, unsigned int flags, zcashconsensus_error* err);
EXPORT_SYMBOL int zcash_script_verify(
const unsigned char *scriptPubKey, unsigned int scriptPubKeyLen,
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
} // extern "C"

View File

@ -17,8 +17,8 @@
#include "test/test_bitcoin.h"
#include "test/test_util.h"
#if defined(HAVE_CONSENSUS_LIB)
#include "script/zcashconsensus.h"
#if defined(HAVE_SCRIPT_LIB)
#include "script/zcash_script.h"
#endif
#include <fstream>
@ -81,10 +81,16 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, ui
CMutableTransaction tx2 = tx;
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);
#if defined(HAVE_CONSENSUS_LIB)
#if defined(HAVE_SCRIPT_LIB)
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
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
}

View File

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