Skip to content

Commit c87b957

Browse files
TheBlueMattsipa
authored andcommitted
Only pass things committed to by tx's witness hash to CScriptCheck
This clarifies a bit more the ways in which the new script execution cache could break consensus in the future if additional data from the CCoins object were to be used as a part of script execution. After this change, any such consensus breaks should be very visible to reviewers, hopefully ensuring no such changes can be made.
1 parent f68cdfe commit c87b957

File tree

4 files changed

+16
-6
lines changed

4 files changed

+16
-6
lines changed

src/test/script_P2SH_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ BOOST_AUTO_TEST_CASE(sign)
112112
{
113113
CScript sigSave = txTo[i].vin[0].scriptSig;
114114
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
115-
bool sigOK = CScriptCheck(CCoins(txFrom, 0), txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
115+
const CTxOut& output = txFrom.vout[txTo[i].vin[0].prevout.n];
116+
bool sigOK = CScriptCheck(output.scriptPubKey, output.nValue, txTo[i], 0, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC, false, &txdata)();
116117
if (i == j)
117118
BOOST_CHECK_MESSAGE(sigOK, strprintf("VerifySignature %d %d", i, j));
118119
else

src/test/transaction_tests.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,8 @@ BOOST_AUTO_TEST_CASE(test_big_witness_transaction) {
481481

482482
for(uint32_t i = 0; i < mtx.vin.size(); i++) {
483483
std::vector<CScriptCheck> vChecks;
484-
CScriptCheck check(coins, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata);
484+
const CTxOut& output = coins.vout[tx.vin[i].prevout.n];
485+
CScriptCheck check(output.scriptPubKey, output.nValue, tx, i, SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_WITNESS, false, &txdata);
485486
vChecks.push_back(CScriptCheck());
486487
check.swap(vChecks.back());
487488
control.Add(vChecks);

src/validation.cpp

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,8 +1119,16 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
11191119
const CCoins* coins = inputs.AccessCoins(prevout.hash);
11201120
assert(coins);
11211121

1122+
// We very carefully only pass in things to CScriptCheck which
1123+
// are clearly committed to by tx' witness hash. This provides
1124+
// a sanity check that our caching is not introducing consensus
1125+
// failures through additional data in, eg, the coins being
1126+
// spent being checked as a part of CScriptCheck.
1127+
const CScript& scriptPubKey = coins->vout[prevout.n].scriptPubKey;
1128+
const CAmount amount = coins->vout[prevout.n].nValue;
1129+
11221130
// Verify signature
1123-
CScriptCheck check(*coins, tx, i, flags, cacheStore, &txdata);
1131+
CScriptCheck check(scriptPubKey, amount, tx, i, flags, cacheStore, &txdata);
11241132
if (pvChecks) {
11251133
pvChecks->push_back(CScriptCheck());
11261134
check.swap(pvChecks->back());
@@ -1132,7 +1140,7 @@ bool CheckInputs(const CTransaction& tx, CValidationState &state, const CCoinsVi
11321140
// arguments; if so, don't trigger DoS protection to
11331141
// avoid splitting the network between upgraded and
11341142
// non-upgraded nodes.
1135-
CScriptCheck check2(*coins, tx, i,
1143+
CScriptCheck check2(scriptPubKey, amount, tx, i,
11361144
flags & ~STANDARD_NOT_MANDATORY_VERIFY_FLAGS, cacheStore, &txdata);
11371145
if (check2())
11381146
return state.Invalid(false, REJECT_NONSTANDARD, strprintf("non-mandatory-script-verify-flag (%s)", ScriptErrorString(check.GetScriptError())));

src/validation.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,8 +404,8 @@ class CScriptCheck
404404

405405
public:
406406
CScriptCheck(): amount(0), ptxTo(0), nIn(0), nFlags(0), cacheStore(false), error(SCRIPT_ERR_UNKNOWN_ERROR) {}
407-
CScriptCheck(const CCoins& txFromIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
408-
scriptPubKey(txFromIn.vout[txToIn.vin[nInIn].prevout.n].scriptPubKey), amount(txFromIn.vout[txToIn.vin[nInIn].prevout.n].nValue),
407+
CScriptCheck(const CScript& scriptPubKeyIn, const CAmount amountIn, const CTransaction& txToIn, unsigned int nInIn, unsigned int nFlagsIn, bool cacheIn, PrecomputedTransactionData* txdataIn) :
408+
scriptPubKey(scriptPubKeyIn), amount(amountIn),
409409
ptxTo(&txToIn), nIn(nInIn), nFlags(nFlagsIn), cacheStore(cacheIn), error(SCRIPT_ERR_UNKNOWN_ERROR), txdata(txdataIn) { }
410410

411411
bool operator()();

0 commit comments

Comments
 (0)