272ページ中124〜126。

前回まで

取引データが支払か受取か判別する方法を知りたくて読む。

トランザクションscriptとScript言語

Bitcoinクライアントはscriptを実行することでトランザクションの有効性をチェックします。

有効性とは? そのコインの所有者であるかどうかを確認するとか? データ形式が正しいかとか?

UTXOにあるlocking script(解除条件)と通常署名を含んでいるunlocking scriptはこの Script言語で書かれています。

UTXOは未使用アウトプットだっけ? 次の支払いに使うコインデータであり、以前までの受け取りトランザクションデータのこと。

locking scriptunlocking scriptとは? 118ページに以下のようにあった。コインを使用する条件のことらしい。

使用条件(解除条件) トランザクションアウトプットはbitcoin(satoshi単位で表された)を、特定の 解除条件(encumbrance) またはbitcoinを使うにあたって満たさなければいけない条件を定義したlocking scriptと関連づけています。多くの場合、locking scriptは特定の Bitcoinアドレスにアウトプットをロックし、これにより所有権が新しい所有者に移ります。AliceがBobのカ フェにコーヒー代を支払ったとき、彼女のトランザクションのアウトプットにはカフェのBitcoinアドレスに ロックされた0.015bitcoinアウトプットが含まれていました。この0.015bitcoinアウトプットはブロックチェ ーンに記録され、カフェのBitcoinアドレスに紐づいた未使用トランザクションアウトプットセットの一部に なったのです。Bobがこの0.015bitcoinアウトプットを支払いに使うときに、彼のトランザクションはBobの 秘密鍵による署名を含むunlocking scriptを提示することでこの 0.015bitcoinアウトプットのロックを外すのです。

アウトプットはアドレスでロックされている。これにより特定のアドレスでしかそのコインを使用できないようにしている。という意味だろう。たぶん。

アドレスに紐づく秘密鍵による署名とやらでunlocking scriptを提示することで、アウトプットにあるコインを使用可能にする。と。署名とか提示とか動詞がすべてわからない。具体的に何をしているのやら。

とにかくunlocking scriptを提示できたら、そのアウトプットは自分のコインだということが判明するってことかな?

でも、それがおつり用なのか、支払い用なのか、受け取り用なのかはわからない、よね? どうなの? このscriptとやらで取引が支払いか受け取りか判別できるのだろうか?

もっと読み進めてみよう。

トランザクションが有効かチェックされるときは、資金の使用条件を満たして いるかどうかをみるためにそれぞれのインプットにあるunlocking scriptが対応したlocking scriptとともに実行されます。

はい。そのコインを支払おうとしているのがコインの所有者本人であるか確認していると。

今日、Bitcoinネットワークを通して処理される多くのトランザクションは"AliceがBobに支払う"というよう な形式になっており、Pay-to-Public-Key-Hash scriptと呼ばれる scriptに基づいています。しかし、アウトプットをロックしインプットを解錠するscriptを使うことは、プロ グラミング言語を通してトランザクションに無限個の条件を含められることを意味します。つまり、Bitcoin トランザクションは"AliceがBobに支払う"という形式に制限されているわけではないのです。 これは単にこのScript言語によって表現できる可能性の氷山の一角を見せているに過ぎません。

取引データにはscript言語が使われている。そいつはしばしば「A氏がB氏に支払う」ということをあらわすような使われ方をする。でも、それだけがscript言語の能じゃない。もっとほかに色々なことができるんだぜ。という話かな。

なんで取引を解析するのにscript言語とかいうわけのわからん言語を理解しなくちゃいけないの? 面倒くさいだけじゃない? という気分なんだが。きっと海よりも深いワケがあるのだろう。

この節では、 Bitcoinトランザクションのscript言語の要素を説明し、どのように資金の使用に対する完全な条件を表現する のか、どのようにunlocking scriptは条件を満たすことができるのかを説明していきます。

お願いします。それを理解することが支払か受取かを区別する方法につながればいいけど。それさえわからない。

TIP: Bitcoinトランザクションの有効性チェックは静的なパターンに基づいているわけではなく、Script言語の実行を通して行われています。この言語はほとんど無限個の条件を表現することがで きます。このようにしてBitcoinは"プログラム可能な通貨"を実現しているのです。

なんかすごそう。自由度が高いのだろう。でもすごい面倒くさそう。

とにかくトランザクションの有効性とやらを確認するためにscript言語とかいうのが使われていて、そいつは無限個の条件を表現できると。将来の拡張性に備えてそうした作りにしているのかな?

scriptの構築(Lock + Unlock)

Bitcoinのトランザクション有効性チェックエンジンは二種類のscriptによって成り立っています。1つはlocking script、もう1つはunlocking scriptです。

はい。さっき聞きました。

locking scriptはアウトプットに置かれている解除条件で、将来アウトプットを使用する際に満たさなければいけない 条件を指定しています。

このコインを使いたくばlocking scriptを解除してみせよ、ということね。

