<p>One reason is to prevent malleability, which affects the weight of the transaction, and therefore the feerate. The only valid options for <code>OP_CHECKSIGADD</code> are the empty vector, or a valid signature. So the signature must be valid, or intentionally empty. Otherwise, a third party could choose any of the signatures which are intentionally empty or invalid, replace it with junk, and the script could still pass. This junk could be longer than the empty vector, and depending on the possible rules in this scenario, could be variable length, longer or shorter than a valid signature, which would affect the weight, and thus affect the feerate.</p>

CC BY-SA 4.0
2022-07-12T02:04:40.620Z
2022-07-12T02:04:40.620Z
Ava Chow
<p>Invalid signatures <em>generally</em> abort execution in BIP342, because of batch validation, as batch validation has no mechanism for figuring out which signature checks were invalid - only whether or not all are valid or not. Batch validation is not implemented anywhere AFAIK, but BIP340-342 are designed to support it, and thus must reject anything invalid to prevent a consensus failure once it is rolled out.</p>
<p>If you want a signature to not be counted (whether through OP_CHECKSIG or OP_CHECKSIGADD), the signature needs to be exactly equal to the empty string. If an empty string is provided as signature, it is treated as an <em>intentionally missing</em> signature, and counted as 0. But if you provide an actual signature, it must be valid.</p>

CC BY-SA 4.0
2022-07-12T12:30:55.587Z
Assuming batch validation wasn't a consideration it would be a trade-off between malleability (Andrew's answer) and flexibility/forgiveness (allowing a participant in the threshold sig to make a mistake and it not impact the validity of the transaction as long as there were enough valid signatures)? Just trying to understand if malleability was a serious factor in the design decision or not.
Michael Folkson
CC BY-SA 4.0
2022-07-12T14:13:49.950Z
Yeah, I think the malleability argument is also a sufficient, albeit weaker, reason to disallow invalid non-empty signatures (and one that can to some extent be addressed using standardness rules too). It's just generally a cleaner design IMO, allowing more easy reasoning about which signatures are intended to be valid.
Pieter Wuille
CC BY-SA 4.0
2022-07-12T02:00:36.187Z
2022-07-12T02:18:26.270Z
2022-07-12T02:18:26.270Z
Pieter Wuille
<p>I've been working through the <a href="https://raw.githubusercontent.com/bitcoin-core/qa-assets/main/unit_test_data/script_assets_test.json" rel="nofollow noreferrer">static test vectors</a> provided by bitcoin core to implement an interpreter.</p>
<p>Some surprising behavior I found was that in the case of <code>OP_CHECKSIGADD</code>, if an invalid signature is found, the interpreter fails execution rather than continuing. Why is this the case?</p>
<p>In my (likely naive) mental model, it seems that an incorrect signature should not increment the counter on the stack and continue execution.</p>
<p><a href="https://github.com/bitcoin/bitcoin/blob/c92eb6cda0f402b83263c9a9ee129d5d0763fd3f/src/script/interpreter.cpp#L1096" rel="nofollow noreferrer">https://github.com/bitcoin/bitcoin/blob/c92eb6cda0f402b83263c9a9ee129d5d0763fd3f/src/script/interpreter.cpp#L1096</a></p>
<p>This is the test case that triggers the behavior i'm talking about</p>
<pre><code>  {
    &quot;tx&quot;: &quot;020000000342dbdd00df8ddb7968f88bd7c899d66c3007e19d1c71ddba2274f9e900c0cefa82010000006edc7db5db38e3ab6ba99b0b810400a211882152d27173c6a7945a40fe23b7924bff77cf6c0000000092d3c19742dbdd00df8ddb7968f88bd7c899d66c3007e19d1c71ddba2274f9e900c0cefa6101000000a1ea36c301b2d549000000000017a9142177f6af7e86b98028c5e4dd4a82d80f1c6492c7876f818b44&quot;,
    &quot;prevouts&quot;: [&quot;69cd3300000000001976a91410fa7d1c37dc119ceef9b79ec2d4abe7445c468188ac&quot;, &quot;1d6a7600000000002251203b1c3f3adebc2e153ec7d8063cf0f2bb534171c554c0e969269a2f02dddd03f4&quot;, &quot;1f49370000000000225120281511f00d3c3de3d36983e73a04295adb745511db699ce19d0d5331754dadf8&quot;],
    &quot;index&quot;: 2, &quot;flags&quot;: &quot;P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT&quot;,
    &quot;comment&quot;: &quot;siglen/invalid_csa_neg&quot;,
    &quot;final&quot;: true,
    //omit success as it isn't necessary
    &quot;failure&quot;: {
      &quot;scriptSig&quot;: &quot;&quot;,
      &quot;witness&quot;: [
        &quot;ad71936bf8c2bfa761dd70af336e9f3f01f1dc7208f473d548ee025caad1f7fcf020bacfcfbad5b8be77f70655b59824a27fa025b1cefda56a5ca4c5592fafe6&quot;,
        &quot;5220add82ad8000e562efe2b4f7447016e9f9fd3eb73e56e6b0f099c85aedcf34a7cba5287&quot;,
        &quot;c106c3f692377db31176526c691d50a518c745f9aac8c0da21802f7a7652bd9a9d60808dd6363137648795cfbd150458b8cdf5ab35fe9dfd73ca2c2f21059349becc7442164c6ea9ce87a72f0d7197d1c06ae67d7b0f2a864ef793135a35fddbd9&quot;
      ]
    }
  }
