Merge pull request #98 from z-classic/revert-zencash-exploit

Revert ZenCash Exploit
This commit is contained in:
Joshua Yabut 2017-07-10 00:24:25 -04:00 committed by GitHub
commit 20d4581134
6 changed files with 14 additions and 57 deletions

View File

@ -449,8 +449,8 @@ zcash_cli_LDADD = \
#
# zcash-tx binary #
zcash_tx_SOURCES = bitcoin-tx.cpp script/standard.cpp
zcash_tx_CPPFLAGS = $(BITCOIN_INCLUDES) -DZCASH_TX
zcash_tx_SOURCES = bitcoin-tx.cpp
zcash_tx_CPPFLAGS = $(BITCOIN_INCLUDES)
zcash_tx_LDFLAGS = $(RELDFLAGS) $(AM_LDFLAGS) $(LIBTOOL_APP_LDFLAGS)
if TARGET_WINDOWS

View File

@ -5,7 +5,6 @@ noinst_PROGRAMS += zcash-gtest
# test_checktransaction.cpp MUST be before
# any test that calls SelectParams().
zcash_gtest_SOURCES = \
script/standard.cpp \
gtest/main.cpp \
gtest/utils.cpp \
gtest/test_checktransaction.cpp \
@ -42,7 +41,7 @@ zcash_gtest_SOURCES += \
wallet/gtest/test_wallet.cpp
endif
zcash_gtest_CPPFLAGS = -DMULTICORE -fopenmp -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC $(BITCOIN_INCLUDES) -DZCASH_TX
zcash_gtest_CPPFLAGS = -DMULTICORE -fopenmp -DBINARY_OUTPUT -DCURVE_ALT_BN128 -DSTATIC $(BITCOIN_INCLUDES)
zcash_gtest_LDADD = -lgtest -lgmock $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1)

View File

@ -40,7 +40,6 @@ RAW_TEST_FILES = test/data/alertTests.raw
GENERATED_TEST_FILES = $(JSON_TEST_FILES:.json=.json.h) $(RAW_TEST_FILES:.raw=.raw.h)
BITCOIN_TESTS =\
script/standard.cpp \
test/arith_uint256_tests.cpp \
test/bignum.h \
test/addrman_tests.cpp \
@ -100,7 +99,7 @@ BITCOIN_TESTS += \
endif
test_test_bitcoin_SOURCES = $(BITCOIN_TESTS) $(JSON_TEST_FILES) $(RAW_TEST_FILES)
test_test_bitcoin_CPPFLAGS = -fopenmp $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS) -DZCASH_TX
test_test_bitcoin_CPPFLAGS = -fopenmp $(BITCOIN_INCLUDES) -I$(builddir)/test/ $(TESTDEFS) $(EVENT_CFLAGS)
test_test_bitcoin_LDADD = $(LIBBITCOIN_SERVER) $(LIBBITCOIN_CLI) $(LIBBITCOIN_COMMON) $(LIBBITCOIN_UTIL) $(LIBBITCOIN_CRYPTO) $(LIBUNIVALUE) $(LIBLEVELDB) $(LIBMEMENV) \
$(BOOST_LIBS) $(BOOST_UNIT_TEST_FRAMEWORK_LIB) $(LIBSECP256K1) $(EVENT_PTHREADS_LIBS) $(EVENT_LIBS)
if ENABLE_WALLET

View File

