Add consensus branch ID parameter to SignatureHash, remove SigVersion parameter
We do not need to be able to calculate multiple SignatureHash versions for a single transaction format; instead, we use the transaction format to determine the SigVersion. The consensus branch ID *does* need to be passed in from the outside, as only the caller knows the context in which the SignatureHash is being calculated (ie. mempool acceptance vs. block validation). JoinSplit signature verification has been moved into ContextualCheckTransaction, where the consensus branch ID can be obtained. The argument to the sign command for zcash-tx has been modified to take a height in addition to the optional sigtype flags.
This commit is contained in:
parent
6514771a44
commit
be12669982
|
@ -6,6 +6,7 @@
|
|||
#include "clientversion.h"
|
||||
#include "coins.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "keystore.h"
|
||||
#include "primitives/transaction.h"
|
||||
|
@ -70,7 +71,7 @@ static bool AppInitRawTx(int argc, char* argv[])
|
|||
strUsage += HelpMessageOpt("nversion=N", _("Set TX version to N"));
|
||||
strUsage += HelpMessageOpt("outaddr=VALUE:ADDRESS", _("Add address-based output to TX"));
|
||||
strUsage += HelpMessageOpt("outscript=VALUE:SCRIPT", _("Add raw script output to TX"));
|
||||
strUsage += HelpMessageOpt("sign=SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
|
||||
strUsage += HelpMessageOpt("sign=HEIGHT:SIGHASH-FLAGS", _("Add zero or more signatures to transaction") + ". " +
|
||||
_("This command requires JSON registers:") +
|
||||
_("prevtxs=JSON object") + ", " +
|
||||
_("privatekeys=JSON object") + ". " +
|
||||
|
@ -334,10 +335,27 @@ static CAmount AmountFromValue(const UniValue& value)
|
|||
return amount;
|
||||
}
|
||||
|
||||
static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
|
||||
static void MutateTxSign(CMutableTransaction& tx, const string& strInput)
|
||||
{
|
||||
int nHashType = SIGHASH_ALL;
|
||||
// separate HEIGHT:SIGHASH-FLAGS in string
|
||||
size_t pos = strInput.find(':');
|
||||
if ((pos == 0) ||
|
||||
(pos == (strInput.size() - 1)))
|
||||
throw runtime_error("Invalid sighash flag separator");
|
||||
|
||||
// extract and validate HEIGHT
|
||||
string strHeight = strInput.substr(0, pos);
|
||||
int nHeight = atoi(strHeight);
|
||||
if (nHeight <= 0) {
|
||||
throw runtime_error("invalid height");
|
||||
}
|
||||
|
||||
// extract and validate SIGHASH-FLAGS
|
||||
int nHashType = SIGHASH_ALL;
|
||||
string flagStr;
|
||||
if (pos != string::npos) {
|
||||
flagStr = strInput.substr(pos + 1, string::npos);
|
||||
}
|
||||
if (flagStr.size() > 0)
|
||||
if (!findSighashFlags(nHashType, flagStr))
|
||||
throw runtime_error("unknown sighash flag/sign option");
|
||||
|
@ -427,6 +445,9 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
|
|||
|
||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||
|
||||
// Grab the consensus branch ID for the given height
|
||||
auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
|
||||
|
||||
// Sign what we can:
|
||||
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
|
||||
CTxIn& txin = mergedTx.vin[i];
|
||||
|
@ -441,14 +462,14 @@ static void MutateTxSign(CMutableTransaction& tx, const string& flagStr)
|
|||
SignatureData sigdata;
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
if (!fHashSingle || (i < mergedTx.vout.size()))
|
||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata);
|
||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
||||
|
||||
// ... and merge in other signatures:
|
||||
BOOST_FOREACH(const CTransaction& txv, txVariants)
|
||||
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i));
|
||||
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
||||
UpdateTransaction(mergedTx, i, sigdata);
|
||||
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount)))
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), consensusBranchId))
|
||||
fComplete = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -45,6 +45,8 @@ public:
|
|||
|
||||
|
||||
CMutableTransaction GetValidTransaction() {
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
CMutableTransaction mtx;
|
||||
mtx.vin.resize(2);
|
||||
mtx.vin[0].prevout.hash = uint256S("0000000000000000000000000000000000000000000000000000000000000001");
|
||||
|
@ -74,7 +76,7 @@ CMutableTransaction GetValidTransaction() {
|
|||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
if (dataToBeSigned == one) {
|
||||
throw std::runtime_error("SignatureHash failed");
|
||||
}
|
||||
|
@ -352,23 +354,27 @@ TEST(checktransaction_tests, bad_txns_prevout_null) {
|
|||
}
|
||||
|
||||
TEST(checktransaction_tests, bad_txns_invalid_joinsplit_signature) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
|
||||
CMutableTransaction mtx = GetValidTransaction();
|
||||
mtx.joinSplitSig[0] += 1;
|
||||
CTransaction tx(mtx);
|
||||
|
||||
MockCValidationState state;
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
|
||||
CheckTransactionWithoutProofVerification(tx, state);
|
||||
ContextualCheckTransaction(tx, state, 0, 100);
|
||||
}
|
||||
|
||||
TEST(checktransaction_tests, non_canonical_ed25519_signature) {
|
||||
SelectParams(CBaseChainParams::REGTEST);
|
||||
|
||||
CMutableTransaction mtx = GetValidTransaction();
|
||||
|
||||
// Check that the signature is valid before we add L
|
||||
{
|
||||
CTransaction tx(mtx);
|
||||
MockCValidationState state;
|
||||
EXPECT_TRUE(CheckTransactionWithoutProofVerification(tx, state));
|
||||
EXPECT_TRUE(ContextualCheckTransaction(tx, state, 0, 100));
|
||||
}
|
||||
|
||||
// Copied from libsodium/crypto_sign/ed25519/ref10/open.c
|
||||
|
@ -389,7 +395,7 @@ TEST(checktransaction_tests, non_canonical_ed25519_signature) {
|
|||
|
||||
MockCValidationState state;
|
||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false)).Times(1);
|
||||
CheckTransactionWithoutProofVerification(tx, state);
|
||||
ContextualCheckTransaction(tx, state, 0, 100);
|
||||
}
|
||||
|
||||
TEST(checktransaction_tests, OverwinterConstructors) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h"
|
||||
#include "utiltest.h"
|
||||
|
@ -70,9 +71,10 @@ TEST(Validation, ContextualCheckInputsPassesWithCoinbase) {
|
|||
FakeCoinsViewDB fakeDB;
|
||||
CCoinsViewCache view(&fakeDB);
|
||||
|
||||
auto consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CValidationState state;
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
EXPECT_TRUE(ContextualCheckInputs(tx, state, view, false, 0, false, txdata, Params(CBaseChainParams::MAIN).GetConsensus()));
|
||||
EXPECT_TRUE(ContextualCheckInputs(tx, state, view, false, 0, false, txdata, Params(CBaseChainParams::MAIN).GetConsensus(), consensusBranchId));
|
||||
}
|
||||
|
||||
TEST(Validation, ReceivedBlockTransactions) {
|
||||
|
|
77
src/main.cpp
77
src/main.cpp
|
@ -758,7 +758,7 @@ bool CheckFinalTx(const CTransaction &tx, int flags)
|
|||
* 2. P2SH scripts with a crazy number of expensive
|
||||
* CHECKSIG/CHECKMULTISIG operations
|
||||
*/
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, uint32_t consensusBranchId)
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return true; // Coinbases don't use vin normally
|
||||
|
@ -784,7 +784,7 @@ bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
|||
// IsStandardTx() will have already returned false
|
||||
// and this method isn't called.
|
||||
vector<vector<unsigned char> > stack;
|
||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SIGVERSION_BASE))
|
||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), consensusBranchId))
|
||||
return false;
|
||||
|
||||
if (whichType == TX_SCRIPTHASH)
|
||||
|
@ -886,6 +886,30 @@ bool ContextualCheckTransaction(const CTransaction& tx, CValidationState &state,
|
|||
}
|
||||
}
|
||||
|
||||
if (!(tx.IsCoinBase() || tx.vjoinsplit.empty())) {
|
||||
auto consensusBranchId = CurrentEpochBranchId(nHeight, Params().GetConsensus());
|
||||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
uint256 dataToBeSigned;
|
||||
try {
|
||||
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
} catch (std::logic_error ex) {
|
||||
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
|
||||
REJECT_INVALID, "error-computing-signature-hash");
|
||||
}
|
||||
|
||||
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
|
||||
|
||||
// We rely on libsodium to check that the signature is canonical.
|
||||
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
|
||||
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
|
||||
dataToBeSigned.begin(), 32,
|
||||
tx.joinSplitPubKey.begin()
|
||||
) != 0) {
|
||||
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
|
||||
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1082,30 +1106,6 @@ bool CheckTransactionWithoutProofVerification(const CTransaction& tx, CValidatio
|
|||
if (txin.prevout.IsNull())
|
||||
return state.DoS(10, error("CheckTransaction(): prevout is null"),
|
||||
REJECT_INVALID, "bad-txns-prevout-null");
|
||||
|
||||
if (tx.vjoinsplit.size() > 0) {
|
||||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
uint256 dataToBeSigned;
|
||||
try {
|
||||
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
} catch (std::logic_error ex) {
|
||||
return state.DoS(100, error("CheckTransaction(): error computing signature hash"),
|
||||
REJECT_INVALID, "error-computing-signature-hash");
|
||||
}
|
||||
|
||||
BOOST_STATIC_ASSERT(crypto_sign_PUBLICKEYBYTES == 32);
|
||||
|
||||
// We rely on libsodium to check that the signature is canonical.
|
||||
// https://github.com/jedisct1/libsodium/commit/62911edb7ff2275cccd74bf1c8aefcc4d76924e0
|
||||
if (crypto_sign_verify_detached(&tx.joinSplitSig[0],
|
||||
dataToBeSigned.begin(), 32,
|
||||
tx.joinSplitPubKey.begin()
|
||||
) != 0) {
|
||||
return state.DoS(100, error("CheckTransaction(): invalid joinsplit signature"),
|
||||
REJECT_INVALID, "bad-txns-invalid-joinsplit-signature");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1148,6 +1148,9 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
if (pfMissingInputs)
|
||||
*pfMissingInputs = false;
|
||||
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
auto consensusBranchId = CurrentEpochBranchId(nextBlockHeight, Params().GetConsensus());
|
||||
|
||||
// Node operator can choose to reject tx by number of transparent inputs
|
||||
static_assert(std::numeric_limits<size_t>::max() >= std::numeric_limits<int64_t>::max(), "size_t too small");
|
||||
size_t limit = (size_t) GetArg("-mempooltxinputlimit", 0);
|
||||
|
@ -1165,7 +1168,6 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
|
||||
// DoS level set to 10 to be more forgiving.
|
||||
// Check transaction contextually against the set of consensus rules which apply in the next block to be mined.
|
||||
int nextBlockHeight = chainActive.Height() + 1;
|
||||
if (!ContextualCheckTransaction(tx, state, nextBlockHeight, 10)) {
|
||||
return error("AcceptToMemoryPool: ContextualCheckTransaction failed");
|
||||
}
|
||||
|
@ -1260,7 +1262,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
}
|
||||
|
||||
// Check for non-standard pay-to-script-hash in inputs
|
||||
if (Params().RequireStandard() && !AreInputsStandard(tx, view))
|
||||
if (Params().RequireStandard() && !AreInputsStandard(tx, view, consensusBranchId))
|
||||
return error("AcceptToMemoryPool: nonstandard transaction input");
|
||||
|
||||
// Check that the transaction doesn't have an excessive number of
|
||||
|
@ -1348,7 +1350,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
// Check against previous transactions
|
||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus()))
|
||||
if (!ContextualCheckInputs(tx, state, view, true, STANDARD_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
|
||||
{
|
||||
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
||||
}
|
||||
|
@ -1362,7 +1364,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||
// There is a similar check in CreateNewBlock() to prevent creating
|
||||
// invalid blocks, however allowing such transactions into the mempool
|
||||
// can be exploited as a DoS attack.
|
||||
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus()))
|
||||
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
|
||||
{
|
||||
return error("AcceptToMemoryPool: BUG! PLEASE REPORT THIS! ConnectInputs failed against MANDATORY but not STANDARD flags %s", hash.ToString());
|
||||
}
|
||||
|
@ -1727,7 +1729,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
|
|||
|
||||
bool CScriptCheck::operator()() {
|
||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), &error)) {
|
||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) {
|
||||
return ::error("CScriptCheck(): %s:%d VerifySignature failed: %s", ptxTo->GetHash().ToString(), nIn, ScriptErrorString(error));
|
||||
}
|
||||
return true;
|
||||
|
@ -1810,7 +1812,7 @@ bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoins
|
|||
}
|
||||
}// namespace Consensus
|
||||
|
||||
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, std::vector<CScriptCheck> *pvChecks)
|
||||
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &inputs, bool fScriptChecks, unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams, uint32_t consensusBranchId, std::vector<CScriptCheck> *pvChecks)
|
||||
{
|
||||
if (!tx.IsCoinBase())
|
||||
{
|
||||
|
@ -1835,7 +1837,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
|
|||
assert(coins);
|
||||
|
||||
// Verify signature
|
||||
CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata);
|
||||
CScriptCheck check(*coins, tx, i, flags, cacheStore, consensusBranchId, &txdata);
|
||||
if (pvChecks) {
|
||||
pvChecks->push_back(CScriptCheck());
|
||||
check.swap(pvChecks->back());
|
||||
|
@ -1848,7 +1850,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
|
|||
// avoid splitting the network between upgraded and
|
||||
// non-upgraded nodes.
|
||||
CScriptCheck check2(*coins, tx, i,
|
||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata);
|
||||
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, consensusBranchId, &txdata);
|
||||
if (check2())
|
||||
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));
|
||||
}
|
||||
|
@ -2238,6 +2240,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||
assert(tree.root() == old_tree_root);
|
||||
}
|
||||
|
||||
// Grab the consensus branch ID for the block's height
|
||||
auto consensusBranchId = CurrentEpochBranchId(pindex->nHeight, Params().GetConsensus());
|
||||
|
||||
std::vector<PrecomputedTransactionData> txdata;
|
||||
txdata.reserve(block.vtx.size()); // Required so that pointers to individual PrecomputedTransactionData don't get invalidated
|
||||
for (unsigned int i = 0; i < block.vtx.size(); i++)
|
||||
|
@ -2277,7 +2282,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
|||
nFees += view.GetValueIn(tx)-tx.GetValueOut();
|
||||
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), nScriptCheckThreads ? &vChecks : NULL))
|
||||
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, false, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL))
|
||||
return false;
|
||||
control.Add(vChecks);
|
||||
}
|
||||
|
@ -3721,7 +3726,7 @@ bool static LoadBlockIndexDB()
|
|||
pindex->nCachedBranchId = pindex->pprev->nCachedBranchId;
|
||||
}
|
||||
} else {
|
||||
pindex->nCachedBranchId = NetworkUpgradeInfo[Consensus::BASE_SPROUT].nBranchId;
|
||||
pindex->nCachedBranchId = SPROUT_BRANCH_ID;
|
||||
}
|
||||
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == NULL))
|
||||
setBlockIndexCandidates.insert(pindex);
|
||||
|
|
13
src/main.h
13
src/main.h
|
@ -306,7 +306,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
|
|||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
* @return True if all inputs (scriptSigs) use only standard transaction forms
|
||||
*/
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, uint32_t consensusBranchId);
|
||||
|
||||
/**
|
||||
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
|
||||
|
@ -331,7 +331,8 @@ unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& ma
|
|||
* instead of being performed inline.
|
||||
*/
|
||||
bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsViewCache &view, bool fScriptChecks,
|
||||
unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata, const Consensus::Params& consensusParams,
|
||||
unsigned int flags, bool cacheStore, PrecomputedTransactionData& txdata,
|
||||
const Consensus::Params& consensusParams, uint32_t consensusBranchId,
|
||||
std::vector<CScriptCheck> *pvChecks = NULL);
|
||||
|
||||
/** Check a transaction contextually against a set of consensus rules */
|
||||
|
@ -390,14 +391,15 @@ private:
|
|||
unsigned int nIn;
|
||||
unsigned int nFlags;
|
||||
bool cacheStore;
|
||||
uint32_t consensusBranchId;
|
||||
ScriptError error;
|
||||
PrecomputedTransactionData *txdata;
|
||||
|
||||
public:
|
||||
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
|
||||
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), consensusBranchId(0), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
|
||||
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, uint32_t consensusBranchIdIn, PrecomputedTransactionData* txdataIn) :
|
||||
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
|
||||
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), consensusBranchId(consensusBranchIdIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
|
||||
|
||||
bool operator()();
|
||||
|
||||
|
@ -408,6 +410,7 @@ public:
|
|||
std::swap(nIn, check.nIn);
|
||||
std::swap(nFlags, check.nFlags);
|
||||
std::swap(cacheStore, check.cacheStore);
|
||||
std::swap(consensusBranchId, check.consensusBranchId);
|
||||
std::swap(error, check.error);
|
||||
std::swap(txdata, check.txdata);
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "base58.h"
|
||||
#include "chainparams.h"
|
||||
#include "consensus/consensus.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#ifdef ENABLE_MINING
|
||||
#include "crypto/equihash.h"
|
||||
|
@ -143,6 +144,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||
LOCK2(cs_main, mempool.cs);
|
||||
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||
const int nHeight = pindexPrev->nHeight + 1;
|
||||
uint32_t consensusBranchId = CurrentEpochBranchId(nHeight, chainparams.GetConsensus());
|
||||
pblock->nTime = GetAdjustedTime();
|
||||
const int64_t nMedianTimePast = pindexPrev->GetMedianTimePast();
|
||||
CCoinsViewCache view(pcoinsTip);
|
||||
|
@ -294,7 +296,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
|||
// create only contains transactions that are valid in new blocks.
|
||||
CValidationState state;
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus()))
|
||||
if (!ContextualCheckInputs(tx, state, view, true, MANDATORY_SCRIPT_VERIFY_FLAGS, true, txdata, Params().GetConsensus(), consensusBranchId))
|
||||
continue;
|
||||
|
||||
UpdateCoins(tx, view, nHeight);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "base58.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
|
@ -839,6 +840,9 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
|
|||
|
||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||
|
||||
// Grab the current consensus branch ID
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
|
||||
// Script verification errors
|
||||
UniValue vErrors(UniValue::VARR);
|
||||
|
||||
|
@ -859,17 +863,17 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
|
|||
SignatureData sigdata;
|
||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||
if (!fHashSingle || (i < mergedTx.vout.size()))
|
||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata);
|
||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
||||
|
||||
// ... and merge in other signatures:
|
||||
BOOST_FOREACH(const CMutableTransaction& txv, txVariants) {
|
||||
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i));
|
||||
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
||||
}
|
||||
|
||||
UpdateTransaction(mergedTx, i, sigdata);
|
||||
|
||||
ScriptError serror = SCRIPT_ERR_OK;
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), &serror)) {
|
||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), consensusBranchId, &serror)) {
|
||||
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ bool static CheckMinimalPush(const valtype& data, opcodetype opcode) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* serror)
|
||||
bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, uint32_t consensusBranchId, ScriptError* serror)
|
||||
{
|
||||
static const CScriptNum bnZero(0);
|
||||
static const CScriptNum bnOne(1);
|
||||
|
@ -828,7 +828,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
//serror is set
|
||||
return false;
|
||||
}
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
|
||||
bool fSuccess = checker.CheckSig(vchSig, vchPubKey, script, consensusBranchId);
|
||||
|
||||
popstack(stack);
|
||||
popstack(stack);
|
||||
|
@ -886,7 +886,7 @@ bool EvalScript(vector<vector<unsigned char> >& stack, const CScript& script, un
|
|||
}
|
||||
|
||||
// Check signature
|
||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, sigversion);
|
||||
bool fOk = checker.CheckSig(vchSig, vchPubKey, script, consensusBranchId);
|
||||
|
||||
if (fOk) {
|
||||
isig++;
|
||||
|
@ -1083,14 +1083,25 @@ PrecomputedTransactionData::PrecomputedTransactionData(const CTransaction& txTo)
|
|||
hashOutputs = GetOutputsHash(txTo);
|
||||
}
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache)
|
||||
SigVersion SignatureHashVersion(const CTransaction& txTo)
|
||||
{
|
||||
if (txTo.fOverwintered) {
|
||||
return SIGVERSION_OVERWINTER;
|
||||
} else {
|
||||
return SIGVERSION_SPROUT;
|
||||
}
|
||||
}
|
||||
|
||||
uint256 SignatureHash(const CScript& scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, uint32_t consensusBranchId, const PrecomputedTransactionData* cache)
|
||||
{
|
||||
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
|
||||
// nIn out of range
|
||||
throw logic_error("input index is out of range");
|
||||
}
|
||||
|
||||
if (sigversion == SIGVERSION_WITNESS_V0) {
|
||||
auto sigversion = SignatureHashVersion(txTo);
|
||||
|
||||
if (sigversion == SIGVERSION_OVERWINTER) {
|
||||
uint256 hashPrevouts;
|
||||
uint256 hashSequence;
|
||||
uint256 hashOutputs;
|
||||
|
@ -1159,7 +1170,7 @@ bool TransactionSignatureChecker::VerifySignature(const std::vector<unsigned cha
|
|||
return pubkey.Verify(sighash, vchSig);
|
||||
}
|
||||
|
||||
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn, const vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
CPubKey pubkey(vchPubKey);
|
||||
if (!pubkey.IsValid())
|
||||
|
@ -1174,7 +1185,7 @@ bool TransactionSignatureChecker::CheckSig(const vector<unsigned char>& vchSigIn
|
|||
|
||||
uint256 sighash;
|
||||
try {
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion, this->txdata);
|
||||
sighash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, this->txdata);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
}
|
||||
|
@ -1222,7 +1233,7 @@ bool TransactionSignatureChecker::CheckLockTime(const CScriptNum& nLockTime) con
|
|||
}
|
||||
|
||||
|
||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror)
|
||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, uint32_t consensusBranchId, ScriptError* serror)
|
||||
{
|
||||
set_error(serror, SCRIPT_ERR_UNKNOWN_ERROR);
|
||||
|
||||
|
@ -1231,12 +1242,12 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||
}
|
||||
|
||||
vector<vector<unsigned char> > stack, stackCopy;
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, SIGVERSION_BASE, serror))
|
||||
if (!EvalScript(stack, scriptSig, flags, checker, consensusBranchId, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (flags & SCRIPT_VERIFY_P2SH)
|
||||
stackCopy = stack;
|
||||
if (!EvalScript(stack, scriptPubKey, flags, checker, SIGVERSION_BASE, serror))
|
||||
if (!EvalScript(stack, scriptPubKey, flags, checker, consensusBranchId, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (stack.empty())
|
||||
|
@ -1263,7 +1274,7 @@ bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigne
|
|||
CScript pubKey2(pubKeySerialized.begin(), pubKeySerialized.end());
|
||||
popstack(stack);
|
||||
|
||||
if (!EvalScript(stack, pubKey2, flags, checker, SIGVERSION_BASE, serror))
|
||||
if (!EvalScript(stack, pubKey2, flags, checker, consensusBranchId, serror))
|
||||
// serror is set
|
||||
return false;
|
||||
if (stack.empty())
|
||||
|
|
|
@ -97,16 +97,16 @@ struct PrecomputedTransactionData
|
|||
|
||||
enum SigVersion
|
||||
{
|
||||
SIGVERSION_BASE = 0,
|
||||
SIGVERSION_WITNESS_V0 = 1,
|
||||
SIGVERSION_SPROUT = 0,
|
||||
SIGVERSION_OVERWINTER = 1,
|
||||
};
|
||||
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, SigVersion sigversion, const PrecomputedTransactionData* cache = NULL);
|
||||
uint256 SignatureHash(const CScript &scriptCode, const CTransaction& txTo, unsigned int nIn, int nHashType, const CAmount& amount, uint32_t consensusBranchId, const PrecomputedTransactionData* cache = NULL);
|
||||
|
||||
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, uint32_t consensusBranchId) const
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -133,7 +133,7 @@ protected:
|
|||
public:
|
||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
|
||||
TransactionSignatureChecker(const CTransaction* 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;
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
bool CheckLockTime(const CScriptNum& nLockTime) const;
|
||||
};
|
||||
|
||||
|
@ -146,7 +146,7 @@ public:
|
|||
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
||||
};
|
||||
|
||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, SigVersion sigversion, ScriptError* error = NULL);
|
||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, ScriptError* serror = NULL);
|
||||
bool EvalScript(std::vector<std::vector<unsigned char> >& stack, const CScript& script, unsigned int flags, const BaseSignatureChecker& checker, uint32_t consensusBranchId, ScriptError* error = NULL);
|
||||
bool VerifyScript(const CScript& scriptSig, const CScript& scriptPubKey, unsigned int flags, const BaseSignatureChecker& checker, uint32_t consensusBranchId, ScriptError* serror = NULL);
|
||||
|
||||
#endif // BITCOIN_SCRIPT_INTERPRETER_H
|
||||
|
|
|
@ -19,7 +19,7 @@ typedef vector<unsigned char> valtype;
|
|||
|
||||
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, nIn, amountIn) {}
|
||||
|
||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
CKey key;
|
||||
if (!keystore->GetKey(address, key))
|
||||
|
@ -27,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
|||
|
||||
uint256 hash;
|
||||
try {
|
||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, sigversion);
|
||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId);
|
||||
} catch (logic_error ex) {
|
||||
return false;
|
||||
}
|
||||
|
@ -38,16 +38,16 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
|
||||
static bool Sign1(const CKeyID& address, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
|
||||
{
|
||||
vector<unsigned char> vchSig;
|
||||
if (!creator.CreateSig(vchSig, address, scriptCode, sigversion))
|
||||
if (!creator.CreateSig(vchSig, address, scriptCode, consensusBranchId))
|
||||
return false;
|
||||
ret.push_back(vchSig);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, SigVersion sigversion)
|
||||
static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreator& creator, const CScript& scriptCode, std::vector<valtype>& ret, uint32_t consensusBranchId)
|
||||
{
|
||||
int nSigned = 0;
|
||||
int nRequired = multisigdata.front()[0];
|
||||
|
@ -55,7 +55,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
|
|||
{
|
||||
const valtype& pubkey = multisigdata[i];
|
||||
CKeyID keyID = CPubKey(pubkey).GetID();
|
||||
if (Sign1(keyID, creator, scriptCode, ret, sigversion))
|
||||
if (Sign1(keyID, creator, scriptCode, ret, consensusBranchId))
|
||||
++nSigned;
|
||||
}
|
||||
return nSigned==nRequired;
|
||||
|
@ -68,7 +68,7 @@ static bool SignN(const vector<valtype>& multisigdata, const BaseSignatureCreato
|
|||
* Returns false if scriptPubKey could not be completely satisfied.
|
||||
*/
|
||||
static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptPubKey,
|
||||
std::vector<valtype>& ret, txnouttype& whichTypeRet, SigVersion sigversion)
|
||||
std::vector<valtype>& ret, txnouttype& whichTypeRet, uint32_t consensusBranchId)
|
||||
{
|
||||
CScript scriptRet;
|
||||
uint160 h160;
|
||||
|
@ -86,10 +86,10 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
|||
return false;
|
||||
case TX_PUBKEY:
|
||||
keyID = CPubKey(vSolutions[0]).GetID();
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, sigversion);
|
||||
return Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId);
|
||||
case TX_PUBKEYHASH:
|
||||
keyID = CKeyID(uint160(vSolutions[0]));
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, sigversion))
|
||||
if (!Sign1(keyID, creator, scriptPubKey, ret, consensusBranchId))
|
||||
return false;
|
||||
else
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ static bool SignStep(const BaseSignatureCreator& creator, const CScript& scriptP
|
|||
|
||||
case TX_MULTISIG:
|
||||
ret.push_back(valtype()); // workaround CHECKMULTISIG bug
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, sigversion));
|
||||
return (SignN(vSolutions, creator, scriptPubKey, ret, consensusBranchId));
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
@ -129,13 +129,13 @@ static CScript PushAll(const vector<valtype>& values)
|
|||
return result;
|
||||
}
|
||||
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata)
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPubKey, SignatureData& sigdata, uint32_t consensusBranchId)
|
||||
{
|
||||
CScript script = fromPubKey;
|
||||
bool solved = true;
|
||||
std::vector<valtype> result;
|
||||
txnouttype whichType;
|
||||
solved = SignStep(creator, script, result, whichType, SIGVERSION_BASE);
|
||||
solved = SignStep(creator, script, result, whichType, consensusBranchId);
|
||||
CScript subscript;
|
||||
|
||||
if (solved && whichType == TX_SCRIPTHASH)
|
||||
|
@ -144,14 +144,14 @@ bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& fromPu
|
|||
// the final scriptSig is the signatures from that
|
||||
// and then the serialized subscript:
|
||||
script = subscript = CScript(result[0].begin(), result[0].end());
|
||||
solved = solved && SignStep(creator, script, result, whichType, SIGVERSION_BASE) && whichType != TX_SCRIPTHASH;
|
||||
solved = solved && SignStep(creator, script, result, whichType, consensusBranchId) && whichType != TX_SCRIPTHASH;
|
||||
result.push_back(std::vector<unsigned char>(subscript.begin(), subscript.end()));
|
||||
}
|
||||
|
||||
sigdata.scriptSig = PushAll(result);
|
||||
|
||||
// Test solution
|
||||
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker());
|
||||
return solved && VerifyScript(sigdata.scriptSig, fromPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, creator.Checker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn)
|
||||
|
@ -168,7 +168,7 @@ void UpdateTransaction(CMutableTransaction& tx, unsigned int nIn, const Signatur
|
|||
tx.vin[nIn].scriptSig = data.scriptSig;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType)
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
|
||||
|
@ -176,24 +176,24 @@ bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutabl
|
|||
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
|
||||
|
||||
SignatureData sigdata;
|
||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata);
|
||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
|
||||
UpdateTransaction(txTo, nIn, sigdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType)
|
||||
bool SignSignature(const CKeyStore &keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, uint32_t consensusBranchId)
|
||||
{
|
||||
assert(nIn < txTo.vin.size());
|
||||
CTxIn& txin = txTo.vin[nIn];
|
||||
assert(txin.prevout.n < txFrom.vout.size());
|
||||
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
||||
|
||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType);
|
||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId);
|
||||
}
|
||||
|
||||
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const vector<valtype>& vSolutions,
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, SigVersion sigversion)
|
||||
const vector<valtype>& sigs1, const vector<valtype>& sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
// Combine all the signatures we've got:
|
||||
set<valtype> allsigs;
|
||||
|
@ -221,7 +221,7 @@ static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSi
|
|||
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, consensusBranchId))
|
||||
{
|
||||
sigs[pubkey] = sig;
|
||||
break;
|
||||
|
@ -254,8 +254,8 @@ struct Stacks
|
|||
|
||||
Stacks() {}
|
||||
explicit Stacks(const std::vector<valtype>& scriptSigStack_) : script(scriptSigStack_) {}
|
||||
explicit Stacks(const SignatureData& data) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), SIGVERSION_BASE);
|
||||
explicit Stacks(const SignatureData& data, uint32_t consensusBranchId) {
|
||||
EvalScript(script, data.scriptSig, SCRIPT_VERIFY_STRICTENC, BaseSignatureChecker(), consensusBranchId);
|
||||
}
|
||||
|
||||
SignatureData Output() const {
|
||||
|
@ -268,7 +268,7 @@ struct Stacks
|
|||
|
||||
static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const txnouttype txType, const vector<valtype>& vSolutions,
|
||||
Stacks sigs1, Stacks sigs2, SigVersion sigversion)
|
||||
Stacks sigs1, Stacks sigs2, uint32_t consensusBranchId)
|
||||
{
|
||||
switch (txType)
|
||||
{
|
||||
|
@ -300,25 +300,26 @@ static Stacks CombineSignatures(const CScript& scriptPubKey, const BaseSignature
|
|||
Solver(pubKey2, txType2, vSolutions2);
|
||||
sigs1.script.pop_back();
|
||||
sigs2.script.pop_back();
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, sigversion);
|
||||
Stacks result = CombineSignatures(pubKey2, checker, txType2, vSolutions2, sigs1, sigs2, consensusBranchId);
|
||||
result.script.push_back(spk);
|
||||
return result;
|
||||
}
|
||||
case TX_MULTISIG:
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, sigversion));
|
||||
return Stacks(CombineMultisig(scriptPubKey, checker, vSolutions, sigs1.script, sigs2.script, consensusBranchId));
|
||||
default:
|
||||
return Stacks();
|
||||
}
|
||||
}
|
||||
|
||||
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2)
|
||||
const SignatureData& scriptSig1, const SignatureData& scriptSig2,
|
||||
uint32_t consensusBranchId)
|
||||
{
|
||||
txnouttype txType;
|
||||
vector<vector<unsigned char> > vSolutions;
|
||||
Solver(scriptPubKey, txType, vSolutions);
|
||||
|
||||
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1), Stacks(scriptSig2), SIGVERSION_BASE).Output();
|
||||
return CombineSignatures(scriptPubKey, checker, txType, vSolutions, Stacks(scriptSig1, consensusBranchId), Stacks(scriptSig2, consensusBranchId), consensusBranchId).Output();
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -328,7 +329,7 @@ class DummySignatureChecker : public BaseSignatureChecker
|
|||
public:
|
||||
DummySignatureChecker() {}
|
||||
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool CheckSig(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -341,7 +342,7 @@ const BaseSignatureChecker& DummySignatureCreator::Checker() const
|
|||
return dummyChecker;
|
||||
}
|
||||
|
||||
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const
|
||||
bool DummySignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||
{
|
||||
// Create a dummy signature that is a valid DER-encoding
|
||||
vchSig.assign(72, '\000');
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
virtual const BaseSignatureChecker& Checker() const =0;
|
||||
|
||||
/** Create a singular (non-script) signature. */
|
||||
virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const =0;
|
||||
virtual bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const =0;
|
||||
};
|
||||
|
||||
/** A signature creator for transactions. */
|
||||
|
@ -41,7 +41,7 @@ class TransactionSignatureCreator : public BaseSignatureCreator {
|
|||
public:
|
||||
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
||||
const BaseSignatureChecker& Checker() const { return checker; }
|
||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const;
|
||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
};
|
||||
|
||||
class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
|
||||
|
@ -56,7 +56,7 @@ class DummySignatureCreator : public BaseSignatureCreator {
|
|||
public:
|
||||
DummySignatureCreator(const CKeyStore* keystoreIn) : BaseSignatureCreator(keystoreIn) {}
|
||||
const BaseSignatureChecker& Checker() const;
|
||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, SigVersion sigversion) const;
|
||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||
};
|
||||
|
||||
struct SignatureData {
|
||||
|
@ -67,14 +67,14 @@ struct SignatureData {
|
|||
};
|
||||
|
||||
/** Produce a script signature using a generic signature creator. */
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata);
|
||||
bool ProduceSignature(const BaseSignatureCreator& creator, const CScript& scriptPubKey, SignatureData& sigdata, uint32_t consensusBranchId);
|
||||
|
||||
/** Produce a script signature for a transaction. */
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType);
|
||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType);
|
||||
bool SignSignature(const CKeyStore &keystore, const CScript& fromPubKey, CMutableTransaction& txTo, unsigned int nIn, const CAmount& amount, int nHashType, uint32_t consensusBranchId);
|
||||
bool SignSignature(const CKeyStore& keystore, const CTransaction& txFrom, CMutableTransaction& txTo, unsigned int nIn, int nHashType, uint32_t consensusBranchId);
|
||||
|
||||
/** Combine two script signatures using a generic signature checker, intelligently, possibly with OP_0 placeholders. */
|
||||
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2);
|
||||
SignatureData CombineSignatures(const CScript& scriptPubKey, const BaseSignatureChecker& checker, const SignatureData& scriptSig1, const SignatureData& scriptSig2, uint32_t consensusBranchId);
|
||||
|
||||
/** Extract signature data from a transaction, and insert it. */
|
||||
SignatureData DataFromTransaction(const CMutableTransaction& tx, unsigned int nIn);
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "zcashconsensus.h"
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "primitives/transaction.h"
|
||||
#include "pubkey.h"
|
||||
#include "script/interpreter.h"
|
||||
|
@ -86,7 +87,8 @@ int zcashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int
|
|||
set_error(err, zcashconsensus_ERR_OK);
|
||||
PrecomputedTransactionData txdata(tx);
|
||||
CAmount am(0);
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn, am, txdata), NULL);
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
return VerifyScript(tx.vin[nIn].scriptSig, CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen), flags, TransactionSignatureChecker(&tx, nIn, am, txdata), consensusBranchId, NULL);
|
||||
} catch (const std::exception&) {
|
||||
return set_error(err, zcashconsensus_ERR_TX_DESERIALIZE); // Error deserializing
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "keystore.h"
|
||||
#include "main.h"
|
||||
#include "net.h"
|
||||
|
@ -119,6 +120,8 @@ CTransaction RandomOrphan()
|
|||
|
||||
BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
CKey key;
|
||||
key.MakeNewKey(true);
|
||||
CBasicKeyStore keystore;
|
||||
|
@ -151,7 +154,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|||
tx.vout.resize(1);
|
||||
tx.vout[0].nValue = 1*CENT;
|
||||
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
|
||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL, consensusBranchId);
|
||||
|
||||
AddOrphanTx(tx, i);
|
||||
}
|
||||
|
@ -171,7 +174,7 @@ BOOST_AUTO_TEST_CASE(DoS_mapOrphans)
|
|||
tx.vin[j].prevout.n = j;
|
||||
tx.vin[j].prevout.hash = txPrev.GetHash();
|
||||
}
|
||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL);
|
||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL, consensusBranchId);
|
||||
// Re-use same signature for other inputs
|
||||
// (they don't have to be valid for this test)
|
||||
for (unsigned int j = 1; j < tx.vin.size(); j++)
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
"in=4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485:0",
|
||||
"set=privatekeys:[\"5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf\"]",
|
||||
"set=prevtxs:[{\"txid\":\"4d49a71ec9da436f71ec4ee231d04f292a29cd316f598bb7068feccabdc59485\",\"vout\":0,\"scriptPubKey\":\"76a91491b24bf9f5288532960ac687abb035127b1d28a588ac\"}]",
|
||||
"sign=ALL",
|
||||
"sign=1:ALL",
|
||||
"outaddr=0.001:t1Ruz6gK4QPZoPPGpHaieupnnh62mktjQE7"],
|
||||
"output_cmp": "txcreatesign.hex"
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "key.h"
|
||||
#include "keystore.h"
|
||||
#include "main.h"
|
||||
|
@ -26,9 +27,9 @@ typedef vector<unsigned char> valtype;
|
|||
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
|
||||
|
||||
CScript
|
||||
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn)
|
||||
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn, uint32_t consensusBranchId)
|
||||
{
|
||||
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
CScript result;
|
||||
result << OP_0; // CHECKMULTISIG bug workaround
|
||||
|
@ -44,6 +45,7 @@ sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction,
|
|||
|
||||
BOOST_AUTO_TEST_CASE(multisig_verify)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
unsigned int flags = SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC;
|
||||
|
||||
ScriptError err;
|
||||
|
@ -83,21 +85,21 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
|||
// Test a AND b:
|
||||
keys.assign(1,key[0]);
|
||||
keys.push_back(key[1]);
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err));
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
keys.assign(1,key[i]);
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 1: %d", i));
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err), strprintf("a&b 1: %d", i));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
||||
|
||||
keys.assign(1,key[1]);
|
||||
keys.push_back(key[i]);
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), &err), strprintf("a&b 2: %d", i));
|
||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err), strprintf("a&b 2: %d", i));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
|
@ -105,21 +107,21 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
|||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
keys.assign(1,key[i]);
|
||||
s = sign_multisig(a_or_b, keys, txTo[1], 0);
|
||||
s = sign_multisig(a_or_b, keys, txTo[1], 0, consensusBranchId);
|
||||
if (i == 0 || i == 1)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
}
|
||||
}
|
||||
s.clear();
|
||||
s << OP_0 << OP_1;
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), &err));
|
||||
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
|
||||
|
||||
|
||||
|
@ -128,15 +130,15 @@ BOOST_AUTO_TEST_CASE(multisig_verify)
|
|||
{
|
||||
keys.assign(1,key[i]);
|
||||
keys.push_back(key[j]);
|
||||
s = sign_multisig(escrow, keys, txTo[2], 0);
|
||||
s = sign_multisig(escrow, keys, txTo[2], 0, consensusBranchId);
|
||||
if (i < j && i < 3 && j < 3)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 1: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err), strprintf("escrow 1: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
else
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), &err), strprintf("escrow 2: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err), strprintf("escrow 2: %d %d", i, j));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
}
|
||||
}
|
||||
|
@ -277,6 +279,8 @@ BOOST_AUTO_TEST_CASE(multisig_Solver1)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(multisig_Sign)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Test SignSignature() (and therefore the version of Solver() that signs transactions)
|
||||
CBasicKeyStore keystore;
|
||||
CKey key[4];
|
||||
|
@ -313,7 +317,7 @@ BOOST_AUTO_TEST_CASE(multisig_Sign)
|
|||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "key.h"
|
||||
#include "keystore.h"
|
||||
|
@ -32,6 +33,8 @@ Serialize(const CScript& s)
|
|||
static bool
|
||||
Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, ScriptError& err)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Create dummy to/from transactions:
|
||||
CMutableTransaction txFrom;
|
||||
txFrom.vout.resize(1);
|
||||
|
@ -45,7 +48,7 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri
|
|||
txTo.vin[0].scriptSig = scriptSig;
|
||||
txTo.vout[0].nValue = 1;
|
||||
|
||||
return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), &err);
|
||||
return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), consensusBranchId, &err);
|
||||
}
|
||||
|
||||
|
||||
|
@ -54,6 +57,7 @@ BOOST_FIXTURE_TEST_SUITE(script_P2SH_tests, BasicTestingSetup)
|
|||
BOOST_AUTO_TEST_CASE(sign)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
// Pay-to-script-hash looks like this:
|
||||
// scriptSig: <sig> <sig...> <serialized_script>
|
||||
// scriptPubKey: HASH160 <hash> EQUAL
|
||||
|
@ -107,7 +111,7 @@ BOOST_AUTO_TEST_CASE(sign)
|
|||
}
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||
}
|
||||
// All of the above should be OK, and the txTos have valid signatures
|
||||
// Check to make sure signature verification fails if we use the wrong ScriptSig:
|
||||
|
@ -117,7 +121,7 @@ BOOST_AUTO_TEST_CASE(sign)
|
|||
{
|
||||
CScript sigSave = txTo[i].vin[0].scriptSig;
|
||||
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
|
||||
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
|
||||
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, consensusBranchId, &txdata)();
|
||||
if (i == j)
|
||||
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
|
||||
else
|
||||
|
@ -157,6 +161,7 @@ BOOST_AUTO_TEST_CASE(norecurse)
|
|||
BOOST_AUTO_TEST_CASE(set)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
// Test the CScript::Set* methods
|
||||
CBasicKeyStore keystore;
|
||||
CKey key[4];
|
||||
|
@ -206,7 +211,7 @@ BOOST_AUTO_TEST_CASE(set)
|
|||
}
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL), strprintf("SignSignature %d", i));
|
||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||
BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason), strprintf("txTo[%d].IsStandard", i));
|
||||
}
|
||||
}
|
||||
|
@ -265,6 +270,7 @@ BOOST_AUTO_TEST_CASE(switchover)
|
|||
BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
||||
{
|
||||
LOCK(cs_main);
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
CBasicKeyStore keystore;
|
||||
|
@ -335,16 +341,16 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||
txTo.vin[i].prevout.n = i;
|
||||
txTo.vin[i].prevout.hash = txFrom.GetHash();
|
||||
}
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL));
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL));
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL));
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId));
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL, consensusBranchId));
|
||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL, consensusBranchId));
|
||||
// SignSignature doesn't know how to sign these. We're
|
||||
// not testing validating signatures, so just create
|
||||
// dummy signatures that DO include the correct P2SH scripts:
|
||||
txTo.vin[3].scriptSig << OP_11 << OP_11 << static_cast<vector<unsigned char> >(oneAndTwo);
|
||||
txTo.vin[4].scriptSig << static_cast<vector<unsigned char> >(fifteenSigops);
|
||||
|
||||
BOOST_CHECK(::AreInputsStandard(txTo, coins));
|
||||
BOOST_CHECK(::AreInputsStandard(txTo, coins, consensusBranchId));
|
||||
// 22 P2SH sigops for all inputs (1 for vin[0], 6 for vin[3], 15 for vin[4]
|
||||
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txTo, coins), 22U);
|
||||
|
||||
|
@ -353,7 +359,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||
{
|
||||
CScript t = txTo.vin[i].scriptSig;
|
||||
txTo.vin[i].scriptSig = (CScript() << 11) + t;
|
||||
BOOST_CHECK(!::AreInputsStandard(txTo, coins));
|
||||
BOOST_CHECK(!::AreInputsStandard(txTo, coins, consensusBranchId));
|
||||
txTo.vin[i].scriptSig = t;
|
||||
}
|
||||
|
||||
|
@ -366,7 +372,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||
txToNonStd1.vin[0].prevout.hash = txFrom.GetHash();
|
||||
txToNonStd1.vin[0].scriptSig << static_cast<vector<unsigned char> >(sixteenSigops);
|
||||
|
||||
BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins));
|
||||
BOOST_CHECK(!::AreInputsStandard(txToNonStd1, coins, consensusBranchId));
|
||||
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd1, coins), 16U);
|
||||
|
||||
CMutableTransaction txToNonStd2;
|
||||
|
@ -378,7 +384,7 @@ BOOST_AUTO_TEST_CASE(AreInputsStandard)
|
|||
txToNonStd2.vin[0].prevout.hash = txFrom.GetHash();
|
||||
txToNonStd2.vin[0].scriptSig << static_cast<vector<unsigned char> >(twentySigops);
|
||||
|
||||
BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins));
|
||||
BOOST_CHECK(!::AreInputsStandard(txToNonStd2, coins, consensusBranchId));
|
||||
BOOST_CHECK_EQUAL(GetP2SHSigOpCount(txToNonStd2, coins), 20U);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "data/script_invalid.json.h"
|
||||
#include "data/script_valid.json.h"
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "key.h"
|
||||
#include "keystore.h"
|
||||
|
@ -87,13 +88,13 @@ CMutableTransaction BuildSpendingTransaction(const CScript& scriptSig, const CMu
|
|||
return txSpend;
|
||||
}
|
||||
|
||||
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, bool expect, const std::string& message)
|
||||
void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, uint32_t consensusBranchId, bool expect, const std::string& message)
|
||||
{
|
||||
ScriptError err;
|
||||
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
|
||||
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit);
|
||||
CMutableTransaction tx2 = tx;
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), &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);
|
||||
#if defined(HAVE_CONSENSUS_LIB)
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -188,6 +189,7 @@ private:
|
|||
std::vector<unsigned char> push;
|
||||
std::string comment;
|
||||
int flags;
|
||||
uint32_t consensusBranchId;
|
||||
|
||||
void DoPush()
|
||||
{
|
||||
|
@ -205,7 +207,7 @@ private:
|
|||
}
|
||||
|
||||
public:
|
||||
TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_)
|
||||
TestBuilder(const CScript& redeemScript, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(redeemScript), havePush(false), comment(comment_), flags(flags_), consensusBranchId(0)
|
||||
{
|
||||
if (P2SH) {
|
||||
creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(redeemScript)) << OP_EQUAL);
|
||||
|
@ -237,7 +239,7 @@ public:
|
|||
|
||||
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
|
||||
{
|
||||
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, SIGVERSION_BASE);
|
||||
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, consensusBranchId);
|
||||
std::vector<unsigned char> vchSig, r, s;
|
||||
uint32_t iter = 0;
|
||||
do {
|
||||
|
@ -289,7 +291,7 @@ public:
|
|||
{
|
||||
TestBuilder copy = *this; // Make a copy so we can rollback the push.
|
||||
DoPush();
|
||||
DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, expect, comment);
|
||||
DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, consensusBranchId, expect, comment);
|
||||
*this = copy;
|
||||
return *this;
|
||||
}
|
||||
|
@ -577,6 +579,7 @@ BOOST_AUTO_TEST_CASE(script_build)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(script_valid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
// Read tests from test/data/script_valid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are [ "scriptSig", "scriptPubKey", "flags" ]
|
||||
|
@ -600,12 +603,13 @@ BOOST_AUTO_TEST_CASE(script_valid)
|
|||
CScript scriptPubKey = ParseScript(scriptPubKeyString);
|
||||
unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
|
||||
|
||||
DoTest(scriptPubKey, scriptSig, scriptflags, true, strTest);
|
||||
DoTest(scriptPubKey, scriptSig, scriptflags, consensusBranchId, true, strTest);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_invalid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
// Scripts that should evaluate as invalid
|
||||
UniValue tests = read_json(std::string(json_tests::script_invalid, json_tests::script_invalid + sizeof(json_tests::script_invalid)));
|
||||
|
||||
|
@ -625,12 +629,14 @@ BOOST_AUTO_TEST_CASE(script_invalid)
|
|||
CScript scriptPubKey = ParseScript(scriptPubKeyString);
|
||||
unsigned int scriptflags = ParseScriptFlags(test[2].get_str());
|
||||
|
||||
DoTest(scriptPubKey, scriptSig, scriptflags, false, strTest);
|
||||
DoTest(scriptPubKey, scriptSig, scriptflags, consensusBranchId, false, strTest);
|
||||
}
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_PushData)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Check that PUSHDATA1, PUSHDATA2, and PUSHDATA4 create the same value on
|
||||
// the stack as the 1-75 opcodes do.
|
||||
static const unsigned char direct[] = { 1, 0x5a };
|
||||
|
@ -640,29 +646,29 @@ BOOST_AUTO_TEST_CASE(script_PushData)
|
|||
|
||||
ScriptError err;
|
||||
vector<vector<unsigned char> > directStack;
|
||||
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||
BOOST_CHECK(EvalScript(directStack, CScript(&direct[0], &direct[sizeof(direct)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
vector<vector<unsigned char> > pushdata1Stack;
|
||||
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||
BOOST_CHECK(EvalScript(pushdata1Stack, CScript(&pushdata1[0], &pushdata1[sizeof(pushdata1)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), consensusBranchId, &err));
|
||||
BOOST_CHECK(pushdata1Stack == directStack);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
vector<vector<unsigned char> > pushdata2Stack;
|
||||
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||
BOOST_CHECK(EvalScript(pushdata2Stack, CScript(&pushdata2[0], &pushdata2[sizeof(pushdata2)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), consensusBranchId, &err));
|
||||
BOOST_CHECK(pushdata2Stack == directStack);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
vector<vector<unsigned char> > pushdata4Stack;
|
||||
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), SIGVERSION_BASE, &err));
|
||||
BOOST_CHECK(EvalScript(pushdata4Stack, CScript(&pushdata4[0], &pushdata4[sizeof(pushdata4)]), SCRIPT_VERIFY_P2SH, BaseSignatureChecker(), consensusBranchId, &err));
|
||||
BOOST_CHECK(pushdata4Stack == directStack);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
CScript
|
||||
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction)
|
||||
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, uint32_t consensusBranchId)
|
||||
{
|
||||
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
CScript result;
|
||||
//
|
||||
|
@ -684,15 +690,17 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
|
|||
return result;
|
||||
}
|
||||
CScript
|
||||
sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction)
|
||||
sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction, uint32_t consensusBranchId)
|
||||
{
|
||||
std::vector<CKey> keys;
|
||||
keys.push_back(key);
|
||||
return sign_multisig(scriptPubKey, keys, transaction);
|
||||
return sign_multisig(scriptPubKey, keys, transaction, consensusBranchId);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
ScriptError err;
|
||||
CKey key1, key2, key3;
|
||||
key1.MakeNewKey(true);
|
||||
|
@ -705,24 +713,26 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG12)
|
|||
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
|
||||
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
|
||||
|
||||
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12);
|
||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
|
||||
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
txTo12.vout[0].nValue = 2;
|
||||
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
|
||||
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12);
|
||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
|
||||
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12);
|
||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), &err));
|
||||
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
ScriptError err;
|
||||
CKey key1, key2, key3, key4;
|
||||
key1.MakeNewKey(true);
|
||||
|
@ -738,60 +748,62 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
|
|||
|
||||
std::vector<CKey> keys;
|
||||
keys.push_back(key1); keys.push_back(key2);
|
||||
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key1); keys.push_back(key3);
|
||||
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key2); keys.push_back(key3);
|
||||
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
|
||||
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
|
||||
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
|
||||
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
|
||||
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
keys.clear();
|
||||
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
|
||||
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||
|
||||
keys.clear(); // Must have signatures
|
||||
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23);
|
||||
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), &err));
|
||||
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
||||
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_combineSigs)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Test the CombineSignatures function
|
||||
CAmount amount = 0;
|
||||
CBasicKeyStore keystore;
|
||||
|
@ -812,61 +824,61 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||
CScript& scriptSig = txTo.vin[0].scriptSig;
|
||||
|
||||
SignatureData empty;
|
||||
SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty);
|
||||
SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty, consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig.empty());
|
||||
|
||||
// Single signature case:
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL); // changes scriptSig
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId); // changes scriptSig
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
CScript scriptSigCopy = scriptSig;
|
||||
// Signing again will give a different, valid signature:
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
||||
|
||||
// P2SH, single-signature case:
|
||||
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
|
||||
keystore.AddCScript(pkSingle);
|
||||
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
scriptSigCopy = scriptSig;
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
||||
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
|
||||
scriptSigCopy = CScript() << OP_0 << static_cast<vector<unsigned char> >(pkSingle);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
|
||||
// Hardest case: Multisig 2-of-3
|
||||
scriptPubKey = GetScriptForMultisig(2, pubkeys);
|
||||
keystore.AddCScript(scriptPubKey);
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty);
|
||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||
|
||||
// A couple of partially-signed versions:
|
||||
vector<unsigned char> sig1;
|
||||
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, consensusBranchId);
|
||||
BOOST_CHECK(keys[0].Sign(hash1, sig1));
|
||||
sig1.push_back(SIGHASH_ALL);
|
||||
vector<unsigned char> sig2;
|
||||
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, SIGVERSION_BASE);
|
||||
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, consensusBranchId);
|
||||
BOOST_CHECK(keys[1].Sign(hash2, sig2));
|
||||
sig2.push_back(SIGHASH_NONE);
|
||||
vector<unsigned char> sig3;
|
||||
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, SIGVERSION_BASE);
|
||||
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, consensusBranchId);
|
||||
BOOST_CHECK(keys[2].Sign(hash3, sig3));
|
||||
sig3.push_back(SIGHASH_SINGLE);
|
||||
|
||||
|
@ -882,32 +894,34 @@ BOOST_AUTO_TEST_CASE(script_combineSigs)
|
|||
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
|
||||
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
|
||||
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == partial1a);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete12);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete12);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete12);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete13);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete23);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == complete23);
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a));
|
||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a), consensusBranchId);
|
||||
BOOST_CHECK(combined.scriptSig == partial3c);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(script_standard_push)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
ScriptError err;
|
||||
for (int i=0; i<67000; i++) {
|
||||
CScript script;
|
||||
script << i;
|
||||
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Number " << i << " is not pure push.");
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Number " << i << " push is not minimal data.");
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), consensusBranchId, &err), "Number " << i << " push is not minimal data.");
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
|
||||
|
@ -916,7 +930,7 @@ BOOST_AUTO_TEST_CASE(script_standard_push)
|
|||
CScript script;
|
||||
script << data;
|
||||
BOOST_CHECK_MESSAGE(script.IsPushOnly(), "Length " << i << " is not pure push.");
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), &err), "Length " << i << " push is not minimal data.");
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(script, CScript() << OP_1, SCRIPT_VERIFY_MINIMALDATA, BaseSignatureChecker(), consensusBranchId, &err), "Length " << i << " push is not minimal data.");
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -93,7 +93,7 @@ void static RandomScript(CScript &script) {
|
|||
script << oplist[insecure_rand() % (sizeof(oplist)/sizeof(oplist[0]))];
|
||||
}
|
||||
|
||||
void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
|
||||
void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t consensusBranchId) {
|
||||
tx.fOverwintered = insecure_rand() % 2;
|
||||
if (tx.fOverwintered) {
|
||||
// Versions outside known ranges throw an exception during parsing
|
||||
|
@ -160,7 +160,7 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle) {
|
|||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(tx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
assert(crypto_sign_detached(&tx.joinSplitSig[0], NULL,
|
||||
dataToBeSigned.begin(), 32,
|
||||
|
@ -173,11 +173,12 @@ BOOST_FIXTURE_TEST_SUITE(sighash_tests, JoinSplitTestingSetup)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(sighash_test)
|
||||
{
|
||||
uint32_t overwinterBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
|
||||
seed_insecure_rand(false);
|
||||
|
||||
#if defined(PRINT_SIGHASH_JSON)
|
||||
std::cout << "[\n";
|
||||
std::cout << "\t[\"raw_transaction, script, input_index, hashType, signature_hash (result)\"],\n";
|
||||
std::cout << "\t[\"raw_transaction, script, input_index, hashType, branchId, signature_hash (result)\"],\n";
|
||||
#endif
|
||||
int nRandomTests = 50000;
|
||||
|
||||
|
@ -186,15 +187,16 @@ BOOST_AUTO_TEST_CASE(sighash_test)
|
|||
#endif
|
||||
for (int i=0; i<nRandomTests; i++) {
|
||||
int nHashType = insecure_rand();
|
||||
uint32_t consensusBranchId = insecure_rand() % 2 ? SPROUT_BRANCH_ID : overwinterBranchId;
|
||||
CMutableTransaction txTo;
|
||||
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE);
|
||||
RandomTransaction(txTo, (nHashType & 0x1f) == SIGHASH_SINGLE, consensusBranchId);
|
||||
CScript scriptCode;
|
||||
RandomScript(scriptCode);
|
||||
int nIn = insecure_rand() % txTo.vin.size();
|
||||
|
||||
uint256 sh, sho;
|
||||
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
||||
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, SIGVERSION_BASE);
|
||||
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, consensusBranchId);
|
||||
#if defined(PRINT_SIGHASH_JSON)
|
||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||
ss << txTo;
|
||||
|
@ -203,7 +205,8 @@ BOOST_AUTO_TEST_CASE(sighash_test)
|
|||
std::cout << HexStr(ss.begin(), ss.end()) << "\", \"";
|
||||
std::cout << HexStr(scriptCode) << "\", ";
|
||||
std::cout << nIn << ", ";
|
||||
std::cout << nHashType << ", \"";
|
||||
std::cout << nHashType << ", ";
|
||||
std::cout << consensusBranchId << ", \"";
|
||||
std::cout << (txTo.fOverwintered ? sh.GetHex() : sho.GetHex()) << "\"]";
|
||||
if (i+1 != nRandomTests) {
|
||||
std::cout << ",";
|
||||
|
@ -236,6 +239,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|||
|
||||
std::string raw_tx, raw_script, sigHashHex;
|
||||
int nIn, nHashType;
|
||||
uint32_t consensusBranchId;
|
||||
uint256 sh;
|
||||
CTransaction tx;
|
||||
CScript scriptCode = CScript();
|
||||
|
@ -246,7 +250,8 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|||
raw_script = test[1].get_str();
|
||||
nIn = test[2].get_int();
|
||||
nHashType = test[3].get_int();
|
||||
sigHashHex = test[4].get_str();
|
||||
consensusBranchId = test[4].get_int();
|
||||
sigHashHex = test[5].get_str();
|
||||
|
||||
uint256 sh;
|
||||
CDataStream stream(ParseHex(raw_tx), SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
@ -278,7 +283,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
|||
continue;
|
||||
}
|
||||
|
||||
sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, SIGVERSION_BASE);
|
||||
sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, consensusBranchId);
|
||||
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "init.h"
|
||||
#include "clientversion.h"
|
||||
#include "checkqueue.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "core_io.h"
|
||||
#include "key.h"
|
||||
|
@ -92,6 +93,8 @@ BOOST_FIXTURE_TEST_SUITE(transaction_tests, JoinSplitTestingSetup)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Read tests from test/data/tx_valid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
|
@ -161,7 +164,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
|||
CAmount amount = 0;
|
||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err),
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err),
|
||||
strTest + comment);
|
||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||
}
|
||||
|
@ -178,6 +181,8 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
// Read tests from test/data/tx_invalid.json
|
||||
// Format is an array of arrays
|
||||
// Inner arrays are either [ "comment" ]
|
||||
|
@ -246,7 +251,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
|||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||
CAmount amount = 0;
|
||||
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), &err);
|
||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err);
|
||||
}
|
||||
BOOST_CHECK_MESSAGE(!fValid, strTest + comment);
|
||||
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||
|
@ -395,6 +400,7 @@ BOOST_AUTO_TEST_CASE(test_basic_joinsplit_verification)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
auto verifier = libzcash::ProofVerifier::Strict();
|
||||
CMutableTransaction tx;
|
||||
tx.nVersion = 2;
|
||||
|
@ -422,13 +428,14 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
|||
jsdesc->nullifiers[0] = GetRandHash();
|
||||
jsdesc->nullifiers[1] = GetRandHash();
|
||||
|
||||
BOOST_CHECK(!CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(!ContextualCheckTransaction(newTx, state, 0, 100));
|
||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
|
||||
|
||||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(newTx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
assert(crypto_sign_detached(&newTx.joinSplitSig[0], NULL,
|
||||
dataToBeSigned.begin(), 32,
|
||||
|
@ -436,6 +443,7 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
|||
) == 0);
|
||||
|
||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||
BOOST_CHECK(ContextualCheckTransaction(newTx, state, 0, 100));
|
||||
}
|
||||
{
|
||||
// Ensure that values within the joinsplit are well-formed.
|
||||
|
@ -525,6 +533,8 @@ BOOST_AUTO_TEST_CASE(test_simple_joinsplit_invalidity)
|
|||
|
||||
BOOST_AUTO_TEST_CASE(test_Get)
|
||||
{
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
|
||||
CBasicKeyStore keystore;
|
||||
CCoinsView coinsDummy;
|
||||
CCoinsViewCache coins(&coinsDummy);
|
||||
|
@ -545,19 +555,20 @@ BOOST_AUTO_TEST_CASE(test_Get)
|
|||
t1.vout[0].nValue = 90*CENT;
|
||||
t1.vout[0].scriptPubKey << OP_1;
|
||||
|
||||
BOOST_CHECK(AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK(AreInputsStandard(t1, coins, consensusBranchId));
|
||||
BOOST_CHECK_EQUAL(coins.GetValueIn(t1), (50+21+22)*CENT);
|
||||
|
||||
// Adding extra junk to the scriptSig should make it non-standard:
|
||||
t1.vin[0].scriptSig << OP_11;
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins, consensusBranchId));
|
||||
|
||||
// ... as should not having enough:
|
||||
t1.vin[0].scriptSig = CScript();
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins));
|
||||
BOOST_CHECK(!AreInputsStandard(t1, coins, consensusBranchId));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
||||
uint32_t consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
|
||||
CMutableTransaction mtx;
|
||||
mtx.fOverwintered = true;
|
||||
mtx.nVersion = 3;
|
||||
|
@ -596,7 +607,7 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
|||
|
||||
// sign all inputs
|
||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()));
|
||||
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()), consensusBranchId);
|
||||
assert(hashSigned);
|
||||
}
|
||||
|
||||
|
@ -626,7 +637,7 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
|||
|
||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||
std::vector<CScriptCheck> vChecks;
|
||||
CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH, false, &txdata);
|
||||
CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH, false, consensusBranchId, &txdata);
|
||||
vChecks.push_back(CScriptCheck());
|
||||
check.swap(vChecks.back());
|
||||
control.Add(vChecks);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#include "utiltest.h"
|
||||
|
||||
#include "consensus/upgrades.h"
|
||||
|
||||
CWalletTx GetValidReceive(ZCJoinSplit& params,
|
||||
const libzcash::SpendingKey& sk, CAmount value,
|
||||
bool randomInputs) {
|
||||
|
@ -45,11 +47,10 @@ CWalletTx GetValidReceive(ZCJoinSplit& params,
|
|||
mtx.vjoinsplit.push_back(jsdesc);
|
||||
|
||||
// Empty output script.
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
//fifth parameter amount will not be used for joinsplit signing, value arbitrary, also arbitrary decision what to use for sigverion
|
||||
//This is just to get this merge commit to compile later will remove sigversion parameter as choosing sigversion by block height
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL,0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
|
@ -131,9 +132,10 @@ CWalletTx GetValidSpend(ZCJoinSplit& params,
|
|||
mtx.vjoinsplit.push_back(jsdesc);
|
||||
|
||||
// Empty output script.
|
||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL,0,SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "asyncrpcoperation_sendmany.h"
|
||||
#include "asyncrpcqueue.h"
|
||||
#include "amount.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
|
@ -337,6 +338,12 @@ bool AsyncRPCOperation_sendmany::main_impl() {
|
|||
LogPrint("zrpcunsafe", "%s: private output: %s\n", getId(), FormatMoney(z_outputs_total));
|
||||
LogPrint("zrpc", "%s: fee: %s\n", getId(), FormatMoney(minersFee));
|
||||
|
||||
// Grab the current consensus branch ID
|
||||
{
|
||||
LOCK(cs_main);
|
||||
consensusBranchId_ = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
}
|
||||
|
||||
/**
|
||||
* SCENARIO #1
|
||||
*
|
||||
|
@ -994,7 +1001,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(
|
|||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
||||
|
||||
// Add the signature
|
||||
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
|
|
|
@ -73,6 +73,7 @@ private:
|
|||
|
||||
UniValue contextinfo_; // optional data to include in return value from getStatus()
|
||||
|
||||
uint32_t consensusBranchId_;
|
||||
CAmount fee_;
|
||||
int mindepth_;
|
||||
std::string fromaddress_;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "asyncrpcqueue.h"
|
||||
#include "amount.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
|
@ -302,12 +303,15 @@ void AsyncRPCOperation_shieldcoinbase::sign_send_raw_transaction(UniValue obj)
|
|||
|
||||
|
||||
UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInfo & info) {
|
||||
uint32_t consensusBranchId;
|
||||
uint256 anchor;
|
||||
{
|
||||
LOCK(cs_main);
|
||||
consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
anchor = pcoinsTip->GetBestAnchor();
|
||||
}
|
||||
|
||||
|
||||
if (anchor.IsNull()) {
|
||||
throw std::runtime_error("anchor is null");
|
||||
}
|
||||
|
@ -369,7 +373,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
|||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
if (!(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
#include "amount.h"
|
||||
#include "base58.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "core_io.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
|
@ -2840,7 +2841,8 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
|||
// Empty output script.
|
||||
CScript scriptCode;
|
||||
CTransaction signTx(mtx);
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, SIGVERSION_BASE);
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
||||
|
||||
// Add the signature
|
||||
assert(crypto_sign_detached(&mtx.joinSplitSig[0], NULL,
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "base58.h"
|
||||
#include "checkpoints.h"
|
||||
#include "coincontrol.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "init.h"
|
||||
#include "main.h"
|
||||
|
@ -2768,6 +2769,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
}
|
||||
}
|
||||
|
||||
// Grab the current consensus branch ID
|
||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||
|
||||
// Sign
|
||||
int nIn = 0;
|
||||
CTransaction txNewConst(txNew);
|
||||
|
@ -2777,9 +2781,9 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
|||
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
|
||||
SignatureData sigdata;
|
||||
if (sign)
|
||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata);
|
||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
|
||||
else
|
||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata);
|
||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
|
||||
|
||||
if (!signSuccess)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "crypto/equihash.h"
|
||||
#include "chain.h"
|
||||
#include "chainparams.h"
|
||||
#include "consensus/upgrades.h"
|
||||
#include "consensus/validation.h"
|
||||
#include "main.h"
|
||||
#include "miner.h"
|
||||
|
@ -251,8 +252,9 @@ double benchmark_large_tx()
|
|||
}
|
||||
|
||||
// Sign for all the inputs
|
||||
auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_OVERWINTER].nBranchId;
|
||||
for (size_t i = 0; i < NUM_INPUTS; i++) {
|
||||
SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL);
|
||||
SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
|
||||
}
|
||||
|
||||
// Serialize:
|
||||
|
@ -278,6 +280,7 @@ double benchmark_large_tx()
|
|||
prevPubKey,
|
||||
STANDARD_SCRIPT_VERIFY_FLAGS,
|
||||
TransactionSignatureChecker(&final_spending_tx, i, 1000000),
|
||||
consensusBranchId,
|
||||
&serror));
|
||||
}
|
||||
return timer_stop(tv_start);
|
||||
|
|
Loading…
Reference in New Issue