「会員管理」機能付きの仮想通貨コントラクトをデプロイしてみる(前編)
まったり進行で、引き続きEthereumのお勉強を「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」でやっていきます。
今回は、教科書的には「キャッシュバック機能付き仮想通貨コントラクト」の続きです。
書いているうちに長くなってしまったので、前編と後編に分けることにしましたw
本当ならもう少し早くこれをやりたかったんですが、今回の内容は個人的につまずく箇所がいくつかあったので、「コントラクトの継承と連携(他のコントラクトのメソッド実行)」という記事をはさんでみました。
今回やりたいのは、暗号資産(仮想通貨)が1つあって、これに「紐づくユーザーが各々会員情報を持つ」状況をコントラクトで表現することです。

以下では教科書にあるサンプルコードをデプロイして、動きを追いつつコードについて考えたことなどをコメントしていきます。
今回もBrowser-SolidityでJavaScript VMを使い、すべてweb上で動かします。
アドレスのまとめ
先に、今回使うアドレスをまとめておきます。
今回は、以下4つのアドレスが登場します。
・ユーザーA:0xca35b7d915458ef540ade6068dfe2f44e8fa733c
・ユーザーB:0x14723a09acff6d2a60dcdf7aa4aff308fddc160c
・Membersのデプロイアドレス:0x692a70d2e424a56d2c6c27aa97d1a86395877b3a
・OreOreCoinのデプロイアドレス:0xdc04977a2078c8ffdf086d618d1f961b6c546222
「会員管理」機能付きの仮想通貨コントラクトのデプロイ
コントラクト(コード)の概要
先ほど大まかにご紹介した「やりたい」ことを、コードでどう表現されているかを軽く触れておきます。
コントラクトのコードとしては、だいたい以下のような構造になっています。
(1)所有者管理用コントラクト「Owned」、会員管理用コントラクト「Members」、会員管理機能付き仮想通貨コントラクト「OreOreCoin」の3つが1つの.solファイルに書かれている。
(2)(コードの見通しをよくする目的で)「Members」と「OreOreCoin」が「Owned」のサブコントラクトになっている。
(3)「OreOreCoin」に定義された関数の中で、「Members」で定義された関数を呼び出している
この(3)が、個人的にはポイントだと思っています。
さらに(後から出てきますが)動作させる上では、「Members」に定義された状態変数「coin」に「OreOreCoin」のデプロイアドレスを入れるので、(3)と合わせると「Members」と「OreOreCoin」が入れ子みたいな構造で動きます。
……これを理解するのに時間がかかった……(;´Д`)
各コントラクトは以下のような内容です。
・Owned…オーナーアドレス「owner」の定義と、オーナーアドレスの変更をする。
・Members…状態変数として会員情報を定義し、会員情報と取引履歴を更新する関数を持っている。
・OreOreCoin…暗号資産(仮想通貨)OreOreCoinを定義し、送金、ブラックリスト、キャッシュバック機能を、Membersの情報を使いながら実装する。
コード自体は「はじめてのブロックチェーン・アプリケーション Ethereumによるスマートコントラクト開発入門 (DEV Engineer's Books)」をご参照ください。
コントラクトのデプロイ
いつも通り、サンプルコードをコピペして、コンパイラのバージョンをコードに合わせてコンパイルします。

平和にコンパイルできましたw
初期の頃はコンパイラのバージョンがコードに合っていなくて(選べなかったのか、選ばなかったのかは忘れましたが)、そこそこWarningが出ていましたw
「会員管理」機能付きの仮想通貨コントラクトの動作確認(その1)
会員管理用「Members」コントラクトのデプロイ
まず、「Environment」を「JavaScript VM」にしつつ、教科書通りユーザーA(ここでのアドレス:0xca35b7d915458ef540ade6068dfe2f44e8fa733c)で「Members」をデプロイします。


今回は前の記事のように「new」していないので、いきなり「Members」をデプロイして「Owned」がデプロイされるのか気になっていましたが、「owner」にユーザーAのアドレスが入っているところを見ると、どうやらサブコントラクトをデプロイすると親コントラクトもデプロイされるみたいですね。

……というかむしろ、「Owned」がデプロイされているというよりも、「Owned」に(「クラス」的に)定義された部分はソースをコンパイルした時点で「Members」内でもデプロイできる状態になるので、“「Members」内に(継承された部分として)定義された「Owned」部分”がデプロイされて、“「Members」内に(継承された部分として)定義された”「owner」に値が入ったと考えるべきなのかな。
教科書的にも「MembersコントラクトのオーナーアドレスがユーザAであることを確認」と表現しているし、よく見たら「call to Members.owner」と出ていたりするので、ここでは「Members」の「owner」(=Members.owner)ってことみたいですね。

ちなみに、あとで使うので「Members」コントラクトのデプロイアドレス(0x692a70d2e424a56d2c6c27aa97d1a86395877b3a)もコピっておきます(´・ω・`)
会員ステイタスの作成
教科書通りにサクッと会員ステイタスをpushしていきます。



