Y

TXEDITORを使ってP2SHトランザクションを作る

今回はP2SH

前回はトランザクション作成ツール「TXEDITOR」を使ってOP_RETURNトランザクションを作成しました。今回はP2SH(Pay-to-Script-Hash)トランザクションを作ります。

blog.yzono.com

P2SHトランザクションのscript

P2SH scriptでは、以下例のように Redeem Script が利用されます。

Redeem Script : 1 PubKey1 PubKey2 PubKey3 3 OP_CHECKMULTISIG
Locking Script : OP_HASH160 <20-byte hash of redeem script> OP_EQUAL
Unlocking Script : Sig1 Sig2 redeem script

https://github.com/bitcoinbook/bitcoinbook/blob/first_edition/ch05.asciidoc

TXEDITORによるトランザクション作成 (P2SH to P2PKH)

1.事前準備

  • (1) bitcore-libインストール
  • (2) 新規アドレス作成JS作成
  • (3) 送信元アドレス作成
  • (4) 送信先アドレス作成
  • (5) Redeem Script作成 (P2SH)
  • (6) 送信元アドレス作成 (P2SH)
  • (7) 送信元アドレス (P2SH) に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());

var script = new bitcore.Script.buildPublicKeyHashOut(privateKey.toPublicKey());
console.log("Locking Script : " + script.toString());
console.log("Locking Script (HEX) : " + script.toHex());                                          

(3) 送信元アドレス作成

$ node new_address.js 
Private Key : 4a6c409dfa5057a7a42d3d84ea9f770c9d3ca9a94482e978891648ff17924adf
Private Key (WIF) : cQ5NQnhzCYgosk6GsCboNaWQTcsyagx9pc4tXYqPxd62Bugn5E5o
Public Key : 02dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240
Bitcoin Address : muTmCdJgo4EqGnXDHCMF6sNkf4YTDjshtU
Locking Script : OP_DUP OP_HASH160 20 0x98f740acefa9ab4c101431f470a2d89206c3387c OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a91498f740acefa9ab4c101431f470a2d89206c3387c88ac

(4) 送信先アドレス作成

$ node new_address.js 
Private Key : edbce8501b2b20b3c9219008f308c0fbdfbf6d66e76514ad043835ebd5f5fbd9
Private Key (WIF) : cVYqGma4ceBji5nbvirTgQb8szpoYZJeKKhXuVgojzsB8aNtHAuN
Public Key : 0306f08f9af356b0a9a3f9a27986c22227827fa9034921e1b0cde68b9e1d85044a
Bitcoin Address : mhG2De6Qv7hQEYxGpoXM1QbVC2mQeEqq6Q
Locking Script : OP_DUP OP_HASH160 20 0x131d49a364af8e56e9c74a1aa9f721decde76dea OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a914131d49a364af8e56e9c74a1aa9f721decde76dea88ac

(5) Redeem Script作成 (P2SH)

Script.Script = 送信元.pubkey<改行>OP_CHECKSIG

スクリーンショット 2017-02-17 01.06.41.png

2102dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240ac がRedeem Scriptです。後で使います。⭐

(6) 送信元アドレス作成 (P2SH)

  1. Etc.HASH160.HEX = Script.Script(HEX)
  2. HASHボタンクリック
  3. BASE58 Check = C4, Etc.HASH160.HASH
  4. Encode (HEX > Base58Checkボタンクリック)

スクリーンショット 2017-02-17 01.07.24.png

2NBZty5nmfujDpm8GbTnm5nvbJWC26Y1CNj が P2SHアドレスです。⭐

(7) 送信元アドレス (P2SH) にBitcoinを送付

以下サイトから送信元アドレスを入力するとTestnetで使えるBitcoinがもらえます

http://tpfaucet.appspot.com/

2.送信元のUTXO取得

UTXOはIndieSquare APIを利用して取得します。

$ curl https://apitestnet.indiesquare.me/v2/addresses/2NBZty5nmfujDpm8GbTnm5nvbJWC26Y1CNj/utxos

[
   {
      "scriptPubKey":"a914c8fa4a29e4b4b49ff563ac72355f046fd7fd5dea87",
      "vout":1,
      "confirmations":0,
      "txid":"71d8322e2b70e0a2f561299385baed3d57ae95cb205f1f6c31699681507c9914",
      "amount":0.26
   }
]

3.TXEDITOR (Transactionタブ)を入力

  • txins[0].outpoint.hash = utxoのtxid
  • txins[0].outpoint.index = utxoのvout
  • txins[0].signature_script = Redeem Script ⭐
  • txouts[0].value = utxo.amount * 100000000 - 100000 = 25000000
  • txouts[0].pk_script = 送信先のlocking script

スクリーンショット 2017-02-17 01.12.51.png

4.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-17 01.13.41.png

5.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>Redeem Script ⭐

スクリーンショット 2017-02-17 01.14.50.png

9.TXEDITOR (Transactionタブ)を入力

  • txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-17 01.15.18.png

10.decodeRawTransaction実行

確認のために、decodeRawTransactionを実行

curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000114997c50819669316c1f5f20cb95ae573dedba85932961f5a2e0702b2e32d871010000006c473044022003abfd471e0f5fc0c3686f40a9e150d7a414c4e1e4736854774fdbb0b42815c002207f69026252a4714b63e07f7df6c11560804139e1f8daf8a43f31f3aa33e5b32a01232102dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240acffffffff0140787d01000000001976a914131d49a364af8e56e9c74a1aa9f721decde76dea88ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode

レスポンス

{
   "txid":"2ce380d859449b456811cb3e2d5e94395396a8a722aeecb6470f0b914b8633bf",
   "size":193,
   "version":1,
   "locktime":0,
   "vin":[
      {
         "txid":"71d8322e2b70e0a2f561299385baed3d57ae95cb205f1f6c31699681507c9914",
         "vout":1,
         "scriptSig":{
            "asm":"3044022003abfd471e0f5fc0c3686f40a9e150d7a414c4e1e4736854774fdbb0b42815c002207f69026252a4714b63e07f7df6c11560804139e1f8daf8a43f31f3aa33e5b32a[ALL] 2102dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240ac",
            "hex":"473044022003abfd471e0f5fc0c3686f40a9e150d7a414c4e1e4736854774fdbb0b42815c002207f69026252a4714b63e07f7df6c11560804139e1f8daf8a43f31f3aa33e5b32a01232102dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240ac"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":0.25,
         "n":0,
         "scriptPubKey":{
            "asm":"OP_DUP OP_HASH160 131d49a364af8e56e9c74a1aa9f721decde76dea OP_EQUALVERIFY OP_CHECKSIG",
            "hex":"76a914131d49a364af8e56e9c74a1aa9f721decde76dea88ac",
            "reqSigs":1,
            "type":"pubkeyhash",
            "addresses":[
               "mhG2De6Qv7hQEYxGpoXM1QbVC2mQeEqq6Q"
            ]
         }
      }
   ]
}

8.broadcast実行

broadcast実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000114997c50819669316c1f5f20cb95ae573dedba85932961f5a2e0702b2e32d871010000006c473044022003abfd471e0f5fc0c3686f40a9e150d7a414c4e1e4736854774fdbb0b42815c002207f69026252a4714b63e07f7df6c11560804139e1f8daf8a43f31f3aa33e5b32a01232102dcf1658f38e56fcfcd0f1cab053f1c5b9ca6800420f475e7996b773f63036240acffffffff0140787d01000000001976a914131d49a364af8e56e9c74a1aa9f721decde76dea88ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast

レスポンス

{
   "txid":"2ce380d859449b456811cb3e2d5e94395396a8a722aeecb6470f0b914b8633bf"
}

9.broadcast実行結果

送信できました。

http://tbtc.blockr.io/tx/info/2ce380d859449b456811cb3e2d5e94395396a8a722aeecb6470f0b914b8633bf

TXEDITORを使ってデータアウトプット(OP_RETURN)トランザクションを作る

今回はOP_RETURN

前回はトランザクション作成ツール「TXEDITOR」を使ってマルチシグネチャトランザクションを作成しました。今回はOP_RETURNトランザクションを作ります。

blog.yzono.com

OP_RETURNトランザクションのscript

OP_RETURN scriptはOP_RETURN <data>です。

TXEDITORによるトランザクション作成 (P2PKH to OP_RETURN)

1.事前準備

  • (1) bitcore-libインストール
  • (2) 新規アドレス作成JS作成
  • (3) 送信元アドレス作成
  • (4) 送信元アドレスに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 : ad6d5e5d3026295a72278643216923eaab0fc15be9edff2bd0eb11191164a006
Private Key (WIF) : cTPpbmM8AgdnPa3LmjwgRaLKwFCy7HNSo5EgNikUKGRTeANcL3qD
Public Key : 02179153f2c204e1da5009d0a8fd5cc1b77d304c9f6baf78d46a5e5fdf719f9d5a
Bitcoin Address : msnignvjGzqWm4jGaQW6dBH2DuF7jCaMmi

(4) 送信元アドレスにBitcoinを送付

以下サイトから送信元アドレスを入力するとTestnetで使えるBitcoinがもらえます

http://tpfaucet.appspot.com/

2.送信元のUTXO取得

UTXOはIndieSquare APIを利用して取得します。

$ curl https://apitestnet.indiesquare.me/v2/addresses/msnignvjGzqWm4jGaQW6dBH2DuF7jCaMmi/utxos

[
   {
      "scriptPubKey":"76a914869cce31ac6d760840109da55bd1957c82fbb59588ac",
      "vout":1,
      "confirmations":0,
      "txid":"e0022d1916acad2115a9f087af767d1e1e29f3f33d74b8b44e7999f5c0c8e722",
      "amount":0.88
   }
]

3.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>48656c6c6f⭐

#48656c6c6fはHelloです。http://string-functions.com/string-hex.aspx

スクリーンショット 2017-02-15 21.54.30.png

4.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 = 87900000
  • txouts[0].pk_script = Script.hex

スクリーンショット 2017-02-15 21.54.51.png

5.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-15 21.55.14.png

6.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>送信元のPublic Key

スクリーンショット 2017-02-15 21.55.46.png

7.TXEDITOR (Transactionタブ)を入力

  • txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-15 21.56.13.png

8.decodeRawTransaction実行

確認のために、decodeRawTransactionを実行

curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000122e7c8c0f599794eb4b8743df3f3291e1e7d76af87f0a91521adac16192d02e0010000006a473044022006d2c87e47c690b1a06b9ff5e47161f051289bb8247eb60d9c7af82471e26d20022059b5246b6c795914e25fbf7a95b8c4cc8584a791b1f1e4ec06fb6e0fdeb142ff012102179153f2c204e1da5009d0a8fd5cc1b77d304c9f6baf78d46a5e5fdf719f9d5affffffff01603f3d0500000000076a0548656c6c6f00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode

レスポンス

{
   "txid":"67ba9bcd714c07ca8d2355bf617bceefd5e89271c93ceab8c36707ae408d57b8",
   "size":173,
   "version":1,
   "locktime":0,
   "vin":[
      {
         "txid":"e0022d1916acad2115a9f087af767d1e1e29f3f33d74b8b44e7999f5c0c8e722",
         "vout":1,
         "scriptSig":{
            "asm":"3044022006d2c87e47c690b1a06b9ff5e47161f051289bb8247eb60d9c7af82471e26d20022059b5246b6c795914e25fbf7a95b8c4cc8584a791b1f1e4ec06fb6e0fdeb142ff[ALL] 02179153f2c204e1da5009d0a8fd5cc1b77d304c9f6baf78d46a5e5fdf719f9d5a",
            "hex":"473044022006d2c87e47c690b1a06b9ff5e47161f051289bb8247eb60d9c7af82471e26d20022059b5246b6c795914e25fbf7a95b8c4cc8584a791b1f1e4ec06fb6e0fdeb142ff012102179153f2c204e1da5009d0a8fd5cc1b77d304c9f6baf78d46a5e5fdf719f9d5a"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":0.879,
         "n":0,
         "scriptPubKey":{
            "asm":"OP_RETURN 48656c6c6f",
            "hex":"6a0548656c6c6f",
            "type":"nulldata"
         }
      }
   ]
}

9.broadcast実行

broadcast実行

curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000122e7c8c0f599794eb4b8743df3f3291e1e7d76af87f0a91521adac16192d02e0010000006a473044022006d2c87e47c690b1a06b9ff5e47161f051289bb8247eb60d9c7af82471e26d20022059b5246b6c795914e25fbf7a95b8c4cc8584a791b1f1e4ec06fb6e0fdeb142ff012102179153f2c204e1da5009d0a8fd5cc1b77d304c9f6baf78d46a5e5fdf719f9d5affffffff01603f3d0500000000076a0548656c6c6f00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast

レスポンス

{
   "txid":"67ba9bcd714c07ca8d2355bf617bceefd5e89271c93ceab8c36707ae408d57b8"
}

9.broadcast実行結果

送信できました。

https://www.blocktrail.com/tBTC/tx/67ba9bcd714c07ca8d2355bf617bceefd5e89271c93ceab8c36707ae408d57b8

メッセージ「Hello」も表示されています。

スクリーンショット 2017-02-15 22.21.03.png

OP_RETURNトランザクションはUTXOにならないので(消費できないので)、今回はこれでおしまいです。

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

(7) 送信元アドレスにBitcoinを送付

以下サイトから送信元アドレスを入力するとTestnetで使えるBitcoinがもらえます

http://tpfaucet.appspot.com/

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) ⭐

スクリーンショット 2017-02-14 17.05.09.png

4.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-14 17.08.00.png

5.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>送信元のPublic Key

スクリーンショット 2017-02-14 17.08.36.png

6.TXEDITOR (Transactionタブ)を入力

  • txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-14 17.10.34.png

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

それっぽい結果をみることができます。

スクリーンショット 2017-02-14 18.08.59.png

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) も無事送受信できました。