@ -380,8 +380,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
}
case OP_NOP5:
{
// If it is OP_CHECKBLOCKATHEIGHT then there are should be 3 args in stack: 2 params and 1 ret value from the prev opcode
if (stack.size() == 3) {
if (stack.size() == 2) {
popstack(stack);
popstack(stack);
}

View File

@ -5,7 +5,6 @@
#include "script/standard.h"
#include "main.h"
#include "pubkey.h"
#include "script/script.h"
#include "util.h"
@ -27,9 +26,12 @@ const char* GetTxnOutputType(txnouttype t)
{
case TX_NONSTANDARD: return "nonstandard";
case TX_PUBKEY: return "pubkey";
case TX_PUBKEY_REPLAY: return "pubkeyreplay";
case TX_PUBKEYHASH: return "pubkeyhash";
case TX_PUBKEYHASH_REPLAY: return "pubkeyhashreplay";
case TX_SCRIPTHASH: return "scripthash";
case TX_MULTISIG: return "multisig";
case TX_MULTISIG_REPLAY: return "multisigreplay";
case TX_NULL_DATA: return "nulldata";
}
return NULL;
@ -46,15 +48,15 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
{
// Standard tx, sender provides pubkey, receiver adds signature
mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG));
mTemplates.insert(make_pair(TX_PUBKEY, CScript() << OP_PUBKEY << OP_CHECKSIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
mTemplates.insert(make_pair(TX_PUBKEY_REPLAY, CScript() << OP_PUBKEY << OP_CHECKSIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
// Bitcoin address tx, sender provides hash of pubkey, receiver provides signature and pubkey
mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG));
mTemplates.insert(make_pair(TX_PUBKEYHASH, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
mTemplates.insert(make_pair(TX_PUBKEYHASH_REPLAY, CScript() << OP_DUP << OP_HASH160 << OP_PUBKEYHASH << OP_EQUALVERIFY << OP_CHECKSIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
// Sender provides N pubkeys, receivers provides M signatures
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG));
mTemplates.insert(make_pair(TX_MULTISIG, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
mTemplates.insert(make_pair(TX_MULTISIG_REPLAY, CScript() << OP_SMALLINTEGER << OP_PUBKEYS << OP_SMALLINTEGER << OP_CHECKMULTISIG << OP_SMALLDATA << OP_SMALLDATA << OP_NOP5));
// Empty, provably prunable, data-carrying output
if (GetBoolArg("-datacarrier", true))
@ -72,9 +74,6 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
return true;
}
// OP_CHECKBLOCKATHEIGHT parameters
vector<unsigned char> vchBlockHash, vchBlockHeight;
// Scan templates
const CScript& script1 = scriptPubKey;
BOOST_FOREACH(const PAIRTYPE(txnouttype, CScript)& tplate, mTemplates)
@ -149,52 +148,10 @@ bool Solver(const CScript& scriptPubKey, txnouttype& typeRet, vector<vector<unsi
}
else if (opcode2 == OP_SMALLDATA)
{
// Possible values of OP_CHECKBLOCKATHEIGHT parameters
if (vch1.size() <= sizeof(int))
vchBlockHeight = vch1;
else
vchBlockHash = vch1;
// small pushdata, <= nMaxDatacarrierBytes
if (vch1.size() > nMaxDatacarrierBytes)
break;
}
else if (opcode2 == OP_NOP5)
{
// Full-fledged implementation of the OP_CHECKBLOCKATHEIGHT opcode for verification of vout's
#ifndef ZCASH_TX // This is a workaround. zcash-tx does not have access to chain state so no replay protection is possible
if (vchBlockHeight.size() == 0 || vchBlockHash.size() == 0)
{
LogPrintf("%s: %s: OP_CHECKBLOCKATHEIGHT verification failed. Bad params.", __FILE__, __func__);
break;
}
const int32_t nHeight = CScriptNum(vchBlockHeight, true, sizeof(int)).getint();
if (nHeight < 0 || nHeight > chainActive.Height())
{
LogPrintf("%s: %s: OP_CHECKBLOCKATHEIGHT verification failed. Transaction is non-final. Referenced height: %d", __FILE__, __func__, nHeight);
break;
}
CBlockIndex* pblockindex = chainActive[nHeight];
vector<unsigned char> vchCompareTo(pblockindex->GetBlockHash().begin(), pblockindex->GetBlockHash().end());
vchCompareTo.erase(vchCompareTo.begin(), vchCompareTo.end() - vchBlockHash.size());
if (vchCompareTo != vchBlockHash)
{
LogPrintf("%s: %s: OP_CHECKBLOCKATHEIGHT verification failed. vout block height: %d", __FILE__, __func__, nHeight);
break;
}
#endif
if (opcode1 != opcode2 || vch1 != vch2)
{
break;
}
}
else if (opcode1 != opcode2 || vch1 != vch2)
{
// Others must match exactly

View File

@ -62,9 +62,12 @@ enum txnouttype
TX_NONSTANDARD,
// 'standard' transaction types:
TX_PUBKEY,
TX_PUBKEY_REPLAY,
TX_PUBKEYHASH,
TX_PUBKEYHASH_REPLAY,
TX_SCRIPTHASH,
TX_MULTISIG,
TX_MULTISIG_REPLAY,
TX_NULL_DATA,
};