TXEDITORを使ってマルチシグトランザクションを作る
今回はマルチシグトランザクション
前回はトランザクション作成ツール「TXEDITOR」を使ってP2PKトランザクションを作成しました。今回はマルチシグトランザクションを作ります。
マルチシグトランザクションのscript
マルチシグトランザクションの場合はlocking scriptが M <Public Key 1> <Public Key 2> .. <Public Key N> N OP_CHECKMULTISIG
、unlocking scriptが OP_0 <Signature 1> ... <Signature M>
となります。
今回は 2-of-3マルチシグネチャ条件を設定します。
以下手順の ⭐ マークがあるところが注目ポイントです。
TXEDITORによるトランザクション作成 (P2PKH to マルチシグ)
1.事前準備
- (1) bitcore-libインストール
- (2) 新規アドレス作成JS作成
- (3) 送信元アドレス作成
- (4) 送信先アドレス作成 (3アドレス)
- (5) locking script作成
- (6) 送信元アドレスにBitcoinを送付
- (7) 送信元アドレスにBitcoinを送付
(1) bitcore-libインストール
$ mkdir /tmp/txeditor $ cd /tmp/txeditor $ npm install bitcore-lib $ vi new_address.js
(2) 新規アドレス作成JS作成 (new_address.js)
var bitcore = require('bitcore-lib'); var network = 'testnet'; var privateKey = new bitcore.PrivateKey(network); console.log("Private Key : " + privateKey.toString()); console.log("Private Key (WIF) : " +privateKey.toWIF()); console.log("Public Key : " + privateKey.toPublicKey().toString()); console.log("Bitcoin Address : " + privateKey.toPublicKey().toAddress().toString());
(3) 送信元アドレス作成
$ node new_address.js Private Key : 1b1644ea6ca5941011b880001a19e0fb5e14739feddf96a1003bd946428d2ca7 Private Key (WIF) : cNVMZAvNYWsWnWMpEN7vCwdvfvRn1saC1C3sH2DJW6Zhq2FEWU14 Public Key : 023f3b8d04b9fac2ac10b8b8e7a4d5f033f259d26a74d2b0b77313f41585b3d1b5 Bitcoin Address : mfYRZHwMfvFti3gErrKeBmMmMraFJVRMyJ
(4) 送信先アドレス作成 (3アドレス)
pub1
$ node new_address.js Private Key : 3a49e7f41ff22b017d59b3ea686e8627dc6e46b618b00b1c9da3184437cf3a79 Private Key (WIF) : cPY1Ndne8fhqWRhhVLCWXz9k1oyA4txQGjAyYg91m3vtp4CzJtkd Public Key : 022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc Bitcoin Address : mwvbYhiFB2AbmGfcLAV6JqUtESw8WESqK2
pub2
$ node new_address.js Private Key : 5cc229f92f31d87db8cba3d6891b484a96201eda76e1032f81cf205020fc2aa0 Private Key (WIF) : cQh1eTbsgrW9cRovBMb9GGyyVfaAYevpWobYGyX1AfTjreFLwGmC Public Key : 030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a Bitcoin Address : mzXDxXWB1XoPwJavgtiy59er1jmAxZwwWs
pub3
$ node new_address.js Private Key : d5871141082ba25e38bb55d50acf257977fb8c712db60fc8793841a08d50d1ab Private Key (WIF) : cUjmhGCroB5vvNADTBCZfDVkCiYpTpjBWvk4WDuXt2RCzqKrLXK7 Public Key : 0218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba9 Bitcoin Address : mvU1PgtJJAdP5Xz3rSwtDfsTiEMwWn1BgA
(5) locking_script.js作成
locking scriptを作成します。pub1〜3のPublic Keyの値を設定してください。
$ vi locking_script.js
var bitcore = require('bitcore-lib'); var network = 'testnet'; var pub1 = new bitcore.PublicKey("022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc", network); var pub2 = new bitcore.PublicKey("030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a", network); var pub3 = new bitcore.PublicKey("0218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba9", network); var array = [pub1, pub2, pub3]; var script = new bitcore.Script.buildMultisigOut(array, 2); console.log("Locking Script: " + script.toString()); console.log("Locking Script (HEX) : " + script.toHex());
(6) locking_script.js実行
$ node locking_script.js Locking Script: OP_2 33 0x0218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba9 33 0x022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc 33 0x030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a OP_3 OP_CHECKMULTISIG Locking Script (HEX) : 52210218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba921022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc21030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a53ae
以下サイトから送信元アドレスを入力するとTestnetで使えるBitcoinがもらえます
2.送信元のUTXO取得
UTXOはIndieSquare APIを利用して取得します。
$ curl https://apitestnet.indiesquare.me/v2/addresses/mfYRZHwMfvFti3gErrKeBmMmMraFJVRMyJ/utxos [ { "scriptPubKey":"76a91400472c7ada0f94b832befcdd883501124305fe7b88ac", "vout":0, "confirmations":0, "txid":"203c395cb3bbdab6a44630d4fad22eff21df5518cc102c56ae16c8cf404e3125", "amount":1.6 } ]
3.TXEDITOR (Transactionタブ)を入力
- txins[0].outpoint.hash = utxoのtxid
- txins[0].outpoint.index = utxoのvout
- txins[0].signature_script = utxoのscriptPubKey
- txouts[0].value = utxo.amount * 100000000 - 100000 = 159900000
- txouts[0].pk_script = locking_script.jsを実行した結果 (HEX) ⭐
4.TXEDITOR (Signature(HASHTYPE_ALL))を入力
- Private key (WIF/HEX) = 送信元のPrivate Key (WIF)
5.TXEDITOR (Script)を入力
- Script = Signature + Hash Type<改行>送信元のPublic Key
6.TXEDITOR (Transactionタブ)を入力
- txins[0].signature_script = Script.Hex
7.decodeRawTransaction実行
確認のために、decodeRawTransactionを実行
curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000125314e40cfc816ae562c10cc1855df21ff2ed2fad43046a4b6dabbb35c393c20000000006a47304402202d7e54a6ee2a6ea3de611e3c6336e23753cfaf84e520aef0cd1ade3e02b65851022039396fa77522c3d5ad5f044b04909d7d20012cc1d6bcd0bc66718771db98f8250121023f3b8d04b9fac2ac10b8b8e7a4d5f033f259d26a74d2b0b77313f41585b3d1b5ffffffff0160e31600000000006952210218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba921022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc21030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a53ae00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode
レスポンス
{ "txid":"80020248abc2975a64ae4f1c1298fea530a8acf2f2225cee844569552093ba07", "size":271, "version":1, "locktime":0, "vin":[ { "txid":"203c395cb3bbdab6a44630d4fad22eff21df5518cc102c56ae16c8cf404e3125", "vout":0, "scriptSig":{ "asm":"304402202d7e54a6ee2a6ea3de611e3c6336e23753cfaf84e520aef0cd1ade3e02b65851022039396fa77522c3d5ad5f044b04909d7d20012cc1d6bcd0bc66718771db98f825[ALL] 023f3b8d04b9fac2ac10b8b8e7a4d5f033f259d26a74d2b0b77313f41585b3d1b5", "hex":"47304402202d7e54a6ee2a6ea3de611e3c6336e23753cfaf84e520aef0cd1ade3e02b65851022039396fa77522c3d5ad5f044b04909d7d20012cc1d6bcd0bc66718771db98f8250121023f3b8d04b9fac2ac10b8b8e7a4d5f033f259d26a74d2b0b77313f41585b3d1b5" }, "sequence":4294967295 } ], "vout":[ { "value":0.015, "n":0, "scriptPubKey":{ "asm":"2 0218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba9 022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc 030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a 3 OP_CHECKMULTISIG", "hex":"52210218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba921022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc21030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a53ae", "reqSigs":2, "type":"multisig", "addresses":[ "mvU1PgtJJAdP5Xz3rSwtDfsTiEMwWn1BgA", "mwvbYhiFB2AbmGfcLAV6JqUtESw8WESqK2", "mzXDxXWB1XoPwJavgtiy59er1jmAxZwwWs" ] } } ] }
8.broadcast実行
broadcast実行
$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000125314e40cfc816ae562c10cc1855df21ff2ed2fad43046a4b6dabbb35c393c20000000006a47304402200cd7aa9166960f3374bf655a5c5ba0a47801ae22f8231baa2412e8f47941792e02206b21c44642887b32fd87fb82a052363605c109b31d971ce502322e8148caf1670121023f3b8d04b9fac2ac10b8b8e7a4d5f033f259d26a74d2b0b77313f41585b3d1b5ffffffff0160e18709000000006952210218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba921022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc21030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a53ae00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast
レスポンス
{ "code":200001, "type":"Error", "message":"Broadcast failed", "errors":[ { "field":"txid", "code":"invalid" } ] }
あれ… エラーが出るので https://live.blockcypher.com/btc-testnet/pushtx/ からブロードキャストしました。
9.broadcast実行結果
問題なく送信できました。
http://tbtc.blockr.io/tx/info/c85ab15eddd1faabc86b36b5fb0a963ba4ebb3fd5839404708c5e0eb2dcaa545
それっぽい結果をみることができます。
TXEDITORによるトランザクション作成 (マルチシグ to P2PKH)
Escrowされている金額を別のアドレスに送信します。
sign.js作成
sign.js
var bitcore = require('bitcore-lib'); var network = 'testnet'; var key1 = new bitcore.PrivateKey("3a49e7f41ff22b017d59b3ea686e8627dc6e46b618b00b1c9da3184437cf3a79", network); var key2 = new bitcore.PrivateKey("5cc229f92f31d87db8cba3d6891b484a96201eda76e1032f81cf205020fc2aa0", network); var keys = [key1, key2]; var pub1 = new bitcore.PublicKey("022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc", network); var pub2 = new bitcore.PublicKey("030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a", network); var pub3 = new bitcore.PublicKey("0218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba9", network); var pubkeys = [pub1, pub2, pub3]; var utxo = new bitcore.Transaction.UnspentOutput({ "txId" : "c85ab15eddd1faabc86b36b5fb0a963ba4ebb3fd5839404708c5e0eb2dcaa545", "outputIndex" : 0, "script" : "52210218597441c292cb6d73174c1662ac9d60b76688fd359f90e2d653d1a089c9aba921022bda026d6aee8133f0290449a282f8cfbccafdc064b0b47068854457f38af3bc21030a230982d9706247d5997df1aea7144266c33a2e6c64c6a3a44c5cdf9c0ff58a53ae", "satoshis" : 159900000 }); var multiSigTx = new bitcore.Transaction() .from(utxo, pubkeys, 2) .to("mfYRZHwMfvFti3gErrKeBmMmMraFJVRMyJ", 159800000) .sign(keys); var serialized = multiSigTx.toString(); console.log(serialized);
sign.js実行
$ node sign.js 010000000145a5ca2debe0c50847403958fdb3eba43b960afbb5366bc8abfad1dd5eb15ac800000000920047304402203fa6520a6a8345603a03990ae99e7dd83a482f868f902d8f40298c44e8ea808902205e025a57c47af57892c2b616d3f92c679aefd8ac9cfd3e72f35fce6df96a0ffb01483045022100cebdb64fdc383bdbf88fe2820fe49e2e61642e9e94a3b58baa6efdde42fcf745022024a2a7a54a6c0e25b4e1580be62d336716c771dabd837430c58c392dc4c5afc501ffffffff01c05a8609000000001976a91400472c7ada0f94b832befcdd883501124305fe7b88ac00000000
broadcast実行
https://live.blockcypher.com/btc-testnet/pushtx/ からブロードキャストします。
broadcast実行結果
http://tbtc.blockr.io/tx/info/219a49b6a376e8f4ef86866e93483552679b5157318f0e4085430a3cee24e3d8
後半TXEDITOR関係なくなった感ありますが、Multisig pubkey scripts (いわゆる bare multisig) も無事送受信できました。