5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

QuorumのPrivacy Manager(Tessera)環境構築メモ

5
Last updated at Posted at 2020-04-08

記事の内容

エンタープライズイーサリアムと呼ばれているQuorumに関する記事です。
Quorumの特徴的な機能の1つにPrivacy Manager(Tessera)という機能があります。
これはプライベートトランザクションに対するアクセス制御や暗号化データを他ノードへ送信する機能を有しています。
ただし、この機能はQuorumの標準機能ではなく、Quorumに追加してインストールする必要があります。
公式ドキュメントが若干分かり辛いのと、情報が少し古かったので、やってみたことをメモします。

参考

公式ドキュメント
こちらのPrivacy Managerのインストール部分を実施します

事前準備

JDKのインストール

この記事ではTesseraのバージョンは現時点の最新版である0.10.4を使用しますが、0.10.3以降のバージョンはJavaのバージョンが11以降である必要があります。
0.10.2以前はJava 8になります。
その為、この手順ではJDK 11をインストールしておく必要があります。

VMのメモリ

私はvagrantでCentOS7.4を動かしていましたが、デフォルトのメモリサイズ(1024MB)だと暗号化、復号処理でめちゃくちゃ時間がかかります。
4096MBだとサクサク進めることが出来ました。

Tesseraの環境構築手順

1.Quorumのインストールとtessera.jarのダウンロード

まずはQuorumのインストールをします。

$ git clone https://github.com/jpmorganchase/quorum.git
$ cd quorum
$ make all
$ export PATH=$(pwd)/build/bin:$PATH

次にtessera.jarをダウンロードします。
ダウンロード先はこちらになります。
tessera.jar

とりあえず、現時点の最新版jarをダウンロードします。

$ wget https://oss.sonatype.org/service/local/repositories/releases/content/com/jpmorgan/quorum/tessera-app/0.10.4/tessera-app-0.10.4-app.jar
$ mv tessera-app-0.10.4-app.jar tessera.jar

2.Keyの作成

tessera.jarの準備が出来たので、Keyを作成します。
※メモリサイズが小さいとめちゃくちゃ時間がかかります。私はメモリサイズ 1024MBで30分ほど時間がかかりました。

$ mkdir new-node-1t
$ cd new-node-1t
$ java -jar ../tessera.jar -keygen -filename new-node-1
Enter a password if you want to lock the private key or leave blank

Please re-enter the password (or lack of) to confirm

2020-04-08 02:20:52.712 [main] INFO  com.quorum.tessera.nacl.jnacl.Jnacl - Generating new keypair...
2020-04-08 02:20:52.846 [main] INFO  com.quorum.tessera.nacl.jnacl.Jnacl - Generated public key PublicKey[+fb03AOJiZNiJkHwP24J+Wn1XslaTqZRRewo+FBNsl0=] and private key REDACTED
2020-04-08 02:20:52.868 [main] INFO  c.q.t.config.keys.KeyEncryptorImpl - Encrypting a private key
2020-04-08 02:49:29.354 [main] INFO  c.q.t.config.keys.KeyEncryptorImpl - Private key encrypted
2020-04-08 02:49:29.534 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Newly generated private key has been encrypted
2020-04-08 02:49:32.675 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Saved public key to /home/quorum/new-node-1t/new-node-1.pub
2020-04-08 02:49:32.676 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Saved private key to /home/quorum/new-node-1t/new-node-1.key

処理が完了するとディレクトリに以下の2ファイルが作成されています。

$ ls
new-node-1.key  new-node-1.pub
$ cat new-node-1.pub
+fb03AOJiZNiJkHwP24J+Wn1XslaTqZRRewo+FBNsl0=
$ cat new-node-1.key
{
   "type" : "argon2sbox",
   "data" : {
      "snonce" : "Jv0b8BKkTUCT8G1uSuTUzOAvF3ZaO8E9",
      "asalt" : "JzNHviN1FttUBBSKNfv6Lw==",
      "sbox" : "nTMY1iBYF+0OXeB+qlSpmmuYC4extxsu3YL6pLDaqAE798fLhcAB+YEuTwxVRlXu",
      "aopts" : {
         "variant" : "i",
         "iterations" : 10,
         "memory" : 1048576,
         "parallelism" : 4
      }
   }
}

3.コンフィグファイルを作成する

「yourpath」の部分を作業中のディレクトリに変更します

$ vi config.json
{
   "useWhiteList": false,
   "jdbc": {
       "username": "sa",
       "password": "",
       "url": "jdbc:h2:/yourpath/new-node-1t/db1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0",
       "autoCreateTables": true
   },
   "serverConfigs":[
       {
           "app":"ThirdParty",
           "enabled": true,
           "serverAddress": "http://localhost:9081",
           "communicationType" : "REST"
       },
       {
           "app":"Q2T",
           "enabled": true,
            "serverAddress":"unix:/yourpath/new-node-1t/tm.ipc",
           "communicationType" : "REST"
       },
       {
           "app":"P2P",
           "enabled": true,
           "serverAddress":"http://localhost:9001",
           "sslConfig": {
               "tls": "OFF"
           },
           "communicationType" : "REST"
       }
   ],
   "peer": [
       {
           "url": "http://localhost:9001"
       },
       {
           "url": "http://localhost:9003"
       }
   ],
   "keys": {
       "passwords": [],
       "keyData": [
           {
               "privateKeyPath": "/yourpath/new-node-1t/new-node-1.key",
               "publicKeyPath": "/yourpath/new-node-1t/new-node-1.pub"
           }
       ]
   },
   "alwaysSendTo": []
}

4.他のノードを作成する

他のノードを作成する場合は上記の2.、3.の手順を繰り返します。

$ mkdir new-node-2t
$ cd new-node-2t
$ java -jar ../tessera.jar -keygen -filename new-node-2
Enter a password if you want to lock the private key or leave blank

Please re-enter the password (or lack of) to confirm

2020-04-08 04:09:51.205 [main] INFO  c.q.t.config.keys.KeyEncryptorImpl - Private key encrypted
2020-04-08 04:09:51.432 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Newly generated private key has been encrypted
2020-04-08 04:09:54.881 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Saved public key to /home/quorum/new-node-2t/new-node-2.pub
2020-04-08 04:09:54.882 [main] INFO  c.q.t.k.generation.FileKeyGenerator - Saved private key to /home/quorum/new-node-2t/new-node-2.key

コンフィグファイルを作成する
ドキュメントだとnode1のconfig.jsonをコピーするようになっていますが、新規ファイルを作って、以下の内容を張り付けた方が良いかなと思います。
と言うのも、よく見るとyourpathの部分以外にもポート番号など変わっているところがあるので、単純にpathの修正をするだけの方が間違えにくいかなと思います。

config.json
$ vi config.json
{
   "useWhiteList": false,
   "jdbc": {
       "username": "sa",
       "password": "",
       "url": "jdbc:h2:yourpath/new-node-2t/db1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=0",
       "autoCreateTables": true
   },
   "serverConfigs":[
       {
           "app":"ThirdParty",
           "enabled": true,
           "serverAddress": "http://localhost:9083",
           "communicationType" : "REST"
       },
       {
           "app":"Q2T",
           "enabled": true,
            "serverAddress":"unix:/yourpath/new-node-2t/tm.ipc",
           "communicationType" : "REST"
       },
       {
           "app":"P2P",
           "enabled": true,
           "serverAddress":"http://localhost:9003",
           "sslConfig": {
               "tls": "OFF"
           },
           "communicationType" : "REST"
       }
   ],
   "peer": [
       {
           "url": "http://localhost:9001"
       },
       {
           "url": "http://localhost:9003"
       }
   ],
   "keys": {
       "passwords": [],
       "keyData": [
           {
               "privateKeyPath": "/yourpath/new-node-2t/new-node-2.key",
               "publicKeyPath": "/yourpath/new-node-2t/new-node-2.pub"
           }
       ]
   },
   "alwaysSendTo": []
}

5.Tesseraノードの起動

ドキュメントに従いノードを2つ作ったのでそれぞれバックグラウンドで起動してみます。

$ java -jar ../tessera.jar --configfile config.json >> tessera.log 2>&1 &
[1] 15973
$ Enter
[1]+  Stopped                 java -jar ../tessera.jar --configfile config.json >> tessera.log 2>&1

プロセスが止まってしまいました。ログを確認してみます。

Password for key[0] missing or invalid.
Attempt 1 of 2. Enter a password for the key

パスワードの入力を求められてました。
パスワードのファイルに書いておくのはどうかと思いますが、config.jsonに入力してみます。

config.json
   "keys": {
       "passwords": ["password"],
       "keyData": [
           {
               "privateKeyPath": "/home/quorum/new-node-2t/new-node-2.key",
               "publicKeyPath": "/home/quorum/new-node-2t/new-node-2.pub"
           }
       ]
   },

"passwords"にKey作成時に設定したパスワードを入力し、再度ノードを起動してみます。

