<p>Eltoo relies on a primitive <code>SIGHASH_ANYPREVOUT</code> or <code>SIGHASH_NOINPUT</code> (hereafter referred as APO) <a href="https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki" rel="noreferrer">BPI118</a>, constructing Eltoo from APO would be replacing the <code>CHECKSIG</code> figure 4 of <a href="https://blockstream.com/eltoo.pdf" rel="noreferrer">Eltoo paper</a> with a modified script.</p>
<p>Most of this answer is based on a blog post by Russell O'Connor from <a href="https://blockstream.com/2016/11/02/en-covenants-in-elements-alpha/" rel="noreferrer">this link</a>(which goes into other covenant constructions too). For completeness, let us look at the basics of transaction introspection and later hop into how to construct <code>APO</code>. The answer is for Segwit Signature Hash and the ECDSA signature algorithm. Unfortunately, extending this to taproot requires additional opcodes/other changes which I will explain at the end of the answer.</p>
<ol>
<li><code>OP_CHECKSIGFROMSTACK</code>:(hereafter <code>CSFS</code>) There is no formal proposal for this opcode yet, but most likely this would work as follows: pop 1) a pubkey<code> pk</code>, 2) a message <code>m</code>, and a 3) digital signature <code>sig</code>. The operation would perform the verify the sig as ECSDA.Verify(pk, sha256(m), sig) and push the result onto the stack top.</li>
<li>OP_CAT: Pop two items from stack <code>top</code> and <code>next_top</code> and push <code>next_top || top</code> onto the stack where <code>||</code> denotes the byte string concatenation. I will be assuming a <code>SIGHASH_ALL</code> for the below construction, but the construction can be used for sighash type.</li>
</ol>
<p>First we will look at basic transaction introspection using <code>OP_CAT</code> and <code>OP_CSFS</code>:
Consider the following script:</p>
<pre><code>1. OP_OVER OP_SHA256 &lt;pubKey&gt;
2. 2 OP_PICK 1 OP_CAT OP_OVER
3. OP_CHECKSIGVERIFY
4. OP_CHECKSIGFROMSTACKVERIFY
</code></pre>
<p>with the witness stack</p>
<pre><code>&lt;sig&gt;
&lt;sig_msg&gt;
</code></pre>
<p>Where <code>&lt;fixed_pk&gt;</code> is public whose secret key is known to everyone. Say, the generator <code>G</code> whose secret key is <code>1</code>. <code>&lt;sig_msg&gt;</code> denotes transition digest being signed.</p>
<p>At the end of Step 1, the stack is</p>
<pre><code>&lt;pubKey&gt;
&lt;sha256(&lt;sig_msg&gt;)&gt;
&lt;signature&gt;
&lt;&lt;sig_msg&gt;&gt;
</code></pre>
<p>At the end of step 2, the stack contents are</p>
<pre><code>&lt;pubKey&gt;
&lt;sig;SIGHASH_ALL&gt;
&lt;pubKey&gt;
&lt;sha256(sig_msg)&gt;
&lt;sig&gt;
&lt;sig_msg&gt;
</code></pre>
<p>Note that <code>1</code> is translated as <code>SIGHASH_ALL</code> and catted to <code>sig</code>. This creates a regular bitcoin signature which we can verify using regular <code>OP_CHECKSIG</code>. After Step 3, the stack contents are</p>
<pre><code>&lt;pubKey&gt;
&lt;sha256(sig_msg)&gt;
&lt;sig&gt;
&lt;sig_msg&gt;
</code></pre>
<p>Which would call <code>OP_CHECKSIGFROMSTACKVERIFY</code> to leave only <code>&lt;sig_msg&gt;</code> onto the stack. The OP_CHECKSIGFROMSTACKVERIFY of step 4 uses the same pubKey and signature. This operation performs another SHA-256(double sha256 is required for segwit sighash algorithm) and does a digital signature validation on the doubly hashed &lt;sig_msg&gt;. Note that because we are using exactly the same <code>&lt;pubKey&gt;</code> and <code>&lt;sig&gt;</code> that we used for the previous <code>OP_CHECKSIGVERIFY</code> operation, the current <code>OP_CHECKSIGFROMSTACKVERIFY</code> can only succeed if &lt;sig_msg&gt; is identical to the message that was checked during step 3’s OP_CHECKSIGVERIFY operation. At this point, we are certain that the <code>&lt;sig_msg&gt;</code> on the stack top is the same as the signed transaction message.</p>
<p><em>Note that</em> since the private key to <code>&lt;fixed_pk&gt;</code> is known, anyone can create this signature, but this script would only succeed if the <code>&lt;sig_msg&gt;</code> is correctly specified as mentioned above.</p>
<p><strong>Onto ANYPREVOUT</strong>:</p>
<p>Anyprevout essentially is substituting some things from the regular signature hash messages and replacing those with 0's. In detail, we can now split our <code>sig_msg</code> into multiple parts as defined in <a href="https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki" rel="noreferrer">BIP143</a> using <code>OP_SUBSTR</code>. It is also possible to use <code>OP_CAT</code> to initially supply the split up the message and then CAT it together.</p>
<p>Now that we have signature hash message as per BIP143 on the stack, we manipulate it to make certain fields 0's. In particular, we make items 2-4 0.</p>
<pre><code>2. hashPrevouts (32-byte hash)
3. hashSequence (32-byte hash)
4. outpoint (32-byte hash + 4-byte little endian) 
</code></pre>
<p>We take a <code>OP_DUP OP_SUSTR 0 &lt;4&gt;</code> to get item 1, version. onto the stack. and similarly, obtain a concatenation of items 5-10 onto the stack. Finally, we CAT them together by <code>&lt;ver&gt; &lt;[0; (32+ 32 + (32 +4))]&gt;</code> &lt;items 5.10&gt;` to get a new sighash which we use for Eltoo update key.</p>
<p>Let <code>introspect_script</code> =</p>
<pre><code>OP_OVER OP_SHA256 &lt;pubKey&gt; 2 OP_PICK 1 OP_CAT OP_OVER OP_CHECKSIGVERIFY OP_CHECKSIGFROMSTACKVERIFY
</code></pre>
<p>as we discussed above. And let <code>manipulate_txdata_script</code> be the script to modify the stack contents from BIP143 sighash message to get a new message which sets the respective items to <code>0s</code>. Then our final substitute for <code>OP_CHECKSIGANYPREVOUT</code> would be the following script.</p>
<pre><code>final_script(eltoo_pk) = &lt;introspect_script&gt; &lt;manipulate_txdata_script&gt; &lt;eltoo_pk&gt; OP_CSFS
</code></pre>
<p>Satisfying this would require the following onto the initial witness stack.</p>
<pre><code>&lt;sig_from_fixed_key&gt;
&lt;sig_msg&gt;
&lt;sig_from_eltoo_update_priv_key&gt;
</code></pre>
<p>Lastly, the eltoo script would now look like:</p>
<pre><code>OP_IF
    10 OP_CSV
    2 A(s,i) B(s,i) 2 OP_CHECKMULTISIGVERIFY
OP_ELSE
    &lt;Si + 1&gt; OP_CHECKLOCKTIMEVERIFY
    final_script(Au) final_script(Bu)
OP_ENDIF
</code></pre>
<p>Note how the two of two multi-sig is split into two parts.</p>
<p><strong>Taproot Signature Hash:</strong></p>
<p>The same technique does not work for Taproot Signature Hash algorithm(see <a href="https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki" rel="noreferrer">BIP341</a>) and Schnorr signatures (see <a href="https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki" rel="noreferrer">BIP340</a>) because of tagged hashes. At a high level, because of tags, the size of these messages is more than 520 bytes which is currently the maximum supported by bitcoin network. It is possible to overcome this limitation by adding 1)streaming <code>SHA256</code> opcodes, 2) by raising the per stack element limit, Or 3) adding support for tagged hashes by new opcodes.</p>

CC BY-SA 4.0
2021-07-22T08:45:33.827Z
2021-07-22T08:50:41.947Z
2021-07-22T08:50:41.947Z
sanket1729
<p>I <a href="https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016946.html" rel="noreferrer">read on bitcoin-dev</a> that CHECKSIGFROMSTACKVERIFY (CHECKDATASIG in BCash) can be used to emulate new sighash flags. How would that work, concretely? As an example, please provide an example update transaction based on figure 4 of the <a href="https://blockstream.com/eltoo.pdf" rel="noreferrer">Eltoo paper</a>, or <a href="https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-July/001363.html" rel="noreferrer">aj's simplified lightning (that doesn't work with watchtowers)</a>.</p>

CC BY-SA 4.0
2021-01-28T18:14:31.243Z
You also need OP_CAT or OP_SUBSTR. If you are still interested in this question, I can answer this in detail
sanket1729
CC BY-SA 4.0
2021-01-28T20:49:24.027Z
@sanket1729, Yes, I am still interested! Thanks! Looking forward to reading your answer.
Janus Troelsen
CC BY-SA 4.0
2021-07-22T08:46:22.507Z
Sorry for the super long delay, I finally have an answer for you. This may be a lot to take in, so let me know if something needs more clarification.
sanket1729
<lightning-network><liquid><eltoo><bip118-sighash-anyprevout>
How to emulate SIGHASH_NOINPUT using CHECKSIGFROMSTACKVERIFY?
Janus Troelsen
# How to emulate SIGHASH_NOINPUT using CHECKSIGFROMSTACKVERIFY?

(Asked by: username_0 on 2019-08-01)

I [read on bitcoin-dev](https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2019-May/016946.html) that CHECKSIGFROMSTACKVERIFY (CHECKDATASIG in BCash) can be used to emulate new sighash flags. How would that work, concretely? As an example, please provide an example update transaction based on figure 4 of the [Eltoo paper](https://blockstream.com/eltoo.pdf), or [aj's simplified lightning (that doesn't work with watchtowers)](https://lists.linuxfoundation.org/pipermail/lightning-dev/2018-July/001363.html).

**Tags:** lightning-network, liquid, eltoo, bip118-sighash-anyprevout

> **Comments:**
> **username_1**: You also need OP_CAT or OP_SUBSTR. If you are still interested in this question, I can answer this in detail  
> **username_0**: @username_1, Yes, I am still interested! Thanks! Looking forward to reading your answer.  
> **username_1**: Sorry for the super long delay, I finally have an answer for you. This may be a lot to take in, so let me know if something needs more clarification.  

---

## 1 answers

### Answer by username_1 on 2021-07-22. Score: 7 | Accepted answer

Eltoo relies on a primitive `SIGHASH_ANYPREVOUT` or `SIGHASH_NOINPUT` (hereafter referred as APO) [BPI118](https://github.com/bitcoin/bips/blob/master/bip-0118.mediawiki), constructing Eltoo from APO would be replacing the `CHECKSIG` figure 4 of [Eltoo paper](https://blockstream.com/eltoo.pdf) with a modified script.

Most of this answer is based on a blog post by Russell O'Connor from [this link](https://blockstream.com/2016/11/02/en-covenants-in-elements-alpha/)(which goes into other covenant constructions too). For completeness, let us look at the basics of transaction introspection and later hop into how to construct `APO`. The answer is for Segwit Signature Hash and the ECDSA signature algorithm. Unfortunately, extending this to taproot requires additional opcodes/other changes which I will explain at the end of the answer.

1. `OP_CHECKSIGFROMSTACK`:(hereafter `CSFS`) There is no formal proposal for this opcode yet, but most likely this would work as follows: pop 1) a pubkey `pk`, 2) a message `m`, and a 3) digital signature `sig`. The operation would perform the verify the sig as ECSDA.Verify(pk, sha256(m), sig) and push the result onto the stack top.
2. OP\_CAT: Pop two items from stack `top` and `next_top` and push `next_top || top` onto the stack where `||` denotes the byte string concatenation. I will be assuming a `SIGHASH_ALL` for the below construction, but the construction can be used for sighash type.

First we will look at basic transaction introspection using `OP_CAT` and `OP_CSFS`:
Consider the following script:

```
1. OP_OVER OP_SHA256 <pubKey>
2. 2 OP_PICK 1 OP_CAT OP_OVER
3. OP_CHECKSIGVERIFY
4. OP_CHECKSIGFROMSTACKVERIFY