ここで使う「pushStatus」は「onlyOwner」修飾子がかかっているので、「Members」のオーナーしか実行できません。
なので、「各メンバーが自分でステータスを変更」ということはできません。
一応、教科書に沿って「Members」のオーナーをユーザーB(0x14723a09acff6d2a60dcdf7aa4aff308fddc160c)にしておきます。
この「transferOwnership」も「Members」のオーナーしか実行できません。(という意図なんだと思います。たぶん)
せっかくなので、まだオーナーになっていないユーザーBのアドレスで、ユーザーBが自分をオーナーにするように「transferOwnership」を実行してみましょう。
やってみると……やはりユーザーBはオーナーではないので怒られます。


気を取り直してユーザーAで実行すると、無事に「owner」がユーザーBのアドレスになります。



会員管理機能付き仮想通貨コントラクト「OreOreCoin」のデプロイ
例のごとく教科書に沿って、ユーザーAで「OreOreCoin」をデプロイします。


「OreOreCoin」のオーナーアドレスには、ちゃんとユーザーAのアドレスが入っています。

「OreOreCoin」のデプロイアドレス(0xdc04977a2078c8ffdf086d618d1f961b6c546222)も、後で使うのでコピっておきます。
「Members」と「OreOreCoin」の紐づけ
ここがなかなか理解できなかったのですが、「Members」と「OreOreCoin」を、各々のデプロイアドレスを使って紐づけていきます。
やることは以下の2つです。
(1)ユーザーBで、「Members」のデプロイアドレスを引数にして(「OreOreCoin」内で定義された)「setMembers」を実行する。
(2)「OreOreCoin」のデプロイアドレスを引数にして(「Members」内で定義された)「setCoin」を実行する。(こちらは「Members」のオーナーアドレスという意味で、ユーザーBで実行する必要があります)
まず(1)をやってみます。

次に、(2)を実行します。

上記(1)、(2)で、以下の図のようなことをしています。
(逆に混乱しちゃったら無視してくださいw)

