搭建一个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"]}'