[script] signing and fork replay protection

This commit is contained in:
jc 2018-05-18 09:19:02 -04:00
parent e6e6ffedea
commit b3f1d6dab3
10 changed files with 106 additions and 172 deletions

View File

@ -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<unsigned char>(SIGHASH_ALL));
witness.stack.push_back(ToByteVector(pubkey));

View File

@ -169,6 +169,13 @@ bool static IsValidSignatureEncoding(const std::vector<unsigned char> &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<unsigned char> &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<unsigned char> &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<std::vector<unsigned char> >& 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<std::vector<unsigned char> >& 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<std::vector<unsigned char> >& 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<typename S>
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 <class T>
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<T> 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<T>::VerifySignature(const std::vector<un
}
template <class T>
bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned char>& vchSigIn, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, const int forkid, SigVersion sigversion) const
{
CPubKey pubkey(vchPubKey);
if (!pubkey.IsValid())
@ -1299,10 +1323,15 @@ bool GenericTransactionSignatureChecker<T>::CheckSig(const std::vector<unsigned
std::vector<unsigned char> 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;

View File

@ -12,12 +12,16 @@
#include <vector>
#include <stdint.h>
#include <string>
#include <climits>
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 <class T>
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<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
virtual bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& 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<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& 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;
};

View File

@ -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<valtype> 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<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override { return true; }
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& 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;
}
};

View File

@ -21,7 +21,7 @@ BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
static CScript
sign_multisig(const CScript& scriptPubKey, const std::vector<CKey>& 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

View File

@ -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<unsigned char> 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<CKey>& 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<unsigned char> 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<unsigned char> 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<unsigned char> 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

View File

@ -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);
}
}

View File

@ -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();

View File

@ -56,7 +56,7 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
// Sign:
std::vector<unsigned char> 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<unsigned char> 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<unsigned char> 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<unsigned char> 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;

View File

@ -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);