<p>Your understanding of the commitment root is correct.  Taking advantage of Haskell's laziness, feel free to put <code>undefined</code> into the signature when computing the commitment root.</p>

<p>At the moment, the witness root is not used in the protocol.  There are some ideas on how to use it in more sophisticated protocols, but those ideas haven't been realized yet.  However, the witness root has some uses in testing and development regardless.</p>

<p>Simplicity doesn't use BIP-Schnorr per se.  Rather <code>checkSigHashAll</code> is a Simplicity expression that implements an old draft of BIP-Schnorr.  If you want a signature scheme that supports key recovery, you could implement such a scheme in Simplicity.</p>

<p>Neither the commitment nor witness roots contain any transaction data, mock or otherwise.  Instead the <code>checkSigHashAll</code> Simplicity expression contains <a href="https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Elements/Simplicity/Elements/Primitive.hs#L35-L71" rel="nofollow noreferrer">primitives</a> that, during Simplicity execution, <a href="https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Simplicity/Elements/Programs/CheckSigHashAll.hs#L99" rel="nofollow noreferrer">return the transaction's locktime and version</a></p>

<p>To make a simple 2-of-2 multisig you could write something along the lines of </p>

<pre><code> pkwCheckSigHashAll &lt;pubkeyA&gt; &lt;sigA&gt; &amp;&amp;&amp;
 pkwCheckSigHashAll &lt;pubkeyB&gt; &lt;sigB&gt; &gt;&gt;&gt;
unit
</code></pre>

<p>Since both branches are used in a 2-of-2 multisig, there are no MAST branches.</p>

<p>To make a 1-of-2 multisig you have some options.  One way is</p>

<pre><code> witness &lt;value of type (Bit, Sig)&gt; &gt;&gt;&gt;
 cond (scribe &lt;pubkeyA&gt; &amp;&amp;&amp; iden) (scribe &lt;pubkeyB&gt; &amp;&amp;&amp; iden) &gt;&gt;&gt;
 checkSigHashAll
</code></pre>

<p>However, even after pruning (turning the <code>case</code> within the <code>cond</code> into an <code>assert</code>), the program appear a lot like a 1-of-2 multisig.</p>

<p>Another implementation could be</p>

<pre><code>witness &lt;value of type Bit&gt; &amp;&amp;&amp; unit &gt;&gt;&gt;
cond (pkwCheckSigHashAll &lt;pubkeyA&gt; &lt;sigA&gt;)
     (pkwCheckSigHashAll &lt;pubkeyB&gt; &lt;sigB&gt;)
</code></pre>

<p>In this case after pruning it looks like a 1-sig-or-something else.  Pruning transforms the above expression into something like</p>

<pre><code>witness &lt;0&gt; &amp;&amp;&amp; unit &gt;&gt;&gt;
assertl (drop (pkwCheckSigHashAll &lt;pubkeyB&gt; &lt;sigB&gt;))
        (commitmentRoot (drop (pkwCheckSigHashAll &lt;pubkeyA&gt; &lt;sigA&gt;)))
</code></pre>

<p>where only the commitment root of the untaken branch is revealed.</p>

<p>Be aware that as of the time of writing this, pruning has not been implemented, nor is it the case that pruned expressions are yet enforced by the implementation.  You can still prune expressions by hand though.</p>

CC BY-SA 4.0
2019-09-23T16:52:10.183Z
2019-09-23T16:52:10.183Z
Russell O'Connor
<p>So, I downloaded Simplicity and started a REPL using <code>cabal new-repl Simplicity</code>. Then I enabled type applications using <code>:set -XTypeApplications</code>.</p>

<p>Consider these invocations:</p>

<pre><code>&gt; (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "1")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\CAN\r\201\231\SO0:1\183\130a\DC3m4u!\193\247e\EOT\194nO\US\208\150\&amp;2\182\ACK\203\151&gt;"}}

