Amazon Managed BlockchainでHyperledger Fabric v2.2が利用出来るようになったのでネットワーク作成してチェーンコードを実行してみた

2022.01.05

いわさです。

昨年末にリリースされるという噂だった、Amazon Managed BlockchainのHyperledger Fabric v2.2がついに利用出来るようになりました。
東京リージョンでも使えますね。

Amazon Managed Blockchain (AMB) announces support for Hyperledger Fabric v2.2

v1.4からv2.xでHyperledger Fabricは大きくアップデートされておりセットアップに躓く方もいらっしゃるかもしれません。
今回v2.2でチェーンコードの承認から実行まで試してみたので手順を紹介したいと思います。

Get Started Creating a Hyperledger Fabric Blockchain Network Using Amazon Managed Blockchain - Amazon Managed Blockchain

VPCエンドポイントとピアノードを作成

まずは、マネージメントコンソールでVPCエンドポイントとピアノードを作成しましょう。
ここは従来の手順どおりで問題ありません。
ユーザーのIDとパスワードは忘れないようにしてください。

作成出来たら、Fabricネットワークのサービスエンドポイント、メンバーの認証期間エンドポイント、ピアノードのピアエンドポイントを控えておきます。
度々使います。

VPC内のクライアントからブロックチェーンへアクセス

今回は、Amazon Linux2でDockerを使ってhyperledger/fabric-toolsを使ったクライアントをセットアップします。
というわけで、まずはDockerとComposeをインストールします。

[ec2-user@ip-172-31-42-69 ~]$ sudo yum update -y
[ec2-user@ip-172-31-42-69 ~]$ sudo yum install jq telnet emacs docker libtool libtool-ltdl-devel git -y
[ec2-user@ip-172-31-42-69 ~]$ sudo service docker start
Redirecting to /bin/systemctl start docker.service
[ec2-user@ip-172-31-42-69 ~]$ sudo usermod -a -G docker ec2-user
[ec2-user@ip-172-31-42-69 ~]$ logout
Connection to ec2-52-195-11-212.ap-northeast-1.compute.amazonaws.com closed.
[ec2-user@ip-172-31-42-69 ~]$ sudo curl -L \
> https://github.com/docker/compose/releases/download/1.20.0/docker-compose-`uname \
> -s`-`uname -m` -o /usr/local/bin/docker-compose
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   664  100   664    0     0   2680      0 --:--:-- --:--:-- --:--:--  2688
100 10.3M  100 10.3M    0     0  2855k      0  0:00:03  0:00:03 --:--:-- 4152k
[ec2-user@ip-172-31-42-69 ~]$ sudo chmod a+x /usr/local/bin/docker-compose

後述のセットアップで度々使うので、エンドポイントやパスは環境変数へ登録しておきます。

[ec2-user@ip-172-31-42-69 ~]$ cat ~/.bash_profile 
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
	. ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/.local/bin:$HOME/bin

#export PATH

# GOROOT is the location where Go package is installed on your system
export GOROOT=/usr/local/go

# GOPATH is the location of your work directory
export GOPATH=$HOME/go

# CASERVICEENDPOINT is the endpoint to reach your member's CA
export CASERVICEENDPOINT=ca.m-xxxxxxxxxxx.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30002

# ORDERER is the endpoint to reach your network's orderer
export ORDERER=orderer.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30001

# Update PATH so that you can access the go binary system wide
export PATH=$GOROOT/bin:$PATH
export PATH=$PATH:/home/ec2-user/go/src/github.com/hyperledger/fabric-ca/bin

ピアノードの接続ではTLSを使う必要があります。
ここでは、Hyperledger Fabric CAクライアントを構成します。

CAの接続確認が出来たらモジュールをダウンロードします。

[ec2-user@ip-172-31-42-69 ~]$ curl https://ca.m-xxxxxxxxxxx.n-xxxxxxxxxxx.com:30002/cainfo -k | jq
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  2893    0  2893    0     0   107k      0 --:--:-- --:--:-- --:--:--  108k
{
  "result": {
    "CAName": "m-OT2YQO7XD5C2JB2EKDGSW3F72A",
    "CAChain": "<CAChain>=",
    "IssuerPublicKey": "<IssuePublicKey>",
    "IssuerRevocationPublicKey": "<IssueRevocationPublicKey>=",
    "Version": "1.4.7"
  },
  "errors": [],
  "messages": [],
  "success": true
}
[ec2-user@ip-172-31-42-69 ~]$ mkdir -p /home/ec2-user/go/src/github.com/hyperledger/fabric-ca
[ec2-user@ip-172-31-42-69 ~]$ cd /home/ec2-user/go/src/github.com/hyperledger/fabric-ca
[ec2-user@ip-172-31-42-69 fabric-ca]$ wget https://github.com/hyperledger/fabric-ca/releases/download/v1.5.2/hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gz

...

2022-01-04 21:39:18 (8.98 MB/s) - `hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gz' へ保存完了 [26723281/26723281]

