Zokratesのゼロ知識証明(非対話型)を使ったスマートコントラクト

環境

この投稿の例は、以下の環境で実行しています。

Truffle v5.0.40 (core: 5.0.40)
Solidity v0.5.8 (solc-js)
Node v10.16.2
Web3.js v1.2.1
docker  19.03.4

ゼロ知識証明

取引の履歴を改ざんできない形で、誰からも見えるようにすることで信頼性を保っているブロックチェーンですが、ビジネスシーンではプライバシーを保ちたい場合ばあります。取引の結果、情報自体を開示せずに、情報についての知識所有していることを証明したい、といったニーズがあります。ゼロ知識証明はこうした場合に使われる暗号技術です。

ゼロ知識証明はちゃんとした定義では、「ある人が他の人に、自分の持っている(通常、数学的な)命題が真であることを伝えるのに、真であること以外の何の知識も伝えることなく証明できるようなやりとりの手法
(Wikipediaから引用 :)」となっているようです。

上記の引用の「ある人」が証明者、「他の人」を承認者と呼んでいます。この用語は英語の直訳なのでしょうが,英語だとapproverかapprovedなどの表現になり、行為の主体か客体かがわかりやすいのですが、日本語にしちゃうとこの語感が消えてしまうので分かりにくいですね。

トピック的に抽象的な書き出しになってしまったので、以下では具体的な例で考えてみます。ここでは、下記のビジネスモデルを例に説明したいと思います。

  1. シェアオフィスサービス会社が、オフィスの使用権をNFT(Non-Fungible Token)としてマーケットプレースに出品。
  2. 利用者はマーケットプレースでその使用権と紐づくNFTを購入。
  3. 利用者は、オフィス利用の際に、そのオフィスの使用権を購入したことを証明する。
  4. シェアオフィス業者はその証明を見て承認することで、WiFiやドリンクなどのサービスを提供する

上記のビジネスモデルをゼロ知識証明の問題として定式化すると、
承認者:シェアオフィスサービス会社
証明者:利用者
としなります。

シェアオフィス業者(承認者)がブロックチェーン上で行うことは、

  • オフィスの専有使用権に相当するNFTの発行と出品
  • オフィス利用者(証明者)が提出する証明の承認

利用者(証明者)の行うことは

  • オフィスの専有使用権に相当するNFTの購入。
  • 専有使用権の証明

NFTの発行から購入までのプロセスは、OpenSeaのようなTokeベースのマーケットプレースでの交換を念頭に置いていますが、ここでは単純化してマーケットプレースのステップは省きました。現実はいろいろなプロセスを経て、専有使用権が渡されることになるかと思います。

ここではTruffleでこのモデルを作って、テストしたいと思います。Truffleではデフォルトで10個のアカウントが作成されますが、ここでは、

  • Account0 : シェアオフィス業者
  • Account1 : 利用者

としておきます。この例のために作成するSmart Contractは主に2つです。

  • verifier.sol (Zokratesにより生成)
  • ERC721Impl.sol

この投稿ではまず、Zokratesにより、証明用のverify.solを生成します。

Zokratesによるゼロ知識証明用のスマートコントラクト生成

ゼロ知識証明のツールボックスとして提供されているZokratesを使います。Zokratesでは証明生成用のDomain Specificな言語が定義されていて、この言語で証明ロジックを作成します。

ここでは、sha256のハッシュ値を提示することで、NFTを所持していることを証明します。

import "hashes/sha256/512bitPacked.code" as sha256packed

def main(private field[4] secret, field[2] v) -> (field):
  v == sha256packed(secret)
  return 1

dockerが

docker run -v (マウント先のルートフォルダ):/home/zokrates/code -it zokrates/zokrates /bin/bash

compile

~/zokrates compile -i sha256.code

perform the setup phase

~/zokrates setup

export a solidity verifier

~/zokrates export-verifier

以上の作業により、zokratesの作業ディレクトリに[verify.sol](https://github.com/HajimeK/BlockchainDevND/blob/master/lessons/Zokrates/zokrates/code/square/verifier.sol "verify.sol")というファイルが作成されます。このファイルを使用して、Smart Contractから証明を行います。

Compute witness

 ~/zokrates compute-witness -a 0 0 0 5 263561599766550617289250058199814760685 65303172752238645975888084098459749904

Generate proof

 ~/zokrates generate-proof

この作業により、proof.jsonというファイルが作成されるので、こちらをTruffleのテストスクリプトで使用します。

実際に[verify.sol](https://github.com/HajimeK/BlockchainDevND/blob/master/lessons/Zokrates/zokrates/code/square/verifier.sol "verify.sol")を利用するSmart Contractを実装し、Truffle上でテストするためのファイルを[GitHub](https://github.com/HajimeK/zokratessample "GitHub")にアップロードしました。

適当なフォルダ配下でgit cloneしていただき、

$ git clone https://github.com/HajimeK/zokratessample
$ cd zokratessample
$ npm install
$ cd eth_contract

と順に実行した後、Truffleを以下の通り立ち上げ、migrateした後、テストを実行して下さい。

  • Truffleのコンソールを起動

    $truffle develop
    Truffle Develop started at http://127.0.0.1:8545/
  • コントラクトのコンパイルも兼ね、migrateを実行(いくつか警告が出ます)

    truffle(develop)> migrate --reset
    Compiling your contracts...
    ===========================
    > Compiling ./contracts/ERC721Mintable.sol
    > Compiling ./contracts/Migrations.sol
    > Compiling ./contracts/Oraclize.sol
    > Compiling ./contracts/SolnSquareVerifier.sol
    > Compiling ./../node_modules/openzeppelin-solidity/contracts/drafts/Counters.sol
    > Compiling ./../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol
    > Compiling ./../node_modules/openzeppelin-solidity/contracts/token/ERC721/IERC721Receiver.sol
    > Compiling ./../node_modules/openzeppelin-solidity/contracts/utils/Address.sol
    > Compiling ./../zokrates/code/square/verifier.sol
  • テストを実行

    truffle(develop)> test
    Using network 'develop'.
    Compiling your contracts...
    ===========================
    > Everything is up to date, there is nothing to compile.
    
    Contract: TestERC721Mintable
    match erc721 spec
      ✓ should return total supply
      ✓ should get token balance
      ✓ should return token uri
      ✓ should transfer token from one owner to another (89ms)
    have ownership properties
      ✓ should fail when minting when address is not contract owner
      ✓ should return contract owner
    
    Contract: TestSolnSquareVerifier
    match erc721 spec
      ✓ Test if a new solution can be added for contract - SolnSquareVerifier
    Result {
    '0': '0x0000000000000000000000000000000000000000',
    '1': '0x1598CF27b2D63e17Fa30cE9cdAc39835A600f3aa',
    '2': ,
    __length__: 3,
    from: '0x0000000000000000000000000000000000000000',
    to: '0x1598CF27b2D63e17Fa30cE9cdAc39835A600f3aa',
    tokenId:  }
    ReferenceError: address is not defined
    at contract.mintToken.then (/home/hajime/git/BlockchainDevND/lessons/Zokrates/eth-contracts/test/TestSolnSquareVerifier.js:57:57)
    at process._tickCallback (internal/process/next_tick.js:68:7)
      ✓ Test if an ERC721 token can be minted for contract - SolnSquareVerifier (1363ms)
    
    Contract: Verifier 
    Test for verifyTx
      ✓ Test verification with correct proof (593ms)
      ✓ Test verification with incorrect proof (583ms)
    
    10 passing (6s)

参考ページ

kauri.io

コメント

タイトルとURLをコピーしました