</code></pre>

<script><multi-signature><taproot><opcodes>
Why do invalid signatures in OP_CHECKSIGADD not push to the stack?
Chris Stewart
# Why do invalid signatures in OP_CHECKSIGADD not push to the stack?

(Asked by: username_0 on 2022-07-12)

I've been working through the [static test vectors](https://raw.githubusercontent.com/bitcoin-core/qa-assets/main/unit_test_data/script_assets_test.json) provided by bitcoin core to implement an interpreter.

Some surprising behavior I found was that in the case of `OP_CHECKSIGADD`, if an invalid signature is found, the interpreter fails execution rather than continuing. Why is this the case?

In my (likely naive) mental model, it seems that an incorrect signature should not increment the counter on the stack and continue execution.

<https://github.com/bitcoin/bitcoin/blob/c92eb6cda0f402b83263c9a9ee129d5d0763fd3f/src/script/interpreter.cpp#L1096>

This is the test case that triggers the behavior i'm talking about

```
  {
    "tx": "020000000342dbdd00df8ddb7968f88bd7c899d66c3007e19d1c71ddba2274f9e900c0cefa82010000006edc7db5db38e3ab6ba99b0b810400a211882152d27173c6a7945a40fe23b7924bff77cf6c0000000092d3c19742dbdd00df8ddb7968f88bd7c899d66c3007e19d1c71ddba2274f9e900c0cefa6101000000a1ea36c301b2d549000000000017a9142177f6af7e86b98028c5e4dd4a82d80f1c6492c7876f818b44",
    "prevouts": ["69cd3300000000001976a91410fa7d1c37dc119ceef9b79ec2d4abe7445c468188ac", "1d6a7600000000002251203b1c3f3adebc2e153ec7d8063cf0f2bb534171c554c0e969269a2f02dddd03f4", "1f49370000000000225120281511f00d3c3de3d36983e73a04295adb745511db699ce19d0d5331754dadf8"],
    "index": 2, "flags": "P2SH,DERSIG,CHECKLOCKTIMEVERIFY,CHECKSEQUENCEVERIFY,WITNESS,NULLDUMMY,TAPROOT",
    "comment": "siglen/invalid_csa_neg",
    "final": true,
    //omit success as it isn't necessary
    "failure": {
      "scriptSig": "",
      "witness": [
        "ad71936bf8c2bfa761dd70af336e9f3f01f1dc7208f473d548ee025caad1f7fcf020bacfcfbad5b8be77f70655b59824a27fa025b1cefda56a5ca4c5592fafe6",
        "5220add82ad8000e562efe2b4f7447016e9f9fd3eb73e56e6b0f099c85aedcf34a7cba5287",
        "c106c3f692377db31176526c691d50a518c745f9aac8c0da21802f7a7652bd9a9d60808dd6363137648795cfbd150458b8cdf5ab35fe9dfd73ca2c2f21059349becc7442164c6ea9ce87a72f0d7197d1c06ae67d7b0f2a864ef793135a35fddbd9"
      ]
    }
  }

```

**Tags:** script, multi-signature, taproot, opcodes


---

## 2 answers

### Answer by username_2 on 2022-07-12. Score: 5 | Accepted answer

Invalid signatures *generally* abort execution in BIP342, because of batch validation, as batch validation has no mechanism for figuring out which signature checks were invalid - only whether or not all are valid or not. Batch validation is not implemented anywhere AFAIK, but BIP340-342 are designed to support it, and thus must reject anything invalid to prevent a consensus failure once it is rolled out.

If you want a signature to not be counted (whether through OP\_CHECKSIG or OP\_CHECKSIGADD), the signature needs to be exactly equal to the empty string. If an empty string is provided as signature, it is treated as an *intentionally missing* signature, and counted as 0. But if you provide an actual signature, it must be valid.

> **Comments:**
> **username_3**: Assuming batch validation wasn't a consideration it would be a trade-off between malleability (Andrew's answer) and flexibility/forgiveness (allowing a participant in the threshold sig to make a mistake and it not impact the validity of the transaction as long as there were enough valid signatures)? Just trying to understand if malleability was a serious factor in the design decision or not.  
> **username_2**: Yeah, I think the malleability argument is also a sufficient, albeit weaker, reason to disallow invalid non-empty signatures (and one that can to some extent be addressed using standardness rules too). It's just generally a cleaner design IMO, allowing more easy reasoning about which signatures are intended to be valid.  

---

### Answer by username_1 on 2022-07-12. Score: 5

One reason is to prevent malleability, which affects the weight of the transaction, and therefore the feerate. The only valid options for `OP_CHECKSIGADD` are the empty vector, or a valid signature. So the signature must be valid, or intentionally empty. Otherwise, a third party could choose any of the signatures which are intentionally empty or invalid, replace it with junk, and the script could still pass. This junk could be longer than the empty vector, and depending on the possible rules in this scenario, could be variable length, longer or shorter than a valid signature, which would affect the weight, and thus affect the feerate.


---

