Make `PrecomputedTransactionData` a required argument of `SignatureHash`
The ZIP 244 changes mean that we're going to need to alter every callsite to pass through all of the transparent `CTxOut`s being spent. Given that we need to pass it over to Rust, it makes more sense to just have `PrecomputedTransactionData` be the vehicle for conveying this data across.
This commit is contained in:
parent
3acf7941d6
commit
80f478e67e
|
@ -48,9 +48,11 @@ static void ECDSA(benchmark::State& state)
|
||||||
mtx.vout[i].scriptPubKey = CScript() << OP_1;
|
mtx.vout[i].scriptPubKey = CScript() << OP_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PrecomputedTransactionData txdata(mtx);
|
||||||
|
|
||||||
// sign all inputs
|
// sign all inputs
|
||||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||||
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, SIGHASH_ALL, consensusBranchId);
|
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, txdata, i, 1000, SIGHASH_ALL, consensusBranchId);
|
||||||
assert(hashSigned);
|
assert(hashSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ static void ECDSA(benchmark::State& state)
|
||||||
tx.vin[0].scriptSig,
|
tx.vin[0].scriptSig,
|
||||||
scriptPubKey,
|
scriptPubKey,
|
||||||
SCRIPT_VERIFY_P2SH,
|
SCRIPT_VERIFY_P2SH,
|
||||||
TransactionSignatureChecker(&tx, 0, 1000),
|
TransactionSignatureChecker(&tx, txdata, 0, 1000),
|
||||||
consensusBranchId,
|
consensusBranchId,
|
||||||
&error);
|
&error);
|
||||||
}
|
}
|
||||||
|
|
|
@ -468,6 +468,7 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput)
|
||||||
}
|
}
|
||||||
|
|
||||||
const CKeyStore& keystore = tempKeystore;
|
const CKeyStore& keystore = tempKeystore;
|
||||||
|
const PrecomputedTransactionData txdata(mergedTx);
|
||||||
|
|
||||||
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
bool fHashSingle = ((nHashType & ~SIGHASH_ANYONECANPAY) == SIGHASH_SINGLE);
|
||||||
|
|
||||||
|
@ -488,14 +489,14 @@ static void MutateTxSign(CMutableTransaction& tx, const std::string& strInput)
|
||||||
SignatureData sigdata;
|
SignatureData sigdata;
|
||||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||||
if (!fHashSingle || (i < mergedTx.vout.size()))
|
if (!fHashSingle || (i < mergedTx.vout.size()))
|
||||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, txdata, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
||||||
|
|
||||||
// ... and merge in other signatures:
|
// ... and merge in other signatures:
|
||||||
for (const CTransaction& txv : txVariants)
|
for (const CTransaction& txv : txVariants)
|
||||||
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
sigdata = CombineSignatures(prevPubKey, MutableTransactionSignatureChecker(&mergedTx, txdata, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
||||||
UpdateTransaction(mergedTx, i, sigdata);
|
UpdateTransaction(mergedTx, i, sigdata);
|
||||||
|
|
||||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, i, amount), consensusBranchId))
|
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, MutableTransactionSignatureChecker(&mergedTx, txdata, i, amount), consensusBranchId))
|
||||||
fComplete = false;
|
fComplete = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -113,7 +113,8 @@ void CreateJoinSplitSignature(CMutableTransaction& mtx, uint32_t consensusBranch
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
const PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
if (dataToBeSigned == one) {
|
if (dataToBeSigned == one) {
|
||||||
throw std::runtime_error("SignatureHash failed");
|
throw std::runtime_error("SignatureHash failed");
|
||||||
}
|
}
|
||||||
|
@ -534,20 +535,21 @@ TEST(ContextualCheckShieldedInputsTest, BadTxnsInvalidJoinsplitSignature) {
|
||||||
CMutableTransaction mtx = GetValidTransaction();
|
CMutableTransaction mtx = GetValidTransaction();
|
||||||
mtx.joinSplitSig.bytes[0] += 1;
|
mtx.joinSplitSig.bytes[0] += 1;
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
|
||||||
MockCValidationState state;
|
MockCValidationState state;
|
||||||
// during initial block download, for transactions being accepted into the
|
// during initial block download, for transactions being accepted into the
|
||||||
// mempool (and thus not mined), DoS ban score should be zero, else 10
|
// mempool (and thus not mined), DoS ban score should be zero, else 10
|
||||||
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, 0, false, false, [](const Consensus::Params&) { return true; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, 0, false, false, [](const Consensus::Params&) { return true; });
|
||||||
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, 0, false, false, [](const Consensus::Params&) { return false; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, 0, false, false, [](const Consensus::Params&) { return false; });
|
||||||
// for transactions that have been mined in a block, DoS ban score should
|
// for transactions that have been mined in a block, DoS ban score should
|
||||||
// always be 100.
|
// always be 100.
|
||||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, 0, false, true, [](const Consensus::Params&) { return true; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, 0, false, true, [](const Consensus::Params&) { return true; });
|
||||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, 0, false, true, [](const Consensus::Params&) { return false; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, 0, false, true, [](const Consensus::Params&) { return false; });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ContextualCheckShieldedInputsTest, JoinsplitSignatureDetectsOldBranchId) {
|
TEST(ContextualCheckShieldedInputsTest, JoinsplitSignatureDetectsOldBranchId) {
|
||||||
|
@ -562,11 +564,12 @@ TEST(ContextualCheckShieldedInputsTest, JoinsplitSignatureDetectsOldBranchId) {
|
||||||
// Create a valid transaction for the Sapling epoch.
|
// Create a valid transaction for the Sapling epoch.
|
||||||
CMutableTransaction mtx = GetValidTransaction(saplingBranchId);
|
CMutableTransaction mtx = GetValidTransaction(saplingBranchId);
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
|
||||||
MockCValidationState state;
|
MockCValidationState state;
|
||||||
// Ensure that the transaction validates against Sapling.
|
// Ensure that the transaction validates against Sapling.
|
||||||
EXPECT_TRUE(ContextualCheckShieldedInputs(
|
EXPECT_TRUE(ContextualCheckShieldedInputs(
|
||||||
tx, state, orchardAuth, consensus, saplingBranchId, false, false,
|
tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, false,
|
||||||
[](const Consensus::Params&) { return false; }));
|
[](const Consensus::Params&) { return false; }));
|
||||||
|
|
||||||
// Attempt to validate the inputs against Blossom. We should be notified
|
// Attempt to validate the inputs against Blossom. We should be notified
|
||||||
|
@ -578,7 +581,7 @@ TEST(ContextualCheckShieldedInputsTest, JoinsplitSignatureDetectsOldBranchId) {
|
||||||
HexInt(saplingBranchId)),
|
HexInt(saplingBranchId)),
|
||||||
false, "")).Times(1);
|
false, "")).Times(1);
|
||||||
EXPECT_FALSE(ContextualCheckShieldedInputs(
|
EXPECT_FALSE(ContextualCheckShieldedInputs(
|
||||||
tx, state, orchardAuth, consensus, blossomBranchId, false, false,
|
tx, txdata, state, orchardAuth, consensus, blossomBranchId, false, false,
|
||||||
[](const Consensus::Params&) { return false; }));
|
[](const Consensus::Params&) { return false; }));
|
||||||
|
|
||||||
// Attempt to validate the inputs against Heartwood. All we should learn is
|
// Attempt to validate the inputs against Heartwood. All we should learn is
|
||||||
|
@ -588,7 +591,7 @@ TEST(ContextualCheckShieldedInputsTest, JoinsplitSignatureDetectsOldBranchId) {
|
||||||
10, false, REJECT_INVALID,
|
10, false, REJECT_INVALID,
|
||||||
"bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
"bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
EXPECT_FALSE(ContextualCheckShieldedInputs(
|
EXPECT_FALSE(ContextualCheckShieldedInputs(
|
||||||
tx, state, orchardAuth, consensus, heartwoodBranchId, false, false,
|
tx, txdata, state, orchardAuth, consensus, heartwoodBranchId, false, false,
|
||||||
[](const Consensus::Params&) { return false; }));
|
[](const Consensus::Params&) { return false; }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -603,8 +606,9 @@ TEST(ContextualCheckShieldedInputsTest, NonCanonicalEd25519Signature) {
|
||||||
// Check that the signature is valid before we add L
|
// Check that the signature is valid before we add L
|
||||||
{
|
{
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
MockCValidationState state;
|
MockCValidationState state;
|
||||||
EXPECT_TRUE(ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, saplingBranchId, false, true));
|
EXPECT_TRUE(ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copied from libsodium/crypto_sign/ed25519/ref10/open.c
|
// Copied from libsodium/crypto_sign/ed25519/ref10/open.c
|
||||||
|
@ -622,20 +626,21 @@ TEST(ContextualCheckShieldedInputsTest, NonCanonicalEd25519Signature) {
|
||||||
}
|
}
|
||||||
|
|
||||||
CTransaction tx(mtx);
|
CTransaction tx(mtx);
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
|
||||||
MockCValidationState state;
|
MockCValidationState state;
|
||||||
// during initial block download, for transactions being accepted into the
|
// during initial block download, for transactions being accepted into the
|
||||||
// mempool (and thus not mined), DoS ban score should be zero, else 10
|
// mempool (and thus not mined), DoS ban score should be zero, else 10
|
||||||
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(0, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, saplingBranchId, false, false, [](const Consensus::Params&) { return true; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, false, [](const Consensus::Params&) { return true; });
|
||||||
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(10, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, saplingBranchId, false, false, [](const Consensus::Params&) { return false; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, false, [](const Consensus::Params&) { return false; });
|
||||||
// for transactions that have been mined in a block, DoS ban score should
|
// for transactions that have been mined in a block, DoS ban score should
|
||||||
// always be 100.
|
// always be 100.
|
||||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, saplingBranchId, false, true, [](const Consensus::Params&) { return true; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, true, [](const Consensus::Params&) { return true; });
|
||||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-invalid-joinsplit-signature", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(tx, state, orchardAuth, consensus, saplingBranchId, false, true, [](const Consensus::Params&) { return false; });
|
ContextualCheckShieldedInputs(tx, txdata, state, orchardAuth, consensus, saplingBranchId, false, true, [](const Consensus::Params&) { return false; });
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ChecktransactionTests, OverwinterConstructors) {
|
TEST(ChecktransactionTests, OverwinterConstructors) {
|
||||||
|
@ -1294,9 +1299,10 @@ TEST(ChecktransactionTests, HeartwoodEnforcesSaplingRulesOnShieldedCoinbase) {
|
||||||
|
|
||||||
// Coinbase transaction does not pass shielded input checks, as bindingSig
|
// Coinbase transaction does not pass shielded input checks, as bindingSig
|
||||||
// consensus rule is enforced.
|
// consensus rule is enforced.
|
||||||
|
PrecomputedTransactionData txdata(tx);
|
||||||
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false, "")).Times(1);
|
EXPECT_CALL(state, DoS(100, false, REJECT_INVALID, "bad-txns-sapling-binding-signature-invalid", false, "")).Times(1);
|
||||||
ContextualCheckShieldedInputs(
|
ContextualCheckShieldedInputs(
|
||||||
tx, state, orchardAuth, chainparams.GetConsensus(), heartwoodBranchId, false, true);
|
tx, txdata, state, orchardAuth, chainparams.GetConsensus(), heartwoodBranchId, false, true);
|
||||||
|
|
||||||
RegtestDeactivateHeartwood();
|
RegtestDeactivateHeartwood();
|
||||||
}
|
}
|
||||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -1229,6 +1229,7 @@ bool ContextualCheckTransaction(
|
||||||
|
|
||||||
bool ContextualCheckShieldedInputs(
|
bool ContextualCheckShieldedInputs(
|
||||||
const CTransaction& tx,
|
const CTransaction& tx,
|
||||||
|
const PrecomputedTransactionData& txdata,
|
||||||
CValidationState &state,
|
CValidationState &state,
|
||||||
orchard::AuthValidator& orchardAuth,
|
orchard::AuthValidator& orchardAuth,
|
||||||
const Consensus::Params& consensus,
|
const Consensus::Params& consensus,
|
||||||
|
@ -1259,8 +1260,8 @@ bool ContextualCheckShieldedInputs(
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
try {
|
try {
|
||||||
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
dataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
prevDataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, prevConsensusBranchId);
|
prevDataToBeSigned = SignatureHash(scriptCode, tx, NOT_AN_INPUT, SIGHASH_ALL, 0, prevConsensusBranchId, txdata);
|
||||||
} catch (std::logic_error ex) {
|
} catch (std::logic_error ex) {
|
||||||
// A logic error should never occur because we pass NOT_AN_INPUT and
|
// A logic error should never occur because we pass NOT_AN_INPUT and
|
||||||
// SIGHASH_ALL to SignatureHash().
|
// SIGHASH_ALL to SignatureHash().
|
||||||
|
@ -2001,6 +2002,7 @@ bool AcceptToMemoryPool(
|
||||||
// Check shielded input signatures.
|
// Check shielded input signatures.
|
||||||
if (!ContextualCheckShieldedInputs(
|
if (!ContextualCheckShieldedInputs(
|
||||||
tx,
|
tx,
|
||||||
|
txdata,
|
||||||
state,
|
state,
|
||||||
orchardAuth,
|
orchardAuth,
|
||||||
chainparams.GetConsensus(),
|
chainparams.GetConsensus(),
|
||||||
|
@ -2535,7 +2537,7 @@ void UpdateCoins(const CTransaction& tx, CCoinsViewCache& inputs, int nHeight)
|
||||||
|
|
||||||
bool CScriptCheck::operator()() {
|
bool CScriptCheck::operator()() {
|
||||||
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
const CScript &scriptSig = ptxTo->vin[nIn].scriptSig;
|
||||||
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, nIn, amount, cacheStore, *txdata), consensusBranchId, &error)) {
|
if (!VerifyScript(scriptSig, scriptPubKey, nFlags, CachingTransactionSignatureChecker(ptxTo, *txdata, nIn, amount, cacheStore), consensusBranchId, &error)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -3256,7 +3258,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
|
|
||||||
std::vector<CScriptCheck> vChecks;
|
std::vector<CScriptCheck> vChecks;
|
||||||
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
bool fCacheResults = fJustCheck; /* Don't cache results if we're actually connecting blocks (still consult the cache, though) */
|
||||||
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, fCacheResults, txdata[i], chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL))
|
if (!ContextualCheckInputs(tx, state, view, fExpensiveChecks, flags, fCacheResults, txdata.back(), chainparams.GetConsensus(), consensusBranchId, nScriptCheckThreads ? &vChecks : NULL))
|
||||||
return error("ConnectBlock(): CheckInputs on %s failed with %s",
|
return error("ConnectBlock(): CheckInputs on %s failed with %s",
|
||||||
tx.GetHash().ToString(), FormatStateMessage(state));
|
tx.GetHash().ToString(), FormatStateMessage(state));
|
||||||
control.Add(vChecks);
|
control.Add(vChecks);
|
||||||
|
@ -3265,6 +3267,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
|
||||||
// Check shielded inputs.
|
// Check shielded inputs.
|
||||||
if (!ContextualCheckShieldedInputs(
|
if (!ContextualCheckShieldedInputs(
|
||||||
tx,
|
tx,
|
||||||
|
txdata.back(),
|
||||||
state,
|
state,
|
||||||
orchardAuth,
|
orchardAuth,
|
||||||
chainparams.GetConsensus(),
|
chainparams.GetConsensus(),
|
||||||
|
|
|
@ -373,6 +373,7 @@ bool ContextualCheckInputs(const CTransaction& tx, CValidationState &state, cons
|
||||||
*/
|
*/
|
||||||
bool ContextualCheckShieldedInputs(
|
bool ContextualCheckShieldedInputs(
|
||||||
const CTransaction& tx,
|
const CTransaction& tx,
|
||||||
|
const PrecomputedTransactionData& txdata,
|
||||||
CValidationState &state,
|
CValidationState &state,
|
||||||
orchard::AuthValidator& orchardAuth,
|
orchard::AuthValidator& orchardAuth,
|
||||||
const Consensus::Params& consensus,
|
const Consensus::Params& consensus,
|
||||||
|
@ -449,6 +450,8 @@ private:
|
||||||
bool cacheStore;
|
bool cacheStore;
|
||||||
uint32_t consensusBranchId;
|
uint32_t consensusBranchId;
|
||||||
ScriptError error;
|
ScriptError error;
|
||||||
|
// We store a pointer instead of a reference here, to allow it to be null for
|
||||||
|
// performance reasons (enabling fast swaps in CCheckQueue::Loop).
|
||||||
PrecomputedTransactionData *txdata;
|
PrecomputedTransactionData *txdata;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -219,9 +219,11 @@ public:
|
||||||
uint256 dataToBeSigned;
|
uint256 dataToBeSigned;
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
try {
|
try {
|
||||||
|
PrecomputedTransactionData txdata(mtx);
|
||||||
dataToBeSigned = SignatureHash(
|
dataToBeSigned = SignatureHash(
|
||||||
scriptCode, mtx, NOT_AN_INPUT, SIGHASH_ALL, 0,
|
scriptCode, mtx, NOT_AN_INPUT, SIGHASH_ALL, 0,
|
||||||
CurrentEpochBranchId(nHeight, chainparams.GetConsensus()));
|
CurrentEpochBranchId(nHeight, chainparams.GetConsensus()),
|
||||||
|
txdata);
|
||||||
} catch (std::logic_error ex) {
|
} catch (std::logic_error ex) {
|
||||||
librustzcash_sapling_proving_ctx_free(ctx);
|
librustzcash_sapling_proving_ctx_free(ctx);
|
||||||
throw ex;
|
throw ex;
|
||||||
|
|
|
@ -1043,6 +1043,7 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
|
||||||
// Use CTransaction for the constant parts of the
|
// Use CTransaction for the constant parts of the
|
||||||
// transaction to avoid rehashing.
|
// transaction to avoid rehashing.
|
||||||
const CTransaction txConst(mergedTx);
|
const CTransaction txConst(mergedTx);
|
||||||
|
const PrecomputedTransactionData txdata(txConst);
|
||||||
// Sign what we can:
|
// Sign what we can:
|
||||||
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
|
for (unsigned int i = 0; i < mergedTx.vin.size(); i++) {
|
||||||
CTxIn& txin = mergedTx.vin[i];
|
CTxIn& txin = mergedTx.vin[i];
|
||||||
|
@ -1057,17 +1058,17 @@ UniValue signrawtransaction(const UniValue& params, bool fHelp)
|
||||||
SignatureData sigdata;
|
SignatureData sigdata;
|
||||||
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
// Only sign SIGHASH_SINGLE if there's a corresponding output:
|
||||||
if (!fHashSingle || (i < mergedTx.vout.size()))
|
if (!fHashSingle || (i < mergedTx.vout.size()))
|
||||||
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
ProduceSignature(MutableTransactionSignatureCreator(&keystore, &mergedTx, txdata, i, amount, nHashType), prevPubKey, sigdata, consensusBranchId);
|
||||||
|
|
||||||
// ... and merge in other signatures:
|
// ... and merge in other signatures:
|
||||||
for (const CMutableTransaction& txv : txVariants) {
|
for (const CMutableTransaction& txv : txVariants) {
|
||||||
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
sigdata = CombineSignatures(prevPubKey, TransactionSignatureChecker(&txConst, txdata, i, amount), sigdata, DataFromTransaction(txv, i), consensusBranchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTransaction(mergedTx, i, sigdata);
|
UpdateTransaction(mergedTx, i, sigdata);
|
||||||
|
|
||||||
ScriptError serror = SCRIPT_ERR_OK;
|
ScriptError serror = SCRIPT_ERR_OK;
|
||||||
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, i, amount), consensusBranchId, &serror)) {
|
if (!VerifyScript(txin.scriptSig, prevPubKey, STANDARD_SCRIPT_VERIFY_FLAGS, TransactionSignatureChecker(&txConst, txdata, i, amount), consensusBranchId, &serror)) {
|
||||||
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
TxInErrorToJSON(txin, vErrors, ScriptErrorString(serror));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1179,7 +1179,7 @@ uint256 SignatureHash(
|
||||||
int nHashType,
|
int nHashType,
|
||||||
const CAmount& amount,
|
const CAmount& amount,
|
||||||
uint32_t consensusBranchId,
|
uint32_t consensusBranchId,
|
||||||
const PrecomputedTransactionData* cache)
|
const PrecomputedTransactionData& txdata)
|
||||||
{
|
{
|
||||||
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
|
if (nIn >= txTo.vin.size() && nIn != NOT_AN_INPUT) {
|
||||||
// nIn out of range
|
// nIn out of range
|
||||||
|
@ -1198,10 +1198,9 @@ uint256 SignatureHash(
|
||||||
CDataStream sScriptCode(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream sScriptCode(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
sScriptCode << *(CScriptBase*)(&scriptCode);
|
sScriptCode << *(CScriptBase*)(&scriptCode);
|
||||||
|
|
||||||
if (cache) {
|
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
zcash_transaction_transparent_signature_digest(
|
zcash_transaction_transparent_signature_digest(
|
||||||
cache->preTx.get(),
|
txdata.preTx.get(),
|
||||||
nHashType,
|
nHashType,
|
||||||
nIn,
|
nIn,
|
||||||
reinterpret_cast<const unsigned char*>(sScriptCode.data()),
|
reinterpret_cast<const unsigned char*>(sScriptCode.data()),
|
||||||
|
@ -1209,19 +1208,6 @@ uint256 SignatureHash(
|
||||||
amount,
|
amount,
|
||||||
hash.begin());
|
hash.begin());
|
||||||
return hash;
|
return hash;
|
||||||
} else {
|
|
||||||
PrecomputedTransactionData local(txTo);
|
|
||||||
uint256 hash;
|
|
||||||
zcash_transaction_transparent_signature_digest(
|
|
||||||
local.preTx.get(),
|
|
||||||
nHashType,
|
|
||||||
nIn,
|
|
||||||
reinterpret_cast<const unsigned char*>(sScriptCode.data()),
|
|
||||||
sScriptCode.size(),
|
|
||||||
amount,
|
|
||||||
hash.begin());
|
|
||||||
return hash;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else if (sigversion == SIGVERSION_OVERWINTER || sigversion == SIGVERSION_SAPLING) {
|
} else if (sigversion == SIGVERSION_OVERWINTER || sigversion == SIGVERSION_SAPLING) {
|
||||||
uint256 hashPrevouts;
|
uint256 hashPrevouts;
|
||||||
|
@ -1232,15 +1218,15 @@ uint256 SignatureHash(
|
||||||
uint256 hashShieldedOutputs;
|
uint256 hashShieldedOutputs;
|
||||||
|
|
||||||
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
|
if (!(nHashType & SIGHASH_ANYONECANPAY)) {
|
||||||
hashPrevouts = cache ? cache->hashPrevouts : GetPrevoutHash(txTo);
|
hashPrevouts = txdata.hashPrevouts;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
if (!(nHashType & SIGHASH_ANYONECANPAY) && (nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
||||||
hashSequence = cache ? cache->hashSequence : GetSequenceHash(txTo);
|
hashSequence = txdata.hashSequence;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
if ((nHashType & 0x1f) != SIGHASH_SINGLE && (nHashType & 0x1f) != SIGHASH_NONE) {
|
||||||
hashOutputs = cache ? cache->hashOutputs : GetOutputsHash(txTo);
|
hashOutputs = txdata.hashOutputs;
|
||||||
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
|
} else if ((nHashType & 0x1f) == SIGHASH_SINGLE && nIn < txTo.vout.size()) {
|
||||||
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
|
CBLAKE2bWriter ss(SER_GETHASH, 0, ZCASH_OUTPUTS_HASH_PERSONALIZATION);
|
||||||
ss << txTo.vout[nIn];
|
ss << txTo.vout[nIn];
|
||||||
|
@ -1248,15 +1234,15 @@ uint256 SignatureHash(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!txTo.vJoinSplit.empty()) {
|
if (!txTo.vJoinSplit.empty()) {
|
||||||
hashJoinSplits = cache ? cache->hashJoinSplits : GetJoinSplitsHash(txTo);
|
hashJoinSplits = txdata.hashJoinSplits;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!txTo.vShieldedSpend.empty()) {
|
if (!txTo.vShieldedSpend.empty()) {
|
||||||
hashShieldedSpends = cache ? cache->hashShieldedSpends : GetShieldedSpendsHash(txTo);
|
hashShieldedSpends = txdata.hashShieldedSpends;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!txTo.vShieldedOutput.empty()) {
|
if (!txTo.vShieldedOutput.empty()) {
|
||||||
hashShieldedOutputs = cache ? cache->hashShieldedOutputs : GetShieldedOutputsHash(txTo);
|
hashShieldedOutputs = txdata.hashShieldedOutputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t leConsensusBranchId = htole32(consensusBranchId);
|
uint32_t leConsensusBranchId = htole32(consensusBranchId);
|
||||||
|
|
|
@ -116,7 +116,7 @@ uint256 SignatureHash(
|
||||||
int nHashType,
|
int nHashType,
|
||||||
const CAmount& amount,
|
const CAmount& amount,
|
||||||
uint32_t consensusBranchId,
|
uint32_t consensusBranchId,
|
||||||
const PrecomputedTransactionData* cache = NULL);
|
const PrecomputedTransactionData& txdata);
|
||||||
|
|
||||||
class BaseSignatureChecker
|
class BaseSignatureChecker
|
||||||
{
|
{
|
||||||
|
@ -144,14 +144,13 @@ private:
|
||||||
const CTransaction* txTo;
|
const CTransaction* txTo;
|
||||||
unsigned int nIn;
|
unsigned int nIn;
|
||||||
const CAmount amount;
|
const CAmount amount;
|
||||||
const PrecomputedTransactionData* txdata;
|
const PrecomputedTransactionData& txdata;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
virtual bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(NULL) {}
|
TransactionSignatureChecker(const CTransaction* txToIn, const PrecomputedTransactionData& txdataIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(txdataIn) {}
|
||||||
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, uint32_t consensusBranchId) 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;
|
bool CheckLockTime(const CScriptNum& nLockTime) const;
|
||||||
};
|
};
|
||||||
|
@ -162,7 +161,7 @@ private:
|
||||||
const CTransaction txTo;
|
const CTransaction txTo;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, nInIn, amount), txTo(*txToIn) {}
|
MutableTransactionSignatureChecker(const CMutableTransaction* txToIn, const PrecomputedTransactionData& txdataIn, unsigned int nInIn, const CAmount& amount) : TransactionSignatureChecker(&txTo, txdataIn, nInIn, amount), txTo(*txToIn) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
bool EvalScript(
|
bool EvalScript(
|
||||||
|
|
|
@ -22,7 +22,7 @@ private:
|
||||||
bool store;
|
bool store;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CachingTransactionSignatureChecker(const CTransaction* txToIn, unsigned int nInIn, const CAmount& amount, bool storeIn, PrecomputedTransactionData& txdataIn) : TransactionSignatureChecker(txToIn, nInIn, amount, txdataIn), store(storeIn) {}
|
CachingTransactionSignatureChecker(const CTransaction* txToIn, PrecomputedTransactionData& txdataIn, unsigned int nInIn, const CAmount& amount, bool storeIn) : TransactionSignatureChecker(txToIn, txdataIn, nInIn, amount), store(storeIn) {}
|
||||||
|
|
||||||
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
bool VerifySignature(const std::vector<unsigned char>& vchSig, const CPubKey& vchPubKey, const uint256& sighash) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -17,7 +17,7 @@ using namespace std;
|
||||||
|
|
||||||
typedef std::vector<unsigned char> valtype;
|
typedef std::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) {}
|
TransactionSignatureCreator::TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, const PrecomputedTransactionData& txToDataIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn) : BaseSignatureCreator(keystoreIn), txTo(txToIn), txToData(txToDataIn), nIn(nInIn), nHashType(nHashTypeIn), amount(amountIn), checker(txTo, txToDataIn, nIn, amountIn) {}
|
||||||
|
|
||||||
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId) const
|
bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& address, const CScript& scriptCode, uint32_t consensusBranchId) const
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,7 @@ bool TransactionSignatureCreator::CreateSig(std::vector<unsigned char>& vchSig,
|
||||||
|
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
try {
|
try {
|
||||||
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId);
|
hash = SignatureHash(scriptCode, *txTo, nIn, nHashType, amount, consensusBranchId, txToData);
|
||||||
} catch (logic_error ex) {
|
} catch (logic_error ex) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +172,7 @@ bool SignSignature(
|
||||||
const CKeyStore &keystore,
|
const CKeyStore &keystore,
|
||||||
const CScript& fromPubKey,
|
const CScript& fromPubKey,
|
||||||
CMutableTransaction& txTo,
|
CMutableTransaction& txTo,
|
||||||
|
const PrecomputedTransactionData& txToData,
|
||||||
unsigned int nIn,
|
unsigned int nIn,
|
||||||
const CAmount& amount,
|
const CAmount& amount,
|
||||||
int nHashType,
|
int nHashType,
|
||||||
|
@ -180,7 +181,7 @@ bool SignSignature(
|
||||||
assert(nIn < txTo.vin.size());
|
assert(nIn < txTo.vin.size());
|
||||||
|
|
||||||
CTransaction txToConst(txTo);
|
CTransaction txToConst(txTo);
|
||||||
TransactionSignatureCreator creator(&keystore, &txToConst, nIn, amount, nHashType);
|
TransactionSignatureCreator creator(&keystore, &txToConst, txToData, nIn, amount, nHashType);
|
||||||
|
|
||||||
SignatureData sigdata;
|
SignatureData sigdata;
|
||||||
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
|
bool ret = ProduceSignature(creator, fromPubKey, sigdata, consensusBranchId);
|
||||||
|
@ -192,6 +193,7 @@ bool SignSignature(
|
||||||
const CKeyStore &keystore,
|
const CKeyStore &keystore,
|
||||||
const CTransaction& txFrom,
|
const CTransaction& txFrom,
|
||||||
CMutableTransaction& txTo,
|
CMutableTransaction& txTo,
|
||||||
|
const PrecomputedTransactionData& txToData,
|
||||||
unsigned int nIn,
|
unsigned int nIn,
|
||||||
int nHashType,
|
int nHashType,
|
||||||
uint32_t consensusBranchId)
|
uint32_t consensusBranchId)
|
||||||
|
@ -201,7 +203,7 @@ bool SignSignature(
|
||||||
assert(txin.prevout.n < txFrom.vout.size());
|
assert(txin.prevout.n < txFrom.vout.size());
|
||||||
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
const CTxOut& txout = txFrom.vout[txin.prevout.n];
|
||||||
|
|
||||||
return SignSignature(keystore, txout.scriptPubKey, txTo, nIn, txout.nValue, nHashType, consensusBranchId);
|
return SignSignature(keystore, txout.scriptPubKey, txTo, txToData, nIn, txout.nValue, nHashType, consensusBranchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
static vector<valtype> CombineMultisig(const CScript& scriptPubKey, const BaseSignatureChecker& checker,
|
||||||
|
|
|
@ -33,13 +33,14 @@ public:
|
||||||
/** A signature creator for transactions. */
|
/** A signature creator for transactions. */
|
||||||
class TransactionSignatureCreator : public BaseSignatureCreator {
|
class TransactionSignatureCreator : public BaseSignatureCreator {
|
||||||
const CTransaction* txTo;
|
const CTransaction* txTo;
|
||||||
|
const PrecomputedTransactionData& txToData;
|
||||||
unsigned int nIn;
|
unsigned int nIn;
|
||||||
int nHashType;
|
int nHashType;
|
||||||
CAmount amount;
|
CAmount amount;
|
||||||
const TransactionSignatureChecker checker;
|
const TransactionSignatureChecker checker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
TransactionSignatureCreator(const CKeyStore* keystoreIn, const CTransaction* txToIn, const PrecomputedTransactionData& txToDataIn, unsigned int nInIn, const CAmount& amountIn, int nHashTypeIn=SIGHASH_ALL);
|
||||||
const BaseSignatureChecker& Checker() const { return checker; }
|
const BaseSignatureChecker& Checker() const { return checker; }
|
||||||
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
bool CreateSig(std::vector<unsigned char>& vchSig, const CKeyID& keyid, const CScript& scriptCode, uint32_t consensusBranchId) const;
|
||||||
};
|
};
|
||||||
|
@ -48,7 +49,7 @@ class MutableTransactionSignatureCreator : public TransactionSignatureCreator {
|
||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
|
MutableTransactionSignatureCreator(const CKeyStore* keystoreIn, const CMutableTransaction* txToIn, const PrecomputedTransactionData& txdataIn, unsigned int nInIn, const CAmount& amount, int nHashTypeIn) : TransactionSignatureCreator(keystoreIn, &tx, txdataIn, nInIn, amount, nHashTypeIn), tx(*txToIn) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A signature creator that just produces 72-byte empty signatures. */
|
/** A signature creator that just produces 72-byte empty signatures. */
|
||||||
|
@ -74,6 +75,7 @@ bool SignSignature(
|
||||||
const CKeyStore &keystore,
|
const CKeyStore &keystore,
|
||||||
const CScript& fromPubKey,
|
const CScript& fromPubKey,
|
||||||
CMutableTransaction& txTo,
|
CMutableTransaction& txTo,
|
||||||
|
const PrecomputedTransactionData& txToData,
|
||||||
unsigned int nIn,
|
unsigned int nIn,
|
||||||
const CAmount& amount,
|
const CAmount& amount,
|
||||||
int nHashType,
|
int nHashType,
|
||||||
|
@ -82,6 +84,7 @@ bool SignSignature(
|
||||||
const CKeyStore& keystore,
|
const CKeyStore& keystore,
|
||||||
const CTransaction& txFrom,
|
const CTransaction& txFrom,
|
||||||
CMutableTransaction& txTo,
|
CMutableTransaction& txTo,
|
||||||
|
const PrecomputedTransactionData& txToData,
|
||||||
unsigned int nIn,
|
unsigned int nIn,
|
||||||
int nHashType,
|
int nHashType,
|
||||||
uint32_t consensusBranchId);
|
uint32_t consensusBranchId);
|
||||||
|
|
|
@ -145,7 +145,7 @@ int zcash_script_verify_precomputed(
|
||||||
preTx->tx.vin[nIn].scriptSig,
|
preTx->tx.vin[nIn].scriptSig,
|
||||||
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
|
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
|
||||||
flags,
|
flags,
|
||||||
TransactionSignatureChecker(&preTx->tx, nIn, amount, preTx->txdata),
|
TransactionSignatureChecker(&preTx->tx, preTx->txdata, nIn, amount),
|
||||||
consensusBranchId,
|
consensusBranchId,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ int zcash_script_verify(
|
||||||
tx.vin[nIn].scriptSig,
|
tx.vin[nIn].scriptSig,
|
||||||
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
|
CScript(scriptPubKey, scriptPubKey + scriptPubKeyLen),
|
||||||
flags,
|
flags,
|
||||||
TransactionSignatureChecker(&tx, nIn, amount, txdata),
|
TransactionSignatureChecker(&tx, txdata, nIn, amount),
|
||||||
consensusBranchId,
|
consensusBranchId,
|
||||||
NULL);
|
NULL);
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
|
|
|
@ -157,7 +157,8 @@ BOOST_DATA_TEST_CASE(DoS_mapOrphans, boost::unit_test::data::xrange(static_cast<
|
||||||
tx.vout.resize(1);
|
tx.vout.resize(1);
|
||||||
tx.vout[0].nValue = 1*CENT;
|
tx.vout[0].nValue = 1*CENT;
|
||||||
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
tx.vout[0].scriptPubKey = GetScriptForDestination(key.GetPubKey().GetID());
|
||||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL, consensusBranchId);
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
SignSignature(keystore, txPrev, tx, txdata, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
|
|
||||||
AddOrphanTx(tx, i);
|
AddOrphanTx(tx, i);
|
||||||
}
|
}
|
||||||
|
@ -177,7 +178,8 @@ BOOST_DATA_TEST_CASE(DoS_mapOrphans, boost::unit_test::data::xrange(static_cast<
|
||||||
tx.vin[j].prevout.n = j;
|
tx.vin[j].prevout.n = j;
|
||||||
tx.vin[j].prevout.hash = txPrev.GetHash();
|
tx.vin[j].prevout.hash = txPrev.GetHash();
|
||||||
}
|
}
|
||||||
SignSignature(keystore, txPrev, tx, 0, SIGHASH_ALL, consensusBranchId);
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
SignSignature(keystore, txPrev, tx, txdata, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
// Re-use same signature for other inputs
|
// Re-use same signature for other inputs
|
||||||
// (they don't have to be valid for this test)
|
// (they don't have to be valid for this test)
|
||||||
for (unsigned int j = 1; j < tx.vin.size(); j++)
|
for (unsigned int j = 1; j < tx.vin.size(); j++)
|
||||||
|
|
|
@ -23,9 +23,9 @@ using namespace std;
|
||||||
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
|
BOOST_FIXTURE_TEST_SUITE(multisig_tests, BasicTestingSetup)
|
||||||
|
|
||||||
CScript
|
CScript
|
||||||
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, int whichIn, uint32_t consensusBranchId)
|
sign_multisig(CScript scriptPubKey, vector<CKey> keys, CTransaction transaction, const PrecomputedTransactionData& txdata, int whichIn, uint32_t consensusBranchId)
|
||||||
{
|
{
|
||||||
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 hash = SignatureHash(scriptPubKey, transaction, whichIn, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
CScript result;
|
CScript result;
|
||||||
result << OP_0; // CHECKMULTISIG bug workaround
|
result << OP_0; // CHECKMULTISIG bug workaround
|
||||||
|
@ -71,6 +71,7 @@ BOOST_DATA_TEST_CASE(multisig_verify, boost::unit_test::data::xrange(static_cast
|
||||||
txFrom.vout[2].nValue = 10;
|
txFrom.vout[2].nValue = 10;
|
||||||
|
|
||||||
CMutableTransaction txTo[3]; // Spending transaction
|
CMutableTransaction txTo[3]; // Spending transaction
|
||||||
|
std::vector<PrecomputedTransactionData> txdata;
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
|
@ -78,6 +79,7 @@ BOOST_DATA_TEST_CASE(multisig_verify, boost::unit_test::data::xrange(static_cast
|
||||||
txTo[i].vin[0].prevout.n = i;
|
txTo[i].vin[0].prevout.n = i;
|
||||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||||
txTo[i].vout[0].nValue = 1;
|
txTo[i].vout[0].nValue = 1;
|
||||||
|
txdata.push_back(PrecomputedTransactionData(txTo[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<CKey> keys;
|
vector<CKey> keys;
|
||||||
|
@ -86,21 +88,21 @@ BOOST_DATA_TEST_CASE(multisig_verify, boost::unit_test::data::xrange(static_cast
|
||||||
// Test a AND b:
|
// Test a AND b:
|
||||||
keys.assign(1,key[0]);
|
keys.assign(1,key[0]);
|
||||||
keys.push_back(key[1]);
|
keys.push_back(key[1]);
|
||||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
s = sign_multisig(a_and_b, keys, txTo[0], txdata[0], 0, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], 0, amount), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], txdata[0], 0, amount), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
keys.assign(1,key[i]);
|
keys.assign(1,key[i]);
|
||||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
s = sign_multisig(a_and_b, keys, txTo[0], txdata[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(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], txdata[0], 0, amount), consensusBranchId, &err), strprintf("a&b 1: %d", i));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.assign(1,key[1]);
|
keys.assign(1,key[1]);
|
||||||
keys.push_back(key[i]);
|
keys.push_back(key[i]);
|
||||||
s = sign_multisig(a_and_b, keys, txTo[0], 0, consensusBranchId);
|
s = sign_multisig(a_and_b, keys, txTo[0], txdata[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(!VerifyScript(s, a_and_b, flags, MutableTransactionSignatureChecker(&txTo[0], txdata[0], 0, amount), consensusBranchId, &err), strprintf("a&b 2: %d", i));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -108,21 +110,21 @@ BOOST_DATA_TEST_CASE(multisig_verify, boost::unit_test::data::xrange(static_cast
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
keys.assign(1,key[i]);
|
keys.assign(1,key[i]);
|
||||||
s = sign_multisig(a_or_b, keys, txTo[1], 0, consensusBranchId);
|
s = sign_multisig(a_or_b, keys, txTo[1], txdata[1], 0, consensusBranchId);
|
||||||
if (i == 0 || i == 1)
|
if (i == 0 || i == 1)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
BOOST_CHECK_MESSAGE(VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], txdata[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], txdata[1], 0, amount), consensusBranchId, &err), strprintf("a|b: %d", i));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.clear();
|
s.clear();
|
||||||
s << OP_0 << OP_1;
|
s << OP_0 << OP_1;
|
||||||
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], 0, amount), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(s, a_or_b, flags, MutableTransactionSignatureChecker(&txTo[1], txdata[1], 0, amount), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_SIG_DER, ScriptErrorString(err));
|
||||||
|
|
||||||
|
|
||||||
|
@ -131,15 +133,15 @@ BOOST_DATA_TEST_CASE(multisig_verify, boost::unit_test::data::xrange(static_cast
|
||||||
{
|
{
|
||||||
keys.assign(1,key[i]);
|
keys.assign(1,key[i]);
|
||||||
keys.push_back(key[j]);
|
keys.push_back(key[j]);
|
||||||
s = sign_multisig(escrow, keys, txTo[2], 0, consensusBranchId);
|
s = sign_multisig(escrow, keys, txTo[2], txdata[2], 0, consensusBranchId);
|
||||||
if (i < j && i < 3 && j < 3)
|
if (i < j && i < 3 && j < 3)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err), strprintf("escrow 1: %d %d", i, j));
|
BOOST_CHECK_MESSAGE(VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], txdata[2], 0, amount), consensusBranchId, &err), strprintf("escrow 1: %d %d", i, j));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], 0, amount), consensusBranchId, &err), strprintf("escrow 2: %d %d", i, j));
|
BOOST_CHECK_MESSAGE(!VerifyScript(s, escrow, flags, MutableTransactionSignatureChecker(&txTo[2], txdata[2], 0, amount), consensusBranchId, &err), strprintf("escrow 2: %d %d", i, j));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -215,6 +217,7 @@ BOOST_DATA_TEST_CASE(multisig_Sign, boost::unit_test::data::xrange(static_cast<i
|
||||||
txFrom.vout[2].nValue = 10;
|
txFrom.vout[2].nValue = 10;
|
||||||
|
|
||||||
CMutableTransaction txTo[3]; // Spending transaction
|
CMutableTransaction txTo[3]; // Spending transaction
|
||||||
|
std::vector<PrecomputedTransactionData> txdata;
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
|
@ -222,11 +225,12 @@ BOOST_DATA_TEST_CASE(multisig_Sign, boost::unit_test::data::xrange(static_cast<i
|
||||||
txTo[i].vin[0].prevout.n = i;
|
txTo[i].vin[0].prevout.n = i;
|
||||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||||
txTo[i].vout[0].nValue = 1;
|
txTo[i].vout[0].nValue = 1;
|
||||||
|
txdata.push_back(PrecomputedTransactionData(txTo[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], txdata[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,8 @@ Verify(const CScript& scriptSig, const CScript& scriptPubKey, bool fStrict, Scri
|
||||||
txTo.vin[0].scriptSig = scriptSig;
|
txTo.vin[0].scriptSig = scriptSig;
|
||||||
txTo.vout[0].nValue = 1;
|
txTo.vout[0].nValue = 1;
|
||||||
|
|
||||||
return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue), consensusBranchId, &err);
|
const PrecomputedTransactionData txdata(txTo);
|
||||||
|
return VerifyScript(scriptSig, scriptPubKey, fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE, MutableTransactionSignatureChecker(&txTo, txdata, 0, txFrom.vout[0].nValue), consensusBranchId, &err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,6 +99,7 @@ BOOST_DATA_TEST_CASE(sign, boost::unit_test::data::xrange(static_cast<int>(Conse
|
||||||
BOOST_CHECK(IsStandardTx(txFrom, reason, Params()));
|
BOOST_CHECK(IsStandardTx(txFrom, reason, Params()));
|
||||||
|
|
||||||
CMutableTransaction txTo[8]; // Spending transactions
|
CMutableTransaction txTo[8]; // Spending transactions
|
||||||
|
std::vector<PrecomputedTransactionData> txToData;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
|
@ -106,10 +108,11 @@ BOOST_DATA_TEST_CASE(sign, boost::unit_test::data::xrange(static_cast<int>(Conse
|
||||||
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
txTo[i].vin[0].prevout.hash = txFrom.GetHash();
|
||||||
txTo[i].vout[0].nValue = 1;
|
txTo[i].vout[0].nValue = 1;
|
||||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
||||||
|
txToData.push_back(PrecomputedTransactionData(txTo[i]));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], txToData[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||||
}
|
}
|
||||||
// All of the above should be OK, and the txTos have valid signatures
|
// 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:
|
// Check to make sure signature verification fails if we use the wrong ScriptSig:
|
||||||
|
@ -199,6 +202,7 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast<int>(Consen
|
||||||
BOOST_CHECK(IsStandardTx(txFrom, reason, Params()));
|
BOOST_CHECK(IsStandardTx(txFrom, reason, Params()));
|
||||||
|
|
||||||
CMutableTransaction txTo[4]; // Spending transactions
|
CMutableTransaction txTo[4]; // Spending transactions
|
||||||
|
std::vector<PrecomputedTransactionData> txToData;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
txTo[i].vin.resize(1);
|
txTo[i].vin.resize(1);
|
||||||
|
@ -208,10 +212,11 @@ BOOST_DATA_TEST_CASE(set, boost::unit_test::data::xrange(static_cast<int>(Consen
|
||||||
txTo[i].vout[0].nValue = 1*CENT;
|
txTo[i].vout[0].nValue = 1*CENT;
|
||||||
txTo[i].vout[0].scriptPubKey = inner[i];
|
txTo[i].vout[0].scriptPubKey = inner[i];
|
||||||
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));
|
||||||
|
txToData.push_back(PrecomputedTransactionData(txTo[i]));
|
||||||
}
|
}
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
BOOST_CHECK_MESSAGE(SignSignature(keystore, txFrom, txTo[i], txToData[i], 0, SIGHASH_ALL, consensusBranchId), strprintf("SignSignature %d", i));
|
||||||
BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason, Params()), strprintf("txTo[%d].IsStandard", i));
|
BOOST_CHECK_MESSAGE(IsStandardTx(txTo[i], reason, Params()), strprintf("txTo[%d].IsStandard", i));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,9 +352,10 @@ BOOST_DATA_TEST_CASE(AreInputsStandard, boost::unit_test::data::xrange(static_ca
|
||||||
txTo.vin[i].prevout.n = i;
|
txTo.vin[i].prevout.n = i;
|
||||||
txTo.vin[i].prevout.hash = txFrom.GetHash();
|
txTo.vin[i].prevout.hash = txFrom.GetHash();
|
||||||
}
|
}
|
||||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId));
|
const PrecomputedTransactionData txToData(txTo);
|
||||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 1, SIGHASH_ALL, consensusBranchId));
|
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId));
|
||||||
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, 2, SIGHASH_ALL, consensusBranchId));
|
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, txToData, 1, SIGHASH_ALL, consensusBranchId));
|
||||||
|
BOOST_CHECK(SignSignature(keystore, txFrom, txTo, txToData, 2, SIGHASH_ALL, consensusBranchId));
|
||||||
// SignSignature doesn't know how to sign these. We're
|
// SignSignature doesn't know how to sign these. We're
|
||||||
// not testing validating signatures, so just create
|
// not testing validating signatures, so just create
|
||||||
// dummy signatures that DO include the correct P2SH scripts:
|
// dummy signatures that DO include the correct P2SH scripts:
|
||||||
|
|
|
@ -78,8 +78,9 @@ void DoTest(const CScript& scriptPubKey, const CScript& scriptSig, int flags, ui
|
||||||
ScriptError err;
|
ScriptError err;
|
||||||
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
|
CMutableTransaction txCredit = BuildCreditingTransaction(scriptPubKey);
|
||||||
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit);
|
CMutableTransaction tx = BuildSpendingTransaction(scriptSig, txCredit);
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
CMutableTransaction tx2 = tx;
|
CMutableTransaction tx2 = tx;
|
||||||
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, 0, txCredit.vout[0].nValue), consensusBranchId, &err) == expect, message);
|
BOOST_CHECK_MESSAGE(VerifyScript(scriptSig, scriptPubKey, flags, MutableTransactionSignatureChecker(&tx, txdata, 0, txCredit.vout[0].nValue), consensusBranchId, &err) == expect, message);
|
||||||
BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
|
BOOST_CHECK_MESSAGE(expect == (err == SCRIPT_ERR_OK), std::string(ScriptErrorString(err)) + ": " + message);
|
||||||
#if defined(HAVE_SCRIPT_LIB)
|
#if defined(HAVE_SCRIPT_LIB)
|
||||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
@ -230,7 +231,8 @@ public:
|
||||||
|
|
||||||
TestBuilder& PushSig(const CKey& key, int nHashType = SIGHASH_ALL, unsigned int lenR = 32, unsigned int lenS = 32)
|
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, consensusBranchId);
|
const PrecomputedTransactionData txdata(spendTx);
|
||||||
|
uint256 hash = SignatureHash(scriptPubKey, spendTx, 0, nHashType, 0, consensusBranchId, txdata);
|
||||||
std::vector<unsigned char> vchSig, r, s;
|
std::vector<unsigned char> vchSig, r, s;
|
||||||
uint32_t iter = 0;
|
uint32_t iter = 0;
|
||||||
do {
|
do {
|
||||||
|
@ -664,9 +666,9 @@ BOOST_DATA_TEST_CASE(script_PushData, boost::unit_test::data::xrange(static_cast
|
||||||
}
|
}
|
||||||
|
|
||||||
CScript
|
CScript
|
||||||
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, uint32_t consensusBranchId)
|
sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transaction, const PrecomputedTransactionData& txdata, uint32_t consensusBranchId)
|
||||||
{
|
{
|
||||||
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 hash = SignatureHash(scriptPubKey, transaction, 0, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
CScript result;
|
CScript result;
|
||||||
//
|
//
|
||||||
|
@ -688,11 +690,11 @@ sign_multisig(CScript scriptPubKey, std::vector<CKey> keys, CTransaction transac
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
CScript
|
CScript
|
||||||
sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction, uint32_t consensusBranchId)
|
sign_multisig(CScript scriptPubKey, const CKey &key, CTransaction transaction, const PrecomputedTransactionData& txdata, uint32_t consensusBranchId)
|
||||||
{
|
{
|
||||||
std::vector<CKey> keys;
|
std::vector<CKey> keys;
|
||||||
keys.push_back(key);
|
keys.push_back(key);
|
||||||
return sign_multisig(scriptPubKey, keys, transaction, consensusBranchId);
|
return sign_multisig(scriptPubKey, keys, transaction, txdata, consensusBranchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parameterized testing over consensus branch ids
|
// Parameterized testing over consensus branch ids
|
||||||
|
@ -710,20 +712,21 @@ BOOST_DATA_TEST_CASE(script_CHECKMULTISIG12, boost::unit_test::data::xrange(stat
|
||||||
|
|
||||||
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
|
CMutableTransaction txFrom12 = BuildCreditingTransaction(scriptPubKey12);
|
||||||
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
|
CMutableTransaction txTo12 = BuildSpendingTransaction(CScript(), txFrom12);
|
||||||
|
const PrecomputedTransactionData txdata12(txTo12);
|
||||||
|
|
||||||
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12, consensusBranchId);
|
CScript goodsig1 = sign_multisig(scriptPubKey12, key1, txTo12, txdata12, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, txdata12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
txTo12.vout[0].nValue = 2;
|
txTo12.vout[0].nValue = 2;
|
||||||
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(goodsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, txdata12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12, consensusBranchId);
|
CScript goodsig2 = sign_multisig(scriptPubKey12, key2, txTo12, txdata12, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, txdata12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12, consensusBranchId);
|
CScript badsig1 = sign_multisig(scriptPubKey12, key3, txTo12, txdata12, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey12, flags, MutableTransactionSignatureChecker(&txTo12, txdata12, 0, txFrom12.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -743,58 +746,59 @@ BOOST_DATA_TEST_CASE(script_CHECKMULTISIG23, boost::unit_test::data::xrange(stat
|
||||||
|
|
||||||
CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23);
|
CMutableTransaction txFrom23 = BuildCreditingTransaction(scriptPubKey23);
|
||||||
CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23);
|
CMutableTransaction txTo23 = BuildSpendingTransaction(CScript(), txFrom23);
|
||||||
|
const PrecomputedTransactionData txdata23(txTo23);
|
||||||
|
|
||||||
std::vector<CKey> keys;
|
std::vector<CKey> keys;
|
||||||
keys.push_back(key1); keys.push_back(key2);
|
keys.push_back(key1); keys.push_back(key2);
|
||||||
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript goodsig1 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(goodsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key1); keys.push_back(key3);
|
keys.push_back(key1); keys.push_back(key3);
|
||||||
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript goodsig2 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(goodsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key2); keys.push_back(key3);
|
keys.push_back(key2); keys.push_back(key3);
|
||||||
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript goodsig3 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(VerifyScript(goodsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
|
keys.push_back(key2); keys.push_back(key2); // Can't re-use sig
|
||||||
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig1 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig1, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
|
keys.push_back(key2); keys.push_back(key1); // sigs must be in correct order
|
||||||
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig2 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig2, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
|
keys.push_back(key3); keys.push_back(key2); // sigs must be in correct order
|
||||||
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig3 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig3, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
|
keys.push_back(key4); keys.push_back(key2); // sigs must match pubkeys
|
||||||
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig4 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig4, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear();
|
keys.clear();
|
||||||
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
|
keys.push_back(key1); keys.push_back(key4); // sigs must match pubkeys
|
||||||
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig5 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig5, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_EVAL_FALSE, ScriptErrorString(err));
|
||||||
|
|
||||||
keys.clear(); // Must have signatures
|
keys.clear(); // Must have signatures
|
||||||
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23, consensusBranchId);
|
CScript badsig6 = sign_multisig(scriptPubKey23, keys, txTo23, txdata23, consensusBranchId);
|
||||||
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
BOOST_CHECK(!VerifyScript(badsig6, scriptPubKey23, flags, MutableTransactionSignatureChecker(&txTo23, txdata23, 0, txFrom23.vout[0].nValue), consensusBranchId, &err));
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -818,65 +822,66 @@ BOOST_DATA_TEST_CASE(script_combineSigs, boost::unit_test::data::xrange(static_c
|
||||||
|
|
||||||
CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
|
CMutableTransaction txFrom = BuildCreditingTransaction(GetScriptForDestination(keys[0].GetPubKey().GetID()));
|
||||||
CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom);
|
CMutableTransaction txTo = BuildSpendingTransaction(CScript(), txFrom);
|
||||||
|
const PrecomputedTransactionData txToData(txTo);
|
||||||
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
|
CScript& scriptPubKey = txFrom.vout[0].scriptPubKey;
|
||||||
CScript& scriptSig = txTo.vin[0].scriptSig;
|
CScript& scriptSig = txTo.vin[0].scriptSig;
|
||||||
|
|
||||||
SignatureData empty;
|
SignatureData empty;
|
||||||
SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, empty, consensusBranchId);
|
SignatureData combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), empty, empty, consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig.empty());
|
BOOST_CHECK(combined.scriptSig.empty());
|
||||||
|
|
||||||
// Single signature case:
|
// Single signature case:
|
||||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId); // changes scriptSig
|
SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId); // changes scriptSig
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
CScript scriptSigCopy = scriptSig;
|
CScript scriptSigCopy = scriptSig;
|
||||||
// Signing again will give a different, valid signature:
|
// Signing again will give a different, valid signature:
|
||||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
||||||
|
|
||||||
// P2SH, single-signature case:
|
// P2SH, single-signature case:
|
||||||
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
|
CScript pkSingle; pkSingle << ToByteVector(keys[0].GetPubKey()) << OP_CHECKSIG;
|
||||||
keystore.AddCScript(pkSingle);
|
keystore.AddCScript(pkSingle);
|
||||||
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
|
scriptPubKey = GetScriptForDestination(CScriptID(pkSingle));
|
||||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
scriptSigCopy = scriptSig;
|
scriptSigCopy = scriptSig;
|
||||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSigCopy || combined.scriptSig == scriptSig);
|
||||||
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
|
// dummy scriptSigCopy with placeholder, should always choose non-placeholder:
|
||||||
scriptSigCopy = CScript() << OP_0 << vector<unsigned char>(pkSingle.begin(), pkSingle.end());
|
scriptSigCopy = CScript() << OP_0 << vector<unsigned char>(pkSingle.begin(), pkSingle.end());
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSigCopy), SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSig), SignatureData(scriptSigCopy), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
|
|
||||||
// Hardest case: Multisig 2-of-3
|
// Hardest case: Multisig 2-of-3
|
||||||
scriptPubKey = GetScriptForMultisig(2, pubkeys);
|
scriptPubKey = GetScriptForMultisig(2, pubkeys);
|
||||||
keystore.AddCScript(scriptPubKey);
|
keystore.AddCScript(scriptPubKey);
|
||||||
SignSignature(keystore, txFrom, txTo, 0, SIGHASH_ALL, consensusBranchId);
|
SignSignature(keystore, txFrom, txTo, txToData, 0, SIGHASH_ALL, consensusBranchId);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(scriptSig), empty, consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), empty, SignatureData(scriptSig), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == scriptSig);
|
BOOST_CHECK(combined.scriptSig == scriptSig);
|
||||||
|
|
||||||
// A couple of partially-signed versions:
|
// A couple of partially-signed versions:
|
||||||
vector<unsigned char> sig1;
|
vector<unsigned char> sig1;
|
||||||
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 hash1 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_ALL, 0, consensusBranchId, txToData);
|
||||||
BOOST_CHECK(keys[0].Sign(hash1, sig1));
|
BOOST_CHECK(keys[0].Sign(hash1, sig1));
|
||||||
sig1.push_back(SIGHASH_ALL);
|
sig1.push_back(SIGHASH_ALL);
|
||||||
vector<unsigned char> sig2;
|
vector<unsigned char> sig2;
|
||||||
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, consensusBranchId);
|
uint256 hash2 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_NONE, 0, consensusBranchId, txToData);
|
||||||
BOOST_CHECK(keys[1].Sign(hash2, sig2));
|
BOOST_CHECK(keys[1].Sign(hash2, sig2));
|
||||||
sig2.push_back(SIGHASH_NONE);
|
sig2.push_back(SIGHASH_NONE);
|
||||||
vector<unsigned char> sig3;
|
vector<unsigned char> sig3;
|
||||||
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, consensusBranchId);
|
uint256 hash3 = SignatureHash(scriptPubKey, txTo, 0, SIGHASH_SINGLE, 0, consensusBranchId, txToData);
|
||||||
BOOST_CHECK(keys[2].Sign(hash3, sig3));
|
BOOST_CHECK(keys[2].Sign(hash3, sig3));
|
||||||
sig3.push_back(SIGHASH_SINGLE);
|
sig3.push_back(SIGHASH_SINGLE);
|
||||||
|
|
||||||
|
@ -892,21 +897,21 @@ BOOST_DATA_TEST_CASE(script_combineSigs, boost::unit_test::data::xrange(static_c
|
||||||
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
|
CScript complete13 = CScript() << OP_0 << sig1 << sig3;
|
||||||
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
|
CScript complete23 = CScript() << OP_0 << sig2 << sig3;
|
||||||
|
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial1b), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial1a), SignatureData(partial1b), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == partial1a);
|
BOOST_CHECK(combined.scriptSig == partial1a);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1a), SignatureData(partial2a), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial1a), SignatureData(partial2a), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete12);
|
BOOST_CHECK(combined.scriptSig == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial1a), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial2a), SignatureData(partial1a), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete12);
|
BOOST_CHECK(combined.scriptSig == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial1b), SignatureData(partial2b), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial1b), SignatureData(partial2b), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete12);
|
BOOST_CHECK(combined.scriptSig == complete12);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial1b), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial3b), SignatureData(partial1b), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete13);
|
BOOST_CHECK(combined.scriptSig == complete13);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial2a), SignatureData(partial3a), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial2a), SignatureData(partial3a), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete23);
|
BOOST_CHECK(combined.scriptSig == complete23);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial2b), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial3b), SignatureData(partial2b), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == complete23);
|
BOOST_CHECK(combined.scriptSig == complete23);
|
||||||
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, 0, amount), SignatureData(partial3b), SignatureData(partial3a), consensusBranchId);
|
combined = CombineSignatures(scriptPubKey, MutableTransactionSignatureChecker(&txTo, txToData, 0, amount), SignatureData(partial3b), SignatureData(partial3a), consensusBranchId);
|
||||||
BOOST_CHECK(combined.scriptSig == partial3c);
|
BOOST_CHECK(combined.scriptSig == partial3c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -202,7 +202,8 @@ void static RandomTransaction(CMutableTransaction &tx, bool fSingle, uint32_t co
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(tx);
|
CTransaction signTx(tx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
assert(ed25519_sign(
|
assert(ed25519_sign(
|
||||||
&joinSplitPrivKey,
|
&joinSplitPrivKey,
|
||||||
|
@ -236,10 +237,11 @@ BOOST_AUTO_TEST_CASE(sighash_test)
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
RandomScript(scriptCode);
|
RandomScript(scriptCode);
|
||||||
int nIn = insecure_rand() % txTo.vin.size();
|
int nIn = insecure_rand() % txTo.vin.size();
|
||||||
|
const PrecomputedTransactionData txdata(txTo);
|
||||||
|
|
||||||
uint256 sh, sho;
|
uint256 sh, sho;
|
||||||
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
sho = SignatureHashOld(scriptCode, txTo, nIn, nHashType);
|
||||||
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, consensusBranchId);
|
sh = SignatureHash(scriptCode, txTo, nIn, nHashType, 0, consensusBranchId, txdata);
|
||||||
#if defined(PRINT_SIGHASH_JSON)
|
#if defined(PRINT_SIGHASH_JSON)
|
||||||
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
|
||||||
ss << txTo;
|
ss << txTo;
|
||||||
|
@ -334,7 +336,8 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, consensusBranchId);
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
sh = SignatureHash(scriptCode, tx, nIn, nHashType, 0, consensusBranchId, txdata);
|
||||||
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -127,7 +127,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||||
CAmount amount = 0;
|
CAmount amount = 0;
|
||||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||||
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
BOOST_CHECK_MESSAGE(VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err),
|
verify_flags, TransactionSignatureChecker(&tx, txdata, i, amount), consensusBranchId, &err),
|
||||||
strTest + comment);
|
strTest + comment);
|
||||||
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||||
}
|
}
|
||||||
|
@ -219,7 +219,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||||
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
unsigned int verify_flags = ParseScriptFlags(test[2].get_str());
|
||||||
CAmount amount = 0;
|
CAmount amount = 0;
|
||||||
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
fValid = VerifyScript(tx.vin[i].scriptSig, mapprevOutScriptPubKeys[tx.vin[i].prevout],
|
||||||
verify_flags, TransactionSignatureChecker(&tx, i, amount, txdata), consensusBranchId, &err);
|
verify_flags, TransactionSignatureChecker(&tx, txdata, i, amount), consensusBranchId, &err);
|
||||||
}
|
}
|
||||||
BOOST_CHECK_MESSAGE(!fValid, strTest + comment);
|
BOOST_CHECK_MESSAGE(!fValid, strTest + comment);
|
||||||
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
BOOST_CHECK_MESSAGE(err != SCRIPT_ERR_OK, ScriptErrorString(err) + comment);
|
||||||
|
@ -451,15 +451,17 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
||||||
jsdesc->nullifiers[0] = GetRandHash();
|
jsdesc->nullifiers[0] = GetRandHash();
|
||||||
jsdesc->nullifiers[1] = GetRandHash();
|
jsdesc->nullifiers[1] = GetRandHash();
|
||||||
|
|
||||||
|
const PrecomputedTransactionData txdata(newTx);
|
||||||
|
|
||||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||||
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
||||||
BOOST_CHECK(!ContextualCheckShieldedInputs(newTx, state, orchardAuth, Params().GetConsensus(), consensusBranchId, false, true));
|
BOOST_CHECK(!ContextualCheckShieldedInputs(newTx, txdata, state, orchardAuth, Params().GetConsensus(), consensusBranchId, false, true));
|
||||||
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
|
BOOST_CHECK(state.GetRejectReason() == "bad-txns-invalid-joinsplit-signature");
|
||||||
|
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(newTx);
|
CTransaction signTx(newTx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
assert(ed25519_sign(
|
assert(ed25519_sign(
|
||||||
&joinSplitPrivKey,
|
&joinSplitPrivKey,
|
||||||
|
@ -469,7 +471,7 @@ void test_simple_joinsplit_invalidity(uint32_t consensusBranchId, CMutableTransa
|
||||||
state = CValidationState();
|
state = CValidationState();
|
||||||
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
BOOST_CHECK(CheckTransactionWithoutProofVerification(newTx, state));
|
||||||
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
BOOST_CHECK(ContextualCheckTransaction(newTx, state, Params(), 0, true));
|
||||||
BOOST_CHECK(ContextualCheckShieldedInputs(newTx, state, orchardAuth, Params().GetConsensus(), consensusBranchId, false, true));
|
BOOST_CHECK(ContextualCheckShieldedInputs(newTx, txdata, state, orchardAuth, Params().GetConsensus(), consensusBranchId, false, true));
|
||||||
BOOST_CHECK_EQUAL(state.GetRejectReason(), "");
|
BOOST_CHECK_EQUAL(state.GetRejectReason(), "");
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -670,9 +672,11 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
||||||
mtx.vout[i].scriptPubKey = CScript() << OP_1;
|
mtx.vout[i].scriptPubKey = CScript() << OP_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrecomputedTransactionData txdata(mtx);
|
||||||
|
|
||||||
// sign all inputs
|
// sign all inputs
|
||||||
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
|
||||||
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, i, 1000, sigHashes.at(i % sigHashes.size()), consensusBranchId);
|
bool hashSigned = SignSignature(keystore, scriptPubKey, mtx, txdata, i, 1000, sigHashes.at(i % sigHashes.size()), consensusBranchId);
|
||||||
assert(hashSigned);
|
assert(hashSigned);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,7 +686,6 @@ BOOST_AUTO_TEST_CASE(test_big_overwinter_transaction) {
|
||||||
ssout >> tx;
|
ssout >> tx;
|
||||||
|
|
||||||
// check all inputs concurrently, with the cache
|
// check all inputs concurrently, with the cache
|
||||||
PrecomputedTransactionData txdata(tx);
|
|
||||||
boost::thread_group threadGroup;
|
boost::thread_group threadGroup;
|
||||||
CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
CCheckQueue<CScriptCheck> scriptcheckqueue(128);
|
||||||
CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
|
CCheckQueueControl<CScriptCheck> control(&scriptcheckqueue);
|
||||||
|
@ -915,11 +918,13 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
amount = test[5].get_int64();
|
amount = test[5].get_int64();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PrecomputedTransactionData txdata(tx);
|
||||||
|
|
||||||
BOOST_CHECK_EQUAL(
|
BOOST_CHECK_EQUAL(
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_ALL,
|
SIGHASH_ALL,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[6].getValStr());
|
test[6].getValStr());
|
||||||
|
|
||||||
|
@ -928,7 +933,7 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_NONE,
|
SIGHASH_NONE,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[7].getValStr());
|
test[7].getValStr());
|
||||||
}
|
}
|
||||||
|
@ -938,7 +943,7 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_SINGLE,
|
SIGHASH_SINGLE,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[8].getValStr());
|
test[8].getValStr());
|
||||||
}
|
}
|
||||||
|
@ -948,7 +953,7 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_ALL | SIGHASH_ANYONECANPAY,
|
SIGHASH_ALL | SIGHASH_ANYONECANPAY,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[9].getValStr());
|
test[9].getValStr());
|
||||||
}
|
}
|
||||||
|
@ -958,7 +963,7 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_NONE | SIGHASH_ANYONECANPAY,
|
SIGHASH_NONE | SIGHASH_ANYONECANPAY,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[10].getValStr());
|
test[10].getValStr());
|
||||||
}
|
}
|
||||||
|
@ -968,7 +973,7 @@ BOOST_AUTO_TEST_CASE(TxV5)
|
||||||
SignatureHash(
|
SignatureHash(
|
||||||
scriptCode, tx, nIn,
|
scriptCode, tx, nIn,
|
||||||
SIGHASH_SINGLE | SIGHASH_ANYONECANPAY,
|
SIGHASH_SINGLE | SIGHASH_ANYONECANPAY,
|
||||||
amount, *tx.GetConsensusBranchId()
|
amount, *tx.GetConsensusBranchId(), txdata
|
||||||
).GetHex(),
|
).GetHex(),
|
||||||
test[11].getValStr());
|
test[11].getValStr());
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,8 +48,9 @@ BOOST_FIXTURE_TEST_CASE(tx_mempool_block_doublespend, TestChain100Setup)
|
||||||
spends[i].vout[0].scriptPubKey = scriptPubKey;
|
spends[i].vout[0].scriptPubKey = scriptPubKey;
|
||||||
|
|
||||||
// Sign:
|
// Sign:
|
||||||
|
const PrecomputedTransactionData txdata(spends[i]);
|
||||||
std::vector<unsigned char> vchSig;
|
std::vector<unsigned char> vchSig;
|
||||||
uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, coinbaseTxns[0].vout[0].nValue, SPROUT_BRANCH_ID);
|
uint256 hash = SignatureHash(scriptPubKey, spends[i], 0, SIGHASH_ALL, coinbaseTxns[0].vout[0].nValue, SPROUT_BRANCH_ID, txdata);
|
||||||
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
|
BOOST_CHECK(coinbaseKey.Sign(hash, vchSig));
|
||||||
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
vchSig.push_back((unsigned char)SIGHASH_ALL);
|
||||||
spends[i].vin[0].scriptSig << vchSig;
|
spends[i].vin[0].scriptSig << vchSig;
|
||||||
|
|
|
@ -446,12 +446,13 @@ TransactionBuilderResult TransactionBuilder::Build()
|
||||||
//
|
//
|
||||||
|
|
||||||
auto consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
|
auto consensusBranchId = CurrentEpochBranchId(nHeight, consensusParams);
|
||||||
|
const PrecomputedTransactionData txdata(mtx);
|
||||||
|
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
uint256 dataToBeSigned;
|
uint256 dataToBeSigned;
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
try {
|
try {
|
||||||
dataToBeSigned = SignatureHash(scriptCode, mtx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
dataToBeSigned = SignatureHash(scriptCode, mtx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
} catch (std::logic_error ex) {
|
} catch (std::logic_error ex) {
|
||||||
librustzcash_sapling_proving_ctx_free(ctx);
|
librustzcash_sapling_proving_ctx_free(ctx);
|
||||||
return TransactionBuilderResult("Could not construct signature hash: " + std::string(ex.what()));
|
return TransactionBuilderResult("Could not construct signature hash: " + std::string(ex.what()));
|
||||||
|
@ -498,7 +499,7 @@ TransactionBuilderResult TransactionBuilder::Build()
|
||||||
SignatureData sigdata;
|
SignatureData sigdata;
|
||||||
bool signSuccess = ProduceSignature(
|
bool signSuccess = ProduceSignature(
|
||||||
TransactionSignatureCreator(
|
TransactionSignatureCreator(
|
||||||
keystore, &txNewConst, nIn, tIn.value, SIGHASH_ALL),
|
keystore, &txNewConst, txdata, nIn, tIn.value, SIGHASH_ALL),
|
||||||
tIn.scriptPubKey, sigdata, consensusBranchId);
|
tIn.scriptPubKey, sigdata, consensusBranchId);
|
||||||
|
|
||||||
if (!signSuccess) {
|
if (!signSuccess) {
|
||||||
|
|
|
@ -69,7 +69,8 @@ CMutableTransaction GetValidSproutReceiveTransaction(
|
||||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
const PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(ed25519_sign(
|
assert(ed25519_sign(
|
||||||
|
@ -184,7 +185,8 @@ CWalletTx GetValidSproutSpend(const libzcash::SproutSpendingKey& sk,
|
||||||
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
uint32_t consensusBranchId = SPROUT_BRANCH_ID;
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
const PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(ed25519_sign(
|
assert(ed25519_sign(
|
||||||
|
|
|
@ -834,7 +834,8 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_);
|
PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId_, txdata);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
if (!ed25519_sign(
|
if (!ed25519_sign(
|
||||||
|
|
|
@ -361,7 +361,8 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
PrecomputedTransactionData txdata(signTx);
|
||||||
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
if (!ed25519_sign(
|
if (!ed25519_sign(
|
||||||
|
|
|
@ -2889,8 +2889,9 @@ UniValue zc_raw_joinsplit(const UniValue& params, bool fHelp)
|
||||||
// Empty output script.
|
// Empty output script.
|
||||||
CScript scriptCode;
|
CScript scriptCode;
|
||||||
CTransaction signTx(mtx);
|
CTransaction signTx(mtx);
|
||||||
|
PrecomputedTransactionData txdata(signTx);
|
||||||
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
auto consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus());
|
||||||
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId);
|
uint256 dataToBeSigned = SignatureHash(scriptCode, signTx, NOT_AN_INPUT, SIGHASH_ALL, 0, consensusBranchId, txdata);
|
||||||
|
|
||||||
// Add the signature
|
// Add the signature
|
||||||
assert(ed25519_sign(
|
assert(ed25519_sign(
|
||||||
|
|
|
@ -4767,13 +4767,14 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||||
// Sign
|
// Sign
|
||||||
int nIn = 0;
|
int nIn = 0;
|
||||||
CTransaction txNewConst(txNew);
|
CTransaction txNewConst(txNew);
|
||||||
|
const PrecomputedTransactionData txdata(txNewConst);
|
||||||
for (const std::pair<const CWalletTx*, unsigned int>& coin : setCoins)
|
for (const std::pair<const CWalletTx*, unsigned int>& coin : setCoins)
|
||||||
{
|
{
|
||||||
bool signSuccess;
|
bool signSuccess;
|
||||||
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
|
const CScript& scriptPubKey = coin.first->vout[coin.second].scriptPubKey;
|
||||||
SignatureData sigdata;
|
SignatureData sigdata;
|
||||||
if (sign)
|
if (sign)
|
||||||
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
|
signSuccess = ProduceSignature(TransactionSignatureCreator(this, &txNewConst, txdata, nIn, coin.first->vout[coin.second].nValue, SIGHASH_ALL), scriptPubKey, sigdata, consensusBranchId);
|
||||||
else
|
else
|
||||||
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
|
signSuccess = ProduceSignature(DummySignatureCreator(this), scriptPubKey, sigdata, consensusBranchId);
|
||||||
|
|
||||||
|
|
|
@ -238,10 +238,12 @@ double benchmark_large_tx(size_t nInputs)
|
||||||
spending_tx.vin.emplace_back(input_hash, 0);
|
spending_tx.vin.emplace_back(input_hash, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PrecomputedTransactionData txdata(spending_tx);
|
||||||
|
|
||||||
// Sign for all the inputs
|
// Sign for all the inputs
|
||||||
auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId;
|
auto consensusBranchId = NetworkUpgradeInfo[Consensus::UPGRADE_SAPLING].nBranchId;
|
||||||
for (size_t i = 0; i < nInputs; i++) {
|
for (size_t i = 0; i < nInputs; i++) {
|
||||||
SignSignature(tempKeystore, prevPubKey, spending_tx, i, 1000000, SIGHASH_ALL, consensusBranchId);
|
SignSignature(tempKeystore, prevPubKey, spending_tx, txdata, i, 1000000, SIGHASH_ALL, consensusBranchId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spending tx has all its inputs signed and does not need to be mutated anymore
|
// Spending tx has all its inputs signed and does not need to be mutated anymore
|
||||||
|
@ -250,13 +252,12 @@ double benchmark_large_tx(size_t nInputs)
|
||||||
// Benchmark signature verification costs:
|
// Benchmark signature verification costs:
|
||||||
struct timeval tv_start;
|
struct timeval tv_start;
|
||||||
timer_start(tv_start);
|
timer_start(tv_start);
|
||||||
PrecomputedTransactionData txdata(final_spending_tx);
|
|
||||||
for (size_t i = 0; i < nInputs; i++) {
|
for (size_t i = 0; i < nInputs; i++) {
|
||||||
ScriptError serror = SCRIPT_ERR_OK;
|
ScriptError serror = SCRIPT_ERR_OK;
|
||||||
assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
|
assert(VerifyScript(final_spending_tx.vin[i].scriptSig,
|
||||||
prevPubKey,
|
prevPubKey,
|
||||||
STANDARD_SCRIPT_VERIFY_FLAGS,
|
STANDARD_SCRIPT_VERIFY_FLAGS,
|
||||||
TransactionSignatureChecker(&final_spending_tx, i, 1000000, txdata),
|
TransactionSignatureChecker(&final_spending_tx, txdata, i, 1000000),
|
||||||
consensusBranchId,
|
consensusBranchId,
|
||||||
&serror));
|
&serror));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue