Skip to content

Commit b77b0cc

Browse files
committed
Add MissingDataBehavior and make TransactionSignatureChecker handle it
This allows specifying how *TransactionSignatureChecker will behave when presented with missing transaction data such as amounts spent, BIP341 data, or spent outputs. As all call sites still (implicitly) use MissingDataBehavior::ASSERT_FAIL, this commit introduces no change in behavior.
1 parent 4ba1bab commit b77b0cc

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

src/script/interpreter.cpp

+17-3
Original file line numberDiff line numberDiff line change
@@ -1488,8 +1488,20 @@ static const CHashWriter HASHER_TAPLEAF = TaggedHash("TapLeaf");
14881488
static const CHashWriter HASHER_TAPBRANCH = TaggedHash("TapBranch");
14891489
static const CHashWriter HASHER_TAPTWEAK = TaggedHash("TapTweak");
14901490

1491+
static bool HandleMissingData(MissingDataBehavior mdb)
1492+
{
1493+
switch (mdb) {
1494+
case MissingDataBehavior::ASSERT_FAIL:
1495+
assert(!"Missing data");
1496+
break;
1497+
case MissingDataBehavior::FAIL:
1498+
return false;
1499+
}
1500+
assert(!"Unknown MissingDataBehavior value");
1501+
}
1502+
14911503
template<typename T>
1492-
bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache)
1504+
bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata, const T& tx_to, uint32_t in_pos, uint8_t hash_type, SigVersion sigversion, const PrecomputedTransactionData& cache, MissingDataBehavior mdb)
14931505
{
14941506
uint8_t ext_flag, key_version;
14951507
switch (sigversion) {
@@ -1509,7 +1521,9 @@ bool SignatureHashSchnorr(uint256& hash_out, const ScriptExecutionData& execdata
15091521
assert(false);
15101522
}
15111523
assert(in_pos < tx_to.vin.size());
1512-
assert(cache.m_bip341_taproot_ready && cache.m_spent_outputs_ready);
1524+
if (!(cache.m_bip341_taproot_ready && cache.m_spent_outputs_ready)) {
1525+
return HandleMissingData(mdb);
1526+
}
15131527

15141528
CHashWriter ss = HASHER_TAPSIGHASH;
15151529

@@ -1696,7 +1710,7 @@ bool GenericTransactionSignatureChecker<T>::CheckSchnorrSignature(Span<const uns
16961710
}
16971711
uint256 sighash;
16981712
assert(this->txdata);
1699-
if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, *this->txdata)) {
1713+
if (!SignatureHashSchnorr(sighash, execdata, *txTo, nIn, hashtype, sigversion, *this->txdata, m_mdb)) {
17001714
return set_error(serror, SCRIPT_ERR_SCHNORR_SIG_HASHTYPE);
17011715
}
17021716
if (!VerifySchnorrSignature(sig, pubkey, sighash)) return set_error(serror, SCRIPT_ERR_SCHNORR_SIG);

src/script/interpreter.h

+12-2
Original file line numberDiff line numberDiff line change
@@ -247,11 +247,21 @@ class BaseSignatureChecker
247247
virtual ~BaseSignatureChecker() {}
248248
};
249249

250+
/** Enum to specify what *TransactionSignatureChecker's behavior should be
251+
* when dealing with missing transaction data.
252+
*/
253+
enum class MissingDataBehavior
254+
{
255+
ASSERT_FAIL, //!< Abort execution through assertion failure (for consensus code)
256+
FAIL, //!< Just act as if the signature was invalid
257+
};
258+
250259
template <class T>
251260
class GenericTransactionSignatureChecker : public BaseSignatureChecker
252261
{
253262
private:
254263
const T* txTo;
264+
const MissingDataBehavior m_mdb;
255265
unsigned int nIn;
256266
const CAmount amount;
257267
const PrecomputedTransactionData* txdata;
@@ -261,8 +271,8 @@ class GenericTransactionSignatureChecker : public BaseSignatureChecker
261271
virtual bool VerifySchnorrSignature(Span<const unsigned char> sig, const XOnlyPubKey& pubkey, const uint256& sighash) const;
262272

263273
public:
264-
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
265-
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn) : txTo(txToIn), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
274+
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, MissingDataBehavior mdb = MissingDataBehavior::ASSERT_FAIL) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(nullptr) {}
275+
GenericTransactionSignatureChecker(const T* txToIn, unsigned int nInIn, const CAmount& amountIn, const PrecomputedTransactionData& txdataIn, MissingDataBehavior mdb = MissingDataBehavior::ASSERT_FAIL) : txTo(txToIn), m_mdb(mdb), nIn(nInIn), amount(amountIn), txdata(&txdataIn) {}
266276
bool CheckECDSASignature(const std::vector<unsigned char>& scriptSig, const std::vector<unsigned char>& vchPubKey, const CScript& scriptCode, SigVersion sigversion) const override;
267277
bool CheckSchnorrSignature(Span<const unsigned char> sig, Span<const unsigned char> pubkey, SigVersion sigversion, const ScriptExecutionData& execdata, ScriptError* serror = nullptr) const override;
268278
bool CheckLockTime(const CScriptNum& nLockTime) const override;

0 commit comments

Comments
 (0)