<p>The real requirement is that the extra input to <code>OP_CHECKMULTISIG</code> is a zero (that is: the empty byte array).</p>

<p>For non-SegWit inputs, the only canonical way to get such a zero on the stack is by including an <code>OP_0</code> in the <code>scriptSig</code>. <code>OP_0</code> just pushes an empty byte array onto the stack.</p>

<p>In SegWit inputs there is no longer a script to build that stack. Instead, <em>you specify the stack directly</em>. As a result, not just the recommended way, but <strong>the only way</strong> is adding an empty array to the <code>scriptWitness</code>.</p>

CC BY-SA 3.0
2018-02-26T12:52:55.327Z
2018-02-26T12:52:55.327Z
Pieter Wuille
<p>For anyone working in the core test framework, I used this code to create a 2 of 2 multisig witness stack with a null dummy as the first element on the stack:</p>

<blockquote>
  <p>witness_program = CScript([OP_2, pubkey1, pubkey2, OP_2,OP_CHECKMULTISIG]</p>
  
  <p>tx.wit.vtxinwit[0].scriptWitness.stack = [b'', sig1, sig2,
  witness_program]</p>
</blockquote>

<p>I'm not a Python programmer so it took me some time to figure out that all I needed was b'' to create an empty byte array element.</p>

CC BY-SA 4.0
2019-07-30T14:35:12.227Z
2019-07-30T14:35:12.227Z
Richard Myers
<p>As per the note at <a href="https://bitcoin.org/en/developer-guide#multisig" rel="nofollow noreferrer">Developer Guide - MultiSig</a> and <a href="https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki" rel="nofollow noreferrer">BIP147</a> when using OP_CHECKMULTISIG an OP_0 needs to be prefaced to the scriptSig to accommodate a bug in the original Bitcoin implementation.</p>

<p>If the same workaround is applied in a Witness Program the script seems to fail the SCRIPT_FLAGS_VERIFY_NULLDUMMY check. What's the correct way to add the OP_0 to a MultiSig Witness Program? Adding an OP_0 as per the sample below results in a final stack element containing 0x00 which fails the check. </p>



<pre><code>auto aliceKeyData = ParseHex("bbc27228ddcb9209d7fd6f36b02f7dfa6252af40bb2f1cbc7a557da8027ff866");
CKey aliceKey{};
aliceKey.Set(aliceKeyData.begin(), aliceKeyData.end(), true);
CPubKey alicePubkey = aliceKey.GetPubKey();

auto keyData = ParseHex("619c335025c7f4012e556c2a58b2506e30b8511b53ade95ea316fd8c3286feb9");
CKey bobKey{};
bobKey.Set(keyData.begin(), keyData.end(), true);
CPubKey bobPubKey = bobKey.GetPubKey();

CScript redeemScript = CScript{} &lt;&lt; OP_1 &lt;&lt; ToByteVector(alicePubkey) &lt;&lt; ToByteVector(bobPubKey) &lt;&lt; OP_2 &lt;&lt; OP_CHECKMULTISIG;
uint256 redeemScriptHash{};
CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(redeemScriptHash.begin());
CScript scriptPubkey = CScript{} &lt;&lt; OP_0 &lt;&lt; ToByteVector(redeemScriptHash); // P2WSH

int amount = 600000000;

CScript scriptSig;
CScriptWitness scriptWitness;
CMutableTransaction tx = BuildFundingTransaction(scriptSig, scriptWitness, amount);

uint256 coinZeroSigHash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0);

CScript op0Script = CScript{} &lt;&lt; OP_0;

std::vector&lt;uint8_t&gt; coinZeroBobSig{};
bobKey.Sign(coinZeroSigHash, coinZeroBobSig, 0);
coinZeroBobSig.push_back(SIGHASH_ALL);

CScriptWitness&amp; witness = tx.vin[0].scriptWitness;
witness.stack.push_back(ToByteVector(op0Script));  // &lt;-- Results in 0x00 stack element in Witness Program.
witness.stack.push_back(ToByteVector(coinZeroBobSig));
witness.stack.push_back(ToByteVector(redeemScript));

CDataStream txSpendingStm(SER_NETWORK, PROTOCOL_VERSION);
txSpendingStm &lt;&lt; tx;
std::cout &lt;&lt; "Spending Tx: " &lt;&lt; CTransaction(tx).ToString() &lt;&lt; std::endl;

bitcoinconsensus_error err;
auto spendCoinZeroResult = bitcoinconsensus_verify_script_with_amount(scriptPubkey.data(), scriptPubkey.size(), amount, (const unsigned char*)&amp;txSpendingStm[0], txSpendingStm.size(), 0, bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL, &amp;err);
std::cout &lt;&lt; "Spend Coin Zero result: " &lt;&lt; spendCoinZeroResult &lt;&lt; ", error code " &lt;&lt; err &lt;&lt; std::endl;
</code></pre>

<p>One trivial fix is to add an empty vector to the Witness Program stack rather than an OP_0, such as by using <strong>witness.stack.emplace_back()</strong> instead of <strong>witness.stack.push_back(ToByteVector(op0Script))</strong>, but is that likely to cause any other issues?</p>

