From b3f1d6dab30be2c07e405a62d40cdd6a4064bbb0 Mon Sep 17 00:00:00 2001 From: jc Date: Fri, 18 May 2018 09:19:02 -0400 Subject: [PATCH] [script] signing and fork replay protection --- src/bench/verify_script.cpp | 2 +- src/script/interpreter.cpp | 95 +++++++++++++-------- src/script/interpreter.h | 12 ++- src/script/sign.cpp | 15 ++-- src/test/multisig_tests.cpp | 2 +- src/test/script_tests.cpp | 122 ++------------------------- src/test/sighash_tests.cpp | 6 +- src/test/test_bitcoin.cpp | 2 + src/test/txvalidationcache_tests.cpp | 8 +- src/validation.cpp | 14 +-- 10 files changed, 106 insertions(+), 172 deletions(-) diff --git a/src/bench/verify_script.cpp b/src/bench/verify_script.cpp index 4100519d4..7f187ac05 100644 --- a/src/bench/verify_script.cpp +++ b/src/bench/verify_script.cpp @@ -75,7 +75,7 @@ static void VerifyScriptBench(benchmark::State& state) CMutableTransaction txSpend = BuildSpendingTransaction(scriptSig, txCredit); CScriptWitness& witness = txSpend.vin[0].scriptWitness; witness.stack.emplace_back(); - key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back(), 0); + key.Sign(SignatureHash(witScriptPubkey, txSpend, 0, SIGHASH_ALL, FORKID_NONE, txCredit.vout[0].nValue, SigVersion::WITNESS_V0), witness.stack.back(), 0); witness.stack.back().push_back(static_cast(SIGHASH_ALL)); witness.stack.push_back(ToByteVector(pubkey)); diff --git a/src/script/interpreter.cpp b/src/script/interpreter.cpp index 4e6fc690d..79d36e48d 100644 --- a/src/script/interpreter.cpp +++ b/src/script/interpreter.cpp @@ -169,6 +169,13 @@ bool static IsValidSignatureEncoding(const std::vector &sig) { return true; } +uint32_t static GetHashType(const valtype &vchSig) { + if (vchSig.size() == 0) + return 0; + // check IsValidSignatureEncoding()'s comment for vchSig format + return vchSig.back(); +} + bool static IsLowDERSignature(const valtype &vchSig, ScriptError* serror) { if (!IsValidSignatureEncoding(vchSig)) { return set_error(serror, SCRIPT_ERR_SIG_DER); @@ -190,13 +197,22 @@ bool static IsDefinedHashtypeSignature(const valtype &vchSig) { if (vchSig.size() == 0) { return false; } - unsigned char nHashType = vchSig[vchSig.size() - 1] & (~(SIGHASH_ANYONECANPAY)); + unsigned char nHashType = GetHashType(vchSig) & (~(SIGHASH_ANYONECANPAY|SIGHASH_FORKID)); if (nHashType < SIGHASH_ALL || nHashType > SIGHASH_SINGLE) return false; return true; } +bool static UsesForkId(uint32_t nHashType) { + return nHashType & SIGHASH_FORKID; +} + +bool static UsesForkId(const valtype &vchSig) { + uint32_t nHashType = GetHashType(vchSig); + return UsesForkId(nHashType); +} + bool CheckSignatureEncoding(const std::vector &vchSig, unsigned int flags, ScriptError* serror) { // Empty signature. Not strictly DER encoded, but allowed to provide a // compact way to provide an invalid signature for use with CHECK(MULTI)SIG @@ -210,6 +226,8 @@ bool CheckSignatureEncoding(const std::vector &vchSig, unsigned i return false; } else if ((flags & SCRIPT_VERIFY_STRICTENC) != 0 && !IsDefinedHashtypeSignature(vchSig)) { return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE); + } else if ((flags & SCRIPT_VERIFY_FORKID) != 0 && !UsesForkId(vchSig)) { + return set_error(serror, SCRIPT_ERR_SIG_HASHTYPE); } return true; } @@ -300,6 +318,8 @@ bool EvalScript(std::vector >& stack, const CScript& int nOpCount = 0; bool fRequireMinimal = (flags & SCRIPT_VERIFY_MINIMALDATA) != 0; + const int forkid = (flags & SCRIPT_VERIFY_FORKID) ? FORKID_IN_USE : 0; + try { while (pc < pend) @@ -924,14 +944,11 @@ bool EvalScript(std::vector >& stack, const CScript& valtype& vchSig = stacktop(-2); valtype& vchPubKey = stacktop(-1); - // Subset of script starting at the most recent codeseparator - CScript scriptCode(pbegincodehash, pend); - if (!CheckSignatureEncoding(vchSig, flags, serror) || !CheckPubKeyEncoding(vchPubKey, flags, sigversion, serror)) { //serror is set return false; } - bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, sigversion); + bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, forkid, sigversion); if (!fSuccess && (flags & SCRIPT_VERIFY_NULLFAIL) && vchSig.size()) return set_error(serror, SCRIPT_ERR_SIG_NULLFAIL); @@ -995,7 +1012,7 @@ bool EvalScript(std::vector >& stack, const CScript& } // Check signature - bool fOk = checker.CheckSig(vchSig, vchPubKey, script, sigversion); + bool fOk = checker.CheckSig(vchSig, vchPubKey, script, forkid, sigversion); if (fOk) { isig++; @@ -1092,24 +1109,9 @@ public: /** Serialize the passed scriptCode */ template void SerializeScriptCode(S &s) const { - CScript::const_iterator it = scriptCode.begin(); - CScript::const_iterator itBegin = it; - opcodetype opcode; - unsigned int nCodeSeparators = 0; - while (scriptCode.GetOp(it, opcode)) { - if (opcode == OP_CODESEPARATOR) - nCodeSeparators++; - } - ::WriteCompactSize(s, scriptCode.size() - nCodeSeparators); - it = itBegin; - while (scriptCode.GetOp(it, opcode)) { - if (opcode == OP_CODESEPARATOR) { - s.write((char*)&itBegin[0], it-itBegin-1); - itBegin = it; - } - } - if (itBegin != scriptCode.end()) - s.write((char*)&itBegin[0], it-itBegin); + auto size = scriptCode.size(); + ::WriteCompactSize(s, size); + s.write((char*)&scriptCode.begin()[0], size); } /** Serialize an input of txTo */ @@ -1121,6 +1123,7 @@ public: // Serialize the prevout ::Serialize(s, txTo.vin[nInput].prevout); // Serialize the script + assert(nInput != NOT_AN_INPUT); if (nInput != nIn) // Blank out other inputs' signatures ::Serialize(s, CScript()); @@ -1161,6 +1164,23 @@ public: SerializeOutput(s, nOutput); // Serialize nLockTime ::Serialize(s, txTo.nLockTime); + + // Serialize vjoinsplit + if (txTo.nVersion >= 2) { + // + // SIGHASH_* functions will hash portions of + // the transaction for use in signatures. This + // keeps the JoinSplit cryptographically bound + // to the transaction. + // + ::Serialize(s, txTo.vjoinsplit); + if (txTo.vjoinsplit.size() > 0) { + ::Serialize(s, txTo.joinSplitPubKey); + + CTransaction::joinsplit_sig_t nullSig = {}; + ::Serialize(s, nullSig); + } + } } }; @@ -1213,9 +1233,11 @@ template PrecomputedTransactionData::PrecomputedTransactionData(const CTransacti template PrecomputedTransactionData::PrecomputedTransactionData(const CMutableTransaction& txTo); template -uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache) +uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const int forkid, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache) { - assert(nIn < txTo.vin.size()); + if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) { + throw std::logic_error("input index is out of range"); + } if (sigversion == SigVersion::WITNESS_V0) { uint256 hashPrevouts; @@ -1263,22 +1285,24 @@ uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn return ss.GetHash(); } - static const uint256 one(uint256S("0000000000000000000000000000000000000000000000000000000000000001")); // Check for invalid use of SIGHASH_SINGLE if ((nHashType & 0x1f) == SIGHASH_SINGLE) { if (nIn >= txTo.vout.size()) { - // nOut out of range - return one; + throw std::logic_error("no matching output for SIGHASH_SINGLE"); } } + int nForkHashType = nHashType; + if (UsesForkId(nHashType)) + nForkHashType |= forkid << 8; + // Wrapper to serialize only the necessary parts of the transaction being signed CTransactionSignatureSerializer txTmp(txTo, scriptCode, nIn, nHashType); // Serialize and hash CHashWriter ss(SER_GETHASH, 0); - ss << txTmp << nHashType; + ss << txTmp << nForkHashType; return ss.GetHash(); } @@ -1289,7 +1313,7 @@ bool GenericTransactionSignatureChecker::VerifySignature(const std::vector -bool GenericTransactionSignatureChecker::CheckSig(const std::vector& vchSigIn, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const +bool GenericTransactionSignatureChecker::CheckSig(const std::vector& vchSigIn, const std::vector& vchPubKey, const CScript& scriptCode, const int forkid, SigVersion sigversion) const { CPubKey pubkey(vchPubKey); if (!pubkey.IsValid()) @@ -1299,10 +1323,15 @@ bool GenericTransactionSignatureChecker::CheckSig(const std::vector vchSig(vchSigIn); if (vchSig.empty()) return false; - int nHashType = vchSig.back(); + int nHashType = GetHashType(vchSig); vchSig.pop_back(); - uint256 sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata); + uint256 sighash; + try { + sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, forkid, amount, sigversion, this->txdata); + } catch (std::logic_error ex) { + return false; + } if (!VerifySignature(vchSig, pubkey, sighash)) return false; diff --git a/src/script/interpreter.h b/src/script/interpreter.h index e6de3acc5..d8756b368 100644 --- a/src/script/interpreter.h +++ b/src/script/interpreter.h @@ -12,12 +12,16 @@ #include #include #include +#include class CPubKey; class CScript; class CTransaction; class uint256; +/** Special case nIn for signing JoinSplits. */ +const unsigned int NOT_AN_INPUT = UINT_MAX; + /** Signature hash types/flags */ enum { @@ -28,6 +32,8 @@ enum SIGHASH_ANYONECANPAY = 0x80, }; +static const int SIGHASH_FLAGS_MASK = SIGHASH_FORKID | SIGHASH_ANYONECANPAY; +static const int SIGHASH_BASE_MASK = ~SIGHASH_FLAGS_MASK; enum { @@ -158,12 +164,12 @@ static constexpr size_t WITNESS_V0_SCRIPTHASH_SIZE = 32; static constexpr size_t WITNESS_V0_KEYHASH_SIZE = 20; template -uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr); +uint256 SignatureHash(const CScript& scriptCode, const T& txTo, unsigned int nIn, int nHashType, const int forkid, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = nullptr); class BaseSignatureChecker { public: - virtual bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const + virtual bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, const int forkid, SigVersion sigversion) const { return false; } @@ -196,7 +202,7 @@ protected: public: GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {} GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {} - bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override; + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, const int forkid, SigVersion sigversion) const override; bool CheckLockTime(const CScriptNum& nLockTime) const override; bool CheckSequence(const CScriptNum& nSequence) const override; }; diff --git a/src/script/sign.cpp b/src/script/sign.cpp index c5468f633..d3da8efc9 100644 --- a/src/script/sign.cpp +++ b/src/script/sign.cpp @@ -26,7 +26,12 @@ bool MutableTransactionSignatureCreator::CreateSig(const SigningProvider& provid if (sigversion == SigVersion::WITNESS_V0 && !key.IsCompressed()) return false; - uint256 hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion); + uint256 hash; + try { + hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, FORKID_IN_USE, amount, sigversion); + } catch (std::logic_error ex) { + return false; + } if (!key.Sign(hash, vchSig)) return false; vchSig.push_back((unsigned char)nHashType); @@ -209,7 +214,7 @@ bool SignSignature(const SigningProvider &provider, const CScript& fromPubKey, C { assert(nIn < txTo.vin.size()); - MutableTransactionSignatureCreator creator(&txTo, nIn, amount, nHashType); + MutableTransactionSignatureCreator creator(&txTo, nIn, amount, nHashType | SIGHASH_FORKID); SignatureData sigdata; bool ret = ProduceSignature(provider, creator, fromPubKey, sigdata); @@ -257,7 +262,7 @@ static std::vector CombineMultisig(const CScript& scriptPubKey, const B if (sigs.count(pubkey)) continue; // Already got a sig for this pubkey - if (checker.CheckSig(sig, pubkey, scriptPubKey, sigversion)) + if (checker.CheckSig(sig, pubkey, scriptPubKey, FORKID_IN_USE, sigversion)) { sigs[pubkey] = sig; break; @@ -395,7 +400,7 @@ class DummySignatureChecker final : public BaseSignatureChecker { public: DummySignatureChecker() {} - bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; } + bool CheckSig(const std::vector& scriptSig, const std::vector& vchPubKey, const CScript& scriptCode, const int forkid, SigVersion sigversion) const override { return true; } }; const DummySignatureChecker DUMMY_CHECKER; @@ -415,7 +420,7 @@ public: vchSig[4 + 33] = 0x02; vchSig[5 + 33] = 32; vchSig[6 + 33] = 0x01; - vchSig[6 + 33 + 32] = SIGHASH_ALL; + vchSig[6 + 33 + 32] = SIGHASH_ALL | SIGHASH_FORKID; return true; } }; diff --git a/src/test/multisig_tests.cpp b/src/test/multisig_tests.cpp index 77db9f5c5..ff71d6ab6 100644 --- a/src/test/multisig_tests.cpp +++ b/src/test/multisig_tests.cpp @@ -21,7 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup) static CScript sign_multisig(const CScript& scriptPubKey, const std::vector& keys, const CTransaction& transaction, int whichIn) { - uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); CScript result; result << OP_0; // CHECKMULTISIG bug workaround diff --git a/src/test/script_tests.cpp b/src/test/script_tests.cpp index c05e60996..af6049c17 100644 --- a/src/test/script_tests.cpp +++ b/src/test/script_tests.cpp @@ -365,7 +365,7 @@ public: TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32, SigVersion sigversion = SigVersion::BASE, CAmount amount = 0) { - uint256 hash = SignatureHash(script, spendTx, 0, nHashType, amount, sigversion); + uint256 hash = SignatureHash(script, spendTx, 0, nHashType, FORKID_NONE, amount, sigversion); std::vector vchSig, r, s; uint32_t iter = 0; do { @@ -515,7 +515,7 @@ BOOST_AUTO_TEST_CASE(script_build) tests.push_back(TestBuilder(CScript() << ToByteVector(keys.pubkey0C) << OP_CHECKSIG, "P2SH(P2PK), bad redeemscript", SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).PushRedeem().DamagePush(10).ScriptError(SCRIPT_ERR_EVAL_FALSE)); - + tests.push_back(TestBuilder(CScript() << OP_DUP << OP_HASH160 << ToByteVector(keys.pubkey0.GetID()) << OP_EQUALVERIFY << OP_CHECKSIG, "P2SH(P2PKH)", SCRIPT_VERIFY_P2SH, true ).PushSig(keys.key0).Push(keys.pubkey0).PushRedeem()); @@ -1033,7 +1033,7 @@ BOOST_AUTO_TEST_CASE(script_PushData) static CScript sign_multisig(const CScript& scriptPubKey, const std::vector& keys, const CTransaction& transaction) { - uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); CScript result; // @@ -1229,15 +1229,15 @@ BOOST_AUTO_TEST_CASE(script_combineSigs) // A couple of partially-signed versions: std::vector sig1; - uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(keys[0].Sign(hash1, sig1)); sig1.push_back(SIGHASH_ALL); std::vector sig2; - uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SigVersion::BASE); + uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(keys[1].Sign(hash2, sig2)); sig2.push_back(SIGHASH_NONE); std::vector sig3; - uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SigVersion::BASE); + uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(keys[2].Sign(hash3, sig3)); sig3.push_back(SIGHASH_SINGLE); @@ -1340,116 +1340,6 @@ ScriptFromHex(const char* hex) return CScript(data.begin(), data.end()); } - -BOOST_AUTO_TEST_CASE(script_FindAndDelete) -{ - // Exercise the FindAndDelete functionality - CScript s; - CScript d; - CScript expect; - - s = CScript() << OP_1 << OP_2; - d = CScript(); // delete nothing should be a no-op - expect = s; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); - BOOST_CHECK(s == expect); - - s = CScript() << OP_1 << OP_2 << OP_3; - d = CScript() << OP_2; - expect = CScript() << OP_1 << OP_3; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = CScript() << OP_3 << OP_1 << OP_3 << OP_3 << OP_4 << OP_3; - d = CScript() << OP_3; - expect = CScript() << OP_1 << OP_4; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 4); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("0302ff03"); // PUSH 0x02ff03 onto stack - d = ScriptFromHex("0302ff03"); - expect = CScript(); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("0302ff030302ff03"); // PUSH 0x2ff03 PUSH 0x2ff03 - d = ScriptFromHex("0302ff03"); - expect = CScript(); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("0302ff030302ff03"); - d = ScriptFromHex("02"); - expect = s; // FindAndDelete matches entire opcodes - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("0302ff030302ff03"); - d = ScriptFromHex("ff"); - expect = s; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); - BOOST_CHECK(s == expect); - - // This is an odd edge case: strip of the push-three-bytes - // prefix, leaving 02ff03 which is push-two-bytes: - s = ScriptFromHex("0302ff030302ff03"); - d = ScriptFromHex("03"); - expect = CScript() << ParseHex("ff03") << ParseHex("ff03"); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2); - BOOST_CHECK(s == expect); - - // Byte sequence that spans multiple opcodes: - s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY - d = ScriptFromHex("feed51"); - expect = s; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); // doesn't match 'inside' opcodes - BOOST_CHECK(s == expect); - - s = ScriptFromHex("02feed5169"); // PUSH(0xfeed) OP_1 OP_VERIFY - d = ScriptFromHex("02feed51"); - expect = ScriptFromHex("69"); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("516902feed5169"); - d = ScriptFromHex("feed51"); - expect = s; - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 0); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("516902feed5169"); - d = ScriptFromHex("02feed51"); - expect = ScriptFromHex("516969"); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = CScript() << OP_0 << OP_0 << OP_1 << OP_1; - d = CScript() << OP_0 << OP_1; - expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = CScript() << OP_0 << OP_0 << OP_1 << OP_0 << OP_1 << OP_1; - d = CScript() << OP_0 << OP_1; - expect = CScript() << OP_0 << OP_1; // FindAndDelete is single-pass - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 2); - BOOST_CHECK(s == expect); - - // Another weird edge case: - // End with invalid push (not enough data)... - s = ScriptFromHex("0003feed"); - d = ScriptFromHex("03feed"); // ... can remove the invalid push - expect = ScriptFromHex("00"); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); - - s = ScriptFromHex("0003feed"); - d = ScriptFromHex("00"); - expect = ScriptFromHex("03feed"); - BOOST_CHECK_EQUAL(FindAndDelete(s, d), 1); - BOOST_CHECK(s == expect); -} - BOOST_AUTO_TEST_CASE(script_HasValidOps) { // Exercise the HasValidOps functionality diff --git a/src/test/sighash_tests.cpp b/src/test/sighash_tests.cpp index 6b8856ef4..43693e1e3 100644 --- a/src/test/sighash_tests.cpp +++ b/src/test/sighash_tests.cpp @@ -35,7 +35,7 @@ uint256 static SignatureHashOld(CScript scriptCode, const CTransaction& txTo, un // In case concatenating two scripts ends up with two codeseparators, // or an extra one at the end, this prevents all those possible incompatibilities. - FindAndDelete(scriptCode, CScript(OP_CODESEPARATOR)); + //FindAndDelete(scriptCode, CScript(OP_CODESEPARATOR)); // Blank out other inputs' signatures for (unsigned int i = 0; i < txTmp.vin.size(); i++) @@ -138,7 +138,7 @@ BOOST_AUTO_TEST_CASE(sighash_test) uint256 sh, sho; sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType); - sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SigVersion::BASE); + sh = SignatureHash(scriptCode, txTo, nIn, nHashType, FORKID_NONE, 0, SigVersion::BASE); #if defined(PRINT_SIGHASH_JSON) CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); ss << txTo; @@ -204,7 +204,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data) continue; } - sh = SignatureHash(scriptCode, *tx, nIn, nHashType, 0, SigVersion::BASE); + sh = SignatureHash(scriptCode, *tx, nIn, nHashType, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest); } } diff --git a/src/test/test_bitcoin.cpp b/src/test/test_bitcoin.cpp index e9814edc2..17448460a 100644 --- a/src/test/test_bitcoin.cpp +++ b/src/test/test_bitcoin.cpp @@ -47,6 +47,8 @@ std::ostream& operator<<(std::ostream& os, const uint256& num) BasicTestingSetup::BasicTestingSetup(const std::string& chainName) { + assert(init_and_check_sodium() != -1); + SHA256AutoDetect(); RandomInit(); ECC_Start(); diff --git a/src/test/txvalidationcache_tests.cpp b/src/test/txvalidationcache_tests.cpp index 06497667c..cc197c798 100644 --- a/src/test/txvalidationcache_tests.cpp +++ b/src/test/txvalidationcache_tests.cpp @@ -56,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup) // Sign: std::vector vchSig; - uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back((unsigned char)SIGHASH_ALL); spends[i].vin[0].scriptSig << vchSig; @@ -182,7 +182,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Sign, with a non-DER signature { std::vector vchSig; - uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(p2pk_scriptPubKey, spend_tx, 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back((unsigned char) 0); // padding byte makes this non-DER vchSig.push_back((unsigned char)SIGHASH_ALL); @@ -256,7 +256,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Sign std::vector vchSig; - uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(spend_tx.vout[2].scriptPubKey, invalid_with_cltv_tx, 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_cltv_tx.vin[0].scriptSig = CScript() << vchSig << 101; @@ -284,7 +284,7 @@ BOOST_FIXTURE_TEST_CASE(checkinputs_test, TestChain100Setup) // Sign std::vector vchSig; - uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, 0, SigVersion::BASE); + uint256 hash = SignatureHash(spend_tx.vout[3].scriptPubKey, invalid_with_csv_tx, 0, SIGHASH_ALL, FORKID_NONE, 0, SigVersion::BASE); BOOST_CHECK(coinbaseKey.Sign(hash, vchSig)); vchSig.push_back((unsigned char)SIGHASH_ALL); invalid_with_csv_tx.vin[0].scriptSig = CScript() << vchSig << 101; diff --git a/src/validation.cpp b/src/validation.cpp index 6f894bd41..a3a3e4c18 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -436,7 +436,7 @@ bool CheckSequenceLocks(const CTransaction &tx, int flags, LockPoints* lp, bool } // Returns the script flags which should be checked for a given block -static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& chainparams); +static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const CChainParams& chainparams); static void LimitMempoolSize(CTxMemPool& pool, size_t limit, unsigned long age) { int expired = pool.Expire(GetTime() - age); @@ -940,7 +940,7 @@ static bool AcceptToMemoryPoolWorker(const CChainParams& chainparams, CTxMemPool // There is a similar check in CreateNewBlock() to prevent creating // invalid blocks (using TestBlockValidity), however allowing such // transactions into the mempool can be exploited as a DoS attack. - unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(chainActive.Tip(), Params().GetConsensus()); + unsigned int currentBlockScriptVerifyFlags = GetBlockScriptFlags(chainActive.Tip(), Params()); if (!CheckInputsFromMempoolAndCache(tx, state, view, pool, currentBlockScriptVerifyFlags, true, txdata)) { // If we're using promiscuousmempoolflags, we may hit this normally // Check if current block has some flags that scriptVerifyFlags @@ -1789,9 +1789,11 @@ static bool IsScriptWitnessEnabled(const Consensus::Params& params) return params.vDeployments[Consensus::DEPLOYMENT_SEGWIT].nTimeout != 0; } -static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consensus::Params& consensusparams) { +static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const CChainParams& chainparams) { AssertLockHeld(cs_main); + const Consensus::Params& consensusparams = chainparams.GetConsensus(); + unsigned int flags = SCRIPT_VERIFY_NONE; flags |= SCRIPT_VERIFY_P2SH; @@ -1807,9 +1809,9 @@ static unsigned int GetBlockScriptFlags(const CBlockIndex* pindex, const Consens } // Start enforcing rules for first hard fork - if (isForkEnabled(pindex->nHeight)){ + if (isForkEnabled(pindex->nHeight, chainparams.ForkStartHeight())){ flags |= SCRIPT_VERIFY_FORKID; - flags |= SCRIPT_VERIFY_WITNESS_BOOTSTRAP; + flags |= SCRIPT_VERIFY_WITNESS_FORK; } // Start enforcing BIP68 (sequence locks) and BIP112 (CHECKSEQUENCEVERIFY) using versionbits logic. @@ -1941,7 +1943,7 @@ bool CChainState::ConnectBlock(const CBlock& block, CValidationState& state, CBl } // Get the script flags for this block - unsigned int flags = GetBlockScriptFlags(pindex, chainparams.GetConsensus()); + unsigned int flags = GetBlockScriptFlags(pindex, chainparams); int64_t nTime2 = GetTimeMicros(); nTimeForks += nTime2 - nTime1; LogPrint(BCLog::BENCH, " - Fork checks: %.2fms [%.2fs (%.2fms/blk)]\n", MILLI * (nTime2 - nTime1), nTimeForks * MICRO, nTimeForks * MILLI / nBlocksTotal);