Fabric测试网络使用

Fabric测试网络使用

测试网络设置环境变量记录

Org1:

1
2
3
4
5
6
7
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051

Org2:

1
2
3
4
5
6
7
export PATH=${PWD}/../bin:${PWD}:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:9051

2.2.1下载样例源码

运行命令下载最新版的FabricFabric CA以及 hyperledger/fabric-samples

1
curl -sSL https://bit.ly/2ysbOFE | bash -s

上面的命令干了这些事情:

  • 下载 hyperledger/fabric-samples
  • 签出适当的版本标签
  • 将Hyperledger Fabric平台特定的二进制文件和配置文件安装到Fabric-samples的/ bin和/ config目录中指定的版本
  • 下载指定版本的Hyperledger Fabric docker镜像,包括:
    • hyperledger/fabric-peer
    • hyperledger/fabric-orderer
    • hyperledger/fabric-ccenv
    • hyperledger/fabric-tools
    • hyperledger/fabric-baseos
    • hyperledger/fabric-ca

2.2.2使用Fabric测试网络

启动Fabric测试网络

1.进入fabric-samples/test-network,可以看到network.sh文件,可以运行./network.sh -h来显示帮助

1
cd fabric-samples/test-network
1
2
3
4
5
6
7
8
9
10
11
(base) apple@WHOAMIdeMacBook-Pro:~/code/open-source/blockchain/hyperledger/fabric-samples/test-network$     ll
total 72
-rw-r--r-- 1 apple staff 777 Dec 14 18:36 README.md
drwxr-xr-x 12 apple staff 384 Dec 14 18:36 addOrg3
drwxr-xr-x 3 apple staff 96 Dec 14 18:36 configtx
drwxr-xr-x 5 apple staff 160 Dec 14 18:36 docker
-rwxr-xr-x 1 apple staff 18645 Dec 14 18:36 network.sh
drwxr-xr-x 7 apple staff 224 Dec 14 18:36 organizations
-rwxr-xr-x 1 apple staff 8202 Dec 14 18:36 scriptUtils.sh
drwxr-xr-x 6 apple staff 192 Dec 14 18:36 scripts
drwxr-xr-x 3 apple staff 96 Dec 14 18:36 system-genesis-block

2.停止原来正在运行的docker容器

1
./network.sh down

3.启动网络

**注意事项:**必须在$USER/fabric-samples/test-network目录下执行此脚本,否则会报错

1
./network.sh up

这个脚本启动两个peer节点,一个ordering节点。这个脚本不会创建channel,我的脚本运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Creating network "net_test" 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_peer0.org2.example.com" with default driver
Creating orderer.example.com ... done
Creating peer0.org1.example.com ... done
Creating peer0.org2.example.com ... done
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
31c36a007eb0 hyperledger/fabric-peer:latest "peer node start" 1 second ago Up Less than a second 7051/tcp, 0.0.0.0:9051->9051/tcp peer0.org2.example.com
42f314195c64 hyperledger/fabric-orderer:latest "orderer" 1 second ago Up Less than a second 0.0.0.0:7050->7050/tcp orderer.example.com
de62f2f44a03 hyperledger/fabric-peer:latest "peer node start" 1 second ago Up Less than a second 0.0.0.0:7051->7051/tcp peer0.org1.example.com
e9af4c11538c cordite/network-map:latest "/usr/bin/java -cp /…" 5 days ago Exited (143) 3 days ago network-map
5128423bb8d7 redis:5.0 "docker-entrypoint.s…" 5 months ago Exited (0) 7 weeks ago redis
6796aadc5173 mysql "docker-entrypoint.s…" 7 months ago Exited (0) 7 weeks ago mysql
66c3ac55f920 neo4j "/sbin/tini -g -- /d…" 7 months ago Exited (0) 7 months ago

docker面板显示如下:

image-20201214185835819

Peers是Fabric network的组成部分,Peers存储区块链账本并在提交之前验证交易。Peers运行包含业务逻辑的智能合约,智能合约用于管理区块链上的账本。

在网络上的每个Peer都属于一个团体,上图显示的测试网络中的两个peer分别属于组织peer0.org1.example.com和组织peer0.org2.example.com

每个Fabric network同样包含ordering service,Peers在验证交易和提交交易到区块链的时候,他们不自己决定交易的顺序和区块中包含哪些交易。在分布式网络中,peers可能分布的特别远,所以让peers对交易顺序达成共识的成本是很高的。

ordering service的存在是为了让peers专注于交易验证和提交到账本中。在接收到客户端提交的交易时,ordering service会对其进行排序,然后把这些交易添加到区块中。然后将这些区块分发给peer节点,peer节点再把区块写入区块链。Ordering节点还运行系统通道,该通道定义了Fabric network的能力,像如何制作区块以及节点可以使用哪些版本的Fabric。系统通道还定义了哪些组织是属于该联盟的。

上面的测试网络只运行了一个Ordering节点,在实际的网络中可能存在多个Ordering节点,由一个或多个组织进行操作。不同的Ordering节点使用Raft共识算法来就网络上的交易顺序达成一致。

创建channel

通道是特定网络成员之间的专用通信层。通道只能由被邀请加入通道的的组织使用,并且对网络上的其他成员不可见。每个通道都有一个单独的区块链账单,被邀请的组织加入通道上的其他peer以存储channel账本和验证通道上的交易。

在org2和org2之间创建通道,默认的channel名称为mychannel。

1
./network.sh createChannel

如果运行成功,则会看到如下日志

1
Channel successfully joined

也可以指定channel的名称,并且你可以创建多个channel。

1
./network.sh createChannel -c channel1

如果你想一步启动测试网络并创建channel,可以使用下面的命令。

1
./network.sh up createChannel