```

with the witness stack

```
<sig>
<sig_msg>

```

Where `<fixed_pk>` is public whose secret key is known to everyone. Say, the generator `G` whose secret key is `1`. `<sig_msg>` denotes transition digest being signed.

At the end of Step 1, the stack is

```
<pubKey>
<sha256(<sig_msg>)>
<signature>
<<sig_msg>>

```

At the end of step 2, the stack contents are

```
<pubKey>
<sig;SIGHASH_ALL>
<pubKey>
<sha256(sig_msg)>
<sig>
<sig_msg>

```

Note that `1` is translated as `SIGHASH_ALL` and catted to `sig`. This creates a regular bitcoin signature which we can verify using regular `OP_CHECKSIG`. After Step 3, the stack contents are

```
<pubKey>
<sha256(sig_msg)>
<sig>
<sig_msg>

```

Which would call `OP_CHECKSIGFROMSTACKVERIFY` to leave only `<sig_msg>` onto the stack. The OP\_CHECKSIGFROMSTACKVERIFY of step 4 uses the same pubKey and signature. This operation performs another SHA-256(double sha256 is required for segwit sighash algorithm) and does a digital signature validation on the doubly hashed <sig\_msg>. Note that because we are using exactly the same `<pubKey>` and `<sig>` that we used for the previous `OP_CHECKSIGVERIFY` operation, the current `OP_CHECKSIGFROMSTACKVERIFY` can only succeed if <sig\_msg> is identical to the message that was checked during step 3’s OP\_CHECKSIGVERIFY operation. At this point, we are certain that the `<sig_msg>` on the stack top is the same as the signed transaction message.

*Note that* since the private key to `<fixed_pk>` is known, anyone can create this signature, but this script would only succeed if the `<sig_msg>` is correctly specified as mentioned above.

**Onto ANYPREVOUT**:

Anyprevout essentially is substituting some things from the regular signature hash messages and replacing those with 0's. In detail, we can now split our `sig_msg` into multiple parts as defined in [BIP143](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki) using `OP_SUBSTR`. It is also possible to use `OP_CAT` to initially supply the split up the message and then CAT it together.

Now that we have signature hash message as per BIP143 on the stack, we manipulate it to make certain fields 0's. In particular, we make items 2-4 0.

```
2. hashPrevouts (32-byte hash)
3. hashSequence (32-byte hash)
4. outpoint (32-byte hash + 4-byte little endian) 