<multi-signature><consensus>
P2WSH-MultiSig fails with documented OP_0 workaround
sipsorcery
# P2WSH-MultiSig fails with documented OP_0 workaround

(Asked by: username_0 on 2018-02-26)

As per the note at [Developer Guide - MultiSig](https://bitcoin.org/en/developer-guide#multisig) and [BIP147](https://github.com/bitcoin/bips/blob/master/bip-0147.mediawiki) when using OP\_CHECKMULTISIG an OP\_0 needs to be prefaced to the scriptSig to accommodate a bug in the original Bitcoin implementation.

If the same workaround is applied in a Witness Program the script seems to fail the SCRIPT\_FLAGS\_VERIFY\_NULLDUMMY check. What's the correct way to add the OP\_0 to a MultiSig Witness Program? Adding an OP\_0 as per the sample below results in a final stack element containing 0x00 which fails the check.

```
auto aliceKeyData = ParseHex("bbc27228ddcb9209d7fd6f36b02f7dfa6252af40bb2f1cbc7a557da8027ff866");
CKey aliceKey{};
aliceKey.Set(aliceKeyData.begin(), aliceKeyData.end(), true);
CPubKey alicePubkey = aliceKey.GetPubKey();

auto keyData = ParseHex("619c335025c7f4012e556c2a58b2506e30b8511b53ade95ea316fd8c3286feb9");
CKey bobKey{};
bobKey.Set(keyData.begin(), keyData.end(), true);
CPubKey bobPubKey = bobKey.GetPubKey();

CScript redeemScript = CScript{} << OP_1 << ToByteVector(alicePubkey) << ToByteVector(bobPubKey) << OP_2 << OP_CHECKMULTISIG;
uint256 redeemScriptHash{};
CSHA256().Write(redeemScript.data(), redeemScript.size()).Finalize(redeemScriptHash.begin());
CScript scriptPubkey = CScript{} << OP_0 << ToByteVector(redeemScriptHash); // P2WSH

int amount = 600000000;

CScript scriptSig;
CScriptWitness scriptWitness;
CMutableTransaction tx = BuildFundingTransaction(scriptSig, scriptWitness, amount);

uint256 coinZeroSigHash = SignatureHash(redeemScript, tx, 0, SIGHASH_ALL, amount, SIGVERSION_WITNESS_V0);

CScript op0Script = CScript{} << OP_0;

std::vector<uint8_t> coinZeroBobSig{};
bobKey.Sign(coinZeroSigHash, coinZeroBobSig, 0);
coinZeroBobSig.push_back(SIGHASH_ALL);

CScriptWitness& witness = tx.vin[0].scriptWitness;
witness.stack.push_back(ToByteVector(op0Script));  // <-- Results in 0x00 stack element in Witness Program.
witness.stack.push_back(ToByteVector(coinZeroBobSig));
witness.stack.push_back(ToByteVector(redeemScript));

CDataStream txSpendingStm(SER_NETWORK, PROTOCOL_VERSION);
txSpendingStm << tx;
std::cout << "Spending Tx: " << CTransaction(tx).ToString() << std::endl;

bitcoinconsensus_error err;
auto spendCoinZeroResult = bitcoinconsensus_verify_script_with_amount(scriptPubkey.data(), scriptPubkey.size(), amount, (const unsigned char*)&txSpendingStm[0], txSpendingStm.size(), 0, bitcoinconsensus_SCRIPT_FLAGS_VERIFY_ALL, &err);
std::cout << "Spend Coin Zero result: " << spendCoinZeroResult << ", error code " << err << std::endl;

```

One trivial fix is to add an empty vector to the Witness Program stack rather than an OP\_0, such as by using **witness.stack.emplace\_back()** instead of **witness.stack.push\_back(ToByteVector(op0Script))**, but is that likely to cause any other issues?

**Tags:** multi-signature, consensus


---

## 2 answers

### Answer by username_1 on 2018-02-26. Score: 2 | Accepted answer

The real requirement is that the extra input to `OP_CHECKMULTISIG` is a zero (that is: the empty byte array).

For non-SegWit inputs, the only canonical way to get such a zero on the stack is by including an `OP_0` in the `scriptSig`. `OP_0` just pushes an empty byte array onto the stack.

In SegWit inputs there is no longer a script to build that stack. Instead, *you specify the stack directly*. As a result, not just the recommended way, but **the only way** is adding an empty array to the `scriptWitness`.


---

### Answer by username_2 on 2019-07-30. Score: 1

For anyone working in the core test framework, I used this code to create a 2 of 2 multisig witness stack with a null dummy as the first element on the stack:

> witness\_program = CScript([OP\_2, pubkey1, pubkey2, OP\_2,OP\_CHECKMULTISIG]
>
> tx.wit.vtxinwit[0].scriptWitness.stack = [b'', sig1, sig2,
> witness\_program]

I'm not a Python programmer so it took me some time to figure out that all I needed was b'' to create an empty byte array element.


---