TXEDITORを使ってP2PKトランザクションを作る

今回はP2PK

前回はP2PKHトランザクショントランザクション作成ツール「TXEDITOR」で作成しました。今回はP2PKトランザクションも作ってみます。(飽きるまでいろいろなパターン試してみます)

blog.yzono.com

P2PKH vs P2PK

Pay to public key script (P2PK) は、P2PKHの簡易版です。一般的にはP2PKHが使われています。P2PKHはOUTPUTを支払うまで公開鍵を公開しないためP2PKよりセキュアです。

P2PKトランザクションのscript

P2PKの場合はlocking scriptが <Public Key A> OP_CHECKSIG 、unlocking scriptが <Signature from Private Key A> となっている部分がP2PKHとの違いです。

以下手順の ⭐ マークがあるところがP2PKHと異なる部分です。

TXEDITORによるトランザクション作成

1.事前準備

  • (1) bitcore-libインストール
  • (2) 新規アドレス作成JS作成
  • (3) 送信元アドレス作成
  • (4) 送信先アドレス作成
  • (5) 送信元アドレスに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);
// var privateKey = new bitcore.PrivateKey("929f890e36a725449e53945b1f7a64a124a9fb4b31d735426a2d9ac8166ff1f9", 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());

var script = new bitcore.Script.buildPublicKeyHashOut(privateKey.toPublicKey());
console.log("Locking Script : " + script.toString());
console.log("Locking Script (HEX) : " + script.toHex());

