Standard Transactions
Bitcoinでは標準的なTransactionというものがあります。
Standard Transactions
これは、tx_out
のpk_script
に設定するscript
の形式の事といっても過言ではないと思います。
SegwitがActiveになる前は、5つのStandard Transactions
が定められていました。
ここではbitcoin-cli
を使って、5つのStandard Transactions
に送信し、送信されたものを、さらに送信してみます。
Pay To Public Key Hash (P2PKH)
現在のBitcoinで最も使われている形式です。(今後はSegwitへ移行していくと思いますが・・・)
Transaction
のoutput
に設定する、Pubkey script
(pk_script
やlocking script
など呼び方は様々)
は、下記の上段にある形式となります。
また、使うときにinput
に設定する、Signature script
(scriptSig
やunlocking script
など呼び方は様々)
は、下記の下段になる形となります。
Pubkey script : OP_DUP OP_HASH160 <PubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
Signature script: <sig> <pubkey>
ここでは、以下の<pubkey>
(公開鍵)を利用します。
これからHASH160
を計算して、<PubKeyHash>
を求め、Pubkey script
にします。
<pubkey> : 027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70af
<PubKeyHash> : 925d4028880bd0c9d68fbc7fc7dfee976698629c
Pubkey script: 76a914925d4028880bd0c9d68fbc7fc7dfee976698629c88ac
Pay To Script Hash (P2SH)
Transaction
のoutput
が受け取り、input
が支払いになります。
支払いには、どのTransaction
(txid
)のどのoutput
(vout
)が自分が所有している事を証明する必要があります。
P2PKH、Multisig、Public、では決まったScript形式によって、これらを実現する事ができます。
それ以外のScriptを組みたい場合に使うのが、このP2SHとなります。(これもSegwitへ移行していくと思います。)
下記の上段がoutput
に設定するScript、下段がinput
に設定するScriptとなります。
独自のScriptをredeemScript
と言います。
Pubkey script : OP_HASH160 <Hash160(redeemScript)> OP_EQUAL
Signature script: <sig> [sig] [sig...] <redeemScript>
ここでは、Redeem script
をマルチサインとします。
3つのpubkey
(公開鍵)から、2つの署名があれば良いScriptとします。
この場合、Signature script
は下記の一番下となります。
先頭にOP_0
がありますが、これはOP_CHECKMULTISIG
のバグで必要となっています。
Redeem script : OP_2 <A pubkey> <B pubkey> <C pubkey> OP_3 OP_CHECKMULTISIG
Pubkey script : OP_HASH160 <Hash160(redeemScript)> OP_EQUAL
Signature script: OP_0 <A sig> <C sig> <redeemScript>
実際に以下の3つのpubkey
を利用して、<redeemScript>
をつくります。
それをHASH160
をしたものが<Hash160(redeemScript)>
となります。
これを、Pubkey script
にします。
<A pubkey> : 02e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b
<B pubkey> : 02ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6
<C pubkey> : 0271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a9
<redeemScript>: 522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae
<Hash160(redeemScript)>: f58d75163cbaa805d2c63f8bdf11b59f19062ce4
Pubkey script: a914f58d75163cbaa805d2c63f8bdf11b59f19062ce487
Multisig
これはマルチサインの形となります。
n
個の公開鍵からm
個の署名で良いという形式です。n
とm
は1から15まで(n<=m
)可能です。
Pubkey script : <m> <A pubkey> [B pubkey] [C pubkey...] <n> OP_CHECKMULTISIG
Signature script: OP_0 <A sig> [B sig] [C sig...]
P2SHと同じように、以下の3つのpubkey
を利用して、Pubkey script
を作成します。
3つのpubkey
(公開鍵)から、2つの署名があれば良いというマルチサインです。
<A pubkey> : 02e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b
<B pubkey> : 02ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6
<C pubkey> : 0271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a9
Pubkey script: OP_2 <A pubkey> <B pubkey> <C pubkey> OP_3 OP_CHECKMULTISIG
Pubkey script: 522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae
Pubkey
初期の形式となります、bitcoind
でマイニングするとこの形式が使われているようです。
下記の上段がoutput
に設定するScript、下段がinput
に設定するScriptとなります。
Pubkey script : <pubkey> OP_CHECKSIG
Signature script: <sig>
P2PKHと同じように、以下の<pubkey>
(公開鍵)を利用すると、Pubkey script
は以下のようになります。
<pubkey> : 027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70af
Pubkey script: 21027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70afac
Null Data
これは特殊なoutput
で、input
には使う事が出来ません。したがって、outpot
のvalue
が0
でも許されます。
コメントなどの用途で、実際には日時を入れる事が多いようです。
ただし、これを入れるとTransaction
のデータ量が増える為、手数料(fee
)が高くなります。
Pubkey Script
の先頭にOP_RETURN
を入れるだけで良いです。
Pubkey Script: OP_RETURN <0 to 40 bytes of data>
(Null data scripts cannot be spent, so there's no signature script.)
今回は、データを以下の上段にします。
その場合、Pubkey Script
は以下の下段にのようになります。
<0 to 40 bytes of data>: 00112233445566778899aabbccddeeff
Pubkey Script : 6a1000112233445566778899aabbccddeeff
Transactionの送信
5つのStandard Transactions
に送信してみましょう。
regtest
でBitcoinを起動します。(Bitcoindの起動と停止)
Bitcoinを所持しているか確認します。
./bitcoin-cli -regtest getbalance
無い場合は、generate
を行います。
./bitcoin-cli -regtest generate 101
createrawtransaction
でTransaction
を作成したいのですが、P2PKHとP2SHにしか対応していないようなので、
以下のTransaction
を作成しました。
010000000005509e9800000000001976a914925d4028880bd0c9d68fbc7fc7dfee976698629c88ac509e98000000000017a914f58d75163cbaa805d2c63f8bdf11b59f19062ce487509e98000000000069522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae509e9800000000002321027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70afac0000000000000000126a1000112233445566778899aabbccddeeff00000000
まずは、Transaction
の内容をdecoderawtransaction
で見てみます。
input
(vin
)が0個、output
(vout
)が5個、「Null Data
」以外、それぞれ0.10002000 BTC
づつ入れます。
./bitcoin-cli -regtest decoderawtransaction 010000000005509e9800000000001976a914925d4028880bd0c9d68fbc7fc7dfee976698629c88ac509e98000000000017a914f58d75163cbaa805d2c63f8bdf11b59f19062ce487509e98000000000069522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae509e9800000000002321027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70afac0000000000000000126a1000112233445566778899aabbccddeeff00000000
このTransaction
を送信する為に、fundrawtransaction
を使って、必要なinput
を追加します。
「"{\"changePosition\":5}"
」オプションは、お釣りのoutput
を一番最後にする為のものです。
./bitcoin-cli -regtest fundrawtransaction 010000000005509e9800000000001976a914925d4028880bd0c9d68fbc7fc7dfee976698629c88ac509e98000000000017a914f58d75163cbaa805d2c63f8bdf11b59f19062ce487509e98000000000069522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae509e9800000000002321027592aab5d43618dda13fba71e3993cd7517a712d3da49664c06ee1bd3d1f70afac0000000000000000126a1000112233445566778899aabbccddeeff00000000 "{\"changePosition\":5}"
※:ここからは、input
がそれぞれの環境で違うので、結果が異なります。自身の環境での結果を利用してください。
結果が以下のように表示されます。
{
"hex": "<transaction hex>",
"changepos": 5,
"fee": 0.00008180
}
一旦、この<transaction hex>
をdecoderawtransaction
を使って見てみます。
input
(vin
)が1個以上設定されている事がわかります。
また、output
(vout
)の最後にお釣り用のoutput
が追加されている事がわかります。
./bitcoin-cli -regtest decoderawtransaction <transaction hex>
このTransaction
には、input
(vin
)のscriptSig
に何も入っていない為、署名する必要がありあます。
<transaction hex>
をsignrawtransaction
を用いて、署名します。
./bitcoin-cli -regtest signrawtransaction <transaction hex>
結果が以下のように出ます。
{
"hex": "<signed transaction hex>",
"complete": true
}
この<signed transaction hex>
をdecoderawtransaction
を使って見てみます。
./bitcoin-cli -regtest decoderawtransaction <signed transaction hex>
Transaction
のinput
(vin
)にscriptSig
が設定されている事がわかります。
この<signed transaction hex>
をsendrawtransaction
を使って送信します。
./bitcoin-cli -regtest sendrawtransaction <signed transaction hex>
結果は、<txid>
が出ます。(32byte、hexで64文字の値が出ます。)
この<txid>
をコピーしておいてください。この後で使います。
このままでは、ブロックに入らないので、generate
してブロックに入れます。
<txid>
をgetrawtransaction
で見てみます。
./bitcoin-cli -regtest generate 1
./bitcoin-cli -regtest getrawtransaction <txid> 1
5つのStandard Transactions
への送信は完了となります。
Transactionの利用
5つのStandard Transactions
への送信が出来たと思います。
4つの、output
(vout
)を利用していきたいと思います。
(1つは、「Null Data
」なので利用できません。)
送信先は、全て以下とします。
address : mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh
Pay To Public Key Hash (P2PKH)
先ほど送信した、<txid>
の0
番目がP2PKHなので、createrawtransaction
でTransaction
を作成します。
(value
は、手数料(fee
)2,000 satoshi
を引いた、0.1 BTC
としています。)
./bitcoin-cli -regtest createrawtransaction "[{\"txid\":\"<txid>\",\"vout\":0}]" "{\"mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh\":0.1}"
結果はTransaction
のhex
(<p2pkh transaction hex>
)が出ます、これをコピーしてください。
この<p2pkh transaction hex>
をdecoderawtransaction
を使って見てみます。
./bitcoin-cli -regtest decoderawtransaction <p2pkh transaction hex>
この、Transaction
はscriptSig
に何も入っていない為、署名が必要となります。
private key
は以下のとおりです。
<p2phk prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN8kokULeTxo
<p2pkh transaction hex>
から、signrawtransaction
を使って署名します。
./bitcoin-cli -regtest signrawtransaction <p2pkh transaction hex> "[]" "[\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN8kokULeTxo\"]"
結果が以下のように出ます。
{
"hex": "<signed p2pkh transaction hex>",
"complete": true
}
この<signed p2pkh transaction hex>
をsendrawtransaction
を使って送信します。
./bitcoin-cli -regtest sendrawtransaction <signed p2pkh transaction hex>
結果は、<p2pkh txid>
が出ます。(32byte、hexで64文字の値が出ます。)
このままでは、ブロックに入らないので、generate
してブロックに入れます。
<p2pkh txid>
をgetrawtransaction
で見てみます。
./bitcoin-cli -regtest generate 1
./bitcoin-cli -regtest getrawtransaction <p2pkh txid> 1
Pay To Script Hash (P2SH)
送信した、<txid>
の1
番目がP2SHなので、createrawtransaction
でTransaction
を作成します。
(value
は、手数料(fee
)2,000 satoshi
を引いた、0.1 BTC
としています。)
./bitcoin-cli -regtest createrawtransaction "[{\"txid\":\"<txid>\",\"vout\":1}]" "{\"mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh\":0.1}"
結果はTransaction
のhex
(<p2sh transaction hex>
)が出ます、これをコピーしてください。
この<p2sh transaction hex>
をdecoderawtransaction
を使って見てみます。
./bitcoin-cli -regtest decoderawtransaction <p2sh transaction hex>
この、Transaction
はscriptSig
に何も入っていない為、署名が必要となります。
このP2SHは、3つのpubkey
(公開鍵)から、2つの署名が必要です。
2つのprivate key
は以下のとおりです。
<p2sh A prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN9QKPG3J8w2
<p2sh C prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMNAhLetXSy6B
<p2sh transaction hex>
と<txid>
から、signrawtransaction
を使って署名します。
P2SHの場合、redeemScript
が必要となる為、signrawtransaction
の第2パラメータが必要となります。
./bitcoin-cli -regtest signrawtransaction <p2sh transaction hex> "[{\"txid\":\"<txid>\",\"vout\":1,\"scriptPubKey\":\"a914f58d75163cbaa805d2c63f8bdf11b59f19062ce487\",\"redeemScript\":\"522102e5740e63bad28081ed7cf654dd6c19029ca03382fc05ab5f5dda81f2c55b845b2102ec6d499aefd540e90357f1004a136049d1f7df5ad99c44c46e3ed4169e40acb6210271550e6c83a9381f35c568d1a80e11fa3e0efc97dfd0e0f17492a2edb64c37a953ae\"}]" "[\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN9QKPG3J8w2\",\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMNAhLetXSy6B\"]"
結果が以下のように出ます。
{
"hex": "<signed p2sh transaction hex>",
"complete": true
}
この<signed p2sh transaction hex>
をsendrawtransaction
を使って送信します。
./bitcoin-cli -regtest sendrawtransaction <signed p2sh transaction hex>
結果は、<p2sh txid>
が出ます。(32byte、hexで64文字の値が出ます。)
このままでは、ブロックに入らないので、generate
してブロックに入れます。
<p2sh txid>
をgetrawtransaction
で見てみます。
./bitcoin-cli -regtest generate 1
./bitcoin-cli -regtest getrawtransaction <p2sh txid> 1
Multisig
送信した、<txid>
の2
番目がMultisigなので、createrawtransaction
でTransaction
を作成します。
(value
は、手数料(fee
)2,000 satoshi
を引いた、0.1 BTC
としています。)
./bitcoin-cli -regtest createrawtransaction "[{\"txid\":\"<txid>\",\"vout\":2}]" "{\"mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh\":0.1}"
結果はTransaction
のhex
(<multisig transaction hex>
)が出ます、これをコピーしてください。
この<multisig transaction hex>
をdecoderawtransaction
を使って見てみます。
./bitcoin-cli -regtest decoderawtransaction <multisig transaction hex>
この、Transaction
はscriptSig
に何も入っていない為、署名が必要となります。
このMultisigは、3つのpubkey
(公開鍵)から、2つの署名が必要です。
2つのprivate key
は以下のとおりです。
<p2sh A prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN9QKPG3J8w2
<p2sh C prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMNAhLetXSy6B
<multisig transaction hex>
と<txid>
から、signrawtransaction
を使って署名します。
P2SHの場合、redeemScript
が必要となる為、signrawtransaction
の第2パラメータが必要となります。
./bitcoin-cli -regtest signrawtransaction <multisig transaction hex> "[]" "[\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN9QKPG3J8w2\",\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMNAhLetXSy6B\"]"
結果が以下のように出ます。
{
"hex": "<signed multisig transaction hex>",
"complete": true
}
この<signed multisig transaction hex>
をsendrawtransaction
を使って送信します。
./bitcoin-cli -regtest sendrawtransaction <signed multisig transaction hex>
結果は、<multisig txid>
が出ます。(32byte、hexで64文字の値が出ます。)
このままでは、ブロックに入らないので、generate
してブロックに入れます。
<multisig txid>
をgetrawtransaction
で見てみます。
./bitcoin-cli -regtest generate 1
./bitcoin-cli -regtest getrawtransaction <multisig txid> 1
Pubkey
送信した、<txid>
の3
番目がPubkeyなので、createrawtransaction
でTransaction
を作成します。
(value
は、手数料(fee
)2,000 satoshi
を引いた、0.1 BTC
としています。)
./bitcoin-cli -regtest createrawtransaction "[{\"txid\":\"<txid>\",\"vout\":3}]" "{\"mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh\":0.1}"
結果はTransaction
のhex
(<p2pk transaction hex>
)が出ます、これをコピーしてください。
この<p2pk transaction hex>
をdecoderawtransaction
を使って見てみます。
./bitcoin-cli -regtest decoderawtransaction <p2pk transaction hex>
この、Transaction
はscriptSig
に何も入っていない為、署名が必要となります。
private key
は以下のとおりです。
<p2pk prvkey> : cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN8kokULeTxo
<p2pk transaction hex>
から、signrawtransaction
を使って署名します。
./bitcoin-cli -regtest signrawtransaction <p2pk transaction hex> "[]" "[\"cMahea7zqjxrtgAbB7LSGbcQUr1uX1ojuat9jZodMN8kokULeTxo\"]"
結果が以下のように出ます。
{
"hex": "<signed p2pk transaction hex>",
"complete": true
}
この<signed p2pk transaction hex>
をsendrawtransaction
を使って送信します。
./bitcoin-cli -regtest sendrawtransaction <signed p2pk transaction hex>
結果は、<p2pk txid>
が出ます。(32byte、hexで64文字の値が出ます。)
このままでは、ブロックに入らないので、generate
してブロックに入れます。
<p2pk txid>
をgetrawtransaction
で見てみます。
./bitcoin-cli -regtest generate 1
./bitcoin-cli -regtest getrawtransaction <p2pk txid> 1
確認
以下を実行して、アドレスに送信された事を確認してみましょう。
./bitcoin-cli -regtest importaddress mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh
./bitcoin-cli -regtest getreceivedbyaddress mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh
./bitcoin-cli -regtest listunspent 1 9999999 "[\"mrkcWXtBEiTsgrjFDppGNZZU1Zgr7bnseh\"]"
0.4 BTC
入っている事が確認できます。