搭建一个Fabric网络
注意:本文是我自己尝试本地搭建fabric的一个流程记录,可能对你没有意义
Table of Contents
1 安装编译
2 生成证书文件
2.1 生成证书配置文件目录
mkdir -p demo/crypto-dir
2.2 编辑证书配置文件
vim crypto-config.yaml
文件内容如下:
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
Template:
Count: 2
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
2.3 根据配置文件生成证书
cryptogen generate --config=crypto-config.yaml --output ./crypto-dir
2.4 查看生成的证书文件
-> tree crypto-dir/ -L 3
crypto-dir/
├── ordererOrganizations
│ └── example.com
│ ├── ca
│ ├── msp
│ ├── orderers
│ ├── tlsca
│ └── users
└── peerOrganizations
├── org1.example.com
│ ├── ca
│ ├── msp
│ ├── peers
│ ├── tlsca
│ └── users
└── org2.example.com
├── ca
├── msp
├── peers
├── tlsca
└── users
20 directories, 0 files
3 创始块生成
3.1 创建目录
mkdir order
3.2 编辑配置文件
vim configtx.yaml
文件内容如下
Profiles:
TwoOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-dir/ordererOrganizations/example.com/msp
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-dir/peerOrganizations/org1.example.com/msp
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-dir/peerOrganizations/org2.example.com/msp
AnchorPeers:
- Host: peer0.org2.example.com
Port: 7051
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Application: &ApplicationDefaults
Organizations:
3.3 根据配置文件生成初始Block
configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./order/order.genesis.block 2018-06-21 15:50:41.461 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-06-21 15:50:41.472 CST [msp] getMspConfig -> INFO 002 Loading NodeOUs 2018-06-21 15:50:41.472 CST [common/tools/configtxgen] doOutputBlock -> INFO 003 Generating genesis block 2018-06-21 15:50:41.473 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Writing genesis block
3.4 查看生成文件内容
tree order order └── order.genesis.block 0 directories, 1 file
3.5 创建channel
➜ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./order/alicetestchannel.tx -channelID alicetestchannel <CeateChannelTx ./order/alicetestchannel.tx -channelID alicetestchannel 2018-06-21 16:35:23.769 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-06-21 16:35:23.781 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx 2018-06-21 16:35:23.784 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs 2018-06-21 16:35:23.811 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx
3.6 创建两个锚点文件
1). 第一个锚节点 ➜ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./order/Org1MSPanchors.tx -channelID alicetestchannel -asOrg Org1MSP <chorPeersUpdate ./order/Org1MSPanchors.tx -channelID alicetestchannel -asOrg Org1MSP 2018-06-21 16:39:03.311 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-06-21 16:39:03.321 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2018-06-21 16:39:03.321 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update 2). 第二个锚节点 ➜ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./order/Org2MSPanchors.tx -channelID alicetestchannel -asOrg Org2MSP <chorPeersUpdate ./order/Org2MSPanchors.tx -channelID alicetestchannel -asOrg Org2MSP 2018-06-21 16:39:33.978 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration 2018-06-21 16:39:33.990 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2018-06-21 16:39:33.990 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
3.7 检查此时文件
➜ tree order tree order order ├── Org1MSPanchors.tx ├── Org2MSPanchors.tx ├── alicetestchannel.tx └── order.genesis.block 0 directories, 4 files
4 Order节点启动
4.1 编辑Order节点配置文件
vim orderer.yaml
文件内容如下:
参考 fabric/sampleconfig/orderer.yaml to demo/orderer.yaml
General:
LedgerType: file
ListenAddress: 0.0.0.0
ListenPort: 7050
TLS:
Enabled: false
PrivateKey: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
Certificate: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
RootCAs:
- ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
ClientAuthRequired: false
ClientRootCAs:
Keepalive:
ServerMinInterval: 60s
ServerInterval: 7200s
ServerTimeout: 20s
LogLevel: debug
LogFormat: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
GenesisMethod: file
GenesisProfile: TwoOrgsOrdererGenesis
GenesisFile: ./order/order.genesis.block
LocalMSPDir: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/msp
LocalMSPID: OrdererMSP
Profile:
Enabled: false
Address: 0.0.0.0:6060
BCCSP:
Default: SW
SW:
Hash: SHA2
Security: 256
FileKeyStore:
KeyStore:
Authentication:
TimeWindow: 15m
FileLedger:
Location: ./order/production/orderer
Prefix: hyperledger-fabric-ordererledger
RAMLedger:
HistorySize: 1000
Kafka:
Retry:
ShortInterval: 5s
ShortTotal: 10m
LongInterval: 5m
LongTotal: 12h
NetworkTimeouts:
DialTimeout: 10s
ReadTimeout: 10s
WriteTimeout: 10s
Metadata:
RetryBackoff: 250ms
RetryMax: 3
Producer:
RetryBackoff: 100ms
RetryMax: 3
Consumer:
RetryBackoff: 2s
Verbose: false
TLS:
Enabled: false
PrivateKey:
Certificate:
RootCAs:
Version:
Debug:
BroadcastTraceDir:
DeliverTraceDir:
4.2 启动Order节点
orderer start
5 Peer节点启动
5.1 创建Peer节点目录
mkdir peer
5.2 创建Peer节点配置文件
vim core.yaml
文件内容如下:
logging:
level: info
cauthdsl: warning
gossip: warning
grpc: error
ledger: info
msp: warning
policies: warning
peer:
gossip: warning
format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
peer:
id: peer0.org1.example.com
networkId: dev
listenAddress: 0.0.0.0:7051
chaincodeListenAddress: 0.0.0.0:7052
address: 0.0.0.0:7051
addressAutoDetect: false
gomaxprocs: -1
keepalive:
minInterval: 60s
client:
interval: 60s
timeout: 20s
deliveryClient:
interval: 60s
timeout: 20s
gossip:
bootstrap: 127.0.0.1:7051
useLeaderElection: true
orgLeader: false
endpoint:
maxBlockCountToStore: 100
maxPropagationBurstLatency: 10ms
maxPropagationBurstSize: 10
propagateIterations: 1
propagatePeerNum: 3
pullInterval: 4s
pullPeerNum: 3
requestStateInfoInterval: 4s
publishStateInfoInterval: 4s
stateInfoRetentionInterval:
publishCertPeriod: 10s
skipBlockVerification: false
dialTimeout: 3s
connTimeout: 2s
recvBuffSize: 20
sendBuffSize: 200
digestWaitTime: 1s
requestWaitTime: 1500ms
responseWaitTime: 2s
aliveTimeInterval: 5s
aliveExpirationTimeout: 25s
reconnectInterval: 25s
externalEndpoint:
election:
startupGracePeriod: 15s
membershipSampleInterval: 1s
leaderAliveThreshold: 10s
leaderElectionDuration: 5s
pvtData:
pullRetryThreshold: 60s
transientstoreMaxBlockRetention: 1000
pushAckTimeout: 3s
btlPullMargin: 10
events:
address: 0.0.0.0:7053
buffersize: 100
timeout: 10ms
timewindow: 15m
keepalive:
minInterval: 60s
tls:
enabled: false
clientAuthRequired: false
cert:
file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt
key:
file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key
rootcert:
file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
clientRootCAs:
files:
- tls/ca.crt
clientKey:
file:
clientCert:
file:
authentication:
timewindow: 15m
fileSystemPath: ./peer/production
BCCSP:
Default: SW
SW:
Hash: SHA2
Security: 256
FileKeyStore:
KeyStore:
PKCS11:
Library:
Label:
Pin:
Hash:
Security:
FileKeyStore:
KeyStore:
mspConfigPath: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp
localMspId: Org1MSP
client:
connTimeout: 3s
deliveryclient:
reconnectTotalTimeThreshold: 3600s
connTimeout: 3s
reConnectBackoffThreshold: 3600s
localMspType: bccsp
profile:
enabled: false
listenAddress: 0.0.0.0:6060
adminService:
handlers:
authFilters:
-
name: DefaultAuth
-
name: ExpirationCheck # This filter checks identity x509 certificate expiration
decorators:
-
name: DefaultDecorator
endorsers:
escc:
name: DefaultEndorsement
library:
validators:
vscc:
name: DefaultValidation
library:
validatorPoolSize:
discovery:
enabled: true
authCacheEnabled: true
authCacheMaxSize: 1000
authCachePurgeRetentionRatio: 0.75
orgMembersAllowedAccess: false
vm:
endpoint: unix:///var/run/docker.sock
docker:
tls:
enabled: false
ca:
file: docker/ca.crt
cert:
file: docker/tls.crt
key:
file: docker/tls.key
attachStdout: false
hostConfig:
NetworkMode: host
Dns:
# - 192.168.0.1
LogConfig:
Type: json-file
Config:
max-size: "50m"
max-file: "5"
Memory: 2147483648
chaincode:
id:
path:
name:
builder: $(DOCKER_NS)/fabric-ccenv:latest
pull: false
golang:
runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)
dynamicLink: false
car:
runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)
java:
Dockerfile: |
from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-1.1.0
node:
runtime: $(BASE_DOCKER_NS)/fabric-baseimage:$(ARCH)-$(BASE_VERSION)
startuptimeout: 300s
executetimeout: 30s
mode: net
keepalive: 0
system:
cscc: enable
lscc: enable
escc: enable
vscc: enable
qscc: enable
systemPlugins:
logging:
level: info
shim: warning
format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'
ledger:
blockchain:
state:
stateDatabase: goleveldb
couchDBConfig:
couchDBAddress: 127.0.0.1:5984
username:
password:
maxRetries: 3
maxRetriesOnStartup: 10
requestTimeout: 35s
queryLimit: 10000
maxBatchUpdateSize: 1000
warmIndexesAfterNBlocks: 1
history:
enableHistoryDatabase: true
metrics:
enabled: false
reporter: statsd
interval: 1s
statsdReporter:
address: 0.0.0.0:8125
flushInterval: 2s
flushBytes: 1432
promReporter:
listenAddress: 0.0.0.0:8080
5.3 启动Peer节点
# 设置环境变量为当前目录 export set FABRIC_CFG_PATH=/Users/nisen/fabric-dir/demo # 启动 peer node start
6 创建Channel
6.1 创建Channel
# 设置环境变量 ➜ export set CORE_PEER_LOCALMSPID=Org1MSP ➜ export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp # 应当运行: peer channel create -t 50 -o orderer.example.com:7050 -c alicetestchannel -f /Users/nisen/fabric-dir/demo/order/alicetestchannel.tx # 但因为都在本地部署,实际上没有域名,所以实际运行: peer channel create -t 50 -o 127.0.0.1:7050 -c alicetestchannel -f /Users/nisen/fabric-dir/demo/order/alicetestchannel.tx 2018-06-21 17:31:20.399 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-06-21 17:31:20.462 CST [channelCmd] InitCmdFactory -> INFO 002 Endorser and orderer connections initialized 2018-06-21 17:31:20.683 CST [main] main -> INFO 003 Exiting..... # 运行完后会在当前目录生成alicetestchannel.block
6.2 让已经运行的peer加入channel
➜ export set CORE_PEER_LOCALMSPID=Org1MSP ➜ export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp ➜ export set CORE_PEER_ADDRESS=peer0.org1.example.com:7051 ➜ peer channel join -b ./alicetestchannel.block Error: Error getting endorser client channel: endorser client failed to connect to peer0.org1.example.com:7051: failed to create new connection: context deadline exceeded 域名不可用,修改为 ➜ export set CORE_PEER_ADDRESS=localhost:7051 ➜ peer channel join -b ./alicetestchannel.block 2018-06-21 17:36:02.053 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-06-21 17:36:02.106 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel 2018-06-21 17:36:02.106 CST [main] main -> INFO 003 Exiting.....
6.3 更新锚节点peer
➜ export set CORE_PEER_LOCALMSPID=Org1MSP ➜ export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp ➜ export set CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # 域名不可用,需要修改 ➜ peer channel update -o localhost:7050 -c alicetestchannel -f ./order/Org1MSPanchors.tx 2018-06-21 17:39:03.820 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized 2018-06-21 17:39:03.884 CST [channelCmd] update -> INFO 002 Successfully submitted channel update 2018-06-21 17:39:03.885 CST [main] main -> INFO 003 Exiting.....
7 部署chancode
7.1 显示peer所加入的channel
➜ peer channel list 2018-06-21 17:40:16.125 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized Channels peers has joined: alicetestchannel 2018-06-21 17:40:16.132 CST [main] main -> INFO 002 Exiting.....
7.2 部署chancode
➜ peer chaincode install -n examplechaincode -v 1.1 -p simpledemo 2018-06-21 17:49:58.103 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc 2018-06-21 17:49:58.103 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc 2018-06-21 17:49:59.043 CST [main] main -> INFO 003 Exiting.....
7.3 实例化chaincode
➜ peer chaincode instantiate -o localhost:7050 -C \
alicetestchannel -n examplechaincode -v 1.1 -c '{"Args":["init","a","100","b","200"]}' \
-P "OR ('Org1MSP.member','Org2MSP.member')"
2018-06-21 17:52:25.318 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-06-21 17:52:25.318 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-06-21 17:52:48.665 CST [main] main -> INFO 003 Exiting.....
7.4 查看运行的容器
➜ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 47d28c47b6eb dev-peer0.org1.example.com-examplechaincode-1.1-d2b990146ffe74fcdfcdc76dbb4ad69ae46eb0a557d438972c6b66673ce3517e "chaincode -peer.add…" 9 seconds ago Up 8 seconds dev-peer0.org1.example.com-examplechaincode-1.1
7.5 调用chaincode
➜ peer chaincode invoke -o localhost:7050 -C alicetestchannel -n examplechaincode -c '{"Args":["invoke","a","b","1"]}'