Build a stand-alone fabric1 based on Raft consensus 4 network environment
During this period, the fabric community has been updated to version 2.3, but most of the companies using fabric business still use fabric 1 Version 4. The purpose of writing this blog is to supplement the tool articles built by fabric.
1. Introduction to preparations for building fabric network environment
Fabric1 4. In the network environment, three orderer nodes are to be built to form a sequential consensus organization orderer; There are two organizations Org1 and Org2, in which each organization contains two peer nodes, as well as client nodes, couchdb, etc. see Table 1.1 for details:
fabric1.4 network nodes |
---|
orderer.example.com |
orderer1.example.com |
orderer2.example.com |
peer0.org1.example.com |
peer1.org1.example.com |
peer0.org2.example.com |
peer1.org2.example.com |
cli |
couchdb |
First, set up the environment configuration of the host machine of the fabric network, including installing go language, installing docker, docker compose, etc. the specific installation steps are as follows:
- Execute the command wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz Download the go binary source package.
- Execute the command tar -zxvf go1 11.linux-amd64. tar. GZ - C / usr / local / unzip.
- Execute the command mkdir $HOME/code/go -p to create the project directory of go.
- Execute the command VIM in the home directory Bashrc, and fill in the environment variable of go language at the end of the file, that is, add the configuration in the following code block to the end of the file.
export GOROOT="/usr/local/go" export GOPATH="$HOME/code/go" export GOBIN="$HOME/code/go/bin" export PATH="$PATH:$GOROOT/bin:$GOPATH/bin"
- Execute the command source Bashrc to make the newly configured environment variable take effect.
- Execute the command go version to view the version of the current go language.
- Execute the command go env to view the configuration environment of the current go language.
- Check whether there is a in the home directory of the current host PIP directory, if not, execute the command MKDIR PIP and execute the command VIM pip Conf, write the contents of the following code block to PIP Conf file.
[global] index-url=http://mirrors.aliyun.com/pypi/simple/ [install] trusted-host=mirrors.aliyun.com
- Execute the command PIP install docker compose to install docker compose (docker orchestration tool).
- Execute the command docker compose version to view the currently installed version of docker compose tool.
- Execute the command apt get install docker IO to install docker. If an error is reported, the docker cannot be located IO, execute the command apt get update first, and then install docker
- Execute the command CD $gopath / SRC / GitHub COM / hyperledger enters the specified directory. The directory path is related to the binary source code tool pulled later. If the path is wrong, the binary tool pull will fail. Execute the command git clone https://github.com/hyperledger/fabric.git , pull down the fabric source code. If there is no git command in the host, download it by executing apt get install GIT.
- Execute the command git clone https://github.com/hyperledger/fabric-samples.git Pull down fabric samples. Here are some official examples and fabric environment configurations in various modes.
- Execute the command CD fabric samples / scripts, enter the scripts directory, and modify bootstrap The image version in SH is 1.4.0 - > 1.4.1, 0.4.14 - > 0.4.15. Building a fabric network under raft requires the latest docker image version. If the version is not new enough, the container will exit. For example, the order container will fail to recognize the etcdraft consensus.
- Execute bootstrap The SH script is mainly used to pull the binary toolkit and the latest docker image. After the script is executed, the binary tools will be in the fabric samples / bin directory. You only need to execute the cp cryptogen configtxlator configtxgen /usr/local/bin command to use the tools globally.
- If bootstrap cannot be executed successfully For the SH script, you need to pull the binary source code tool and docker image in two steps. First, for the binary tool, you can first enter the / fabric directory and execute git checkout - B v1 4.1, go to the current fabric source code branch v1 4.1. Execute make release to pull the binary source code tool. After execution, there will be a downloaded binary source code tool in the directory of fabric/release/linux-amd64/bin, and then execute the command CP cryptogen configtxgen configurator / usr / local / bin to set the tool to be used by the whole Bureau.
- In addition, the latest image of docker can be pulled by shell script to execute the command vim docker_images.sh, fill in the following code block into the file, and then execute chmod +x docker_images.sh adds execution permission to the script file, and finally executes/ docker_images.sh will fabric1 4. Pull down the matched docker image.
#!/bin/bash docker pull hyperledger/fabric-ca:1.4.1 docker tag hyperledger/fabric-ca:1.4.1 hyperledger/fabric-ca:latest docker pull hyperledger/fabric-tools:1.4.1 docker tag hyperledger/fabric-tools:1.4.1 hyperledger/fabric-tools:latest docker pull hyperledger/fabric-ccenv:1.4.1 docker tag hyperledger/fabric-ccenv:1.4.1 hyperledger/fabric-ccenv:latest docker pull hyperledger/fabric-orderer:1.4.1 docker tag hyperledger/fabric-orderer:1.4.1 hyperledger/fabric-orderer:latest docker pull hyperledger/fabric-peer:1.4.1 docker tag hyperledger/fabric-peer:1.4.1 hyperledger/fabric-peer:latest docker pull hyperledger/fabric-javaenv:1.4.1 docker tag hyperledger/fabric-javaenv:1.4.1 hyperledger/fabric-javaenv:latest docker pull hyperledger/fabric-zookeeper:0.4.15 docker tag hyperledger/fabric-zookeeper:0.4.15 hyperledger/fabric-zookeeper:latest docker pull hyperledger/fabric-kafka:0.4.15 docker tag hyperledger/fabric-kafka:0.4.15 hyperledger/fabric-kafka:latest docker pull hyperledger/fabric-couchdb:0.4.15 docker tag hyperledger/fabric-couchdb:0.4.15 hyperledger/fabric-couchdb:latest docker pull hyperledger/fabric-baseos:0.4.15 docker tag hyperledger/fabric-baseos:0.4.15 hyperledger/fabric-baseos:latest
Here, we have completed the construction of the fabric network host environment. Now we go to the fabric network configuration section.
2. Multi machine fabric network deployment based on Raft consensus
This section is to configure each node in the fabric network, which mainly involves the node certificate, channel file, creation block file and dock er configuration file of each node in the fabric.
- In the home directory or create the root directory of the fabric network project, execute MKDIR raft example.
- Enter the root directory just created and create the static configuration file crypto config. Required to generate the certificates of each node of the fabric network Yaml, this file can be copied in fabric samples, or execute the command VI crypto config Yaml creates the file and copies the contents of the following code block into the file.
OrdererOrgs: - Name: Orderer Domain: example.com Specs: - Hostname: orderer - Hostname: orderer1 - Hostname: orderer2 PeerOrgs: - Name: Org1 Domain: org1.example.com EnableNodeOUs: true Template: Count: 2 Users: Count: 2 - Name: Org2 Domain: org2.example.com EnableNodeOUs: true Template: Count: 2 Users: Count: 2
- Execute the command cryptogen generate -- config/ crypto-config. Yaml generates certificates for each node in the current directory.
- Next, configure the static configuration file configtx Yaml, this file can be copied in farbic samples, or execute the command VI configtx Yaml and fill in the following code blocks into the file.
--- Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: crypto-config/ordererOrganizations/example.com/msp Policies: Readers: Type: Signature Rule: "OR('OrdererMSP.member')" Writers: Type: Signature Rule: "OR('OrdererMSP.member')" Admins: Type: Signature Rule: "OR('OrdererMSP.admin')" - &Org1 Name: Org1MSP ID: Org1MSP MSPDir: crypto-config/peerOrganizations/org1.example.com/msp AnchorPeers: - Host: peer0.org1.example.com Port: 7051 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')" - &Org2 Name: Org2MSP ID: Org2MSP MSPDir: crypto-config/peerOrganizations/org2.example.com/msp AnchorPeers: - Host: peer0.org2.example.com Port: 9051 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')" Capabilities: Channel: &ChannelCapabilities V1_3: true Orderer: &OrdererCapabilities V1_1: true Application: &ApplicationCapabilities V1_3: true V1_2: false V1_1: false Application: &ApplicationDefaults Organizations: Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" Capabilities: <<: *ApplicationCapabilities Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer.example.com:7050 BatchTimeout: 2s BatchSize: MaxMessageCount: 200 AbsoluteMaxBytes: 2 MB PreferredMaxBytes: 512 KB Kafka: Brokers: - 127.0.0.1:9092 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: &ChannelDefaults Policies: Readers: Type: ImplicitMeta Rule: "ANY Readers" Writers: Type: ImplicitMeta Rule: "ANY Writers" Admins: Type: ImplicitMeta Rule: "MAJORITY Admins" Capabilities: <<: *ChannelCapabilities Profiles: TwoOrgsOrdererGenesis: <<: *ChannelDefaults Capabilities: <<: *ChannelCapabilities Orderer: <<: *OrdererDefaults OrdererType: etcdraft EtcdRaft: Consenters: - Host: orderer.example.com Port: 7050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt - Host: orderer1.example.com Port: 8050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt - Host: orderer2.example.com Port: 9050 ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt Addresses: - orderer0.example.com:7050 - orderer1.example.com:8050 - orderer2.example.com:9050 Organizations: - *OrdererOrg Capabilities: <<: *OrdererCapabilities Application: <<: *ApplicationDefaults Organizations: - <<: *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2 TwoOrgsChannel: Consortium: SampleConsortium <<: *ChannelDefaults Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2 Capabilities: <<: *ApplicationCapabilities
- Next, you need to create a directory to place channel files, creation block files, etc. execute the command MKDIR channel artifacts to create a folder.
- Generate the creation block file and execute the command configtxgen - profile twoorgorderergenesis - channelid systemchannel - outputblock/ channel-artifacts/genesis. Block generates the creation block of the system file.
- Generate the application channel file and execute the command configtxgen - profile twoorgschannel - outputcreatechanneltx/ channel-artifacts/channel. TX - channelid testchnel generates a channel file for creating an application channel.
- Generate the anchor node file of Org1 and execute the command configtxgen - profile twoorgschannel - outputanchorpeersupdate/ channel-artifacts/Org1MSPanchors. TX - channelid appchannel - asorg org1msp, generate Org1 to update the anchor node.
- Generate the anchor node file of Org2 and execute the command configtxgen - profile twoorgschannel - outputanchorpeersupdate/ channel-artifacts/Org2MSPanchors. TX - channelid appchannel - asorg org2msp, generate Org2 to update the anchor node.
- Next, you need to configure the docker configuration file of the orderer organization. This part will configure the configuration of the three orderer nodes under the orderer organization. Here, you need to configure two files. First, the first file is docker compose orderer Yaml, configure the non-public configuration of three orderer nodes here, and execute VI docker compose orderer Yaml and copy the contents of the following code block to a file.
version: '2' volumes: orderer1.example.com: orderer2.example.com: orderer.example.com: networks: byfn: services: orderer1.example.com: extends: file: base/orderer-base.yaml service: orderer-base environment: - ORDERER_GENERAL_LISTENPORT=8050 container_name: orderer1.example.com networks: - byfn volumes: - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/var/hyperledger/orderer/msp - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/:/var/hyperledger/orderer/tls - orderer1.example.com:/var/hyperledger/production/orderer ports: - 8050:8050 orderer2.example.com: extends: file: base/orderer-base.yaml service: orderer-base environment: - ORDERER_GENERAL_LISTENPORT=9050 container_name: orderer2.example.com networks: - byfn volumes: - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/var/hyperledger/orderer/msp - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/:/var/hyperledger/orderer/tls - orderer2.example.com:/var/hyperledger/production/orderer ports: - 9050:9050 orderer.example.com: extends: file: base/orderer-base.yaml service: orderer-base environment: - ORDERER_GENERAL_LISTENPORT=7050 container_name: orderer.example.com networks: - byfn volumes: - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls - orderer.example.com:/var/hyperledger/production/orderer ports: - 7050:7050
- The second file to configure orderer is orderer base Yaml, the public configuration of the orderer node is placed here. Because it belongs to the public basic configuration, it is recommended to create a base folder under the root directory raft example and execute the command VI orderer base Yaml and copy the contents of the following code block into the file.
version: '2' services: orderer-base: image: hyperledger/fabric-orderer:latest environment: - FABRIC_LOGGING_SPEC=INFO - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 - ORDERER_GENERAL_BOOTSTRAPMETHOD=file - ORDERER_GENERAL_BOOTSTRAPFILE=/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] - 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
- Next, you need to configure the peer nodes of Org1 and Org2. Here, you need to configure two files. Like order, the first file needs to configure different configuration information between peers; The second file needs to configure the public configuration information between peers. First, the first file docker compose peer Yaml, execute the command VI docker-compose-peer Yaml, paste the contents of the following code block into the file.
version: '2' services: peer0.org1.example.com: container_name: peer0.org1.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer0.org1.example.com - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_LISTENADDRESS=0.0.0.0:7051 - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984 - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls - peer0.org1.example.com:/var/hyperledger/production ports: - 7051:7051 networks: - byfn peer1.org1.example.com: container_name: peer1.org1.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org1.example.com - CORE_PEER_ADDRESS=peer1.org1.example.com:8051 - CORE_PEER_LISTENADDRESS=0.0.0.0:8051 - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984 - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls - peer1.org1.example.com:/var/hyperledger/production ports: - 8051:8051 networks: - byfn peer0.org2.example.com: container_name: peer0.org2.example.com extends: file: peer-base.yaml service: peer-base environment: - 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_USELEADERELECTION=true - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:10051 - CORE_PEER_LOCALMSPID=Org2MSP - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984 - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls - peer0.org2.example.com:/var/hyperledger/production ports: - 9051:9051 networks: - byfn peer1.org2.example.com: container_name: peer1.org2.example.com extends: file: peer-base.yaml service: peer-base environment: - CORE_PEER_ID=peer1.org2.example.com - CORE_PEER_ADDRESS=peer1.org2.example.com:10051 - CORE_PEER_LISTENADDRESS=0.0.0.0:10051 - CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:10052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:10051 - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051 - CORE_PEER_LOCALMSPID=Org2MSP - CORE_LEDGER_STATE_STATEDATABASE=CouchDB - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984 - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME= - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= volumes: - /var/run/:/host/var/run/ - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls - peer1.org2.example.com:/var/hyperledger/production ports: - 10051:10051 networks: - byfn
- The second file for configuring peer is peer base Yaml, associate this file with order base Yaml is placed in the base directory together, and execute the command VI peer base Yaml, copy the contents of the following code block to the file.
version: '2' services: peer-base: image: hyperledger/fabric-peer:latest environment: - 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=raft-example_byfn - GODEBUG=netdns=go - FABRIC_LOGGING_SPEC=info #- FABRIC_LOGGING_SPEC=DEBUG - CORE_PEER_TLS_ENABLED=true - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_ORGLEADER=false - 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 # Allow more time for chaincode container to build on install. - CORE_CHAINCODE_EXECUTETIMEOUT=300s working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer command: peer node start
- Next, configure the docker file of couchdb. couchdb is used as the index database of four peer s. Execute the command VI docker compose couchdb Yaml, copy the contents of the following code block to a file.
version: '2' networks: byfn: services: couchdb: container_name: couchdb image: couchdb:latest # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password # for CouchDB. This will prevent CouchDB from operating in an "Admin Party" mode. environment: - COUCHDB_USER= - COUCHDB_PASSWORD= # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service, # for example map it to utilize Fauxton User Interface in dev environments. ports: - "5984:5984" networks: - byfn
- Finally, configure the client container for accessing the fabric network. The docker configuration of the container is actually the configuration of peers. The client container uses the identity of one of the peers to access the entire fabric network and executes the command VI docker compose cli Yaml, copy the contents of the following code block to a file.
version: '2' cli: container_name: cli image: hyperledger/fabric-tools:latest tty: true stdin_open: true environment: - GOPATH=/opt/gopath - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock #- FABRIC_LOGGING_SPEC=DEBUG - FABRIC_LOGGING_SPEC=INFO - CORE_PEER_ID=cli - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_TLS_ENABLED=true - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key - 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 - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer command: /bin/bash volumes: - /var/run/:/host/var/run/ - ./chaincode/:/opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/ - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts depends_on: - peer0.org1.example.com - peer1.org1.example.com - peer0.org2.example.com - peer1.org2.example.com networks: - byfn
- Here, the docker configuration of each node in the fabric has been configured. Next, create a chain code folder in the root directory to store the chain code, and put the chain code in the chain code folder. The chain code I use this time is the chain code of the official instance, as shown in the following code block.
/* Copyright IBM Corp. 2016 All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package main //WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of //calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has //to be modified as well with the new ID of chaincode_example02. //chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of //hard-coding. import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" pb "github.com/hyperledger/fabric/protos/peer" ) // SimpleChaincode example simple Chaincode implementation type SimpleChaincode struct { } func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Init") _, args := stub.GetFunctionAndParameters() var A, B string // Entities var Aval, Bval int // Asset holdings var err error if len(args) != 4 { return shim.Error("Incorrect number of arguments. Expecting 4") } // Initialize the chaincode A = args[0] Aval, err = strconv.Atoi(args[1]) if err != nil { return shim.Error("Expecting integer value for asset holding") } B = args[2] Bval, err = strconv.Atoi(args[3]) if err != nil { return shim.Error("Expecting integer value for asset holding") } fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) // Write the state to the ledger err = stub.PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Invoke") function, args := stub.GetFunctionAndParameters() if function == "invoke" { // Make payment of X units from A to B return t.invoke(stub, args) } else if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } else if function == "query" { // the old "Query" is now implemtned in invoke return t.query(stub, args) } return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") } // Transaction makes payment of X units from A to B func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { var A, B string // Entities var Aval, Bval int // Asset holdings var X int // Transaction value var err error if len(args) != 3 { return shim.Error("Incorrect number of arguments. Expecting 3") } A = args[0] B = args[1] // Get the state from the ledger // TODO: will be nice to have a GetAllState call to ledger Avalbytes, err := stub.GetState(A) if err != nil { return shim.Error("Failed to get state") } if Avalbytes == nil { return shim.Error("Entity not found") } Aval, _ = strconv.Atoi(string(Avalbytes)) Bvalbytes, err := stub.GetState(B) if err != nil { return shim.Error("Failed to get state") } if Bvalbytes == nil { return shim.Error("Entity not found") } Bval, _ = strconv.Atoi(string(Bvalbytes)) // Perform the execution X, err = strconv.Atoi(args[2]) if err != nil { return shim.Error("Invalid transaction amount, expecting a integer value") } Aval = Aval - X Bval = Bval + X fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) // Write the state back to the ledger err = stub.PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } // Deletes an entity from state func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } A := args[0] // Delete the key from the state in ledger err := stub.DelState(A) if err != nil { return shim.Error("Failed to delete state") } return shim.Success(nil) } // query callback representing the query of a chaincode func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response { var A string // Entities var err error if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting name of the person to query") } A = args[0] // Get the state from the ledger Avalbytes, err := stub.GetState(A) if err != nil { jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}" return shim.Error(jsonResp) } if Avalbytes == nil { jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}" return shim.Error(jsonResp) } jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}" fmt.Printf("Query Response:%s\n", jsonResp) return shim.Success(Avalbytes) } func main() { err := shim.Start(new(SimpleChaincode)) if err != nil { fmt.Printf("Error starting Simple chaincode: %s", err) } }
- Create a script to start the fabric network, create a directory scripts under the root directory to store the script, and execute the command VI up SH, copy the contents of the following code block to the file.
docker-compose -f ../docker-compose-orderer.yaml up -d sleep 5 docker-compose -f ../docker-compose-couchdb.yaml up -d docker-compose -f ../docker-compose-peer.yaml up -d docker-compose -f ../docker-compose-cli.yaml up -d
-Create a script to close the fabric network. Similarly, in the scripts directory, execute the command VI down SH, copy the contents of the following code block to the file.
docker-compose -f ../docker-compose-orderer.yaml down --volume --remove-orphans docker-compose -f ../docker-compose-couchdb.yaml down --volume --remove-orphans docker-compose -f ../docker-compose-peer.yaml down --volume --remove-orphans docker-compose -f ../docker-compose-cli.yaml down. --volume --remove-orphans docker network prune
- The last step is to add dns mapping for the container on the host, execute the command vi /etc/hosts, enter the host file, and copy the contents in the following code block to the last line of the file.
127.0.0.1 couchdb orderer.example.com orderer1.example.com orderer2.example.com peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com cli
- Execute script up SH starts the whole fabric network, and then enters the part of interacting with the fabric network.
Using cli container to interact with fabric underlying network
This part interacts with fabric network through cli container, including channel creation, node joining channel, node installation chain code, invoke call chain code, etc.
- First, enter the CLI container and execute the command docker exec -it cli bash to enter the CLI container. The default working path of the CLI container is / opt / gopath / SRC / GitHub COM / hyperledger / fabric / peer, which is on docker-compose-cli.com Working directory configured in yaml container.
- First, create the application channel. This will use the previously generated channel file. This file has been mounted in the channel artifacts folder in the current working directory through the data volume. Execute the command peer channel create - O orderer exam ple. com:7050 -c testchannel -f ./ channel-artifacts/channel. tx --tls true --cafile /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com/msp/tlscacerts/tlsca. example. Com-cert.pem creates a channel. After successful creation, a block file with the channel name command will be generated in the current directory. For example, the currently generated file is testchanel block.
- Next, update the anchor node of org1. This operation can be performed once on any node of each organization. Execute the command peer channel update - O order example. com:7050 -c testchannel -f ./ channel-artifacts/Org1MSPanchors. tx --tls true --cafile /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com/msp/tlscacerts/tlsca. example. com-cert.pem
- Next, add the of the current peer node to the channel. The current node refers to the node configured in the c li environment variable. Here, it is in docker compose cli Peer0.0 is configured in yaml org1. example. COM, execute the command peer channel join - B testchnel Block, peer0 org1. example. The com node has joined the channel. You can view the channels joined by the current node by executing the command peer channel list.
- Next, install the chain code for the current node and execute the command peer chaincode install - n MYCC - v 1.0 - L golang - P GitHub COM / chaincode, peer0 org1. example. Com node has installed the chain code.
- Next, you need to perform the operations of adding channels and installing chain codes for other peer nodes. You need to switch the nodes by switching the environment variables of cli. The following code block has the settings for switching the environment variables of the other three nodes, which can be executed according to the rules.
#Switch to peer1 org1. example. Com node export CORE_PEER_ADDRESS=peer1.org1.example.com:8051 export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt #Set peer1 org1. example. The com node is added to the channel peer channel join -b testchannel.block #Is peer1 org1. example. Com node installation chain code peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode #Switch to peer0 org2. example. Com node export CORE_PEER_LOCALMSPID=Org2MSP export CORE_PEER_ADDRESS=peer0.org2.example.com:9051 export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp #Update the anchor node for org2 peer channel update -o orderer.example.com:7050 -c testchannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem #Set peer0 org2. example. Com node join channel peer channel join -b testchannel.block #Is peer0 org2. example. Com node installation chain code peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode #Switch to peer1 org2. example. Com node export CORE_PEER_ADDRESS=peer1.org2.example.com:10051 export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.crt export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.key export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt #Set peer1 org2. example. The com node is added to the channel peer channel join -b testchannel.block #Is peer1 org2. example. Com node installation chain code peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode
- Here, all peers have been added to the channel and the chain code has been installed. Now instantiate the chain code. This operation can be performed on any node. Execute the command peer chaincode instantiate iate - O order example. com:7050 --tls true --cafile /opt/gopath/src/github. com/hyperledg er/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com /msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n mycc -l golang -v 1.0 -c '{"Arg s":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")'
- The following operation is to initialize the chain code. This operation corresponds to the init function in the chain code. Execute the command peer chaincode instantiate iate - O order example. com:7050 --tls true --cafile /opt/gopath/src/github. com/hyperledg er/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com /msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n mycc -l golang -v 1.0 -c '{"Arg s":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")'.
- Next, perform an invoke operation on the chain code, transfer 10 yuan from a to B, and execute the command peer chaincode invoke - O order example. com:7050 --tls true --cafile /opt/gopath/src /github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer0. example. com/msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n myc c --peerAddresses peer0. org1. example. com:7051 --tlsRootCertFiles /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/peerOrganization/org1. example. com/peers/peer0. org1. example. com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'.
- Next, query the chain code to find out how much money a has left. Execute the command peer chaincode query - C testchnel - n MYCC - C '{args ": [" query "," a "]}'.
This is the Raft based fabric1 This is the end of the stand-alone network of 4. Welcome to discuss in the comment area or put forward your opinions on my blog.