jasonruan 2018.11.17
本文是自己学习超级账本Fabric的第一篇文章,主要是体验了下基本功能——快速搭建起网络环境,并利用自带sample,体会了一下链码的部署与调用,为后续逐步深入其内部原理和链码开发做一个铺垫。
自己初学超级账本Fabric,其众多的术语确实弄得有些蒙圈,以下摘记部分术语。
术语 | 含义 |
---|---|
Anchor Peer(锚节点) | 通道中能被所有对等节点探测,并能与之进行通信的一种对等节点。 通道中的每个成员都有一个或多个锚节点,允许属于不同身份的节点来发现通道中存在的其他节点。 |
Block(区块) | 区块是一组有序的交易集合,在通道中经过哈希加密后与前序区块连接。 |
Chaincode(链码) | 区块链上的应用代码,扩展自"智能合约"概念。 |
Channel(通道) | Fabric 网络上的私有隔离。通道中的链码和交易只有加入该通道的节点可见。 |
Consensus (共识) | 共识是贯穿整个交易流程, 对包含块的一组交易的正确性的全面验证。 |
Endorser(背书节点) | 负责检验某个交易是否合法,是否愿意为之担保、签名。 |
Fabric-CA(证书节点) | 默认的证书管理组件,它向网络成员及其用户颁发基于PKI的证书。 CA为每个成员颁发一个根证书,为没有授权用户颁发一个注册证书,为每个注册证书颁发大量交易证书。 |
Genesis Block(创世区块) | 是区块链上的第一个区块,是初始化区块链网络或通道的配置区块 |
Ledger(账本) | 账本是由通道中每个peer维护的数据库。 |
MSP(Member Service Provider,成员服务提供者) | 抽象的实现成员服务(身份验证,证书管理等)的组件,实现对不同类型的成员服务的可拔插支持。 |
Orderer Peer(排序节点) | 负责排序看到的交易,提供全局确认的顺序。 |
Ordering Service(排序服务) | 将交易排序放入block的节点的集合。排序服务独立与peer流程之外,并以先到先服务的方式为网络上所有的通道做交易排序。 |
State Database(状态数据库) | 当前状态数据存储在状态数据库中,以便从chaincode进行有效读取和查询。这些数据库包括levelDB和couchDB。 |
Transaction(交易) | 执行账本上的某个函数调用或者部署 chaincode。调用的具体函数在 chaincode 中实现。 |
Validating Peer(验证节点) | 维护账本的核心节点,参与一致性维护、对交易的验证和执行。 |
World State(世界状态) | 即最新的全局账本状态。Fabric 用它来存储历史交易发生后产生的最新的状态,可以用键值或文档数据库实现。 |
省略具体安装步骤
ubuntu 18.04
go 1.11.2
docker-ce 18.09
docker-compose 1.23.1
下载地址:https://github.com/hyperledger/fabric
$ git clone https://github.com/hyperledger/fabric.git
Cloning into 'fabric'...
remote: Enumerating objects: 183, done.
remote: Counting objects: 100% (183/183), done.
remote: Compressing objects: 100% (164/164), done.
remote: Total 81151 (delta 64), reused 135 (delta 18), pack-reused 80968
Receiving objects: 100% (81151/81151), 77.50 MiB | 440.00 KiB/s, done.
Resolving deltas: 100% (51831/51831), done.
步骤:
进入clone好的源码目录fabric/scripts
执行bootstrap.sh
脚本,该脚本将执行如下操作:
> 首先是安装fabric-samples
(1)下载hyperledger/fabric-samples
Installing hyperledger/fabric-samples repo
===> Cloning hyperledger/fabric-samples repo and checkout v1.3.0
(2)下载当前平台的fabric二进制包
===> Downloading version 1.3.0 platform specific fabric binaries
===> Downloading: https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/linux-amd64-1.3.0/hyperledger-fabric-linux-amd64-1.3.0.tar.gz
(3)下载当前平台的CA客户端
===> Downloading version 1.3.0 platform specific fabric-ca-client binary
===> Downloading: https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric-ca/hyperledger-fabric-ca/linux-amd64-1.3.0/hyperledger-fabric-ca-linux-amd64-1.3.0.tar.gz
> 接下来拉取fabric镜像
(4)peer节点镜像
==> FABRIC IMAGE: peer
1.3.0: Pulling from hyperledger/fabric-peer
Digest: sha256:6756c7c48234ae6b0a8822a378681017cf6dbfeadfbf1f8a528ee6c4db343621
Status: Image is up to date for hyperledger/fabric-peer:1.3.0
(5)排序节点镜像
==> FABRIC IMAGE: orderer
1.3.0: Pulling from hyperledger/fabric-orderer
Digest: sha256:6ee1abcfd84031765d67544e5d6b4f3af08c3f064312c65715587d392fe7c3eb
Status: Image is up to date for hyperledger/fabric-orderer:1.3.0
(6)CC环境镜像
==> FABRIC IMAGE: ccenv
1.3.0: Pulling from hyperledger/fabric-ccenv
Digest: sha256:05fce5513fcae3110ac041469ed9e0e4c9661f44782f52ef5d8930eb416c2197
Status: Image is up to date for hyperledger/fabric-ccenv:1.3.0
(7)工具镜像
==> FABRIC IMAGE: tools
1.3.0: Pulling from hyperledger/fabric-tools
Digest: sha256:058cff3b378c1f3ebe35d56deb7bf33171bf19b327d91b452991509b8e9c7870
Status: Image is up to date for hyperledger/fabric-tools:1.3.0
> 下面拉取fabric CA镜像
(8)CA镜像
==> FABRIC CA IMAGE
1.3.0: Pulling from hyperledger/fabric-ca
Digest: sha256:83abc367c5273a12d59ef9777637eb6c1abf04a5d00d66a0bffc55c40075850e
Status: Image is up to date for hyperledger/fabric-ca:1.3.0
> 最后拉取第三方docker镜像
(9)couchdb镜像
==> THIRDPARTY DOCKER IMAGE: couchdb
0.4.13: Pulling from hyperledger/fabric-couchdb
Digest: sha256:b26dfcf9abb466ffb60d0734d0c5c3bf1d4816c96e944ba69584d94681028cfd
Status: Image is up to date for hyperledger/fabric-couchdb:0.4.13
(10)kafka镜像
==> THIRDPARTY DOCKER IMAGE: kafka
0.4.13: Pulling from hyperledger/fabric-kafka
Digest: sha256:7caa31210504bc99ae45d19d528671f238d25418d9433c42f8c582ba415703b4
Status: Image is up to date for hyperledger/fabric-kafka:0.4.13
(11)zookeeper镜像
==> THIRDPARTY DOCKER IMAGE: zookeeper
0.4.13: Pulling from hyperledger/fabric-zookeeper
Digest: sha256:9fdff6aa2c086816ad693339c25f1e49ea4a0b6b7102c7342aff4137991a15a1
Status: Image is up to date for hyperledger/fabric-zookeeper:0.4.13
镜像拉取完毕后,列出镜像清单
===> List out hyperledger docker images
hyperledger/fabric-ca 1.3.0 5c6b20ba944f 4 weeks ago 244MB
hyperledger/fabric-ca latest 5c6b20ba944f 4 weeks ago 244MB
hyperledger/fabric-tools 1.3.0 c056cd9890e7 4 weeks ago 1.5GB
hyperledger/fabric-tools latest c056cd9890e7 4 weeks ago 1.5GB
hyperledger/fabric-ccenv 1.3.0 953124d80237 4 weeks ago 1.38GB
hyperledger/fabric-ccenv latest 953124d80237 4 weeks ago 1.38GB
hyperledger/fabric-orderer 1.3.0 f430f581b46b 4 weeks ago 145MB
hyperledger/fabric-orderer latest f430f581b46b 4 weeks ago 145MB
hyperledger/fabric-peer 1.3.0 f3ea63abddaa 4 weeks ago 151MB
hyperledger/fabric-peer latest f3ea63abddaa 4 weeks ago 151MB
hyperledger/fabric-zookeeper 0.4.13 e62e0af39193 4 weeks ago 1.39GB
hyperledger/fabric-zookeeper latest e62e0af39193 4 weeks ago 1.39GB
hyperledger/fabric-kafka 0.4.13 4121ea662c47 4 weeks ago 1.4GB
hyperledger/fabric-kafka latest 4121ea662c47 4 weeks ago 1.4GB
hyperledger/fabric-couchdb 0.4.13 1d3266e01e64 4 weeks ago 1.45GB
hyperledger/fabric-couchdb latest 1d3266e01e64 4 weeks ago 1.45GB
hyperledger/fabric-baseos amd64-0.4.13 f0fe49196c40 4 weeks ago 124MB
下面基于fabric-samples提供的BYFN(
build your first network
),来快速的构建我们第一个超级账本fabric网络,以此来熟悉整个运行过程。
进入到:fabric/scripts/fabric-samples/first-network/
,执行命令:
$ sudo ./byfn.sh -m generate -c jschannel
这条命令也可以不用执行,在使用up
命令启动网络时,若发现未生成所需配置,会自动进行执行。
该条命令将根据配置文件(crypto-config.yaml
)生成初始化配置,包含Peer节点、排序服务节点的MSP证书
# crypto-config.yaml
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
configtx.yaml
生成创世区块等
# configtx.yaml
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
Policies:
......
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
Policies:
Readers:
......
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
- &Org2
......
Capabilities:
......
Application: &ApplicationDefaults
Organizations:
Policies:
......
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
......
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Policies:
......
Channel: &ChannelDefaults
......
Capabilities:
<<: *ChannelCapabilities
Profiles:
......
使用cryptogen工具为组织org1和org2生成MSP证书
,MSP证书是超级账本网络实体的身份标识,实体在通信和交易时,使用证书进行签名和验证。成功执行后,证书文件将会放到crypto-config
目录中。
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
为排序服务生成创世区块,成功执行后,会在channel-artifacts
目录下生成创世区块文件:genesis.block
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
+ configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
生成通道配置文件channel.tx
,成功执行后,会在channel-artifacts
目录下生成通道配置channel.tx
#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID jschannel
生成Org1MSP
和Org2MSP
的锚节点配置,成功执行后,生成的锚点配置文件Org1MSPanchors.tx
和Org2MSPanchors.tx
同样位于目录channel-artifacts
中。
#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID jschannel -asOrg Org1MSP
#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID jschannel -asOrg Org2MSP
综上,命令执行完后,将会在当前目录生成两个文件夹,内容分别如下:
channel-artifacts
)
$ tree channel-artifacts/
channel-artifacts/
├── channel.tx # 通道配置创世区块
├── genesis.block # 排序服务创世区块
├── Org1MSPanchors.tx # Org1锚节点配置
└── Org2MSPanchors.tx # Org2锚节点配置
crypto-config
)> 该目录存放生成排序服务节点和Peer节点的MSP证书文件
$ tree crypto-config
crypto-config
├── ordererOrganizations
│ └── example.com
│ ├── ca
│ │ ├── 2b749470c3d6cae6d63caa7b69ee9ebbc310ca68526521e444012f186e97bd92_sk
│ │ └── ca.example.com-cert.pem
│ ├── msp
│ │ ├── admincerts
│ │ │ └── [email protected]
│ │ ├── cacerts
│ │ │ └── ca.example.com-cert.pem
│ │ └── tlscacerts
│ │ └── tlsca.example.com-cert.pem
│ ├── orderers
│ │ └── orderer.example.com
│ │ ├── msp
│ │ └── tls
│ │ ├── ca.crt
│ │ ├── server.crt
│ │ └── server.key
│ ├── tlsca
│ │ ├── c79b35c1154c5377923a77dfa6036707652715671e2b1450e6313b64a65f238e_sk
│ │ └── tlsca.example.com-cert.pem
│ └── users
│ └── [email protected]
│ ├── msp
└── peerOrganizations
├── org1.example.com
│ ├── ca
│ ├── msp
│ ├── peers
│ ├── tlsca
│ └── users
└── org2.example.com
$ sudo ./byfn.sh -m up -c jschannel
执行该命令后,首先会根据docker-compose-cli.yaml
配置文件启动超级账本fabric网络
其中包含了1个排序服务节点、4个Peer节点,以及1个命令行容器cli
# docker-compose-cli.yaml
services:
orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com
networks:
- byfn
peer0.org1.example.com:
container_name: peer0.org1.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org1.example.com
networks:
- byfn
peer1.org1.example.com:
......
peer0.org2.example.com:
container_name: peer0.org2.example.com
extends:
file: base/docker-compose-base.yaml
service: peer0.org2.example.com
networks:
- byfn
peer1.org2.example.com:
......
cli:
container_name: cli
image: hyperledger/fabric-tools:$IMAGE_TAG
tty: true
stdin_open: true
environment:
......
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: /bin/bash
volumes:
- ./../chaincode/:/opt/gopath/src/github.com/chaincode
- ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
......
depends_on:
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
networks:
- byfn
看到下面信息,表明超级账本Fabric网络已经启动完毕。
Creating network "net_byfn" with the default driver
Creating volume "net_orderer.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating peer1.org2.example.com ... done
Creating orderer.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer0.org2.example.com ... done
Creating peer0.org1.example.com ... done
Creating cli ... done
使用docker ps
命令查看容器启动情况
$ sudo docker ps
CONTAINER ID IMAGE COMMAND PORTS NAMES
c32c37c5742f hyperledger/fabric-tools:latest "/bin/bash" cli
dadda8aff9ae hyperledger/fabric-peer:latest "peer node start" 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
f35e303b931d hyperledger/fabric-peer:latest "peer node start" 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
5bf8fdf0f804 hyperledger/fabric-peer:latest "peer node start" 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
48c9b04f48db hyperledger/fabric-peer:latest "peer node start" 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
023b2fed2737 hyperledger/fabric-orderer:latest "orderer" 0.0.0.0:7050->7050/tcp orderer.example.com
在启动网络 使用的
$ sudo ./byfn.sh -m up -c jschannel
中,启动的cli
容器会调用scripts/script.sh
脚本,该脚本会进行通道创建、Peer节点加入通道、安装和实例化链码等,并进行链码的调用和查询。下面我们对命令进行进一步的说明。
scripts/script.sh
中执行的具体命令如下,每个命令都对应一个shell脚本函数
## Create channel
createChannel
## Join all the peers to the channel
joinChannel
## Set the anchor peers for each org in the channel
updateAnchorPeers 0 1
updateAnchorPeers 0 2
## Install chaincode on peer0.org1 and peer0.org2
installChaincode 0 1
installChaincode 0 2
# Instantiate chaincode on peer0.org2
instantiateChaincode 0 2
# Query chaincode on peer0.org1
chaincodeQuery 0 1 100
# Invoke chaincode on peer0.org1 and peer0.org2
chaincodeInvoke 0 1 0 2
## Install chaincode on peer1.org2
installChaincode 1 2
# Query on chaincode on peer1.org2, check if the result is 90
chaincodeQuery 1 2 90
进入cli
容器,执行创建通道命令。成功执行后,将在cli
容器的当前路径下生成通道配置jschannel.block
,加入通道操作时需要使用。
Channel name : jschannel
Creating channel...
+ peer channel create -o orderer.example.com:7050 -c jschannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
===================== Channel 'mychannel' created =====================
通过在cli
容器中设置不同的环境变量,设置连接的Peer节点和MSP等,依次将4个Peer节点加入通道
+ peer channel join -b jschannel.block
Having all peers join the channel...
===================== peer0.org1 joined channel 'jschannel' =====================
+ peer channel join -b jschannel.block
===================== peer1.org1 joined channel 'jschannel' =====================
+ peer channel join -b jschannel.block
===================== peer0.org2 joined channel 'jschannel' =====================
+ peer channel join -b jschannel.block
===================== peer1.org2 joined channel 'jschannel' =====================
Updating anchor peers for org1...
+ peer channel update -o orderer.example.com:7050 -c jschannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile
========= Anchor peers updated for org 'Org1MSP' on channel 'jschannel' =========
Updating anchor peers for org2...
+ peer channel update -o orderer.example.com:7050 -c jschannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile
========== Anchor peers updated for org 'Org2MSP' on channel 'jschannel' ==========
peer0.org1
和peer0.org2
)上安装链码应用程序通过链码执行智能合约的功能,需要先在Peer节点上安装链码,然后在通道上实例化链码
Installing chaincode on peer0.org1...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
===================== Chaincode is installed on peer0.org1 =====================
Install chaincode on peer0.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
===================== Chaincode is installed on peer0.org2 =====================
peer0.org2
)上实例化链码实例化链码只需要执行一次,这条命令比较复杂,-c:指定初始化参数;-P:指定了背书策略,链码的每个交易需要由Org1MSP
和Org2MSP
两个组织都进行背书签名,才能通过背书策略,继续进入后续交易流程。成功执行后,会启动链码容器mycc
。
Instantiating chaincode on peer0.org2...
+ peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C jschannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'
========= Chaincode is instantiated on peer0.org2 on channel 'jschannel' =========
peer0.org1
)上执行链码查询a的值
Querying chaincode on peer0.org1...
========== Querying on peer0.org1 on channel 'jschannel'... ==========
+ peer chaincode query -C jschannel -n mycc -c '{"Args":["query","a"]}'
100
========== Query successful on peer0.org1 on channel 'jschannel' ==========
peer0.org1
)调用链码,从a转10到b
Sending invoke transaction on peer0.org1 peer0.org2...
+ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C jschannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
==== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'jschannel' ====
peer1.org2
)安装链码
Installing chaincode on peer1.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
===================== Chaincode is installed on peer1.org2 =====================
peer1.org2
)执行链码查询a的值
Querying chaincode on peer1.org2...
========== Querying on peer1.org2 on channel 'jschannel'... ==========
+ peer chaincode query -C jschannel -n mycc -c '{"Args":["query","a"]}'
90
========= Query successful on peer1.org2 on channel 'jschannel' =========
========= All GOOD, BYFN execution completed ===========
测试完成后,使用如下命令,关闭网络
$ sudo ./byfn.sh -m down
本文通过分解的方式,逐步介绍了搭建超级账本Fabric网络的基本过程以及链码部署和调用的方法,在理解和掌握了最基本的步骤后,也为后续自己深入学习超级账本的原理和开发更为复杂的链码应用打下基础。