foreword
A supplement to the previous chapter: What if I don't want to test fabric in the root environment?
In fact, you only need to use the root account when creating and starting docker. Of course, because some files will be created when it is up, these files need to be delegated. First, transfer the files chown
to ordinary users, or chmod -R 775
, otherwise, follow-up non-root user operations Will be permission denied.
In addition, the previous chapter mainly refers to the official example of Hyperledger to try to start the network. Here I did some research, and tried to operate peer and channel through NodeJS API and fabric-client, but in the end I found it very inconvenient. Even if I use this API, I still need to use the official commands under the bin, for example You need to use cryptogen to create a node key configuration file. So after comprehensive consideration, I decided to hand over the network deployment and environment construction to the shell. Only the contract itself, and the logic to operate the contract are developed using typescript or javascript through nodejs.
general steps
Let's take a look at the steps required from docker startup to contract deployment in a regular Fabric network:
start
Create Organization and Orderer
Use cryptogen or ca to create organizations. If using cryptogen it is as follows:
Create an organization first, the organization node
is used here crypto-config-orgX.yaml
to create an organization file, yaml please go to the official sample to find the file template
int=1
cryptogen generate --config=./organizations/cryptogen/crypto-config-org$int.yaml --output="organizations"
This can be flexible, int can be any integer, used to represent organizations 1, 2, 3, 4... you can create countless organizations
Create an order node
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
The org node and the order node have different responsibilities
- The orderer is called a sorting node, a network node that provides consensus services, for example, using Kafka or PBFT
- The peer maintains the network node of the ledger, and usually acts as an endorsement or bookkeeping role in Hyperledger Fabric.
- In addition, there is a comitter, which checks the legality of the transaction and finally submits the transaction to the blockchain.
start node
docker-compose docker-compose-test-net.yaml up -d
Docker configuration and startup needs to be handled by yourself. Here is a docker-compose template reference. fabric-sample/test-network/docker
There are more detailed configuration files under the official
version: '2.4'
volumes:
orderer.example.com:
peer0.org1.example.com:
networks:
test:
name: fabric_test
services:
orderer.example.com:
container_name: orderer.example.com
image: hyperledger/fabric-orderer:latest
labels:
service: hyperledger-fabric
environment:
- FABRIC_LOGGING_SPEC=INFO
- ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
- ORDERER_GENERAL_LISTENPORT=7050
- 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_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]
- ORDERER_GENERAL_BOOTSTRAPMETHOD=none
- ORDERER_CHANNELPARTICIPATION_ENABLED=true
- ORDERER_ADMIN_TLS_ENABLED=true
- ORDERER_ADMIN_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
- ORDERER_ADMIN_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
- ORDERER_ADMIN_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
- ORDERER_ADMIN_TLS_CLIENTROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
- ORDERER_ADMIN_LISTENADDRESS=0.0.0.0:16050
- ORDERER_OPERATIONS_LISTENADDRESS=0.0.0.0:17050
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
- 16050:16050
- 17050:17050
networks:
- test
peer0.org1.example.com:
container_name: peer0.org1.example.com
image: hyperledger/fabric-peer:latest
labels:
service: hyperledger-fabric
environment:
#Generic peer variables
- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_test
- FABRIC_LOGGING_SPEC=INFO
#- FABRIC_LOGGING_SPEC=DEBUG
- CORE_PEER_TLS_ENABLED=true
- CORE_PEER_PROFILE_ENABLED=false
- 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 variables
- 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_BOOTSTRAP=peer0.org1.example.com:7051
- CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:17051
volumes:
- ${
DOCKER_SOCK}:/host/var/run/docker.sock
- ../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
- 17051:17051
networks:
- test
Note here that the organization encrypted file just cryptogen
created is mapped to the volumes of each node by docker, which is the identity file of each node. There are two examples here, one is order and the other is org.
Create channels
To create a channel, first create the genesis block of the channel. In fact, a channel of the fabric is a chain. However, I still feel that this step is too cumbersome. Can IBM provide the function of automatically creating the creation block?
Alright, let's create the genesis block:
CHANNEL_NAME=mychannel
configtxgen -profile ApplicationGenesis -outputBlock ./channel-artifacts/${CHANNEL_NAME}.block -channelID $CHANNEL_NAME
Then, let's create the channel:
export ORDERER_CA=${
PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${
PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${
PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:16050 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
Creating a channel is actually adding the orderer node to the channel first, according to the channel creation block just created. This step is more interesting. Why is the orderer added to the channel first, and why is the command used osnadmin
? The official did not find a reasonable explanation, so we put it aside for now.
join the channel
ORG=1
export CORE_PEER_LOCALMSPID="Org${ORG}MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${
PWD}/organizations/peerOrganizations/org${ORG}.example.com/peers/peer0.org${ORG}.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${
PWD}/organizations/peerOrganizations/org${ORG}.example.com/users/Admin@org${ORG}.example.com/msp
P0PORT=`expr 7049 + $ORG \* 2`
export CORE_PEER_ADDRESS=localhost:$P0PORT
BLOCKFILE="./channel-artifacts/${CHANNEL_NAME}.block"
peer channel join -b $BLOCKFILE
The above shell is to add org1 to the channel. Joining is the last line of script, but before that, you must set the ring variable to verify the identity of the node, which is actually "signing" to join.
set anchor node
Since the nodes themselves do not communicate with each other, to set other nodes anchored to the node, a function called setAnchorPeer is officially used to set the anchor node. I won’t go into details here, and the code is relatively long. Please refer to the scripts directory of the official sample. down setAnchorPeer.sh
.
I personally think this step is very cumbersome. Why do you need to manually set the anchor node after setting the channel? Can the channel not provide a way for each node to communicate? I don't quite understand the operation of hyperledg.
The above is the minimum fabric network built, and the next chapter will talk about the deployment contract.