超级账本底层文件学习
通道交易信息和创世块准备完毕后就可以启动区块链网络
docker-compose -f docker-compose-cli.yaml up -d
超级账本网络的创建主要包含四个步骤:
- 创建网络拓扑结构,创建MSP相关资料并签名
- 创建通道配置信息
- 启动网络,并创建通道
- 安装并实例化链码
创建网络拓扑结构,初始化MSP信息并签名
工具cryptogen用来创建网络的拓扑结构,初始化MSP信息,并对所有组织和节点进行签名。
cryptogen位于fabric/build/bin目录下,它使用了crypto-config.yaml作为配置文件,使用==[cryptogen showtemplate]==查看配置文件模板实际上,示例代码的crypto-config.yaml就是基于这个模板修改的。具体的配置方法参加模板说明。示例配置文件生产力如下所在的拓扑网络:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lEbM9R8E-1624008602430)(C:\Users\hp\AppData\Roaming\Typora\typora-user-images\image-20210421160713484.png)]
如果,包含了两种类型的组织:OrdererOrgs和PeerOrgs。一个Orderer组织下面有一个节点;而Peers有两个组织,每个组织通过Template创建了两个Peers。因此,根据该配置文件,cryptogen将会生成5个节点:
- orderer.example.com
- peer0.org1.example.com
- peer1.org1.example.com
- peer0.org2.example.com
- peer1.org2.example.com
../../fabric/build/bin/cryptogen generate --config=./crypto-config.yaml
命令将会在在当前目录下生成crypto-config目录。使用命令[tree crypto-config]命令可以查看目录的整体结构。简单的说,cryptogen完成了以下工作:
- 为每个组织生成了签名,包括orderer组织和peer组织。
- 为每个组织生成了MSP信息,包括orderer组织和peer组织。
- 为组织内的每个成员生成了签名。
- 为每个组织定了用一个管理员和一个用户。
至此,网络的拓扑结构生成完毕。MSP模块将使用这些内容对节点进行安全管理和认证。
创建通道配置信息
通道配置信息包括三个方面的内容:创世区块、通道配置信息和各个组织的Anchor Peer
。使用configtxgen来完成通道配置信息的创建。可以使用[configtxgen --help]查看工具的使用方法,和cryptogen不同,configtxgen指定使用configtx.yaml。
- configtx.yaml主要定义了两个profile:TwoOrgsOrdererGenesis和TwoOrgsChannel。cryptogen
- TwoOrgsOrdererGenesis主要用于Orderer节点的定义;
Organizations
- TwoOrgsChannel主要用于Peer节点的定义。
Channel
- 每个profile都定义了capability和组织的内部信息;
- 组织信息都包括Name(节点名字);ID(用来标识该节点);MSPDir(指定msp信息地址,有上面cryptogen工具生成)。
对于Peer节点,还需要定义Anchor Peer的信息。
export CHANNEL_NAME=shimzhaochnl
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
使用了TwoOrgsChannel的profile,生成了名外shimzhaochnl的通道。通道配置信息保存在了channel.tx文件中。
配置Anchor Peer
Anchor Peer是一个组织内负责与其他组织打交道的门户节点,通常情况它也是背书节点。一个组织可以有多个节点加入到区块链网络,但是必须有至少一个Anchor Peer。Anchor Peer的配置可以使用下面的命令完成:
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
项目中的命名为:
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
由于Anchor Peer定义在TwoOrgsChannelprofile中,上面分别的命令用到了TwoOrgsChannel profile。上面分别为Org1MSP和OrgMSP定义了Anchor Peer。
通道配置信息创建完毕。生成的文件保存在了当前目录的[channel-artifacts]下面。可以使用下面的命令查看创建的区块信息:
../../fabric/build/bin/configtxgen -inspectBlock ./channel-artifacts/genesis.block
查看通道信息
../../fabric/build/bin/configtxgen -inspectChannelCreateTx ./channel-artifacts/channel.tx
查看组织信息
../../fabric/build/bin/configtxgen -printOrg Org1MSP
启动网络,创建通道
通道交易信息和创世块准备完毕后就可以启动区块链网络了。在这里我们使用docker-compose-cli.yaml文件启动网络:
docker-compose -f docker-compose-cli.yaml up -d
网络启动后我们还需要创建通道、加入通道、更新通道的Anchor Peer配置。
创建通道
创建通道以前我们需要进入到cli节点,cli相当于超级账本的一个application,每次在操作peer的时候它都会去读取下面的环境变量以确定要操作哪一个Peer。cli是通过读取下面的配置文件来确定它连接的是哪个Peer节点。当操作的Peer发送变化的时候都需要重新备注这些环境变量,以确保操作的是正确的Peer节点。这些环境变量包括:
- CORE_PEER_MSPCONFIGPATH:用来指定MSP信息路径,有cryptogen生成
- CORE_PEER_ADDRESS:用来指定节点的网络地址
- CORE_PEER_TLS_ROOTCERT_FILE:用来指定数字签名文件路径
- CORE_PEER_LOCALMSPID:用来指定组织MSPID
因此,首先我们要指定peer0.org1.example.com节点作为cli的连接节点,然后进入cli docker:
vagrant@ubuntu-xenial: first-network$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
vagrant@ubuntu-xenial: first-network$ export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
vagrant@ubuntu-xenial: first-network$ export CORE_PEER_LOCALMSPID="Org1MSP"
vagrant@ubuntu-xenial: first-network$ export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
vagrant@ubuntu-xenial: first-network$ docker exec -it cli bash
root@bfe07b081e03:/opt/gopath/src/github.com/hyperledger/fabric/peer#
注意,接下来我们的操作就会在cli docker内部进行了。为了使用方便,先定义一个全局变量:
root@bfe07b081e03:/opt/gopath/src/github.com/hyperledger/fabric/peer#export CHANNEL_NAME=shimzhaochnl
root@bfe07b081e03:/opt/gopath/src/github.com/hyperledger/fabric/peer#peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
需要说明的是,创建通道本身也是超级账本的一个交易,因此首先交易信息会被发送到Orderder排序节点,Orderer排序服务会将交易信息广播到整个网络的所有节点。上面的命令中指定的channel.tx来自configtxgen创建的通道配置信息;而公钥则是排序节点的公钥。
通道创建完成后我们还需要将每个Peer节点加入到通道中。
加入通道需要借助cli容器。比如下面的操作允许我们将peer0.org1.example.com加入到通道:
#设置环境变量
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#下面的代码在容器内执行,将当期Peer加入通道
peer channel join -b shimzhaochnl.block #注意通道名
#退出
依次将其余的三个Peer都加入到通道中。可以使用[peer channel list]查看当前Peer加入了哪些通道。
制定每个Org的Anchor Peer。这个过程也是通过cli容器来实现的:
#设置环境变量
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#设置当前连接的Peer为组织的Anchor Peer
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
#退出
通过上面的命令设置了peer0.org1.example.com为Org1的Anchor Peer。可以使用同样的方法设置peer0.Org2.example.com为Org2的Anchor Peer。
在进入容器[docker exec -it cli bash]后,可以使用peer命令查看当前链接节点的各种信息。参看[peer --help]了解更多。
安装并实例化链码
链码(即智能合约)是超级账本的重要组成部分。所有的外部程序(application)对账本的访问都是通过链码实现的。对链码的操作包括安装、实例化、查询和更新。
安装链码
链码的安装也需要进入到cli容易,连接到需要安装的Peer节点,然后执行安装命令。下面的命令用于为peer0.org1.example.com安装链码:
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#为当前Peer安装链码
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
#退出
exit
链码安装完成后可以使用[peer chaincode list --installed]的命令查看是否已经安装成功。接下来,还需要为其它Peer安装链码,通常我们只需要为Anchor Peer安装链码即可。
实例化链码
链码在安装完成后还需要实例化才能起作用,可以使用下面的方法实例化链码:
#设置环境变量
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#实例化链码
peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
#退出
exit
需要注意的是:
[-p]参数用来指定背书策略。比如[-P “OR(‘Org1MSP.peer’,‘Org2MSP.peer’)”]只需要一个节点背书即可;而[-P “AND(‘Org1MSP.peer’,‘Org2MSP.peer’)”]则需要两个节点都背书才可以。
链码的实例化主要是给超级账本的区块付初值。
链码的实例化只需要在任意一个节点完成即可。不需要所有节点都实例化。
查询链码
链码的查询首先需要制定Peer,然后进入cli,再执行查询语句:
#设置环境变量
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#设置通道名
export CHANNEL_NAME=shimzhaochnl
#调用链码查询
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
#退出
exit
更新链码
同理,链码的更新操作类似如下:
#设置环境变量
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#设置通道名
export CHANNEL_NAME=shimzhaochnl
#调用链码更新账本
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
#退出
exit
逻辑上来说,所有Peer保存的账本应该是一致的。可以通过切换Peer来验证所有账本是不是同步更新了。
ub.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -c ‘{“Args”:[“invoke”,“a”,“b”,“10”]}’
#退出
exit
逻辑上来说,所有Peer保存的账本应该是一致的。可以通过切换Peer来验证所有账本是不是同步更新了。