はじめに
今回はHyperledger Fabricのサンプルアプリケーションを動かしてみます。本エントリは次のページで紹介されている手順に従って進めていきます。
Writing Your First Application — hyperledger-fabricdocs master documentation
実行環境
- Max OS High Sierra Version 10.13
- Docker version 17.09.0-ce
- Docker Compose version 1.16.1
- Go version 1.9
- Node.js version 8.6
Hyperledger Fabricのダウンロード
次のコマンドを実行します。
$ mkdir ~/fabric
$ cd ~/fabric
$ curl -sSL https://goo.gl/Q3YRTi | bash
これによりブロックチェーンネットワークを構築するために必要な次のバイナリを入手します。
- cryptogen
- configtxgen
- configtxlator
- peer
$ ls bin
configtxgen configtxlator cryptogen get-docker-images.sh orderer peer
同スクリプトはHyperledger FabricのdockerイメージをDocker Hubよりダウンロードします。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hyperledger/fabric-ca latest 2736904862db 10 days ago 218MB
hyperledger/fabric-ca x86_64-1.1.0-preview 2736904862db 10 days ago 218MB
hyperledger/fabric-tools latest c584c20ac82b 10 days ago 1.42GB
hyperledger/fabric-tools x86_64-1.1.0-preview c584c20ac82b 10 days ago 1.42GB
hyperledger/fabric-couchdb latest 5b8a15e6e972 10 days ago 1.57GB
hyperledger/fabric-couchdb x86_64-1.1.0-preview 5b8a15e6e972 10 days ago 1.57GB
hyperledger/fabric-kafka latest cf09c5534ef9 10 days ago 1.37GB
hyperledger/fabric-kafka x86_64-1.1.0-preview cf09c5534ef9 10 days ago 1.37GB
hyperledger/fabric-zookeeper latest ac127485fdc7 10 days ago 1.37GB
hyperledger/fabric-zookeeper x86_64-1.1.0-preview ac127485fdc7 10 days ago 1.37GB
hyperledger/fabric-orderer latest 2fccc91736df 10 days ago 159MB
hyperledger/fabric-orderer x86_64-1.1.0-preview 2fccc91736df 10 days ago 159MB
hyperledger/fabric-peer latest 337f3d90b452 10 days ago 165MB
hyperledger/fabric-peer x86_64-1.1.0-preview 337f3d90b452 10 days ago 165MB
hyperledger/fabric-javaenv latest cd459b218651 10 days ago 1.49GB
hyperledger/fabric-javaenv x86_64-1.1.0-preview cd459b218651 10 days ago 1.49GB
hyperledger/fabric-ccenv latest 82489d1c11e8 10 days ago 1.35GB
hyperledger/fabric-ccenv x86_64-1.1.0-preview 82489d1c11e8 10 days ago 1.35GB
開発環境のセットアップ
Hyperledger Fabricのサンプルをgitでcloneします。
$ git clone https://github.com/hyperledger/fabric-samples.git
$ cd fabric-samples
以降では次のfabcarディレクトリで作業します。
$ cd fabcar
$ ls
enrollAdmin.js invoke.js package.json query.js registerUser.js startFabric.sh
念のためdockerコンテナとネットワークを削除しておきます。
$ docker rm -f $(docker ps -aq)
$ docker network prune
すでに以降の作業を実施済みの場合には次のコマンドでfabcarチェインコード用のdockerイメージも削除します。
$ docker rmi dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba
アプリケーションの実行に必要なライブラリをインストールするため次のコマンドを実行します。
以降ではCAサーバにアクセスするためにnode_modules/fabric-ca-client、
peerやordering serviceと対話するためにnode_modules/fabric-clientを使用していきます。
$ npm install
続けて次のスクリプトを実行することでネットワークを起動します。このコマンドはFabricの各コンテナを用意します。
fabcarネットワークの詳細はこちらに説明があります。
Understanding the Fabcar Network — hyperledger-fabricdocs master documentation
$ ./startFabric.sh
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba latest bf75bac8b3f9 2 minutes ago 151MB
...
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b4b2e2be6dc7 dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba "chaincode -peer.a..." 4 minutes ago Up 4 minutes dev-peer0.org1.example.com-fabcar-1.0
a4f01226a050 hyperledger/fabric-tools "/bin/bash" 6 minutes ago Up 6 minutes cli
dbce2a81cb36 hyperledger/fabric-peer "peer node start" 7 minutes ago Up 7 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
c83fd30320e2 hyperledger/fabric-couchdb "tini -- /docker-e..." 7 minutes ago Up 7 minutes 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp couchdb
0dd907f8cce3 hyperledger/fabric-orderer "orderer" 7 minutes ago Up 7 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
86ef00f4705d hyperledger/fabric-ca "sh -c 'fabric-ca-..." 7 minutes ago Up 7 minutes 0.0.0.0:7054->7054/tcp ca.example.com
ユーザの登録
前述のネットワーク立ち上げ時にadminユーザが認証局(CA)に登録されています。
enrollAdmin.jsでadminの電子証明書(eCert)を取得します。
このプログラムは公開鍵と秘密鍵をhfc-key-storeに作成し、証明書署名要求(CSR)で公開鍵証明書を発行します。
続けて、registerUser.jsではadminユーザでCAと通信しLedgerにアクセスするuser1ユーザを登録します。このプログラムもまた、CSRを実行し証明書と鍵をhfc-key-storeに出力します。
$ node enrollAdmin.js
$ node registerUser.js
$ ls hfc-key-store/
admin
...-pub
...-priv
user1
...-pub
...-priv
Ledgerの参照
query.jsを使用し、fabcarチェインコードのqueryAllCarsを呼び出します。
fabric-samples/fabcar/query.js
const request = {
chaincodeId: 'fabcar',
fcn: 'queryAllCars',
args: ['']
};
$ node query.js
Store path:.../fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is
[{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},
{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},
{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},
{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},
{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},
{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},
{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},
{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},
{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
実行したチェインコードの関数は次の通りです。
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {
startKey := "CAR0"
endKey := "CAR999"
resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
LedgerにアクセスするAPIの仕様はこちらにあります。
godoc.org
github.com
Ledgerの更新
fabcarチェインコードのcreateCarで新たなCARをLedgerに追加します。
fabric-samples/fabcar/invoke.js
var request = {
chaincodeId: 'fabcar',
fcn: 'createCar',
args: ['CAR10', 'Chevy', 'Volt', 'Red', 'Nick'],
chainId: 'mychannel',
txId: tx_id
};
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) != 5 {
return shim.Error("Incorrect number of arguments. Expecting 5")
}
var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]}
carAsBytes, _ := json.Marshal(car)
APIstub.PutState(args[0], carAsBytes)
return shim.Success(nil)
}
$ node invoke.js
Store path:.../fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Assigning transaction_id: 97ae720f071443b8f73b5ab1e8ed1a87d8a04ba3904479f24cdb146486edcbfa
Transaction proposal was good
Successfully sent Proposal and received ProposalResponse: Status - 200, message - "OK"
info: [EventHub.js]: _connect - options {}
The transaction has been committed on peer localhost:7053
Send transaction promise and event listener promise have completed
Successfully sent transaction to the orderer.
Successfully committed the change to the ledger by the peer
最後にCAR10が正しく追加されているかを確認します。
fabcarのqueryCarに引数CAR10を渡し、query.jsを実行します。
query.js
const request = {
chaincodeId: 'fabcar',
fcn: 'queryCar',
args: ['CAR10']
};
fabric-samples/chaincode/fabcar/fabcar.go
func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
carAsBytes, _ := APIstub.GetState(args[0])
return shim.Success(carAsBytes)
}
$ node query.js
Store path:.../fabric-samples/fabcar/hfc-key-store
Successfully loaded user1 from persistence
Query has completed, checking results
Response is {"colour":"Red","make":"Chevy","model":"Volt","owner":"Nick"}
期待通りの結果が得られました。
さいごに
本エントリではサンプルアプリケーションfabcarを動かしてみました。
Ledgerにアクセスするアプリケーションの実装イメージが少し湧いた気がします。
次回はまだ未定ですが、JavaアプリケーションからHyperledger Fabric SDKを使用してみたいと考えてます。