Multi Sig
## MultiSig {#multi-sig}
Bitcoin allows us to have shared ownership and control over coins with multi-signature transactions or multisig for short.
In order to demonstrate this we will create a ScriptPubKey
that represents an m-of-n multisig. This means that in order to spend the coins, m number of private keys will be needed to sign the spending transaction out of the n number of different public keys provided.
Let’s create a multi sig with Bob, Alice and Satoshi, where two of the three of them need to sign a transaction in order to spend a coin.
Generates this script which you can use as a public key (coin destination address):
As you can see, the scriptPubkey
has the following form: <sigsRequired> <pubkeys…> <pubKeysCount> OP_CHECKMULTISIG
The process for signing it (in order to be able to spend it) is a little more complicated than just calling Transaction.Sign
, which does not work for multisig.
Later we will talk more deeply about the subject but for now let’s use the TransactionBuilder
for signing the transaction.
Imagine the multisig scriptPubKey
received a coin in a transaction called received
:
Bob and Alice agree to pay Nico 1.0 BTC for his services. First they get the Coin
they received from the transaction:
Then, with the TransactionBuilder
, they create an unsigned transaction.
The transaction is not yet signed. Here is how Alice signs it:
And then Bob:
Now, Bob and Alice can combine their signature into one transaction. This transaction will then be valid, because two (Bob and Alice) signatures were used from the three (Bob, Alice and Satoshi) signatures that were initially provided. The requirements of the 'two-of-three' multisig have therefore been met. If this wasn't the case, the network would not accept this transaction, because the nodes reject all unsigned or partially signed transactions.
Before sending the transaction to the network, examine the need of CombineSignatures() method: compare the two transactions 'bobSigned' and 'fullySigned' thoroughly. It will seem like they are identical. It seems like the CombineSignatures() method is needless in this case because the transaction got signed properly without the CombineSignatures() method.
Let's look at a case where CombineSignatures() is required:
The transaction is now ready to be sent to the network, but notice that the CombineSignatures() method was critical here, because both the aliceSigned and the bobSigned transactions were only partially signed, therefore not acceptable by the network. CombineSignatures() combined the two partially signed transactions into one fully signed transaction.
Sidenote: there is an inherent difficulty which arises from this situation. You need to send the newly created, unsigned multi-sig transaction to every signer and after their signed it, you also need to collect the partially signed transactions from them and combine them into one, so that you can publish that on the network. This problem is partially solved by the BIP-0174, because it at least standardizes the data format, but you still need to implement your own way to distribute the data between the signing parties. NBitcoin doesn't have an implementation for BIP-0174 or for the off-chain data distribution yet.
Although the Bitcoin network supports multisig as explained above, the one question worth asking is: How can you expect a user who has no clue about Bitcoin to pay to a complicated multisig script address containing Alice's, Bob's Satoshi's public keys as we have done?
Don’t you think it would be cool if we could represent such a scriptPubKey
as easily and concisely as a regular Bitcoin Address?
Well, this is possible using something called a Bitcoin Script Address (also called Pay to Script Hash or P2SH for short).
Nowadays, native Pay To Multi Sig (as you have seen above) and native P2PK are never used directly. Instead they are wrapped into something called a Pay To Script Hash payment. We will look at this type of payment in the next section.
Last updated