var script = new bitcore.Script.buildPublicKeyOut(privateKey.toPublicKey());
console.log("Locking Script (P2PK) : " + script.toString());
console.log("Locking Script (P2PK) (HEX) : " + script.toHex());

(3) 送信元アドレス作成

$ node new_address.js
Private Key : 42f1a1a307c722448d2daed5b03d5522e878dbcce64e05bee875366a26dcd952
Private Key (WIF) : cPpqCN748doS6ot2WtnoXueueQAGTnaZBgihDd1pHxGj5brqpfVq
Public Key : 0234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8
Bitcoin Address : mrLM6FazFDupo54qmS4z1YgCKg9grkTiTe
Locking Script : OP_DUP OP_HASH160 20 0x76a7d66e4617d488c39c1bd56ec546865059f4a8 OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a91476a7d66e4617d488c39c1bd56ec546865059f4a888ac
Locking Script (P2PK) : 33 0x0234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8 OP_CHECKSIG
Locking Script (P2PK) (HEX) : 210234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8ac

(4) 送信先アドレス作成

$ node new_address.js
Private Key : 74b3fc6da793578599176679648211af7efb2c66da26b6b6a35102ba9e7085df
Private Key (WIF) : cRVZGY8uUHfMCGiV9xb6vc3JT5tf1EP5GaVNkiDH2dvA297hk1YC
Public Key : 02515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654
Bitcoin Address : mqDJGWqwWghJvjqmp4sGRbhL6E1UtC7niY
Locking Script : OP_DUP OP_HASH160 20 0x6a5a718bd46e8998bf61963d9f52303b370ada1e OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a9146a5a718bd46e8998bf61963d9f52303b370ada1e88ac
Locking Script (P2PK) : 33 0x02515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654 OP_CHECKSIG
Locking Script (P2PK) (HEX) : 2102515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654ac

(5) 送信元アドレスにBitcoinを送付

以下サイトから送信元アドレスを入力するとTestnetで使えるBitcoinがもらえます

http://tpfaucet.appspot.com/

2.送信元のUTXO取得

UTXOはIndieSquare APIを利用して取得します。

$ curl https://apitestnet.indiesquare.me/v2/addresses/mrLM6FazFDupo54qmS4z1YgCKg9grkTiTe/utxos

[
   {
      "scriptPubKey":"76a91476a7d66e4617d488c39c1bd56ec546865059f4a888ac",
      "vout":0,
      "confirmations":0,
      "txid":"e99ed03edec61d216dd2c2318ff7f7d5d0450b81b48671c0aad5338711930e09",
      "amount":0.21
   }
]

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 = 20900000
  • txouts[0].pk_script = 送信先アドレスのLocking Script (P2PK) (HEX)⭐

スクリーンショット 2017-02-13 18.56.02.png

4.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-13 18.56.29.png

5.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>送信元のPublic Key

スクリーンショット 2017-02-13 18.56.51.png

6.TXEDITOR (Transactionタブ)を入力

  • txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-13 18.57.10.png

7.decodeRawTransaction実行

decodeRawTransaction実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "0100000001090e93118733d5aac07186b4810b45d0d5f7f78f31c2d26d211dc6de3ed09ee9000000006a47304402206443cded856f293b3d0375c4c04119f1fd0c81eb265e8fb4e371fea851955de802206e675726f6ddb609c1a641418d82df9f4c5c902bc63ad23cd3ec57eb450b04c701210234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8ffffffff01a0e83e0100000000232102515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode

レスポンス