在channel上启动chaincode

启动成功之后,就可以开始使用智能合约来操作channel账本了。智能合约包含了管理区块链账本上资产的业务逻辑。运行在网络上的程序可以调用智能合约在账本上创建、修改、交易资产,这些程序也查询智能合约以读取账本上的数据。

为了确保交易的有效性,使用智能合约创建的交易通常需要通道上的多个组织签名才能被提交到channel账本。交易也需要多次背书,来防止渠道上的某个组织篡改账本或使用未经过同意的逻辑。要签署交易,每个组织都需要在其peer上调用并执行智能合约,然后再签署交易的output。如果output一致并且收集到了足够的签名,交易就可以被提交到账本。指定需要哪些组织执行智能合约的策略叫做背书策略,该策略是为每个chaincode设置的,作为chaincode定义的一部分。

在Fabric中,智能合约以称为chaincode的软件包部署在网络上。chaincode安装在组织的peers上,然后部署到channel,然后就可以在该渠道中用于认可交易并与区块链账本进行交互。在讲chaincode部署到channel上之前,channel上的组织需要对chaincode的内容达成共识。当所需数量的组织达成共识之后,chaincode就可以被提交到channel上,然后chaincode就准备好可以使用了。

搭建完成测试环境之后,可以使用下面的命令来启动chaincode:

1
./network.sh deployCC

我本地的运行结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Chaincode definition committed on channel 'mychannel'
Using organization 1
Querying chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'mychannel'
Chaincode initialization is not required

与网络互动

在启用测试网络之后,你可以使用peerCLI与测试网络进行互动。peerCLI允许你调用已经部署的智能合约、更新channels;也可以通过CLI更新或者部署新的智能合约。

请确保你的操作在test-network目录下进行。

1、把fabric-samplesbin目录下的二进制命令安装到你的客户端环境:

1
export PATH=${PWD}/../bin:$PATH

2、还需要将FABRIC_CFG_PATH设置为指向fabric-samples存储库中的core.yaml文件:

1
export FABRIC_CFG_PATH=$PWD/../config/

3、现在设置环境变量允许你使用Org1的身份操作peerCLI。

1
2
3
4
5
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

4、使用下面的命令用资产初始化账本

1
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'

如果成功你会看到像下面的结果:

1
2020-12-16 15:35:41.511 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

5、现在你可以使用下面的命令查询账本上的资产

1
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'

如果成功你会看到下面的结果:

1
2
3
4
5
6
7
8
[
{"ID": "asset1", "color": "blue", "size": 5, "owner": "Tomoko", "appraisedValue": 300},
{"ID": "asset2", "color": "red", "size": 5, "owner": "Brad", "appraisedValue": 400},
{"ID": "asset3", "color": "green", "size": 10, "owner": "Jin Soo", "appraisedValue": 500},
{"ID": "asset4", "color": "yellow", "size": 10, "owner": "Max", "appraisedValue": 600},
{"ID": "asset5", "color": "black", "size": 15, "owner": "Adriana", "appraisedValue": 700},
{"ID": "asset6", "color": "white", "size": 15, "owner": "Michel", "appraisedValue": 800}
]

6、网络上的成员想要交易资产或者更新资产时就会调用chaincode,使用下面的命令来调用资产转移chaincode来更改资产的owner。

1
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"TransferAsset","Args":["asset6","Christopher"]}'

如果成功结果如下:

1
2020-12-16 15:43:18.062 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

重新查询可以发现asset6的owner已经更改。

1
2
3
4
5
6
7
[
{"ID":"asset1","color":"blue","size":5,"owner":"Tomoko","appraisedValue":300},
{"ID":"asset2","color":"red","size":5,"owner":"Brad","appraisedValue":400},{"ID":"asset3","color":"green","size":10,"owner":"Jin Soo","appraisedValue":500},
{"ID":"asset4","color":"yellow","size":10,"owner":"Max","appraisedValue":600},
{"ID":"asset5","color":"black","size":15,"owner":"Adriana","appraisedValue":700},
{"ID":"asset6","color":"white","size":15,"owner":"Christopher","appraisedValue":800}
]

7、我们在调用chaincode之后,我们来查一下这个调用是如何改变资产的。我们使用Org2来操作,配置环境变量如下:

1
2
3
4
5
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

执行peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'命令结果如下:

1
{"ID":"asset6","color":"white","size":15,"owner":"Christopher","appraisedValue":800}

中断网络

通过执行./network.sh down来中断网络,该命令会停止并删除peer河chaincode的容器;删除org的密钥等数据并从Docker中remove掉chaincode的镜像。该命令还会删除网路上的channel,如果有任何问题可以继续运行./network.sh up

问题处理

创建channel失败,日志如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Channel 'mychannel' created
Join Org1 peers to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=1
2020-12-21 11:22:02.781 CST [comm.tls] ClientHandshake -> ERRO 001 Client TLS handshake failed after 1.769196ms with error: EOF remoteaddress=[::1]:7051
2020-12-21 11:22:03.785 CST [comm.tls] ClientHandshake -> ERRO 002 Client TLS handshake failed after 2.054333ms with error: EOF remoteaddress=[::1]:7051
2020-12-21 11:22:05.113 CST [comm.tls] ClientHandshake -> ERRO 003 Client TLS handshake failed after 2.849348ms with error: EOF remoteaddress=[::1]:7051
Error: error getting endorser client for channel: endorser client failed to connect to localhost:7051: failed to create new connection: context deadline exceeded
After 5 attempts, peer0.org1 has failed to join channel 'mychannel'
Create channel failed

解决方案:

  • 删除所有的测试网络相关的容器
  • 运行./network.sh down
  • 删除docker本地未使用的volume
  • 重试