Fabric2.2.1从零开始搭建网络(非脚本)
1. 生成证书
- 这里使用
cryptogen
工具来生成证书文件
cryptogen showtemplate > crypto-template.yaml # 生成一份模板证书配置文件
- 生成的内容去掉英文注释后大概如下
OrdererOrgs: # orderer组织的配置
- Name: Orderer # 组织名称
Domain: example.com # 组织的域名
EnableNodeOUs: true # 设置了EnableNodeOUs,会在map下生成config.yaml文件
Specs:
- Hostname: orderer # 生成的证书文件会以{{Hostname}}.{{Domain}}呈现 当前的文件名就是
SANS:
- localhost # orderer.example.com
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
# template根据count来生成指定份数的证书文件
# 我的理解是给当前这个组织中的节点生成证书文件
# 例如一个组织中有3个节点那么这个count就是3
Template:
Count: 1
SANS:
- localhost
# Start: 5 指定生成的节点从几开始,不指定就从0开始 peer0.org1.example.com
Users: # 组织中除了Admin之外还需要生成多少个用户,数量由count决定
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 1
SANS:
- localhost
Users:
Count: 1
- 根据配置生成证书
注意:这里的SANS一定要填节点真实的地址,不然会导致后面加入通道加入不进去
cryptogen generate --config=./crypto-template.yaml --output=organizations
2. 生成创世区块
- 生成创世区块也需要一份配置文件
configtx.yaml
我这里直接复制了test-network/configtx/configtx.yaml
下面的
Organizations:
- &OrdererOrg
Name: OrdererOrg # 组织名称
ID: OrdererMSP # 组织id 用来引用组织
MSPDir: organizations/ordererOrganizations/example.com/msp # 组织的msp文件目录
Policies: # 定义组织的一些策略
Readers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Writers:
Type: Signature
Rule: "OR('OrdererMSP.member')"
Admins:
Type: Signature
Rule: "OR('OrdererMSP.admin')"
OrdererEndpoints:
- orderer.example.com:7050
- &Org1
Name: Org1
ID: Org1MSP
MSPDir: organizations/peerOrganizations/org1.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org1MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org1MSP.peer')"
AnchorPeers: # 定义组织的锚节点
- Host: peer0.org1.example.com # 锚节点的host地址
Port: 7051 # 锚节点开放的端口号地址
- &Org2
Name: Org2
ID: Org2MSP
MSPDir: organizations/peerOrganizations/org2.example.com/msp
Policies:
Readers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"
Writers:
Type: Signature
Rule: "OR('Org2MSP.admin', 'Org2MSP.client')"
Admins:
Type: Signature
Rule: "OR('Org2MSP.admin')"
Endorsement:
Type: Signature
Rule: "OR('Org2MSP.peer')"
AnchorPeers:
- Host: peer0.org2.example.com
Port: 9051
# fabric网络的能力配置部分
Capabilities:
Channel: &ChannelCapabilities # Channel配置同时应用于orderer和peer
V2_0: true
Orderer: &OrdererCapabilities # Orderer仅使用于orderer,无需担心升级peer
V2_0: true
Application: &ApplicationCapabilities # Application仅使用于Peer,无需担心升级Orderer
V2_0: true
# Application配置用来定义要写入创世区块或配置交易的应用参数
Application: &ApplicationDefaults
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
LifecycleEndorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
Endorsement:
Type: ImplicitMeta
Rule: "MAJORITY Endorsement"
# Capabilities配置描述应用层级的能力需求
# 这里引用了 前面定义的 &ApplicationCapabilities 锚点 也就是Application的值放在这
Capabilities:
<<: *ApplicationCapabilities
# Orderer配置用来定义要编码写入创世区块或通道交易的排序节点参数
Orderer: &OrdererDefaults
OrdererType: etcdraft # 排序节点的类型 目前有 solo kafka EtcdRaft , 不同的类型对应不同的共识算法的实现
Addresses: # orderer 服务的地址
- orderer.example.com:7050
EtcdRaft: # EtcdRaft排序类型的配置
Consenters:
- Host: orderer.example.com
Port: 7050
ClientTLSCert: organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
ServerTLSCert: organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
BatchTimeout: 1s # 区块打包的时间,到了这个时间就打包区块
BatchSize: # 区块打包的最大包含交易数
MaxMessageCount: 10 # 一个区块里最大的交易数
AbsoluteMaxBytes: 99 MB # 一个区块的最大字节数,任何时候都不能超过
PreferredMaxBytes: 512 KB # 一个区块的建议字节数 # 这里的配置好像没有作用目前我也不知道是啥情况
Organizations:
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
BlockValidation:
Type: ImplicitMeta
Rule: "ANY Writers"
# Channel配置用来定义要写入创世区块或配置交易的通道参数
Channel: &ChannelDefaults
Policies:
Readers:
Type: ImplicitMeta
Rule: "ANY Readers"
Writers:
Type: ImplicitMeta
Rule: "ANY Writers"
Admins:
Type: ImplicitMeta
Rule: "MAJORITY Admins"
Capabilities:
<<: *ChannelCapabilities
# Profiles配置用来定义用于configtxgen工具生成创世区块或配置块的一些配置信息
Profiles:
TwoOrgsOrdererGenesis: # TwoOrgsOrdererGenesis用来生成orderer启动时所需的block,用于生成创世区块
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
# 这里定义了一个联盟
SampleConsortium:
Organizations:
- *Org1
- *Org2
# TwoOrgsChannel用来生成channel配置信息
TwoOrgsChannel:
Consortium: SampleConsortium # 引用上面定义的联盟
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
- 弄好配置文件之后就可以使用
configtxgen
工具来生成创世区块了
configtxgen -configPath ./ -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
选项 | 值 |
---|---|
profile | 在配置文件中配置的Profile |
configPath | configtx.yaml 的文件夹路径注意这里是文件夹的路径而不是具体的文件的路径 |
channeID | system-channel 这是fabric的一个默认的通道 |
outputBlock | 要写入创世块的路径,包含文件名 |
3. 启动网络
- 网络的配置如下需要和
configtx.yaml
中配置的对应
version: '2'
volumes:
orderer.example.com:
peer0.org1.example.com:
peer0.org2.example.com:
networks:
test:
services:
orderer.example.com:
container_name: orderer.example.com
image: hyperledger/fabric-orderer:latest
environment:
- FABRIC_LOGGING_SPEC=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # 监听地址
- ORDERER_GENERAL_LISTENPORT=7050 # 监听端口号
- ORDERER_GENERAL_GENESISMETHOD=file # 指定账本类型(可选file、RAM、json三种)
- ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block # 生成初始区块的配置文件
- ORDERER_GENERAL_LOCALMSPID=OrdererMSP
- ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
# enabled TLS
- ORDERER_GENERAL_TLS_ENABLED=true
- ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key # 签名的私钥文件
- ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt # 证书文件
- ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt] # 可信任的根CA证书
- ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
- ORDERER_KAFKA_VERBOSE=true
- ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
working_dir: /opt/gopath/src/github.com/hyperledger/fabric
command: orderer
volumes:
- ./system-genesis-block/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ./organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
- ./organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
- orderer.example.com:/var/hyperledger/production/orderer
ports:
- 7050:7050
networks:
- test
peer0.org1.example.com:
container_name: peer0.org1.example.com
image: hyperledger/fabric-peer:latest
environment:
# Generic peer variables
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # vm管理系统的端点
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-network_test
- FABRIC_LOGGING_SPEC=INFO
#- FABRIC_LOGGING_SPEC=DEBUG
# TLS设置
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
# Peer specific variabes
- CORE_PEER_ID=peer0.org1.example.com # 指定节点ID
- CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # 节点对外的服务地址
- CORE_PEER_LISTENADDRESS=0.0.0.0:7051 # 侦听本地网络接口上的地址。
- CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052 # 如果没有指定chaincodeListenAddress,则从其中选择address
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 # 侦听入站链码连接的端点。
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 # 启动后的初始节点
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 # 组织外的端点
- CORE_PEER_LOCALMSPID=Org1MSP
volumes:
- /var/run/:/host/var/run/
- ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
- ./organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
- peer0.org1.example.com:/var/hyperledger/production
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
ports:
- 7051:7051
networks:
- test
peer0.org2.example.com:
container_name: peer0.org2.example.com
image: hyperledger/fabric-peer:latest
environment:
#Generic peer variables
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
# the following setting starts chaincode containers on the same
# bridge network as the peers
# https://docs.docker.com/compose/networking/
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=my-network_test
- FABRIC_LOGGING_SPEC=INFO
#- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_PROFILE_ENABLED=true
- CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
- CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
- CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
# Peer specific variabes
- CORE_PEER_ID=peer0.org2.example.com
- CORE_PEER_ADDRESS=peer0.org2.example.com:9051
- CORE_PEER_LISTENADDRESS=0.0.0.0:9051
- CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
- CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
- CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
- CORE_PEER_LOCALMSPID=Org2MSP
volumes:
- /var/run/:/host/var/run/
- ./organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
- ./organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
- peer0.org2.example.com:/var/hyperledger/production
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
command: peer node start
ports:
- 9051:9051
networks:
- test
- 启动网络
这里需要注意CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE需要设置当前docker网络名称默认是 当前文件夹名称_test
docker-compose -f {{你的文件名}} up -d
4. 生成通道和锚节点更新交易配置
- 使用
configtxgen
不仅可以生成创建创世区块还可以生成一些交易的配置,他们的关系如下
- 生成通道交易配置
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputCreateChannelTx ./channel-artifacts/mychannel.tx
- 生成两个组织的锚节点更新交易配置
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -asOrg Org1
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -asOrg Org2
## 这里的 -asOrg 的值是configtx中配置的组织的Name
5. 创建通道加入组织并更新锚节点
- 先配置组织身份环境变量
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_ADDRESS=localhost:7051
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_TLS_ENABLED=true
- 使用我们之前生成的通道交易配置来创建通道
证书的路径需要配置绝对路径使用相对路径会读不到
peer channel create -o localhost:7050 -c mychannel --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/mychannel.tx --outputBlock ./channel-artifacts/mychannel.block --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
- Org1加入通道并更新锚节点
peer channel join -b ./channel-artifacts/mychannel.block
peer channel update -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
- Org2加入通道并更新锚节点
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_ADDRESS=localhost:9051
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_TLS_ENABLED=true
peer channel join -b ./channel-artifacts/mychannel.block
peer channel update -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
6. 安装链码测试
1. 打包链码 这里以fabric的asset-transfer-basic/chaincode-go 为例子
peer lifecycle chaincode package basic.tar.gz --path ./chaincode-go --lang golang --label basic_1
2. Org1和Org2安装链码
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_ADDRESS=localhost:7051
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_TLS_ENABLED=true
peer lifecycle chaincode install basic.tar.gz
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_ADDRESS=localhost:9051
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_TLS_ENABLED=true
peer lifecycle chaincode install basic.tar.gz
3. 审议链码定义
先获取链码的package_id
peer lifecycle chaincode queryinstalled
# 这串就是packageid每个人都不一样的
# basic_1:d612c5afb52543307c8d75b79da3de6b3b8d2f984e005a92db9528d0d9176f7d
用Org1和Org2的身份执行下面的命令来审议链码定义 环境变量在上面
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id Package ID: {{你的packageId}} --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
可以使用checkcommitreadiness
来查询链码审议情况通道中大部分的组织同意即可提交
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json
4. 提交链码定义
使用一个组织身份提交即可
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --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
使用querycommitted
可以查询当前通道中提交的链码
peer lifecycle chaincode querycommitted -C mychannel
5. 调用链码
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --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":[]}'
查询链码
peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'
如果能够查到初始化的数据,那么恭喜你网络搭建成功了!