[ec2-user@ip-172-31-42-69 fabric-ca]$ tar -xzf hyperledger-fabric-ca-linux-amd64-1.5.2.tar.gz

チェーンコードはサンプルで色々なものが公開されています。
本日はこちらのv2.2系のlatestのものを使ってみましょう。

[ec2-user@ip-172-31-42-69 ~]$ git clone --branch v2.2.3 https://github.com/hyperledger/fabric-samples.git
Cloning into 'fabric-samples'...

...

Resolving deltas: 100% (4898/4898), done.

公式ドキュメントの手順ではv1.4.7のイメージを使用していますが、v2.2.3にしました。(後ほどManaged Blockchain v2.2のコンポーネントがv2.2.4であることに気づきましたが・・・)

docker-compose-cli.yaml

version: '2'
services:
  cli:
    container_name: cli
    image: hyperledger/fabric-tools:2.2.3
    tty: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - FABRIC_LOGGING_SPEC=info # Set logging level to debug for more verbose logging
      - CORE_PEER_ID=cli
      - CORE_CHAINCODE_KEEPALIVE=10
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem
      - CORE_PEER_LOCALMSPID=m-xxxxxxxxxxxxxxxxxxxxxxxxxx
      - CORE_PEER_MSPCONFIGPATH=/opt/home/admin-msp
      - CORE_PEER_ADDRESS=nd-xxxxxxxxxxx.m-xxxxxxxxxxx.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30003
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: /bin/bash
    volumes:
        - /var/run/:/host/var/run/
        - /home/ec2-user/fabric-samples/chaincode:/opt/gopath/src/github.com/
        - /home/ec2-user:/opt/home

起動しておきましょう。

[ec2-user@ip-172-31-42-69 ~]$ docker-compose -f docker-compose-cli.yaml up -d

Creating network "ec2user_default" with the default driver
Pulling cli (hyperledger/fabric-tools:2.2.3)...
2.2.3: Pulling from hyperledger/fabric-tools

...

Status: Downloaded newer image for hyperledger/fabric-tools:2.2.3
Creating cli ... done

CA構成

証明書をダウンロードします。コンテナ内からピアノードとの接続時に頻繁に使いますのでマウントボリュームへ保存しておきます。
最後に、CAに対する管理者としてエンロールメントもしておきます。

[ec2-user@ip-172-31-42-69 ~]$ aws s3 cp s3://ap-northeast-1.managedblockchain/etc/managedblockchain-tls-chain.pem  /home/ec2-user/managedblockchain-tls-chain.pem
download: s3://ap-northeast-1.managedblockchain/etc/managedblockchain-tls-chain.pem to ./managedblockchain-tls-chain.pem
[ec2-user@ip-172-31-42-69 ~]$ fabric-ca-client enroll -u 'https://username:password@ca.m-xxxxxxxxxxx.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30002' --tls.certfiles /home/ec2-user/managedblockchain-tls-chain.pem -M /home/ec2-user/admin-msp
2022/01/04 22:02:05 [INFO] TLS Enabled
2022/01/04 22:02:05 [INFO] generating key: &{A:ecdsa S:256}
2022/01/04 22:02:05 [INFO] encoded CSR
2022/01/04 22:02:05 [INFO] Stored client certificate at /home/ec2-user/admin-msp/signcerts/cert.pem
2022/01/04 22:02:05 [INFO] Stored root CA certificate at /home/ec2-user/admin-msp/cacerts/ca-m-xxxxxxxxxxx-n-xxxxxxxxxxx-managedblockchain-ap-northeast-1-amazonaws-com-30002.pem
2022/01/04 22:02:05 [INFO] Stored Issuer public key at /home/ec2-user/admin-msp/IssuerPublicKey
2022/01/04 22:02:05 [INFO] Stored Issuer revocation public key at /home/ec2-user/admin-msp/IssuerRevocationPublicKey
[ec2-user@ip-172-31-42-69 ~]$ cp -r /home/ec2-user/admin-msp/signcerts admin-msp/admincerts

チャネル作成

チャネル構成ファイルを準備し、configtxピアブロックを生成します。
公式ドキュメント上で、構成ファイルの内容はv1.4とv1.2で内容異なる旨に触れられていますが、v2.2はもっと違います。

Organizations:
    - &Org1
        Name: m-xxxxxxxxxxx
        ID: m-xxxxxxxxxxx
        SkipAsForeign: false
        Policies: &Org1Policies
            Readers:
                Type: Signature
                Rule: "OR('Org1.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org1.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org1.admin')"
        MSPDir: /opt/home/admin-msp
        AnchorPeers:
            - Host: 127.0.0.1
              Port: 7051
Capabilities:
    Channel: &ChannelCapabilities
        V2_0: true
    Orderer: &OrdererCapabilities
        V2_0: true
    Application: &ApplicationCapabilities
        V2_0: true
Channel: &ChannelDefaults
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ChannelCapabilities
Application: &ApplicationDefaults
    Organizations:
    Policies: &ApplicationDefaultPolicies
        LifecycleEndorsement:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Endorsement:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"

    Capabilities:
        <<: *ApplicationCapabilities
