@@ -3119,14 +3119,14 @@ uint32_t GenericTransactionSignatureChecker<T>::GetnIn() const
31193119}
31203120
31213121template <class T >
3122- bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& program, const valtype& witness, const rawElementsTapEnv& simplicityRawTap, int64_t budget, ScriptError* serror) const
3122+ bool GenericTransactionSignatureChecker<T>::CheckSimplicity(const valtype& program, const valtype& witness, const rawElementsTapEnv& simplicityRawTap, int64_t minCost, int64_t budget, ScriptError* serror) const
31233123{
31243124 simplicity_err error;
31253125 elementsTapEnv* simplicityTapEnv = simplicity_elements_mallocTapEnv (&simplicityRawTap);
31263126
31273127 assert (txdata->m_simplicity_tx_data );
31283128 assert (simplicityTapEnv);
3129- if (!simplicity_elements_execSimplicity (&error, 0 , txdata->m_simplicity_tx_data .get (), nIn, simplicityTapEnv, txdata->m_hash_genesis_block .data (), 0 , budget, 0 , program.data (), program.size (), witness.data (), witness.size ())) {
3129+ if (!simplicity_elements_execSimplicity (&error, 0 , txdata->m_simplicity_tx_data .get (), nIn, simplicityTapEnv, txdata->m_hash_genesis_block .data (), minCost , budget, 0 , program.data (), program.size (), witness.data (), witness.size ())) {
31303130 assert (!" simplicity_elements_execSimplicity internal error" );
31313131 }
31323132 simplicity_elements_freeTapEnv (simplicityTapEnv);
@@ -3278,9 +3278,11 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
32783278 // BIP341 Taproot: 32-byte non-P2SH witness v1 program (which encodes a P2C-tweaked pubkey)
32793279 if (!(flags & SCRIPT_VERIFY_TAPROOT)) return set_success (serror);
32803280 if (stack.size () == 0 ) return set_error (serror, SCRIPT_ERR_WITNESS_PROGRAM_WITNESS_EMPTY);
3281+ valtype annex;
32813282 if (stack.size () >= 2 && !stack.back ().empty () && stack.back ()[0 ] == ANNEX_TAG) {
32823283 // Drop annex (this is non-standard; see IsWitnessStandard)
3283- const valtype& annex = SpanPopBack (stack);
3284+ // ELEMENTS: store the annex for CheckSimplicity
3285+ annex = SpanPopBack (stack);
32843286 execdata.m_annex_hash = (CHashWriter (SER_GETHASH, 0 ) << annex).GetSHA256 ();
32853287 execdata.m_annex_present = true ;
32863288 } else {
@@ -3322,7 +3324,27 @@ static bool VerifyWitnessProgram(const CScriptWitness& witness, int witversion,
33223324 simplicityRawTap.controlBlock = control.data ();
33233325 simplicityRawTap.pathLen = (control.size () - TAPROOT_CONTROL_BASE_SIZE) / TAPROOT_CONTROL_NODE_SIZE;
33243326 simplicityRawTap.scriptCMR = script_bytes.data ();
3325- return checker.CheckSimplicity (simplicity_program, simplicity_witness, simplicityRawTap, budget, serror);
3327+ // If there is no annex, or we are in consensus checking mode, minCost is set to 0 which effectively disables any overweight cost checks.
3328+ int64_t minCost = 0 ;
3329+ if ((flags & SCRIPT_VERIFY_ANNEX_PADDING) && annex.size () > 0 ) {
3330+ valtype zero_padding (annex.size (), 0 );
3331+ zero_padding[0 ] = ANNEX_TAG;
3332+ if (annex != zero_padding) {
3333+ return set_error (serror, SCRIPT_ERR_SIMPLICITY_PADDING_NONZERO);
3334+ }
3335+ // Compute what the budget would have been without the padding.
3336+ // budget includes the padding cost, so subtracting this stack item won't underflow.
3337+ minCost = budget - ::GetSerializeSize (annex);
3338+ // If the annex exists and is empty (i.e. its size is 1), then the only way the annex could be smaller is by eliminating it entirely.
3339+ // So we use the above computed value for minCost. Note: in that case the minCost is 2 WU less than the budget.
3340+
3341+ // If the annex exists and is non-empty, then we add to minCost the value of an annex that contains one fewer byte.
3342+ if (zero_padding.size () > 1 ) {
3343+ zero_padding.pop_back ();
3344+ minCost += ::GetSerializeSize (zero_padding);
3345+ }
3346+ }
3347+ return checker.CheckSimplicity (simplicity_program, simplicity_witness, simplicityRawTap, minCost, budget, serror);
33263348 }
33273349 if (flags & SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION) {
33283350 return set_error (serror, SCRIPT_ERR_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION);
0 commit comments