マルチシグ

ビットコインに対して所有権を共有することができる。 そのためには m-of-n multi sig を表すscriptPubKeyを作る。つまり、ビットコインを使うためには与えられた n 個の異なる公開鍵に対して、m 個の秘密鍵で署名する必要があるということだ。

ビットコインを使うためにはボブ、アリスそしてサトシのうち2人が署名する必要のある、マルチシグを作ってみよう。

Key bob = new Key();
Key alice = new Key();
Key satoshi = new Key();
var scriptPubKey = PayToMultiSigTemplate
.Instance
.GenerateScriptPubKey(2, new[] { bob.PubKey, alice.PubKey, satoshi.PubKey });
Console.WriteLine(scriptPubKey);
2 0282213c7172e9dff8a852b436a957c1f55aa1a947f2571585870bfb12c0c15d61 036e9f73ca6929dec6926d8e319506cc4370914cd13d300e83fd9c3dfca3970efb 0324b9185ec3db2f209b620657ce0e9a792472d89911e0ac3fc1e5b5fc2ca7683d 3 OP_CHECKMULTISIG

見てのとおり、scriptPubkeyが次のような形式となっている:

<sigsRequired> <pubkeys…> <pubKeysCount> OP_CHECKMULTISIG

署名のプロセスはTransaction.Signと呼ばれるものと比べて少し複雑になっていて、それではマルチシグでは署名できない。

そのテーマについてはあとでより詳しく話すとして、マルチシグのトランザクションへの署名にはTransactionBuilderを使うことにしよう。

マルチシグのscriptPubKeyreceivedというトランザクションでビットコインを受け取ったとしよう。

var received = new Transaction();
received.Outputs.Add(new TxOut(Money.Coins(1.0m), scriptPubKey));

ボブとアリスはニコに、彼のサービスへの対価として1.0BTCを支払うことに同意した。ということでまず、彼らはトランザクションから、すでに受け取ったCoinを取得する。

Coin coin = received.Outputs.AsCoins().First();

それからTransactionBuilderを使って まだ署名されていないトランザクション を生成する。

BitcoinAddress nico = new Key().PubKey.GetAddress(Network.Main);
TransactionBuilder builder = new TransactionBuilder();
Transaction unsigned =
builder
.AddCoins(coin)
.Send(nico, Money.Coins(1.0m))
.BuildTransaction(sign: false);

そのトランザクションはまだ署名されていない。ここでどのようにアリスが署名するかを示す。

Transaction aliceSigned =
builder
.AddCoins(coin)
.AddKeys(alice)
.SignTransaction(unsigned);

それからボブの署名は以下のとおり。

Transaction bobSigned =
builder
.AddCoins(coin)
.AddKeys(bob)
.SignTransaction(aliceSigned);

そして、ボブとアリスは1つのトランザクションに彼らの署名を結合する。

Transaction fullySigned =
builder
.AddCoins(coin)
.CombineSignatures(aliceSigned, bobSigned);
Console.WriteLine(fullySigned);
{
...
"in": [
{
"prev_out": {
"hash": "9df1e011984305b78210229a86b6ade9546dc69c4d25a6bee472ee7d62ea3c16",
"n": 0
},
"scriptSig": "0 3045022100a14d47c762fe7c04b4382f736c5de0b038b8de92649987bc59bca83ea307b1a202203e38dcc9b0b7f0556a5138fd316cd28639243f05f5ca1afc254b883482ddb91f01 3044022044c9f6818078887587cac126c3c2047b6e5425758e67df64e8d682dfbe373a2902204ae7fda6ada9b7a11c4e362a0389b1bf90abc1f3488fe21041a4f7f14f1d856201"
}
],
"out": [
{
"value": "1.00000000",
"scriptPubKey": "OP_DUP OP_HASH160 d4a0f6c5b4bcbf2f5830eabed3daa7304fb794d6 OP_EQUALVERIFY OP_CHECKSIG"
}
]
}

こうしてトランザクションはネットワークに送信できる準備ができた。

ビットコインネットワークが、ここに説明したとおりマルチシグをサポートしているとしても、1つ質問するに値することがある。「マルチシグのScriptPubKeyが、以前の章で見てきたようなビットコインアドレスを使う程度の簡単さで表されていないが、ビットコインに対して知見を持ち合わせていない人に対して、どのようにサトシ、アリスまたはボブのマルチシグに対して支払うようお願いできるのだろうか?」

scriptPubKeyをビットコインアドレスと同じくらい簡単に、そしてコンパクトに表現できるとしたら、素晴らしいことだと思わないだろうか?

そう。これは可能で、Bitcoin Script Address、またの名をPay to Script Hash(P2SH)と呼ばれている。

最近では、ここで見た Pay To Multi SigそのものP2PKそのもの は、説明したとおりに直接使われることは決してなく、Pay To Script Hash による支払いにラップされている。