2020-04-08 06:35:58.992 [main] INFO  c.q.t.config.keys.KeyEncryptorImpl - Decrypting private key
2020-04-08 07:04:53.553 [main] INFO  c.q.t.config.keys.KeyEncryptorImpl - Decrypted private key
2020-04-08 07:04:57.438 [main] WARN  c.q.t.c.c.NoUnmatchedElementsValidator - Ignoring unknown/unmatched json element: enabled
2020-04-08 07:04:57.466 [main] WARN  c.q.t.c.c.NoUnmatchedElementsValidator - Ignoring unknown/unmatched json element: enabled
2020-04-08 07:04:57.472 [main] WARN  c.q.t.c.c.NoUnmatchedElementsValidator - Ignoring unknown/unmatched json element: enabled
Config validation issue: keys.passwords For security reasons, passwords should not be provided directly in the config.  Provide them in a separate file with "passwordFile" or at the CLI prompt during node startup.

エラーが出ました。パスワードは別ファイルに分けるかCLIから入力しろと怒られています。当たり前ですね。
tessera.jarの--helpを見てみましたが"passwordFile"に関するオプションが出てこなかったのでCLIから入力することにします。

$ java -jar ../tessera.jar --help
Usage:

Tessera private transaction manager for Quorum

tessera [OPTIONS] [COMMAND]

Description:

Start a Tessera node.  Other commands exist to manage Tessera encryption keys

Options:
      -configfile, --configfile <config>
                             Path to node configuration file
  -o, --override KEY=VALUE
      -pidfile, --pidfile <pidFilePath>
                             the path to write the PID to
Commands:
  help                        Displays help information about the specified
                                command
  admin                       Admin operations for a Tessera node
  keygen, -keygen             Generate Tessera encryption keys
  keyupdate, -updatepassword  Update the password for a key

一旦、「new-node-1t」、「new-node-2t」配下のconfig.jsonからpasswordを削除し、元の状態に戻します。

バックグラウンド実行だとパスワードの入力が出来ないので、起動方法を変えます。
コンソールを2つ起動し、「new-node-1t」、「new-node-2t」それぞれで実行します。

$ java -jar ../tessera.jar --configfile config.json

2つとも起動が完了するとノード1、ノード2で互いに通信が始まります。

正常に起動が完了していると作業中のディレクトリ配下にいくつかファイルが作成されています。

$ ls
config.json  db1.mv.db  db1.trace.db  new-node-1.key  new-node-1.pub  tessera.log  tm.ipc

この「tm.ipc」を使ってgethの起動を行います。
また、「new-node-1.pub」は次の工程で使いますので、中身を確認しておきます。

$ cat new-node-1.pub
+fb03AOJiZNiJkHwP24J+Wn1XslaTqZRRewo+FBNsl0=

6.Quorumノードの起動

公式ドキュメントだとここからの手順がかなり分かり辛いです。

cd ..
$vi startnode1.sh
... paste below
# !/bin/bash
PRIVATE_CONFIG=/yourpath/new-node-1t/tm.ipc nohup geth --datadir new-node-1 --nodiscover --verbosity 5 --networkid 31337 --raft --raftport 50000 --rpc --rpcaddr 0.0.0.0 --rpcport 22000 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,raft --emitcheckpoints --port 21000 >> node.log 2>&1 &
$vim startnode2.sh
... paste below
# !/bin/bash
PRIVATE_CONFIG=/yourpath/new-node-2t/tm.ipc nohup geth --datadir new-node-2 --nodiscover --verbosity 5 --networkid 31337 --raft --raftport 50001 --raftjoinexisting 2 --rpc --rpcaddr 0.0.0.0 --rpcport 22001 --rpcapi admin,db,eth,debug,miner,net,shh,txpool,personal,web3,quorum,raft --emitcheckpoints --port 21001 2>>node2.log &
$ chmod +x startnode1.sh startnode2.sh
$ ./startnode1.sh
$ ./startnode2.sh

シェルを2つ作成します。「yourpath」の部分は作成中の環境に合わせて修正します。

次にコントラクトデプロイ用のスクリプトを作成します。

private-contract.js
a = eth.accounts[0]
web3.eth.defaultAccount = a;

// abi and bytecode generated from simplestorage.sol:
// > solcjs --bin --abi simplestorage.sol
var abi = [{"constant":true,"inputs":[],"name":"storedData","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"x","type":"uint256"}],"name":"set","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"get","outputs":[{"name":"retVal","type":"uint256"}],"payable":false,"type":"function"},{"inputs":[{"name":"initVal","type":"uint256"}],"payable":false,"type":"constructor"}];