```

We take a `OP_DUP OP_SUSTR 0 <4>` to get item 1, version. onto the stack. and similarly, obtain a concatenation of items 5-10 onto the stack. Finally, we CAT them together by `<ver> <[0; (32+ 32 + (32 +4))]>` <items 5.10>` to get a new sighash which we use for Eltoo update key.

Let `introspect_script` =

```
OP_OVER OP_SHA256 <pubKey> 2 OP_PICK 1 OP_CAT OP_OVER OP_CHECKSIGVERIFY OP_CHECKSIGFROMSTACKVERIFY

```

as we discussed above. And let `manipulate_txdata_script` be the script to modify the stack contents from BIP143 sighash message to get a new message which sets the respective items to `0s`. Then our final substitute for `OP_CHECKSIGANYPREVOUT` would be the following script.

```
final_script(eltoo_pk) = <introspect_script> <manipulate_txdata_script> <eltoo_pk> OP_CSFS

```

Satisfying this would require the following onto the initial witness stack.

```
<sig_from_fixed_key>
<sig_msg>
<sig_from_eltoo_update_priv_key>

```

Lastly, the eltoo script would now look like:

```
OP_IF
    10 OP_CSV
    2 A(s,i) B(s,i) 2 OP_CHECKMULTISIGVERIFY
OP_ELSE
    <Si + 1> OP_CHECKLOCKTIMEVERIFY
    final_script(Au) final_script(Bu)
OP_ENDIF

```

Note how the two of two multi-sig is split into two parts.

**Taproot Signature Hash:**

The same technique does not work for Taproot Signature Hash algorithm(see [BIP341](https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki)) and Schnorr signatures (see [BIP340](https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki)) because of tagged hashes. At a high level, because of tags, the size of these messages is more than 520 bytes which is currently the maximum supported by bitcoin network. It is possible to overcome this limitation by adding 1)streaming `SHA256` opcodes, 2) by raising the per stack element limit, Or 3) adding support for tagged hashes by new opcodes.


---