歴史的に、locking scriptは scriptPubKey と呼ばれていました。というのは、locking scriptに通常公開鍵または Bitcoinアドレスが含まれているからです。この本では、Scriptテクノロジーの可能性をより多く得るために それを"locking script"と呼ぶことにします。

scriptPubKeyはAPIで取引データを取得したときのJSONプロパティにあったな。voutの中にあったと思う。それのことだろう。

"vout": [
    {
        "n": 0,
        "scriptPubKey": {
            "addresses": [
                "MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu"
            ],
            "asm": "OP_DUP OP_HASH160 45fc13c9d3a0df34008291492c39e0efcdd220b8 OP_EQUALVERIFY OP_CHECKSIG",
            "hex": "76a91445fc13c9d3a0df34008291492c39e0efcdd220b888ac",
            "reqSigs": 1,
            "type": "pubkeyhash"
        },
        "value": 1.14114
    },

多くのBitcoinアプリケーションでは、locking scriptと呼んだものが scriptPubKey としてソースコードに出てきます。 unlocking scriptは、locking scriptによってアウトプットに置かれた条件を"解く"または満たす scriptで、アウトプットを使用できるようにします。

はあ。script言語のコンパイラがないと実行できないんだろうな。JavaScriptの中では無理なんだろうなぁ。

unlocking scriptは全てのトランザクションインプットの一部であり、ほとんどの場合秘密鍵からウォレットが作り出し たデジタル署名を含んでいます。歴史的に、unlocking script が通常デジタル署名を含んでいるためunlocking scriptは scriptSig と呼ばれています。多くの Bitcoinアプリケーションのソースコードの中では、unlocking scriptを scriptSig と呼んでいます。この本では、これを"unlocking script" と呼ぶことにしています。というのは、全てのunlocking scriptが署名を含んでいなければいけないわけではなく、locking scriptの解除をするために必要なものは署名以外にもあるということに気づいてもらうためです。

よくわからんけど、scriptはとにかく自由度が高いと。たぶん取引データを作るときに色々なscriptを組めるのだろう。ウォレットやらツールやらによって変わるのだろう。そのせいで支払いか受け取りかも簡単に判断できないデータ構造になっているってことなのか? 勘弁してくれ。

でもこのscriptってトランザクションの有効性を確認するためのものではなかったっけ? なら支払いか受け取りかの判別とは関係ないのでは? わからないけど読み進めるしかない。

scriptSigというのはAPIで取引データを取得したときvinに入っていたっけ。「ほとんどの場合はデジタル署名を含んでいる」とか。デジタル署名ってなに。本人確認するときの印鑑やサインのようなものかな?

全てのBitcoinクライアントはlocking scriptとunlocking scriptを一緒に実行することでトランザクションが有効であることをチェックします。

はい、さっき聞きました。

トランザクションにあ るそれぞれのインプットに対して、有効性チェックソフトウェアは最初にインプットによって参照されている UTXOを取得しようとします。このUTXOは、UTXOを使うときに必要な条件が定義してあるlocking scriptを含んでいます。有効性チェックソフトウェアはこのときこのUTXOの資金を使おうとしているインプ ットに含まれているunlocking scriptを取り出し、locking scriptとunlocking scriptを実行します。

「unlocking scriptを取り出し、locking scriptとunlocking scriptを実行します」ってなに?

これまでの話をまとめてみる。

名前 意味
unlocking script 多くの場合、デジタル署名を含む
locking script コインを使うための解除条件

デジタル署名を取り出して、それを解除条件を達成するために使うってことかな?

unlocklockの引数になるのだろう。lockは施錠する南京錠のほうで、unlockはそれを解錠するのに必要な鍵ってイメージかな?

オリジナルのBitcoinクライアントでは、unlocking scriptとlocking scriptは結合されており順番に実行されていました。セキュリティの観点からこれは2010年に変更されました 。悪意あるunlocking scriptがスタックにデータをプッシュし、locking scriptを意味がないものにしてしまうという弱点が生じてしまうためです。

そういう歴史があるのね。

現在の実装では、次に説明するよ うにunlocking scriptとlocking scriptは別々に実行され、スタックがこれらの間で転送される形で実行されるようになっています。 最初に、スタック実行エンジンを使ってunlocking scriptが実行されます。もしunlocking scriptがエラーなく(例えば、"まだ実行されていない"オペレータが何も残っていないなど)実行されると、メ インスタック(代替スタックではなく)がコピーされlocking scriptが実行されます。もしunlocking scriptからコピーされたスタックデータとともに実行されたlocking scriptの結果が"TRUE"なら、unlocking scriptはlocking scriptによって課されていた条件を解くことに成功したということです。よって、インプットはUTXOを使用 する有効な権限を持っているということになります。

はあ。おめでとうございます。とにかくlocking scriptTRUEを返したときだけ、そのインプットのコインを使用できるってことね。そして、そうなるためには所有者がもつ秘密鍵が必要ってことかな?

もし"TRUE"以外が実行結果に残ってしまっているので あれば、インプットは有効ではありません。UTXOに置いてある使用条件を満たすことができなかったからで す。

ふーん。無効だったらどうなるの?

重要なこととして、UTXOはブロックチェーンに永遠に記録され続けるため成功しなかった場合UTXOで あるという状態は変化せず、何度新しいトランザクションがUTXOを不正に使用しようとしてもUTXOは全く 影響を受けません。UTXOの条件を正しく満たす有効なトランザクションだけがUTXOに"使用済み"という印 をつけ、使用可能な(未使用)UTXOのセットから削除させることができるのです。

無効なときはそのコインの所有者でない何者かが不正利用したものと判断される。それ自体にペナルティがかかるようなこともなく、UXTOにも影響なし。単にそのコインを含むUXTOを使用することはできず無視されるってことか。

トランザクションscriptを評価するためのscriptSigとscriptPubKeyの結合はunlocking scriptとlocking scriptのよくある例(公開鍵ハッシュへの支払い)です。これは、scriptの有効性チェックの前のunlocking scriptとlocking scriptが連結されたscriptを示しています。

以下の取引データをみてみるとscriptSigだのscriptPubKeyというキーワードがある。

    "vin": [
        {
            "scriptSig": {
                "asm": "304402204c24e753f63c57c5d2a944d4f0e66c6190f00ecd57cf2bdb24fe5e69f7e5cd970220591bfffa4e31eb124e43bd9bb2e325bd0e3d741c4c69f9d39acf1c72d2fbf306[ALL] 0257026e027209836532c2cd7807c06e30a889d3cca51884686af8aa2aacafbc1e",
                "hex": "47304402204c24e753f63c57c5d2a944d4f0e66c6190f00ecd57cf2bdb24fe5e69f7e5cd970220591bfffa4e31eb124e43bd9bb2e325bd0e3d741c4c69f9d39acf1c72d2fbf30601210257026e027209836532c2cd7807c06e30a889d3cca51884686af8aa2aacafbc1e"
            },
            "sequence": 4294967295,
            "txid": "bbb38720563500d49f9ab60f05c941c0b24fdc6294a63ca667ba45a03be6a2af",
            "vout": 1
        }
    ],
    "vout": [
        {
            "n": 0,
            "scriptPubKey": {
                "addresses": [
                    "MTH4xy3DCx18X5JqUpyfPuGFtX4xuVoWXk"
                ],
                "asm": "OP_DUP OP_HASH160 d48f250ba88b937f29b0dca914f2e0099485078f OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a914d48f250ba88b937f29b0dca914f2e0099485078f88ac",
                "reqSigs": 1,
                "type": "pubkeyhash"
            },
            "value": 0.1
        },
        {
            "n": 1,
            "scriptPubKey": {
                "addresses": [
                    "MEHCqJbgiNERCH3bRAtNSSD9uxPViEX1nu"
                ],
                "asm": "OP_DUP OP_HASH160 45fc13c9d3a0df34008291492c39e0efcdd220b8 OP_EQUALVERIFY OP_CHECKSIG",
                "hex": "76a91445fc13c9d3a0df34008291492c39e0efcdd220b888ac",
                "reqSigs": 1,
                "type": "pubkeyhash"
            },
            "value": 0.8410725
        }
    ],

また、PDFの図にあったDUP HASH160 <PubHash> EQUALVERIFY CHECKSIGに似たようなやつならあった。voutasmプロパティ値に。OP_というのがついているけど。

OP_DUP OP_HASH160 d48f250ba88b937f29b0dca914f2e0099485078f OP_EQUALVERIFY OP_CHECKSIG

これのことかな? このscript言語を実行しTRUEが返ってきたらそのUXTOに残っているコインを支払いに使えると。

疑問 scriptは支払/受取の判別に使えるか?

名前 意味
unlocking script(vinscriptSig) 多くの場合、デジタル署名を含む
locking script(voutscriptPubKey) コインを使うための解除条件

unlocking scriptと秘密鍵がわかれば、本人だと確認できる。という話だと理解した。

もしそうなら、scriptで支払/受取を判別できるのでは?

たぶん秘密鍵となにか(ブロックヘッダ? ランダム値?)をかけ合わせてできた値と、vinscriptSigにあるasmだかhexだかとを比較照合し一致したら本人と判定するのだろう。

もしそうだとしたら、vinは支払いに使うコインなので、それが自分だったらこの取引データは支払いだと判別できる。もし自分でないなら受け取りだと判別できる。

秘密鍵

気になるのは秘密鍵が必要ということ。たぶんウォレットの中に入っているのだろう。それをブラウザのJavaScriptに渡すのは非常に危険だと思われる。だとしたら、この方法で支払・受取の判定をするのはセキュリティ・リスクがあり事実上不可能。

はたしてこの認識で合っているかはわからない。もしそうならJavaScriptで安全に支払・受取の判定をする方法はあるのか。なかったら詰み。自分でサーバを立てて実装することでしか総支払額を算出できないというオチになる。そんな予感がするけど、読み進めてみよう。