私が理解するにあたって、以下がポイントでした。
(A)「setMembers」は「OreOreCoin」、「setCoin」は「Members」内に定義されている。(名前が入れ子になっていてややこしい)
(B)「setMembers」の定義には「msg.sender」が入っているため、実行ユーザーを気にする必要がある。(後述しますが、「onlyOwner」修飾子がついている「setCoin」も実行ユーザーを気にする必要があります)
(C)「coin」はただのaddress型だけど、「members」はmapping型なので“配列”になっている。(「mapping」は「連想“配列”」であることを忘れていて、当初スカラー量のイメージで読んでいたせいで理解がなかなか進みませんでしたw)
「会員ごとに会員情報を持つ」ことを、
(B)→会員アドレスと会員情報(=Members)の紐づけることで、会員が会員情報を持つこと
(C)→会員アドレスをインデックスとする配列(members)によって、会員ごとに情報を持つこと
という風に実装しています。
ここまでで、ユーザーBの「Members」コントラクトが準備できました。
前編はこのへんで、後編へ続きます。
Keyword : ブロックチェーン暗号資産仮想通貨イーサリアムEthereumSolidityBrowser-Solidityblockcahin
翻訳: zk-SNARKs 入門 (その1) (原題:Introduction to zk-SNARKs (Part 1))
TwitterのDMで怪しげな(笑)アカウントからオススメされたリンク先にあったzk-SNARKsの記事(Introduction to zk-SNARKs (Part 1))、読んでみたらすごく面白かったw
というかこのブログめっちゃ良いぞ!!
……というわけで、自分の勉強がてら翻訳してみました。
皆さんの勉強のご参考になれば幸いです。
そんなに英語が得意なわけではないので、間違いなどあればメールフォームから教えていただけると助かります!
(ちなみに、怪しげなアカウントはdecentriqの公式アカウントですw)
zk-SNARKs 入門 (その1)
概要
この連載では、確率論的なプロトコルの1つで、Goldwasser、Micali、Rackoffにより1985年に初めて記述され、分散台帳技術(DLT)の盛り上がりとともに人気が出てきたゼロ知識証明(ZKPs)について見ていく。まずはこの画期的な仕事の背後にあるいつくかの理論の紹介と、その複雑な機構の種々の要素をどのように実行するのか示すことから始める。Pinocchioプロトコルに従いPythonで実行して、最終的には例題に関するエンドツーエンド[訳注1]のゼロ知識証明になる。主な目標はこのトピックのやさしい入門を提供することで、ZKPsに関する簡潔な数学をかみ砕いて、その背後にあるいくつかの直観的なことを議論する。これに沿って、この技術によって可能になる、いくつかのエキサイティングな応用についても触れる。
そもそも、ZKPとは何のことで、なぜこれを気にしないといけないの?
ZKPは、「証明者(彼女のことはPeggyと呼ぶことにしよう)がある秘密を知っている」ことを秘密の内容を明かさず、承認者(彼のことはVictorと呼ぶことにしよう)にどんな合理的な疑問も残さない証明を与える。たとえばPeggyは、具体的な素因子を明かすことなく非常に大きい合成数の素因数分解を知っていることだったり、解答自体は明かさずに与えられた数独パズルの答えを知っていることをVictorに証明したいのかもしれない。もっと一般的には、ZKPsは検証可能な計算の構成要素として使える:これは弱いクライアントからより計算力の高いワーカーに計算を押し付ける方法で、元のプログラムを実行するのに比べてかなり小さい労力の計算でワーカーが実行した計算の正しさを、クライアントが暗号的学的に証明することができるようなもの。これは、クラウドだけでなく、オンラインのプライバシー、DLTのスケーラビリティや携帯アプリ、その他諸々の応用に影響する非常に強力なパラダイムになっている。
ZKPsについて別の有望な応用は、機械学習の分野にある。この文脈でこの技術は、第三者がモデルのトレーニングや予測の過程で特定のデータが使われたことを証明できるだけでなく、すべてを開示する必要なく特定のデータを持っていることを証明するのに使える。OpenMined は、活発に動いているプライベートでセキュアな機械学習のエコシステムを作るための多重暗号プリミティブ(multiple cryptographic primitives)[訳注2]の先駆的プレジェクト。
だけど、実のところ、ZKPって何?
非常に簡単に言うと、コンピューター上で表現されるとZKPは、Peggyによって注意深く計算され、Victorが計算が正しいことの証明を検証するために実行するたくさんあるブール型のチェックと一緒にして数を並べたものでしかない。したがって、ゼロ知識証明のプロトコルはこれらの数から導かれ、検証の確認で定義される。
非対話性と簡潔性
ゼロ知識分野での研究は増えていて、Goldwasser, Micali と Rackoff による初めの論文(1,2,3,4,5)が出版されてから色んなプロトコルも提案されている。
これらのプロトコルの主な違いの一つは対話性にある。対話的なゼロ知識プロトコルでは検証者が「証明者がある秘密を知っている」ということを信じられるまで、証明者と検証者がたくさんのメッセージをたがいに交換する。各やり取りのラウンドはVictorによって出された「Peggyが正しい解答を提出しないといけない」問題で、その解答はVictorに検証され、プロトコルによって特徴づけられるブール型のチェックを通過したときにだけ受理される。Peggyがその秘密を知らずにNラウンドすべてチェックに通貨してしまう確率は、Nについて指数関数的に減少する。したがって、Victorは内容については何も知ることがないにもかかわらず、「Peggyがその秘密を知っている」ことをVictorが確信できるまで好きなだけ長く、行ったり来たりするやり取りを続けられる。
逆に、非対話型のゼロ知識プロトコルでは、証明者と検証者の間でやり取りが繰り替えされることがない。代わりにただ1つの"ラウンド"があり、これは非同期的に実行される。公開されているデータ(続くセクションや投稿で議論される予定の内容)を使い、Peggyが証明を作り、Victorが利用できる場所に公開する(たとえば分散台帳上に置く)。これにより、Victorは"ラウンド"完了するため、いつでもその証明を検証できる。対話的な場合はたくさんの証明を作るのに対しPeggyはただ1つの証明を作るとしても、無視できる確率を除き、「彼女が、自分で主張する秘密を確かに知っている」ことを検証者は依然として確信できる。結果的に、非対話型アプローチの利点の1つとして、「検証者に依らない」ことがある。Peggyの証明は、手元にあるその問題の実例(たとえば数独パズル)について普遍的で、Victorだけでなくどんな検証者でも、Peggyの「私は解答を持っている」という主張を後から検証できる。
ゼロ知識プロトコルたちの別の違いは簡潔性にあって、Peggyによって生成される証明のサイズを扱う。簡潔性は、ストレージ容量と検証時間という2つの理由で、分散台帳上に発行されたZKPについて重要な役割を担う。ストレージは非常に高価で、たとえば現時点でビットコイン、イーサリアム、NEO、EOSで各台帳に1KBを保存するときの費用はそれぞれ、$3.83、$2.86、$19.38、$3.00となっていて、ピーク時の費用はもっと高い!変動価格と高価なストレージの効果は、1KBあたり$0.001であるファクトムなどの安価で低価格の分散台帳を使うことで相殺できる。にもかかわらず、証明のサイズはできるだけ小さく保つことが依然として望ましい。加えて証明は素早く検証できることが必要で、そうでないとサードパーティにオフロードする効果が薄れる。したがって、チェーンなしのアプリケーションにとって、検証時間が一定であるだけでなく、生成された証明ができるだけ短くて、理想的には問題の内容によらないことが非常に重要となる。
自然な疑問として、「対話型の証明が好まれる場合があるのか?」ということがある。多くの非対話型プロトコルは、一般に「信頼されたセットアップ」といううるさい問題に悩まされていることがわかるが、これは各々を対話型にした代替プロトコルには存在しない。信頼されたセットアップは、証明を計算するときPeggyに利用される公開データの一部を生成するプロセスにある。このセットアップの詳細は後で議論予定だが、簡単に言うと、このセットアップは、乱数源から発生するある数(一般に「有害廃棄物」と呼ばれる)を公開する集団や、集団が集まった大きな集団による。この乱数源にアクセスする誰もが、プロトコルに従って検証者が受け入れるような偽の証明を生成できる。このような理由で、公開された数を生成する集団によって「有害廃棄物」が破壊されることが重要で、これはこのような集団が信頼される必要があることを意味する。これは実質的に、いつくかの非対話型ゼロ知識プロトコルの適用可能性を扱いにくいものにする。
しかしながら多くの場合、非対話性や簡潔性では大して得をするわけではない。非対話性は、たくさんの独立な検証者が、与えられた証明を各々個別に証明者へ問い合わせを行わずに検証したいときにのみ有用となる。簡潔性は、証明を保存するために使われる中間物が非常に高価か、非常に短い検証時間を求めているときのどちらかまたはこの両方であるときにのみ必要となる。しかしながら、分散台帳は特段の例外として一般にストレージは安価で、パブリックブロックチェーン上のブロック間時間に強いられるような厳しい制約がなければ検証時間もまた柔軟であり得る。
これは、2つの対象がHTTPSのように安全なチャネルを使ってやり取りするようなB2Bアプリケーションでは、対話型の証明でやっていけることを意味する。検証者は信頼されたセットアップを実行する責任があるとして、ユースケースに応じて企業がPeggyかVictorの皮をかぶることができる。このやり取りは自然に1対1なので、検証者は偽の証明には興味がなく、オンチェーンに証明を保存する必要もなく、Victorは検証を実行する時間をより多く割く余裕があり、このようなアプリケーションは対話型の状況ではたらく。
このちょっとした遠回りに続いて、この連載で興味のある主題である、非対話型で簡潔な証明に戻る。特に、ここではゼロ知識(zero-knowledge)で、簡潔(Succinct)かつ非対話型(Non-interactive)の計算による知識証明、またの名を「zk-SNARKs」というものに興味がある。特筆すべきアーリーアダプターの中でも匿名暗号通貨のZcashと、スマートコントラクトのプラットフォームであるEthereumで使われており、zk-SNARKsはゼロ知識プロトコルで最も広く使われている。
QAP:計算から多項式へ
zk-SNARKプロトコルをより厳密に説明する前に、いくつかの背景に言及しておかないといけない。
ゼロ知識プロトコル一般に言える複雑なことの1つとして、これらを適用可能にするために、元の問題を完全に変形してやらないといけない、ということがある。
PeggyがVictorに対して、「自分が方程式 x2-4=0 の解を知っている」ことを、この解が何かを明かすことなしに証明したい、という状況を考える。この場合解は自明で、誰でもこの解答を導けるので現実的にはこの問題にゼロ知識証明は不要だが。それもかかわらず、2次多項式に代わってこれを1万次の多項式に簡単に拡張できることを念頭に置きつつ、話を簡単にするために、この連載ではこの例を見る。
それで、この問題をどう読み替えていけば良いのだろうか?
この過程の詳細はVitalik Buterinによる素晴らしい投稿の2次算術プログラム(QAPs:Quadratic Arithmetic Programs)にあり、さらなる読みものとしてこれを強くおすすめする。ここでは、この「変形」の短いまとめを提供する。
まずはコードでこの問題を表すことから始める。すなわちPythonでは、計算を読み替える、次の簡単な関数を定義できる。
def f(x):
y=x**2-4
Peggyとしては「自分だけが知っているある秘密の値xにおいて上の関数を評価すると、yが0になる」ことが目標。明らかに、少なくとも2つの問題がある。
・xの値は知ることなく、関数を実行する最後にyの値の"ピーク"をVictorが得られる方法を見つける必要がある。
・Peggyはプログラムの実行者なので、コードの今の定式化では、VictorはPeggyが確かに実行したどんなコードも制御できない。たとえば、Peggyは条件を満たすy=0というだけのコードを走らせるズルをすることもできる。
これらの問題のどちらも、解決がとても難しいように見える。当然、この答えは上述した問題のかなり非自明な再定式化を必要とし、すなわちこれのQAPへの変換が必要となる。これは、コードの平坦化(code flattening)、rank 1の拘束系(R1CS: rank-1 constraint system)への変換、最後にQAPの定式化、という3つのステップを踏む。
コード平坦化のゴールは、任意の複雑な主張や表現を含むような元のコードを、次の2つの形からなる一続きの主張に変換することとなる。
・x=y(ここで、yは変数でもある数でも良い)
・x=y(op)z (ここで、op∈(+,-,*,/)であり、yとzは変数でも、ある数でも、部分式でも良い)
これらの主張を算術回路のゲートとして考えられる。ここで出している例のプログラムの回路は、次のように見られる。
(元記事の図も参照)
x -----┐
x ---------→ * ---(out_1)---┐
-4----------------------------→ + ---(y)---→
対応する「平坦化されたコード」は次のようなものになる。
def f(x):
out_1 = x * x
y = out_1 - 4
次のステップでは、これをR1CSに変形する。R1CSというのははベクトル(ai, bi, ci)[訳注3]のトリプレットのリストで、この解は、任意の i について
〈ai, s〉 * 〈bi, s〉 - 〈ci, s〉 = 0
を満たすようなベクトル s となる。ここで、〈・,・〉は2つのベクトルのドット積(内積)を表す。このトリプレットは、この方程式を満たすような s を探して満たす必要のあるような拘束条件を定義していると解釈できる。
例に挙げているコードの平坦化したものをR1CSに変換する、自然な方法がある。まずプログラムの主張を満たすようなベクトル(すなわち、プログラム内で使われるすべての変数)を定義する。このベクトルの各成分は1つの変数で、その解 s は各変数を割り当てたものになる。
今のプログラムの変数ベクトルは、次のようなものになる。
s = (1, x, out_1, y)T
1つ目の成分として1を含むのは、後で簡単に見るように、これによって拘束条件を満たすようにするため。
このベクトルを定義して、平坦化したコードの各行を順次処理して適切なai、bi、ciを定義することで、今の行に含まれる計算の読み替えを続ける。
たとえば、この関数の中身で最初の行を読み替えるには、以下のように設定する。
a1 = (0, 1, 0, 0)T
b1 = (0, 1, 0, 0)T
c1 = (0, 0, 1, 0)T
2行目の読み替えには以下を使う。
a2 = (-4, 0, 1, 0)T
b2 = (1, 0, 0, 0)T
c2 = (0, 0, 0, 1)T
この2つの行について、読み替えを展開してチェックしてみる。2行目で-4という定数を表すために、aiの定義のところでsの第1成分で1をどう使うかも見る。
1行目:
〈a1, s〉 * 〈b1, s〉 - 〈c1, s〉
= Σni=1 a1 si * Σni=1 b1 si - Σni=1 c1 si
= x * x - out_1
=0
2行目:
〈a2, s〉 * 〈b2, s〉 - 〈c2, s〉
= Σni=1 a2 si * Σni=1 b2 si - Σni=1 c2 si
= out_1 - 4 - y
=0
上記によって、このPythonプログラムがコンピュータのコードから高速条件の集合へうまく変換された!コードのロジックは制限されたベクトル(ai, bi, ci)のトリプレットに"移送"された。このプログラムの実行は、R1CS方程式
〈ai, s〉 * 〈bi, s〉 - 〈ci, s〉 = 0 ( i は任意)
を満たすようなsの成分を見つけることと等価になっている。
QAPへの変形を完了するのに、ベクトルから多項式へ転換する必要がある。 i ∈ [1, N] として、多項式 Ai(x)、Bi(x)、Ci(x)を定義することから始める。ここで、Nは制限ベクトルの成分の数(今の場合は4)となっている。Ai(n) = an,i (Bi(n)、Ci(n)も同様)と要請し、これらの点に基づいたLagrange補完をすることでこれらの多項式を構成する。
今の例では次のように要請する(Bi、Ciも同様)。
A1(1) = 0
A1(2) = -4
A2(1) = 1
A2(2) = 0
Lagrange補完をすると、次の多項式に到達する。
A1(x) = - 4x + 4
A2(x) = - x + 2
A3(x) = x - 1
A4(x) = 0
B1(x) = x - 1
B2(x) = - x + 2
B3(x) = B4(x) = 0
C1(x) = C2(x) = 0
C3(x) = - x + 2
C4(x) = x - 1
これらの定義によって、今や1つの方程式として上記をR1CSで表現できる。
A(x) * B(x) - C(x) = H(x) * Z(x)
ここで、
A = (A1(x), A2(x), A3(x), A4(x))
B = (B1(x), B2(x), B3(x), B4(x))
C = (C1(x), C2(x), C3(x), C4(x))
A(x) = 〈A, s〉
B(x) = 〈B, s〉
C(x) = 〈C, s〉
Z(x) = (x - 1) (x - 2)
また、H(x)はすべてのxについてA(x) * B(x) - C(x) = H(x) * Z(x)を満たすようなものであると要求する。
まだここ?よろしい!ここで、次のようなことが疑問じゃないだろうか。
・なんでこんなことしたの?
・Z(x)ってなんやねん
・H(x)は何者で、誰が思いつくの?
これらの質問に答えるため、まず次のようなことを見る。定義により
A(1) = a1
A(2) = a2
として、B(x)とC(x)も同様とする。A(x)、B(x)、C(x)の定義も用いると、これは元のR1CS系が以下と等価であることを意味する。
A(x) * B(x) - C(x) = 0 (x∈{1, 2})
これを満たす唯一の方法は、A(x) * B(x) - C(x)が (x - 1) (x - 2) で割り切れるとき、すなわち以下のような H(x) が存在するときとなる。
A(x) * B(x) - C(x) = H(x) (x - 1) (x - 2)
これはH(x)とZ(x)が何かを明らかにしてくれる。しかし、誰がH(x)を計算するのだろうか?H(x)を(A(x) * B(x) - C(x))/Z(x) として計算することにより、背後にあるR1CSを満たすsの成分を知っていることを示すので、H(x)を計算するのは証明者だろう。したがって大雑把に、QAPを(A, B, C, Z)という4-タプル[訳注4]、sをこのQAPの"解"と考えることができる。
最も大事な質問にまだ答えていない。なぜこんなことをする必要があるのだろうか?
Pythonのプログラムとして今の問題を表現していたことを思い出すと、次のような1組の大きな問題に突き当たる。
・Peggyが正しいプログラムを動かしていることを検証する方法が無い
・他のどのんな情報も明かさずに、プログラム実行の最後におけるyの値をどうやってVictorに観測させるかが明確でない
R1CSとして表現された計算だと、Victor妥当なsの割り当てを見るとすると、Peggyが対応するR1CSのプログラムを実行したことを確信できる!これは主な問題の1つをすでに解決している。
QAPを得るためにR1CSをさらに変形する理由は、多項式で説明する方がR1CSで説明するよりも有益だから。次のセクションではこの新しく提案された「問題の再定式化」を、zk-SNARKsを構成する中心となる1つの技術を説明するのに使うが、これは多項式の構造を利用する。
隠れた点における多項式の評価
多項式を処理するうまいやり方の1つに、知らない点で多項式を評価するものがある。これは多項式の目隠し評価(?blind evaluation of polynomials)としても知られる。まってwつまり……どういうことだってばよ?!そう、お分かりの通りこれは不可能に違いない。与えられた多項式
P(x) = a0 + a1 x + a2 x2 + ... + an xn
について、この多項式を評価したいとすれば、xを知らなければいけない。実際に今はこういう場合だけど、いつくかの追加情報を使えるとすれば、評価するときのその点xを知ることなく、多項式を評価できる!
次に、次のような性質を持つある関数 f(x) を使うことを考える。
1.1方向性:与えられた x について簡単に y = f(x) が計算できるが、与えられた y について y = f(x) となる x を見つけることは難しい
2.線形性: f(αx + βy) = αf(x) + βf(y)
3.x≠y ⇒ f(x)≠f(y)
このような関数がどのように目隠し評価する助けになるのか見てみよう。簡単に可視化するために、Peggyがこの問題においてその点で多項式を評価したとVictorが検証できるような方法で、VictorがPeggyに、どちらもが知っているPの目隠し評価を問い合わせるとする。さらに、fは存在して、PeggyもVictorも知っている知っているとする。
まずVictorは、その多項式を評価したいある点 x0 を選ぶ。そしてこの点 x0 を f に食わせて新たな点(zとする)を出して、この z をPeggyに送る。fの1つ目の性質により、Peggyが z から x0 を得られないことに注意する。さらに、f の3つ目の性質から、f(x'0) = z となるような x'0(≠x0)を見つけることもできない。これら2つの事実から、ひとたびPeggyがVictorから z を受け取ると、Peggyが元の x0 を逆算する手段がないことを意味する。
P(x) = a1 x である場合を考える。与えられた z = f(x0) について、Peggyは簡単に P(z) = a1 z を計算できる。 f の線形性により、以下に注意する。
P(z) = P(f(x0)) = a1 f(x0) = f(a1x0) = f (P(x0))
これはまさしく欲しいもので、P(z) の計算により、x0については何も知らず、Peggyが実質的に f (P(x0)) を計算したことになっている!f、P、x0は知っているのでVictorは、ここでPeggyによって計算された P(z) を見て自分のところで f (P(x0)) と比べる。 もしこれら2つの結果が一致すれば、x'0(≠x0)での評価は別の結果になることを考慮すれば、VictorはP が x0 で評価されたことを確信できる。
上記のアプローチを任意の多項式に一般化するために必要な変更は1つで、Victorがより多くの情報をPeggyに送ればよい。特に、d を評価したい多項式の字数として、Victorは以下の情報をPeggyに送れば良い。
f(1), f(x0), f(x02), ..., f(x0d)
この情報を使い、今やPeggyは、x0 について何も知ることなく
f (P(x0))
= f(a0 + a1 x0 + ... + an x0d)
= f(a0) + f(a1 x0) + ... + f(an x0d)
= a0 f(1) + a1 f(x0) + ... + an f(x0d)
を計算でき、さらにVictorは、f、P、x0 を知っているので、この結果が正しいことをチェックできる。
結論
この連載の1つ目の投稿では、簡潔性と対話性というような、ゼロ知識プロトコルのレベルの高い性質のいくつかを議論した。これらに基づいて、zk-SNARKsというこの連頼の主題を導入し、Pythonで書いた簡単なプログラムについてzk-SNARKを構成しようとしたときに生じつ問題のいくつかを紹介した。これはR1CSとQAPの導入に動機づけられていて、コンピュータのコードを、zk-SNARKの構成に親しませてくれて、より形式的で数学的に柔軟な方法でコンピュータのコードを理解させてくれるような、QAPに変形する例を挙げた。最後に、この連載の続編で中心となる予定の、多項式の目隠し評価という強力な道具を道具箱に加えた。
次回は、zk-SNARKという十徳ナイフ(Swiss army knife)[訳注4]を、隠れた点で多項式の評価に使った"魔法の"関数 f を構成するのに必要な道具に拡張し、Pythonでこの技術の実装を提供する。ではまた!
(原文)
・zk-SNARKs 入門 (その1)(decentriq)
(参考)
・増える開発者、増える破壊:Zcashの暗号セレモニーが進行中(COINPOST)
・イーサリアムに導入されたプライバシー保護技術「zk-SNARK」とは(ZOOM)
[訳注1] エンドツーエンド…以下を参考。
・エンドツーエンド原理(Wikipedia)
[訳注2] 暗号プリミティブ…以下を参考。
・公開鍵暗号方式の構成(シニアエンジニアの庵)
[訳注3] この訳では、ベクトルを太字で表現し、上付き添え字の「T」は転置を表す。(矢印表記とか縦ベクトルをブログで書くのがめんどくさかったのでw)
[訳注4] タプル…以下を参考。
・タプル(Wikipedia)
[訳注5] スイス・アーミーナイフ…以下を参考。
・アーミーナイフ(Wikipedia)
ブロックチェーン関連の記事紹介まとめ(2019年2月:#32-59)
ブロックチェーンや暗号資産(仮想通貨)関連の記事や論文などのデイリー紹介ツイート、2か月目のまとめです!
ご興味ある記事があれば、ぜひ元記事も読んでみてください!
<< 2019年1月:#1-31
2019年3月:#60-90 >>
記事紹介まとめ(2019年2月:#32-59)
#ブロックチェーン の期待度は幻滅するにしても、技術的にはこれからですね(´・ω・`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月1日
まずはスケーリングの問題が解決されないとかなぁ。やっぱり #イーサリアム の #ワールドコンピュータ とか #Ripple の #価値のインターネット という世界観が浸透すると熱い!#blockchain #Ethereum #リップル
マイニングできた人の方が有利かと思っていましたが、評価値を減らすんですね(´・ω・`)疑問が解消しましたw#PoS だと結局富が集中しちゃうのが個人的には結構不満ですねー。#ブロックチェーン #blockchain #イーサリアム #Ethereum #仮想通貨 #暗号資産 #暗号通貨
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月2日
#トークンエコノミー って #行動心理学 の言葉だったんですね(´・ω・`)#ブロックチェーン がトークンエコノミーの最適な手段と言っていますが、価値(#暗号資産 の価格)の変動具合はまだ問題なのかなぁ。他方、変動具合による価値上昇の可能性は #インセンティブ 。#blockchain #仮想通貨 #暗号通貨
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月3日
基本的には報酬により特定の行動を促すのが #トークンエコノミー の考え方なんですよね。いかにその #トークン を保有するインセンティブを与えられるか。。トークン自体の価値にとって、利用用途の拡大ってかなり重要ですね(´・ω・`)#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月4日
(アルゴリズムをちゃんと見に行ってないせいもあるけど)いまいち衝突耐性がどうやって保たれているのかがわからない……(;´Д`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月5日
衝突確率が数理的に示せるのかしら……?(完全に素人の質問w)#ブロックチェーン #blockchain
#Ethash アルゴリズムの簡単な説明が意外となかったので、この記事結構役立ちました。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月6日
ちなみにメモリ帯域幅は「単位時間あたりどれだけのデータをメモリから読み出せるかという値」です。#ブロックチェーン #blockchain #イーサリアム #Ethereumhttps://t.co/7rEsfbrUtE
クラスとインスタンスは #オブジェクト指向 の言葉で、クラスは鋳型、インスタンスは鋳型から作った実体です。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月7日
リンク先の「#Java は、クラスを定義してインスタンスを生成し、そのインスタンスを動作させる #プログラミング言語」という言い方が解り易かったです。https://t.co/gfruaab0vB
#ERC20 のところを読むつもりが、 #イーサリアム の基本機能が「トランザクションを記録できるブロックチェーンと、スマートコントラクトを作成できる仮想マシン」という言い回しが良かったwでもEVMのところ、たぶんまだイメージしきれてないな……(;´Д`)#ブロックチェーン #blockchain #Ethereum
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月8日
この記事だけだとイマイチわからん……今のところ、問題がそんな素晴らしく解決されてるような理解に到達できず(;´Д`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月9日
まだちゃんと読めてないですが、ホワイトペーパーも貼っときます。#ブロックチェーン #blockchainhttps://t.co/yhqWvqG5cY
この #PoB って、結局いっぱいお金持ってる人がたくさん利益を得られる仕組みになってるのでは?
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月10日
合意のアルゴリズムはもう少し詳しく調べないとなぁ(´・ω・`)#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
貢献度と言うなら確かに残高が入るのは納得だけど、残高だと結局元々富める人が有利に思える……残高が考慮されないなら保有するモチベーションは下がるか。。完全にランダムに配布だとマイニングのインセンティブにならないしなぁ。#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月11日
今のところやったことはないけど、 #セルフGOX を一度はやってしまいそうで怖い(;´Д`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月12日
これも大衆に広まるためにはそこそこのハードルじゃないかな(´・ω・`)#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
#リップル の送金方法に関しては、これの前の記事にも書いています。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月13日
現在の承認者は殆どリップル社が持っていて中央集権的というのをどこかで見かけましたが、銀行のノードが承認者になる想定なんですね(´・ω・`)#ブロックチェーン #blockchain #Ripplehttps://t.co/6J06Zz9MT3
ここでは #ブロックチェーン 技術に限定していますが、ブロックチェーン2.0ではなくビットコイン2.0と言うときは、ブロックチェーンに限らず #ビットコイン 関連技術の応用な気がします。ちょっと調べた感じだとまだ意味が揺れてるかも。金融庁の研究会資料に何か載ってる……?#bitcoin #blockchain
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月13日
マーケティング領域への #ブロックチェーン 応用を考えるの楽しそうw
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月15日
マーケティングだとプライバシーの問題にぶち当たりそうだなぁ。少なくとも現状では、トランザクションが誰でも見れるとマーケティングに応用って観点からするとマズそうな印象。#blockchain #仮想通貨 #暗号資産 #暗号通貨
この記事自体は2016/12/9と古めですが、ここに書いてあるCoinprism、Colu、CoinSpark、ChromaWalletというスタートアップが今どうなってるか気になる……(´・ω・`)#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨 #ビットコイン #bitcoin
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月16日
将来性のくだりはあまり論理的じゃないように思えるなぁ。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月17日
名前解決自体はどうやってやるんだろう?(´・ω・`)もう少し仕組みも知りたいところ……#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
共有できる情報が限られてる中だと、「誰でもトランザクションを見れる」というプライバシーの問題は解決しないといけないんだろうなぁ。これで言うと、記事にあるINSCHAINの「AIが算出した結果のみを #ブロックチェーン に保存」が1つの解決策になるのかな(´・ω・`)#blockchain #InsurTech
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月18日
#NEO ってかなり色々活動してるんですね。ファンドまであるのか(´・ω・`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月19日
これはICOで集めたお金なのかな?
技術的には既存の言語使えるのが良いなぁ。Slidity勉強するのも楽しいけどもw#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
投票が2段階あって間にランダム要素が入ってるぶん、たしかに #PoW や #PoS にくらべて #dBFT はトークン保有量の効き方が小さくて民主的ですね。トークン保有量に応じて、不正できる可能性はどうなるんだろう?#ブロックチェーン #blockchain
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月20日
ワイに刺さるブログを見つけてしまったぜ……900%のくだりはマジLOVE1000%って言って欲しかった……w
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月21日
たしかに分かりづらいんだよなぁw界隈で言うと、ウォレットちゃうけどコインチェックのUIはすごく使いやすい。#ブロックチェーン #blockchain #仮想通貨 #暗号資産 #暗号通貨
Mastering Ethereumってあるんですね(´・ω・`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月22日
こういう教材系の紹介も、個人的にかなり重宝します!
この記事でも触れられているように、技術的なところに踏み込もうとすると知識が前提とされてることって結構あるんだよなぁ。。#ブロックチェーン #blockchain #Ethereum #イーサリアム
中央機関による発行が希少性に対してマイナスに働くというのは、確かにここで言ってる性質ありますね(´・ω・`)
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月23日
変更できないのって、確かにデメリットにもなるな……これを思うとプロダクトのリリース大変……#ブロックチェーン #blockchain #Ethereum #イーサリアム
この記事の #ブロックチェーン に関する考察が面白い。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月24日
信頼を可能にするための道徳、評判、機関、セキュリティシステム、のくだりが面白かった。
全財産を失う理由で①技術的欠陥と②人的欠陥を比べて、起こる確率が論理的に①<②なら、ブロックチェーンは生きられるのかなと。#blockchain
今までフワッとしか理解できてませんてわしたが、要するに口座振込での支払いがスマートにできる感じですね。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月25日
手数料が安く、しかも素早くできるみたいで何気に使えそう(´・ω・`)
あとは対応する金融機関を増やしておくれ……#リップル #Ripple #SBI #暗号資産 #仮想通貨 #暗号通貨
すでに結構色々参加してるんですね。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月26日
マルチアセット機能は、考えられるサービスの幅が広がりそうで良いな(´・ω・`)#NEM のプロトコルを利用とあるけど、#XEM も使うんだろうか?使うならXEMが結構有望に思える。#ブロックチェーン #blockchain #暗号資産 #仮想通貨 #暗号通貨
全体的にいまいち理解し切れない。。
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月27日
話の流れはわかるけど、動きのとこが。
素朴な疑問で、「coinbaseの形式は任意なので、何が含まれていても他のマイナーは有効と判断」って #ビットコイン の脆弱性にならないの?(´・ω・`)#ブロックチェーン #blockchain
フォークに関する理解はこのレベルの言葉だと理解できるんですが、実装レベルでも理解したいなー。まぁ、そのためには自分で作らないといけないかなwさし当りオモチャのレベルで良いので、簡単なDApps作れるようにならねば……#ブロックチェーン #blockchain
— ぺろりん@ぶろっくちぇーん (@peroincahin) 2019年2月28日