var bytecode = "0x6060604052341561000f57600080fd5b604051602080610149833981016040528080519060200190919050505b806000819055505b505b610104806100456000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632a1afcd914605157806360fe47b11460775780636d4ce63c146097575b600080fd5b3415605b57600080fd5b606160bd565b6040518082815260200191505060405180910390f35b3415608157600080fd5b6095600480803590602001909190505060c3565b005b341560a157600080fd5b60a760ce565b6040518082815260200191505060405180910390f35b60005481565b806000819055505b50565b6000805490505b905600a165627a7a72305820d5851baab720bba574474de3d09dbeaabc674a15f4dd93b974908476542c23f00029";

var simpleContract = web3.eth.contract(abi);
var simple = simpleContract.new(42, {from:web3.eth.accounts[0], data: bytecode, gas: 0x47b760, privateFor: ["+fb03AOJiZNiJkHwP24J+Wn1XslaTqZRRewo+FBNsl0="]}, function(e, contract) {
    if (e) {
        console.log("err creating contract", e);
    } else {
        if (!contract.address) {
            console.log("Contract transaction send: TransactionHash: " + contract.transactionHash + " waiting to be mined...");
        } else {
            console.log("Contract mined! Address: " + contract.address);
            console.log(contract);
        }
    }
});

ここで注意が必要なのが、コード真ん中あたりに"privateFor"とあるので、そこに設定されている値を前の手順で確認した「new-node-1.pub」の値に更新します。

最後にGethのコンソールで動作確認をします。

$ geth attach new-node-1/geth.ipc
Welcome to the Geth JavaScript console!

instance: Geth/v1.8.18-stable-b9e886c4(quorum-v2.5.0)/linux-amd64/go1.11.5
coinbase: 0x7b752f197c4272419b2d5d7a158314049678a43c
at block: 0 (Thu, 01 Jan 1970 09:00:00 JST)
 datadir: /home/quorum/fromscratch/new-node-1
 modules: admin:1.0 debug:1.0 eth:1.0 ethash:1.0 miner:1.0 net:1.0 personal:1.0 raft:1.0 rpc:1.0 txpool:1.0 web3:1.0

> personal.unlockAccount(eth.accounts[0])
Unlock account 0x7b752f197c4272419b2d5d7a158314049678a43c
Passphrase:
true
> loadScript("private-contract.js")
Contract transaction send: TransactionHash: 0x4a4b7655403ede633832c616aea1f2897e510ee14d5c3f17efaa6ed3d0b2e181 waiting to be mined...
true

この様にエラーがでなければ成功です。

トランザクションの情報も確認してみます。

eth.getTransaction("0x4a4b7655403ede633832c616aea1f2897e510ee14d5c3f17efaa6ed3d0b2e181")
{
  blockHash: "0x0000000000000000000000000000000000000000000000000000000000000000",
  blockNumber: null,
  from: "0x7b752f197c4272419b2d5d7a158314049678a43c",
  gas: 4700000,
  gasPrice: 0,
  hash: "0x4a4b7655403ede633832c616aea1f2897e510ee14d5c3f17efaa6ed3d0b2e181",
  input: "0x7f543e0f343deff9de4bcf6c09ffc6729ce978e496de4ae412a8613b0de7ae2a9065a64e31274e2cfbd469d7008a288aca23267b8540439ce8818c61f0cc6f79",
  nonce: 0,
  r: "0x2042bbe7edd4b3db938710ccca72cd25ef743b0bf1adfede5def2f8f921b96ae",
  s: "0x104dcd9ef820c945f2fb00ee000bca2068e304136991636f8543b809ee1cafa8",
  to: null,
  transactionIndex: 0,
  v: "0x25",
  value: 0
}

おわりに

QuorumのPrivacy Manager(Tessera)の環境構築をしてみました。
ドキュメントに沿ってやってみましたが、まだまだどうやって使うのか、何が出来るのかが明確に理解出来ていません。
エンタープライズ領域でブロックチェーンを使う場合、Fabricと並びQuorumも選択肢として挙げられると思います。
そこでQuorumを使って何が出来るのか?Ethereumと明確にどう違うのか?というポイントをこれから理解を深めていきたいと考えてます。

何か有益な使い方などあればメモ程度でどんどんアウトプットしていきます。

※AzureのBlockchain Workbenchで環境を作ると標準でQuorumになり、Privacy Managerも使えるようです。

5
4
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?