Profiles:
    OneOrgChannel:
        <<: *ChannelDefaults
        Consortium: AWSSystemConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli configtxgen -outputCreateChannelTx /opt/home/mychannel.pb -profile OneOrgChannel -channelID mychannel --configPath /opt/home/
2022-01-04 22:20:51.754 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2022-01-04 22:20:51.759 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /opt/home/configtx.yaml
2022-01-04 22:20:51.759 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2022-01-04 22:20:51.761 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer channel create -c mychannel -f /opt/home/mychannel.pb -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls
2022-01-04 22:23:17.750 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-01-04 22:23:20.084 UTC [cli.common] readBlock -> INFO 002 Received block: 0

チャネルが作成出来たら、ピアノードをチャネルに参加させます。

[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer channel join -b mychannel.block \
> -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls
2022-01-04 22:23:47.596 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2022-01-04 22:23:47.761 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

チェーンコードのインストール

ここからv1.4と大きく手順が変わってきます。
v1.4まではソースコードをインストールしてインスタンス化するだけで良かったのですが、v2.0で追加されたライフサイクル機能の関係で、手順が大きく変わっています。

v1.4と同じ流れだとインスタンス化のタイミングで以下のように失敗します。

[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer chaincode instantiate -o $ORDERER -C mychannel -n sacc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls
2022-01-05 00:39:45.326 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2022-01-05 00:39:45.326 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
Error: could not assemble transaction, err proposal response was not successful, error code 500, msg Channel 'mychannel' has been migrated to the new lifecycle, LSCC is now read-only

また、v1.4まで使用できていたサンプルchaincode_example02もv2.0のサンプルからは存在しないので他のサンプルを使いましょう。
公式ドキュメントだとabstoreを使っている手順になっていますが、執筆時点ではv2.2の手順が掲載されておらず私はsaccを使ってみました。

流れとしてはパッケージ化してピアノードへインストールし、チェーンコードを承認しコミットします。

[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode package sacc.tar.gz -p github.com/sacc -l golang --label hoge
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode install sacc.tar.gz
2022-01-05 04:23:19.219 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nEhoge:737b9780e17cc33040467565f1e68926a65d8b06b1402a188fca6ff614cc0a23\022\004hoge" > 
2022-01-05 04:23:19.219 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: hoge:737b9780e17cc33040467565f1e68926a65d8b06b1402a188fca6ff614cc0a23
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: hoge:737b9780e17cc33040467565f1e68926a65d8b06b1402a188fca6ff614cc0a23, Label: hoge
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode approveformyorg -o $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem -C mychannel -n sacc -v 1.0 --sequence 1 --package-id hoge:737b9780e17cc33040467565f1e68926a65d8b06b1402a188fca6ff614cc0a23
2022-01-05 04:24:08.047 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [2bbe1225ad68f8612b1b7805e25709807f6ea26674b0193a615c63dfd393f803] committed with status (VALID) at nd-xxxxxxxxxxx.m-xxxxxxxxxxx.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30003
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode checkcommitreadiness -o $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem -C mychannel -n sacc -v 1.0 --sequence 1
Chaincode definition for chaincode 'sacc', version '1.0', sequence '1' on channel 'mychannel' approval status by org:
m-xxxxxxxxxxx: true
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode commit -o $ORDERER --tls --cafile /opt/home/managedblockchain-tls-chain.pem -C mychannel -n sacc -v 1.0 --sequence 1
2022-01-05 04:25:11.534 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [42ad690dc6773f34073995f0fb18d85d50dbb47adb805b7508e19e0e90e5ad8b] committed with status (VALID) at nd-xxxxxxxxxxx.m-xxxxxxxxxxx.n-xxxxxxxxxxx.managedblockchain.ap-northeast-1.amazonaws.com:30003
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer lifecycle chaincode querycommitted -C mychannel
Committed chaincode definitions on channel 'mychannel':
Name: sacc, Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc

チェーンコード実行

その後はチェーンコードを実行して値の保存と取得が出来ます。

[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer chaincode invoke -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls -C mychannel -c '{"Args":["set","a","100"]}' -n sacc
2022-01-05 04:32:15.156 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 payload:"100" 
[ec2-user@ip-172-31-42-69 ~]$ docker exec cli peer chaincode query -o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls -C mychannel -c '{"Args":["query","a"]}' -n sacc
100

さいごに

本日は、Amazon Managed Blockchainを使って、Hyperledger Fabric v2.2のチェーンコードを実行してみました。
パブリックブロックチェーンばかりで、Hyperledger Fabricというかプライベートブロックチェーン自体初めて触ったもので、新機能の紹介が中々難しかったです。
VPCエンドポイント経由でプライベート利用することも実は初めて知りました。

Hyperledger Fabricのサンプルかなり充実しているので少しづつ試していきたいですね。
また、今後v2.2ならではの機能をご紹介できればと思っています。