&gt; (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "1")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\215\222oj\251&amp;\134\SOZ\202@N\161(\185j2\DELt\156\147\136Nz\183\179\EOTH\166\FS\141F"}}

&gt; (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "0")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\215\222oj\251&amp;\134\SOZ\202@N\161(\185j2\DELt\156\147\136Nz\183\179\EOTH\166\FS\141F"}}
</code></pre>

<p>If I understand correctly, the commitment root goes into an transaction output. Since the signature shouldn't play a role, the output from Haskell makes sense since I change the sig and it doesn't affect the commitment root. The example above seems consistent with this intuition. Are both my intuition and the example code correct?</p>

<p>Now, I can call the same method with <code>WitnessRoot</code>:</p>

<pre><code>&gt; (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "0")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\185\FS\176\179\b{Xc2\216\n\240\186\205v\208\164NW\\\DLE\193:\ETB\bMO\211\152*I%"}}

&gt; (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "0")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\240h\NUL\188z4\ACK\200\ETX\151\DC1&amp;Y\253\t\152\176P\146\186\137\NAKm!\STX\DC3\182\148\193\246\172O"}}

&gt; (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "1")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\205\DEL\132Q\245\166!\196\178\248\136\194aO\243+\145T\200E\129I#\253F\134\173i\243K\154J"}}
</code></pre>

<p>Again, if I understand correctly, the witness root goes into the spending transaction input. It seems like the witness root is affected if I change either signature or public key, which corresponds to my intuition. Simplicity uses BIP-Schnorr which doesn't allow for pubkey recovery. Again, is my intuition consistent with the above code?</p>

<p>I assume these hash values contain mock transaction metadata like nLocktime, embedded in the <code>lib</code>, correct?</p>

<p>Now, let's say I wanted to do a 2-of-2 MAST-based multisig with Simplicity, how would that look like? There must be a way to compose two different calls to CheckSigHashAll. And the spending transaction would surely need to provide a MAST path through the script, how do I pass that to Simplicity? With <a href="https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Core/Simplicity/Term/Core.hs#L84" rel="nofollow noreferrer"><code>oooh</code></a>?</p>

<merkle-tree><blockstream><simplicity>
Intuition for Simplicity's CheckSigHashAll
Janus Troelsen
# Intuition for Simplicity's CheckSigHashAll

(Asked by: username_0 on 2019-09-22)

So, I downloaded Simplicity and started a REPL using `cabal new-repl Simplicity`. Then I enabled type applications using `:set -XTypeApplications`.

Consider these invocations:

```
> (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "1")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\CAN\r\201\231\SO0:1\183\130a\DC3m4u!\193\247e\EOT\194nO\US\208\150\&2\182\ACK\203\151>"}}

> (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "1")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\215\222oj\251&\134\SOZ\202@N\161(\185j2\DELt\156\147\136Nz\183\179\EOTH\166\FS\141F"}}

> (pkwCheckSigHashAll @CommitmentRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "0")))
CommitmentRoot {commitmentRoot = Hash256 {hash256 = 
"\215\222oj\251&\134\SOZ\202@N\161(\185j2\DELt\156\147\136Nz\183\179\EOTH\166\FS\141F"}}

```

If I understand correctly, the commitment root goes into an transaction output. Since the signature shouldn't play a role, the output from Haskell makes sense since I change the sig and it doesn't affect the commitment root. The example above seems consistent with this intuition. Are both my intuition and the example code correct?

Now, I can call the same method with `WitnessRoot`:

```
> (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "0")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\185\FS\176\179\b{Xc2\216\n\240\186\205v\208\164NW\\\DLE\193:\ETB\bMO\211\152*I%"}}

> (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "1")) (Schnorr.Sig (read "0") (read "0")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\240h\NUL\188z4\ACK\200\ETX\151\DC1&Y\253\t\152\176P\146\186\137\NAKm!\STX\DC3\182\148\193\246\172O"}}

> (pkwCheckSigHashAll @WitnessRoot @() lib (Schnorr.PubKey True (read "0")) (Schnorr.Sig (read "0") (read "1")))
WitnessRoot {witnessRoot = Hash256 {hash256 = 
"\205\DEL\132Q\245\166!\196\178\248\136\194aO\243+\145T\200E\129I#\253F\134\173i\243K\154J"}}

```

Again, if I understand correctly, the witness root goes into the spending transaction input. It seems like the witness root is affected if I change either signature or public key, which corresponds to my intuition. Simplicity uses BIP-Schnorr which doesn't allow for pubkey recovery. Again, is my intuition consistent with the above code?

I assume these hash values contain mock transaction metadata like nLocktime, embedded in the `lib`, correct?

Now, let's say I wanted to do a 2-of-2 MAST-based multisig with Simplicity, how would that look like? There must be a way to compose two different calls to CheckSigHashAll. And the spending transaction would surely need to provide a MAST path through the script, how do I pass that to Simplicity? With [`oooh`](https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Core/Simplicity/Term/Core.hs#L84)?

**Tags:** merkle-tree, blockstream, simplicity


---

## 1 answers

### Answer by username_1 on 2019-09-23. Score: 3 | Accepted answer

Your understanding of the commitment root is correct. Taking advantage of Haskell's laziness, feel free to put `undefined` into the signature when computing the commitment root.

At the moment, the witness root is not used in the protocol. There are some ideas on how to use it in more sophisticated protocols, but those ideas haven't been realized yet. However, the witness root has some uses in testing and development regardless.

Simplicity doesn't use BIP-Schnorr per se. Rather `checkSigHashAll` is a Simplicity expression that implements an old draft of BIP-Schnorr. If you want a signature scheme that supports key recovery, you could implement such a scheme in Simplicity.

Neither the commitment nor witness roots contain any transaction data, mock or otherwise. Instead the `checkSigHashAll` Simplicity expression contains [primitives](https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Elements/Simplicity/Elements/Primitive.hs#L35-L71) that, during Simplicity execution, [return the transaction's locktime and version](https://github.com/ElementsProject/simplicity/blob/4ff3395b0b64d446bb5876e5928881d90d14f24b/Haskell/Simplicity/Elements/Programs/CheckSigHashAll.hs#L99)

To make a simple 2-of-2 multisig you could write something along the lines of

```
 pkwCheckSigHashAll <pubkeyA> <sigA> &&&
 pkwCheckSigHashAll <pubkeyB> <sigB> >>>
unit

```

Since both branches are used in a 2-of-2 multisig, there are no MAST branches.

To make a 1-of-2 multisig you have some options. One way is

```
 witness <value of type (Bit, Sig)> >>>
 cond (scribe <pubkeyA> &&& iden) (scribe <pubkeyB> &&& iden) >>>
 checkSigHashAll

```

However, even after pruning (turning the `case` within the `cond` into an `assert`), the program appear a lot like a 1-of-2 multisig.

Another implementation could be

```
witness <value of type Bit> &&& unit >>>
cond (pkwCheckSigHashAll <pubkeyA> <sigA>)
     (pkwCheckSigHashAll <pubkeyB> <sigB>)

```

In this case after pruning it looks like a 1-sig-or-something else. Pruning transforms the above expression into something like

```
witness <0> &&& unit >>>
assertl (drop (pkwCheckSigHashAll <pubkeyB> <sigB>))
        (commitmentRoot (drop (pkwCheckSigHashAll <pubkeyA> <sigA>)))

```

where only the commitment root of the untaken branch is revealed.

Be aware that as of the time of writing this, pruning has not been implemented, nor is it the case that pruned expressions are yet enforced by the implementation. You can still prune expressions by hand though.


---