{
   "txid":"030a05cd13f2b8cdacaafcc1391b54f78110c44036f5aea6c4963533815ad203",
   "size":201,
   "version":1,
   "locktime":0,
   "vin":[
      {
         "txid":"e99ed03edec61d216dd2c2318ff7f7d5d0450b81b48671c0aad5338711930e09",
         "vout":0,
         "scriptSig":{
            "asm":"304402206443cded856f293b3d0375c4c04119f1fd0c81eb265e8fb4e371fea851955de802206e675726f6ddb609c1a641418d82df9f4c5c902bc63ad23cd3ec57eb450b04c7[ALL] 0234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8",
            "hex":"47304402206443cded856f293b3d0375c4c04119f1fd0c81eb265e8fb4e371fea851955de802206e675726f6ddb609c1a641418d82df9f4c5c902bc63ad23cd3ec57eb450b04c701210234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":0.209,
         "n":0,
         "scriptPubKey":{
            "asm":"02515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654 OP_CHECKSIG",
            "hex":"2102515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654ac",
            "reqSigs":1,
            "type":"pubkey",
            "addresses":[
               "mqDJGWqwWghJvjqmp4sGRbhL6E1UtC7niY"
            ]
         }
      }
   ]
}

8.broadcast実行

broadcast実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "0100000001090e93118733d5aac07186b4810b45d0d5f7f78f31c2d26d211dc6de3ed09ee9000000006a47304402206443cded856f293b3d0375c4c04119f1fd0c81eb265e8fb4e371fea851955de802206e675726f6ddb609c1a641418d82df9f4c5c902bc63ad23cd3ec57eb450b04c701210234b9aae1d3600e0e6c0b1be3ac87a82b5ec030d1680faff6eee8735de63f28c8ffffffff01a0e83e0100000000232102515ca98f0e0fc6ecf5a20554bbef48f86b249ec75154a4259e6d4ea8f1f4d654ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast

レスポンス

{
   "txid":"030a05cd13f2b8cdacaafcc1391b54f78110c44036f5aea6c4963533815ad203"
}

9.broadcast実行結果

問題なく送信できました。

http://tbtc.blockr.io/tx/info/030a05cd13f2b8cdacaafcc1391b54f78110c44036f5aea6c4963533815ad203

TXEDITORによるトランザクション作成 (P2PK to P2PKH)

P2PKのUTXOが作成されたので、今度はこれを支払います。

1.送信元のUTXO取得

UTXOはBlockcypherAPIを利用して取得します。(IndieSquareAPIだと空になっていた… バグ?)

$ curl https://api.blockcypher.com/v1/btc/test3/addrs/mqDJGWqwWghJvjqmp4sGRbhL6E1UtC7niY
{
  "address": "mqDJGWqwWghJvjqmp4sGRbhL6E1UtC7niY",
  "total_received": 20900000,
  "total_sent": 0,
  "balance": 20900000,
  "unconfirmed_balance": 0,
  "final_balance": 20900000,
  "n_tx": 1,
  "unconfirmed_n_tx": 0,
  "final_n_tx": 1,
  "txrefs": [
    {
      "tx_hash": "030a05cd13f2b8cdacaafcc1391b54f78110c44036f5aea6c4963533815ad203",
      "block_height": 1088643,
      "tx_input_n": -1,
      "tx_output_n": 0,
      "value": 20900000,
      "ref_balance": 20900000,
      "spent": false,
      "confirmations": 1,
      "confirmed": "2017-02-13T10:04:53Z",
      "double_spend": false
    }
  ],
  "tx_url": "https://api.blockcypher.com/v1/btc/test3/txs/"
}

2.TXEDITOR (Transactionタブ)を入力

  • txins[0].outpoint.hash = utxoのtxid
  • txins[0].outpoint.index = utxoのvout
  • txins[0].signature_script = UTXOのLocking Script (P2PK) (HEX)
  • txouts[0].value = utxo.value - 100000 = 20800000
  • txouts[0].pk_script = 送信先アドレスのLocking Script (HEX)

スクリーンショット 2017-02-13 19.31.41.png

3.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-13 19.32.08.png

4.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type⭐

スクリーンショット 2017-02-13 23.32.16.png

5.TXEDITOR (Transactionタブ)を入力

txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-13 23.32.38.png

6.decodeRawTransaction実行

decodeRawTransaction実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000103d25a81333596c4a6aef53640c41081f7541b39c1fcaaaccdb8f213cd050a03000000004847304402202d8e368701b932088af02e0732452ba7e2d2772b30646a3bce30c3c40cec99e002207b84e3962056b733c2e506a787c34817ef99bfc9e535fe662a1e00c484b7f6b101ffffffff0100623d01000000001976a91476a7d66e4617d488c39c1bd56ec546865059f4a888ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode

レスポンス

{
   "txid":"85cbbe9c15ba34e126a66f324c346f861ff5ec7995db376c25915332d53dfe94",
   "size":157,
   "version":1,
   "locktime":0,
   "vin":[
      {
         "txid":"030a05cd13f2b8cdacaafcc1391b54f78110c44036f5aea6c4963533815ad203",
         "vout":0,
         "scriptSig":{
            "asm":"304402202d8e368701b932088af02e0732452ba7e2d2772b30646a3bce30c3c40cec99e002207b84e3962056b733c2e506a787c34817ef99bfc9e535fe662a1e00c484b7f6b1[ALL]",
            "hex":"47304402202d8e368701b932088af02e0732452ba7e2d2772b30646a3bce30c3c40cec99e002207b84e3962056b733c2e506a787c34817ef99bfc9e535fe662a1e00c484b7f6b101"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":0.208,
         "n":0,
         "scriptPubKey":{
            "asm":"OP_DUP OP_HASH160 76a7d66e4617d488c39c1bd56ec546865059f4a8 OP_EQUALVERIFY OP_CHECKSIG",
            "hex":"76a91476a7d66e4617d488c39c1bd56ec546865059f4a888ac",
            "reqSigs":1,
            "type":"pubkeyhash",
            "addresses":[
               "mrLM6FazFDupo54qmS4z1YgCKg9grkTiTe"
            ]
         }
      }
   ]
}

7.broadcast実行

broadcast実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "010000000103d25a81333596c4a6aef53640c41081f7541b39c1fcaaaccdb8f213cd050a03000000004847304402202d8e368701b932088af02e0732452ba7e2d2772b30646a3bce30c3c40cec99e002207b84e3962056b733c2e506a787c34817ef99bfc9e535fe662a1e00c484b7f6b101ffffffff0100623d01000000001976a91476a7d66e4617d488c39c1bd56ec546865059f4a888ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast

レスポンス

{
   "txid":"85cbbe9c15ba34e126a66f324c346f861ff5ec7995db376c25915332d53dfe94"
}

8.broadcast実行結果

問題なく送信できました。

http://tbtc.blockr.io/tx/info/85cbbe9c15ba34e126a66f324c346f861ff5ec7995db376c25915332d53dfe94

参考

https://programmingblockchain.gitbooks.io/programmingblockchain-japanese/content/other_types_of_ownership/p2pk[h]pay_to_public_key[hash].html https://bitcore.io/api/lib/script

TXEDITORを使ってP2PKHトランザクションを作る

Blockchain Core Camp に参加しました

Blockchain(ビットコイン)コア実装を体験するワークショップに参加しました。

bc-2.jp

TXEDITORによるトランザクション作成

ビットコイントランザクションをWeb画面で作成する面白い体験がありましたので家に帰ってから復習した結果を共有します。

# Digital Garageの方が作成されたトランザクション作成ツール「TXEDITOR」を利用します。

1.事前準備

  • (1) bitcore-libインストール
  • (2) 新規アドレス作成JS作成
  • (3) 送信元アドレス作成
  • (4) 送信先アドレス作成
  • (5) 送信元アドレスにBitcoinを送付

(1) bitcore-libインストール

$ 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);
// var privateKey = new bitcore.PrivateKey("929f890e36a725449e53945b1f7a64a124a9fb4b31d735426a2d9ac8166ff1f9", 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());

var script = new bitcore.Script.buildPublicKeyHashOut(privateKey.toPublicKey());
console.log("Locking Script : " + script.toString());
console.log("Locking Script (HEX) : " + script.toHex());

(3) 送信元アドレス作成

$ node new_address.js
Private Key : bc32f5abc11358b684aaddf879d5de547102d32f87a4e9b61cc01198e36729ed
Private Key (WIF) : cTtY3S5SKLzmGsoySfmHbNb2FwTq3bCw67qQ2oZ4ZRpyt4gqSaia
Public Key : 0328df82ba5d3086703ccf4dc66f59370895abc9dc3e2786243b6bd4f47752668e
Bitcoin Address : mpMvEqrLGGRtSrPFbmxnWC4Fxz95TwP5C8
Locking Script : OP_DUP OP_HASH160 20 0x6103ac34044e1a01842ed9bfc442812bdbd482e3 OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a9146103ac34044e1a01842ed9bfc442812bdbd482e388ac

(4) 送信先アドレス作成

$ node new_address.js
Private Key : bef4ad11ac5ebc6cb2be164395b6e0e47b3c88bacc3d0f4d276d568be103f1b4
Private Key (WIF) : cTytr1cdcWKucVpZ5vSiQnfiVJxngBDwxPzkhkmYByGHHzbpfjCd
Public Key : 0357f0e2adfcfa7288da1e71f9705a6d544f4b526efa3d8c2f59f74f7729852df2
Bitcoin Address : mnNzTHyXRpKJyszKuFenXDtRVwchsK9uBu
Locking Script : OP_DUP OP_HASH160 20 0x4b475af403bb8e544bcca29dc5212c7775fa818f OP_EQUALVERIFY OP_CHECKSIG
Locking Script (HEX) : 76a9144b475af403bb8e544bcca29dc5212c7775fa818f88ac

(5) 送信元アドレスにBitcoinを送付

以下サイトから「mpMvEqrLGGRtSrPFbmxnWC4Fxz95TwP5C8」を入力するとTestnetで使えるBitcoinがもらえます

http://tpfaucet.appspot.com/

2.送信元のUTXO取得

UTXOはIndieSquare APIを利用して取得します。

$ curl https://apitestnet.indiesquare.me/v2/addresses/mpMvEqrLGGRtSrPFbmxnWC4Fxz95TwP5C8/utxos

[
   {
      "scriptPubKey":"76a9146103ac34044e1a01842ed9bfc442812bdbd482e388ac",
      "vout":0,
      "confirmations":0,
      "txid":"70c459dfd852b85f49e8c64a3af29e554cd1fffacf7bcccd28ac1d8ef99b55be",
      "amount":0.043
   }
]

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 * 1000000 - 100000 = 4200000
  • txouts[0].pk_script = 送信先アドレスのLocking Script (HEX)

スクリーンショット 2017-02-12 19.36.28.png

4.TXEDITOR (Signature(HASHTYPE_ALL))を入力

  • Private key (WIF/HEX) = 送信元のPrivate Key (WIF)

スクリーンショット 2017-02-12 19.36.51.png

5.TXEDITOR (Script)を入力

  • Script = Signature + Hash Type<改行>送信元のPublic Key

スクリーンショット 2017-02-12 19.37.15.png

6.TXEDITOR (Transactionタブ)を入力

  • txins[0].signature_script = Script.Hex

スクリーンショット 2017-02-12 19.37.33.png

7.decodeRawTransaction実行

decodeRawTransaction実行

curl -H "Content-Type: application/json" -X POST -d '{"tx": "0100000001be559bf98e1dac28cdcc7bcffaffd14c559ef23a4ac6e8495fb852d8df59c470000000006a47304402207674f93be33f2a8b4a9fbdde81ffc9b6421e8854a17891a5a9db64f3a68e2a7902202f1eed603863afd62806468712ba4eada73bff41b310c1deed485112fc8b996f01210328df82ba5d3086703ccf4dc66f59370895abc9dc3e2786243b6bd4f47752668effffffff0140164000000000001976a9144b475af403bb8e544bcca29dc5212c7775fa818f88ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/decode

レスポンス

{
   "txid":"40e2b155bb7b73623b2b2f8866a455699b76aeab077cd8d310a495e629ad2d6f",
   "size":191,
   "version":1,
   "locktime":0,
   "vin":[
      {
         "txid":"70c459dfd852b85f49e8c64a3af29e554cd1fffacf7bcccd28ac1d8ef99b55be",
         "vout":0,
         "scriptSig":{
            "asm":"304402207674f93be33f2a8b4a9fbdde81ffc9b6421e8854a17891a5a9db64f3a68e2a7902202f1eed603863afd62806468712ba4eada73bff41b310c1deed485112fc8b996f[ALL] 0328df82ba5d3086703ccf4dc66f59370895abc9dc3e2786243b6bd4f47752668e",
            "hex":"47304402207674f93be33f2a8b4a9fbdde81ffc9b6421e8854a17891a5a9db64f3a68e2a7902202f1eed603863afd62806468712ba4eada73bff41b310c1deed485112fc8b996f01210328df82ba5d3086703ccf4dc66f59370895abc9dc3e2786243b6bd4f47752668e"
         },
         "sequence":4294967295
      }
   ],
   "vout":[
      {
         "value":0.042,
         "n":0,
         "scriptPubKey":{
            "asm":"OP_DUP OP_HASH160 4b475af403bb8e544bcca29dc5212c7775fa818f OP_EQUALVERIFY OP_CHECKSIG",
            "hex":"76a9144b475af403bb8e544bcca29dc5212c7775fa818f88ac",
            "reqSigs":1,
            "type":"pubkeyhash",
            "addresses":[
               "mnNzTHyXRpKJyszKuFenXDtRVwchsK9uBu"
            ]
         }
      }
   ]
}

8.broadcast実行

broadcast実行

$ curl -H "Content-Type: application/json" -X POST -d '{"tx": "0100000001be559bf98e1dac28cdcc7bcffaffd14c559ef23a4ac6e8495fb852d8df59c470000000006a47304402207674f93be33f2a8b4a9fbdde81ffc9b6421e8854a17891a5a9db64f3a68e2a7902202f1eed603863afd62806468712ba4eada73bff41b310c1deed485112fc8b996f01210328df82ba5d3086703ccf4dc66f59370895abc9dc3e2786243b6bd4f47752668effffffff0140164000000000001976a9144b475af403bb8e544bcca29dc5212c7775fa818f88ac00000000"}' https://apitestnet.indiesquare.me/v2/transactions/broadcast

レスポンス

{
   "txid":"40e2b155bb7b73623b2b2f8866a455699b76aeab077cd8d310a495e629ad2d6f"
}

9.broadcast実行結果

問題なく送信できました。

http://tbtc.blockr.io/tx/info/40e2b155bb7b73623b2b2f8866a455699b76aeab077cd8d310a495e629ad2d6f

参考

https://developer.indiesquare.me/#broadcast-transaction http://tpfaucet.appspot.com/ http://qiita.com/you21979@github/items/5d3bd71ae2107d03973a

ビットコインの送金時間が遅い!と感じたら送金手数料を確認しましょう

ビットコインの送金時間が遅い!と感じたら送金手数料を確認しましょう

承認時間に12時間かかる!

ビットコインやCounterpartyトークンを送金した時の承認時間がすごく遅いと感じたことはありませんか? 送金手数料を見直すことで解決できるかもしれません。

増加するトランザクション

Bitcoin - Daily Number of Transactions

スクリーンショット 2016-03-03 06.43.07.png

トランザクションは増え続けており、今後もマイナーによるトランザクションの選別が厳しくなっていると予想できます。

マイナーは手数料の高いトランザクションを優先する

PREDICTING BITCOIN FEES FOR TRANSACTIONS SINCE 1759.

スクリーンショット 2016-03-03 06.43.55.png

bitcoinfees.21.coでは、過去24時間のトランザクションのデータから、手数料と承認までの時間をグラフ化しており、現在の推奨手数料を表示してくれます。

手数料が60satoshis/byteの場合は30分以内に承認されていますが、10satoshis/byteの場合は10時間近くかかることが分かります。

APIも提供しているみたいです。

https://bitcoinfees.21.co/api/v1/fees/recommended

{
fastestFee: 60,
halfHourFee: 60,
hourFee: 50
}

bitcoinfees.21.coのグラフが正しいか試してみた

時間帯A

上記グラフの時です。

(1) Bread Wallet

https://blockchain.info/tx/ce9b9adefca584a35cbdbc663cbfa66744fc14ddbc368d513e04e1bc1a88b760

Fee: 0.00006 BTC - Size: 225 bytes = 26 satoshi/byte

Confirmation Time: 2H

(2) counterwallet.io (Counterpartyトークン送信)

https://blockchain.info/tx/e5f66ae192aa551bd66c8f005c0ca30c2efbebe1177e67d15a4668b67a16cd7f

Fee: 0.0001 BTC - Size: 708 bytes = 14 satoshi/byte

Confirmation Time: 12H

時間帯B

スクリーンショット 2016-03-03 08.30.09.png

(1) Blockchain.info (手数料は手動で変更)

https://blockchain.info/tx/0bb438b79339b994595751a06ac7b5ed783a67bcc39a5d5dddfc61d840d35dd9

Fee: 0.0006 BTC - Size: 225 bytes = 266 satoshi/byte

Confirmation Time: 15min

(2) Bread Wallet

https://blockchain.info/tx/0bb438b79339b994595751a06ac7b5ed783a67bcc39a5d5dddfc61d840d35dd9

Fee: 0.00006 BTC - Size: 225 bytes = 26 satoshi/byte

Confirmation Time: 15min

(3) IndieSquare (Counterpartyトークン送信)

https://blockchain.info/tx/4412ee9fc9793ec1fd652beba130cd0dd08b7552138ed74bd324ad4726bbe31d

Fee: 0.0001 BTC - Size: 412 bytes = 24 satoshi/byte

Confirmation Time: 15min

時間帯Aと時間帯Bの確認から分かること

  • グラフと実際の待ち時間はだいたい一致している
  • 時間帯Aはグラフより遅い、時間帯Bはグラフより早い。時間帯による変動が大きいが、グラフにそれが表現されていない気がする(グラフは24時間分のデータだからか)
  • Counterpartyトランザクションも同じようにマイニングされている。

各Walletアプリはどうやって手数料を決めているの?

トランザクションのサイズに対して手数料を決めてます。1byteに対してXsatoshiみたいに。Blockchain.infoアプリは設定を自由に変更できます。また、Bitcoinネットワークの状況を見て適切な手数料を推測しようとしているアプリもあります。

Blockchain.infoアプリの手数料変更画面

IMG_1985.PNG

まとめ

satoshi/byteの設定だけでは、適切な手数料設定は難しいことが分かりました。bitcoinfees.21.coは24時間のデータを元にしていますが、もう少し短い間隔の方が良いと思います。とはいえ、Bread WalletのRedditGithub issueを見る限り、動的な手数料決定は簡単ではなさそうです。簡単ではないでしょうがこの問題を解決すればWalletの差別化になります。

参考

Bitcoin - Daily Number of Transactions

Bread wallet transaction fee

Dynamic fee estimation #267

Are there expire time for unconfirmed transaction

TipMe

TipMe with IndieSquare

Google APIsを使ってGCEのスナップショットを取得する(PHP Laravel5)

Google APIsのPHPクライアント

google/google-api-php-client

githubPHPのクライアントライブラリがあるのでそれを使います。

composer require設定

"google/apiclient": "^2.0.0@RC"

composer autoload設定

"autoload": {
    "classmap": [
        "vendor/google/apiclient/src/Google"
    ],
    "psr-4": {
        "App\\": "app/"
    }
},

Compute Engine API

Compute Engine API Reference

google-api-php-clientは、カレンダーとかメールとか多数のAPIラッパーがあります。今回はスナップショットを作成するので、Compute Engine APIを利用します。

GCEで実行する場合はデフォルトの認証キーが利用できる

Authorizing Requests to Google Compute Engine

If you run applications on your Compute Engine instances, application default credentials can obtain credentials through built-in service accounts

具体的には以下2行で認証情報を設定できます。

$client = new \Google_Client();
$client->useApplicationDefaultCredentials();

スナップショット作成

$client = new \Google_Client();
$client->useApplicationDefaultCredentials();
$client->setScopes([\Google_Service_Compute::COMPUTE]);

$compute_service = new \Google_Service_Compute($client);

// 既存のスナップショット削除
try {
  $compute_service->snapshots->delete('project-name', 'snapshot-name', array());
} catch (\Exception $e) {}

// スナップショット作成
try {
  $snapshot = new \Google_Service_Compute_Snapshot();
  $snapshot->setName('snapshot-name');
  $compute_service->disks->createSnapshot('project-name', 'asia-east1-a', 'instance-name', $snapshot, array());
} catch (\Exception $e) {
    Log::error($e);
}

まとめ

Compute Engine API以外にもBigquery APIなど使えるので今後組み込んでみます。

参考

Authorizing Requests to Google Compute Engine

GCP vs 他社クラウド

Google API - Service account connection - Laravel 5

Google Application Default Credentials

LARAVEL 5 + GOOGLE APIS CLIENT LIBRARY

[GoogleAPI千本ノック] Google Compute Engine API を試してみた

TipMe

TipMe with IndieSquare