Module 4: Exercises and Assessment

Practical Exercises

Exercise 1: Setting Up a Basic Fabric Network

Objective: Set up a basic Hyperledger Fabric network with two organizations, each with one peer, and a single orderer node.

Tasks:

  1. Create a working directory for your network: bash mkdir -p ~/fabric-network cd ~/fabric-network

  2. Create a crypto-config.yaml file: ```bash cat > crypto-config.yaml << EOF OrdererOrgs:

    • Name: Orderer Domain: example.com Specs:
      • Hostname: orderer

PeerOrgs: - Name: Org1 Domain: org1.example.com EnableNodeOUs: true Template: Count: 1 Users: Count: 1

 - Name: Org2
   Domain: org2.example.com
   EnableNodeOUs: true
   Template:
     Count: 1
   Users:
     Count: 1

EOF ```

  1. Create a configtx.yaml file: ```bash cat > configtx.yaml << EOF 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 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 Port: 7051
    • &Org2 Name: Org2MSP ID: Org2MSP MSPDir: crypto-config/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

Capabilities: Channel: &ChannelCapabilities V2_0: true Orderer: &OrdererCapabilities V2_0: true Application: &ApplicationCapabilities V2_0: true

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

Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer.example.com:7050 BatchTimeout: 2s 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" Capabilities: <<: *OrdererCapabilities

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 Orderer: <<: OrdererDefaults Organizations: - OrdererOrg Consortiums: SampleConsortium: Organizations: - Org1 - Org2 TwoOrgsChannel: Consortium: SampleConsortium <<: ChannelDefaults Application: <<: ApplicationDefaults Organizations: - Org1 - Org2 Capabilities: <<: ApplicationCapabilities EOF ```

  1. Create a docker-compose.yaml file: ```bash cat > docker-compose.yaml << EOF version: '3.7'

networks: fabric_network:

services: orderer.example.com: container_name: orderer.example.com image: hyperledger/fabric-orderer:2.5.0 environment: - FABRIC_LOGGING_SPEC=INFO - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 - ORDERER_GENERAL_LISTENPORT=7050 - ORDERER_GENERAL_GENESISMETHOD=file - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block - ORDERER_GENERAL_LOCALMSPID=OrdererMSP - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp - 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] working_dir: /opt/gopath/src/github.com/hyperledger/fabric command: orderer volumes: - ./system-genesis-block/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 ports: - 7050:7050 networks: - fabric_network

 peer0.org1.example.com:
   container_name: peer0.org1.example.com
   image: hyperledger/fabric-peer:2.5.0
   environment:
     - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
     - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_network
     - FABRIC_LOGGING_SPEC=INFO
     - 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
     - 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_EXTERNALENDPOINT=peer0.org1.example.com:7051
     - CORE_PEER_LOCALMSPID=Org1MSP
     - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp
     - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9443
     - CORE_METRICS_PROVIDER=prometheus
     - CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org1"}
     - CORE_CHAINCODE_EXECUTETIMEOUT=300s
   volumes:
     - /var/run/docker.sock:/host/var/run/docker.sock
     - ./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
   working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
   command: peer node start
   ports:
     - 7051:7051
     - 9443:9443
   networks:
     - fabric_network

 peer0.org2.example.com:
   container_name: peer0.org2.example.com
   image: hyperledger/fabric-peer:2.5.0
   environment:
     - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
     - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_network
     - FABRIC_LOGGING_SPEC=INFO
     - 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
     - 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_LOCALMSPID=Org2MSP
     - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp
     - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9444
     - CORE_METRICS_PROVIDER=prometheus
     - CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org2"}
     - CORE_CHAINCODE_EXECUTETIMEOUT=300s
   volumes:
     - /var/run/docker.sock:/host/var/run/docker.sock
     - ./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
   working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
   command: peer node start
   ports:
     - 9051:9051
     - 9444:9444
   networks:
     - fabric_network

 cli:
   container_name: cli
   image: hyperledger/fabric-tools:2.5.0
   tty: true
   stdin_open: true
   environment:
     - GOPATH=/opt/gopath
     - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
     - 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/docker.sock:/host/var/run/docker.sock
     - ./chaincode/:/opt/gopath/src/github.com/chaincode
     - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto
     - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
   networks:
     - fabric_network

EOF ```

  1. Create a deployment script: ```bash cat > deploy-network.sh << EOF #!/bin/bash

# Create directories mkdir -p crypto-config channel-artifacts system-genesis-block chaincode

# Generate crypto material cryptogen generate --config=./crypto-config.yaml --output=./crypto-config

# Set FABRIC_CFG_PATH to the current directory export FABRIC_CFG_PATH=\${PWD}

# Generate genesis block configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block

# Generate channel transaction configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1

# Generate anchor peer updates configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID channel1 -asOrg Org1MSP configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID channel1 -asOrg Org2MSP

# Start the network docker-compose up -d

# Wait for network to start sleep 5

# Create and join channel docker exec cli peer channel create -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/channel1.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

# Join peer0.org1 to channel docker exec cli peer channel join -b channel1.block

# Join peer0.org2 to channel docker exec -e CORE_PEER_LOCALMSPID=Org2MSP -e 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 -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 cli peer channel join -b channel1.block

# Update anchor peers docker exec cli peer channel update -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

docker exec -e CORE_PEER_LOCALMSPID=Org2MSP -e 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 -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 cli peer channel update -o orderer.example.com:7050 -c channel1 -f /opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

echo "Network setup complete!" EOF

chmod +x deploy-network.sh ```

  1. Create a simple chaincode: ```bash mkdir -p chaincode/basic

cat > chaincode/basic/basic.go << EOF package main

import ( "encoding/json" "fmt"

   "github.com/hyperledger/fabric-contract-api-go/contractapi"

)

// SmartContract provides functions for managing assets type SmartContract struct { contractapi.Contract }

// Asset describes basic details of an asset type Asset struct { ID string `json:"id"` Color string `json:"color"` Size int `json:"size"` Owner string `json:"owner"` Value int `json:"value"` }

// InitLedger adds a base set of assets to the ledger func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error { assets := []Asset{ {ID: "asset1", Color: "blue", Size: 5, Owner: "Tom", Value: 100}, {ID: "asset2", Color: "red", Size: 10, Owner: "Jane", Value: 200}, {ID: "asset3", Color: "green", Size: 15, Owner: "Alex", Value: 300}, }

   for _, asset := range assets {
       assetJSON, err := json.Marshal(asset)
       if err != nil {
           return err
       }

       err = ctx.GetStub().PutState(asset.ID, assetJSON)
       if err != nil {
           return fmt.Errorf("failed to put to world state: %v", err)
       }
   }

   return nil

}

// CreateAsset issues a new asset to the world state with given details func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, color string, size int, owner string, value int) error { exists, err := s.AssetExists(ctx, id) if err != nil { return err } if exists { return fmt.Errorf("the asset %s already exists", id) }

   asset := Asset{
       ID:     id,
       Color:  color,
       Size:   size,
       Owner:  owner,
       Value:  value,
   }

   assetJSON, err := json.Marshal(asset)
   if err != nil {
       return err
   }

   return ctx.GetStub().PutState(id, assetJSON)

}

// ReadAsset returns the asset stored in the world state with given id func (s SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (Asset, error) { assetJSON, err := ctx.GetStub().GetState(id) if err != nil { return nil, fmt.Errorf("failed to read from world state: %v", err) } if assetJSON == nil { return nil, fmt.Errorf("the asset %s does not exist", id) }

   var asset Asset
   err = json.Unmarshal(assetJSON, &asset)
   if err != nil {
       return nil, err
   }

   return &asset, nil

}

// AssetExists returns true when asset with given ID exists in world state func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, id string) (bool, error) { assetJSON, err := ctx.GetStub().GetState(id) if err != nil { return false, fmt.Errorf("failed to read from world state: %v", err) }

   return assetJSON != nil, nil

}

func main() { assetChaincode, err := contractapi.NewChaincode(&SmartContract{}) if err != nil { fmt.Printf("Error creating asset chaincode: %v\n", err) return }

   if err := assetChaincode.Start(); err != nil {
       fmt.Printf("Error starting asset chaincode: %v\\n", err)
   }

} EOF

cat > chaincode/basic/go.mod << EOF module basic

go 1.16

require ( github.com/hyperledger/fabric-contract-api-go v1.1.1 ) EOF ```

  1. Create a chaincode deployment script: ```bash cat > deploy-chaincode.sh << EOF #!/bin/bash

# Package the chaincode docker exec cli peer lifecycle chaincode package basic.tar.gz --path /opt/gopath/src/github.com/chaincode/basic/ --lang golang --label basic_1.0

# Install on peer0.org1 docker exec cli peer lifecycle chaincode install basic.tar.gz

# Install on peer0.org2 docker exec -e CORE_PEER_LOCALMSPID=Org2MSP -e 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 -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 cli peer lifecycle chaincode install basic.tar.gz

# Get the package ID PACKAGE_ID=\$(docker exec cli peer lifecycle chaincode queryinstalled | grep basic_1.0 | awk '{print \$3}' | sed 's/,//') echo "Package ID: \$PACKAGE_ID"

# Approve for Org1 docker exec cli peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel1 --name basic --version 1.0 --package-id \$PACKAGE_ID --sequence 1

# Approve for Org2 docker exec -e CORE_PEER_LOCALMSPID=Org2MSP -e 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 -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 cli peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel1 --name basic --version 1.0 --package-id \$PACKAGE_ID --sequence 1

# Commit the chaincode definition docker exec cli peer lifecycle chaincode commit -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID channel1 --name basic --version 1.0 --sequence 1 --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

# Initialize the chaincode docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel1 -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'

echo "Chaincode deployment complete!" EOF

chmod +x deploy-chaincode.sh ```

  1. Create a network teardown script: ```bash cat > teardown-network.sh << EOF #!/bin/bash

# Stop the network docker-compose down --volumes --remove-orphans

# Remove generated files rm -rf crypto-config channel-artifacts system-genesis-block

echo "Network teardown complete!" EOF

chmod +x teardown-network.sh ```

  1. Deploy the network: bash ./deploy-network.sh

  2. Deploy the chaincode: bash ./deploy-chaincode.sh

  3. Test the chaincode: ```bash # Query an asset docker exec cli peer chaincode query -C channel1 -n basic -c '{"function":"ReadAsset","Args":["asset1"]}'

    Create a new asset

    docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel1 -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateAsset","Args":["asset4", "yellow", "10", "Sam", "400"]}'

    Query the new asset

    docker exec cli peer chaincode query -C channel1 -n basic -c '{"function":"ReadAsset","Args":["asset4"]}' ```

Deliverable: A working Hyperledger Fabric network with two organizations, each with one peer, and a single orderer node. The network should have a channel with a deployed chaincode that can create and query assets.

Exercise 2: Adding a New Organization to an Existing Network

Objective: Add a third organization (Org3) to the network created in Exercise 1.

Tasks:

  1. Create a directory for Org3: bash mkdir -p ~/fabric-network/org3 cd ~/fabric-network/org3

  2. Create a crypto-config.yaml file for Org3: ```bash cat > crypto-config.yaml << EOF PeerOrgs:

    • Name: Org3 Domain: org3.example.com EnableNodeOUs: true Template: Count: 1 Users: Count: 1 EOF ```
  3. Generate crypto material for Org3: bash cryptogen generate --config=./crypto-config.yaml --output=./crypto-config

  4. Create a configtx.yaml file for Org3: ```bash cat > configtx.yaml << EOF Organizations:

    • &Org3 Name: Org3MSP ID: Org3MSP MSPDir: crypto-config/peerOrganizations/org3.example.com/msp Policies: Readers: Type: Signature Rule: "OR('Org3MSP.admin', 'Org3MSP.peer', 'Org3MSP.client')" Writers: Type: Signature Rule: "OR('Org3MSP.admin', 'Org3MSP.client')" Admins: Type: Signature Rule: "OR('Org3MSP.admin')" Endorsement: Type: Signature Rule: "OR('Org3MSP.peer')" AnchorPeers:
      • Host: peer0.org3.example.com Port: 11051 EOF ```
  5. Generate the Org3 definition: bash export FABRIC_CFG_PATH=${PWD} configtxgen -printOrg Org3MSP > org3.json

  6. Create a docker-compose file for Org3: ```bash cat > docker-compose-org3.yaml << EOF version: '3.7'

networks: fabric_network: external: true

services: peer0.org3.example.com: container_name: peer0.org3.example.com image: hyperledger/fabric-peer:2.5.0 environment: - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fabric_network - FABRIC_LOGGING_SPEC=INFO - 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 - CORE_PEER_ID=peer0.org3.example.com - CORE_PEER_ADDRESS=peer0.org3.example.com:11051 - CORE_PEER_LISTENADDRESS=0.0.0.0:11051 - CORE_PEER_CHAINCODEADDRESS=peer0.org3.example.com:11052 - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:11052 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:11051 - CORE_PEER_LOCALMSPID=Org3MSP - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9445 - CORE_METRICS_PROVIDER=prometheus - CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org3"} - CORE_CHAINCODE_EXECUTETIMEOUT=300s volumes: - /var/run/docker.sock:/host/var/run/docker.sock - ./crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp - ./crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer command: peer node start ports: - 11051:11051 - 9445:9445 networks: - fabric_network EOF ```

  1. Create a script to add Org3 to the channel: ```bash cat > add-org3.sh << EOF #!/bin/bash

cd ~/fabric-network

# Copy Org3 crypto material cp -r org3/crypto-config/peerOrganizations/org3.example.com crypto-config/peerOrganizations/

# Fetch the channel configuration docker exec cli peer channel fetch config config_block.pb -o orderer.example.com:7050 -c channel1 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

# Copy the config block to the CLI container docker cp org3/org3.json cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/org3.json

# Update the channel configuration docker exec cli bash -c ' configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json

jq -s ".[0] * {\"channel_group\":{\"groups\":{\"Application\":{\"groups\":{\"Org3MSP\":.[1]}}}}}" config.json org3.json > modified_config.json

configtxlator proto_encode --input config.json --type common.Config --output config.pb configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

configtxlator compute_update --channel_id channel1 --original config.pb --updated modified_config.pb --output org3_update.pb

configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json

echo "{\"payload\":{\"header\":{\"channel_header\":{\"channel_id\":\"channel1\", \"type\":2}},\"data\":{\"config_update\":\$(cat org3_update.json)}}}" | jq . > org3_update_in_envelope.json

configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb '

# Sign the configuration update by Org1 docker exec cli peer channel signconfigtx -f org3_update_in_envelope.pb

# Sign the configuration update by Org2 docker exec -e CORE_PEER_LOCALMSPID=Org2MSP -e 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 -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 cli peer channel signconfigtx -f org3_update_in_envelope.pb

# Update the channel docker exec cli peer channel update -f org3_update_in_envelope.pb -c channel1 -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

# Start Org3 peer cd ~/fabric-network/org3 docker-compose -f docker-compose-org3.yaml up -d

# Join Org3 peer to the channel # First, fetch the latest block docker exec cli peer channel fetch 0 channel1.block -o orderer.example.com:7050 -c channel1 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

# Copy the block to the Org3 peer docker cp cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel1.block . docker cp channel1.block peer0.org3.example.com:/opt/gopath/src/github.com/hyperledger/fabric/peer/

# Join Org3 peer to the channel docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer channel join -b /opt/gopath/src/github.com/hyperledger/fabric/peer/channel1.block

# Install chaincode on Org3 peer cd ~/fabric-network docker cp cli:/opt/gopath/src/github.com/chaincode/basic org3/

docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer lifecycle chaincode package basic.tar.gz --path /opt/gopath/src/github.com/hyperledger/fabric/peer/basic/ --lang golang --label basic_1.0

docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer lifecycle chaincode install basic.tar.gz

# Get the package ID PACKAGE_ID=\$(docker exec cli peer lifecycle chaincode queryinstalled | grep basic_1.0 | awk '{print \$3}' | sed 's/,//')

# Approve chaincode for Org3 docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --tls --cafile /etc/hyperledger/fabric/tls/ca.crt --channelID channel1 --name basic --version 1.0 --package-id \$PACKAGE_ID --sequence 1

echo "Org3 has been added to the network!" EOF

chmod +x add-org3.sh ```

  1. Run the script to add Org3: bash ./add-org3.sh

  2. Test that Org3 can interact with the chaincode: ```bash # Query an asset from Org3 docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer chaincode query -C channel1 -n basic -c '{"function":"ReadAsset","Args":["asset1"]}'

# Create a new asset from Org3 docker exec -e CORE_PEER_LOCALMSPID=Org3MSP -e CORE_PEER_TLS_ENABLED=true -e CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt -e CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/msp -e CORE_PEER_ADDRESS=peer0.org3.example.com:11051 peer0.org3.example.com peer chaincode invoke -o orderer.example.com:7050 --tls --cafile /etc/hyperledger/fabric/tls/ca.crt -C channel1 -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"CreateAsset","Args":["asset5", "purple", "15", "Mike", "500"]}' ```

Deliverable: An updated Hyperledger Fabric network with three organizations, each with one peer, and a single orderer node. The third organization should be able to participate in the channel and interact with the chaincode.

Exercise 3: Implementing Monitoring for a Fabric Network

Objective: Set up monitoring for the Hyperledger Fabric network using Prometheus and Grafana.

Tasks:

  1. Create a directory for monitoring: bash mkdir -p ~/fabric-network/monitoring cd ~/fabric-network/monitoring

  2. Create a Prometheus configuration file: ```bash cat > prometheus.yml << EOF global: scrape_interval: 15s evaluation_interval: 15s

scrape_configs: - job_name: 'fabric' static_configs: - targets: ['peer0.org1.example.com:9443', 'peer0.org2.example.com:9444', 'peer0.org3.example.com:9445'] EOF ```

  1. Create a Grafana dashboard configuration: ```bash mkdir -p grafana/dashboards

cat > grafana/dashboards/fabric.json << EOF { "annotations": { "list": [ { "builtIn": 1, "datasource": "-- Grafana --", "enable": true, "hide": true, "iconColor": "rgba(0, 211, 255, 1)", "name": "Annotations & Alerts", "type": "dashboard" } ] }, "editable": true, "gnetId": null, "graphTooltip": 0, "id": 1, "links": [], "panels": [ { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 }, "hiddenSeries": false, "id": 2, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.2.0", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(fabric_endorser_proposals_received[5m])", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Endorsement Rate", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 0 }, "hiddenSeries": false, "id": 4, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.2.0", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "fabric_endorser_proposal_duration_seconds", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Endorsement Duration", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "s", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 0, "y": 8 }, "hiddenSeries": false, "id": 6, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.2.0", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "rate(fabric_ledger_blockchain_height[5m])", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Blockchain Growth Rate", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } }, { "aliasColors": {}, "bars": false, "dashLength": 10, "dashes": false, "datasource": "Prometheus", "fieldConfig": { "defaults": { "custom": {} }, "overrides": [] }, "fill": 1, "fillGradient": 0, "gridPos": { "h": 8, "w": 12, "x": 12, "y": 8 }, "hiddenSeries": false, "id": 8, "legend": { "avg": false, "current": false, "max": false, "min": false, "show": true, "total": false, "values": false }, "lines": true, "linewidth": 1, "nullPointMode": "null", "options": { "alertThreshold": true }, "percentage": false, "pluginVersion": "7.2.0", "pointradius": 2, "points": false, "renderer": "flot", "seriesOverrides": [], "spaceLength": 10, "stack": false, "steppedLine": false, "targets": [ { "expr": "process_resident_memory_bytes", "interval": "", "legendFormat": "{{instance}}", "refId": "A" } ], "thresholds": [], "timeFrom": null, "timeRegions": [], "timeShift": null, "title": "Memory Usage", "tooltip": { "shared": true, "sort": 0, "value_type": "individual" }, "type": "graph", "xaxis": { "buckets": null, "mode": "time", "name": null, "show": true, "values": [] }, "yaxes": [ { "format": "bytes", "label": null, "logBase": 1, "max": null, "min": null, "show": true }, { "format": "short", "label": null, "logBase": 1, "max": null, "min": null, "show": true } ], "yaxis": { "align": false, "alignLevel": null } } ], "refresh": "10s", "schemaVersion": 26, "style": "dark", "tags": [], "templating": { "list": [] }, "time": { "from": "now-6h", "to": "now" }, "timepicker": {}, "timezone": "", "title": "Hyperledger Fabric Metrics", "uid": "fabric", "version": 1 } EOF

cat > grafana/dashboards/dashboard.yml << EOF apiVersion: 1

providers: - name: 'Prometheus' orgId: 1 folder: '' type: file disableDeletion: false editable: true options: path: /etc/grafana/dashboards EOF

cat > grafana/datasources/prometheus.yml << EOF apiVersion: 1

datasources: - name: Prometheus type: prometheus access: proxy orgId: 1 url: http://prometheus:9090 isDefault: true editable: true EOF ```

  1. Create a Docker Compose file for monitoring: ```bash cat > docker-compose-monitoring.yaml << EOF version: '3.7'

networks: fabric_network: external: true

services: prometheus: image: prom/prometheus:v2.30.3 container_name: prometheus volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus_data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.path=/prometheus' - '--web.console.libraries=/usr/share/prometheus/console_libraries' - '--web.console.templates=/usr/share/prometheus/consoles' ports: - 9090:9090 networks: - fabric_network

 grafana:
   image: grafana/grafana:8.2.2
   container_name: grafana
   volumes:
     - grafana_data:/var/lib/grafana
     - ./grafana/datasources:/etc/grafana/provisioning/datasources
     - ./grafana/dashboards:/etc/grafana/provisioning/dashboards
   environment:
     - GF_SECURITY_ADMIN_USER=admin
     - GF_SECURITY_ADMIN_PASSWORD=admin
     - GF_USERS_ALLOW_SIGN_UP=false
   ports:
     - 3000:3000
   networks:
     - fabric_network
   depends_on:
     - prometheus

volumes: prometheus_data: grafana_data: EOF ```

  1. Start the monitoring services: bash docker-compose -f docker-compose-monitoring.yaml up -d

  2. Generate some load on the network: ```bash cd ~/fabric-network

# Create a script to generate load cat > generate-load.sh << EOF #!/bin/bash

for i in {1..20} do asset_id="load_asset_\$i" color="color_\$i" size=\$((i * 5)) owner="owner_\$i" value=\$((i * 100))

 echo "Creating asset \$asset_id"
 docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C channel1 -n basic --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "{\"function\":\"CreateAsset\",\"Args\":[\"\$asset_id\", \"\$color\", \"\$size\", \"\$owner\", \"\$value\"]}"

 sleep 2

done

for i in {1..20} do asset_id="load_asset_\$i"

 echo "Reading asset \$asset_id"
 docker exec cli peer chaincode query -C channel1 -n basic -c "{\"function\":\"ReadAsset\",\"Args\":[\"\$asset_id\"]}"

 sleep 1

done EOF

chmod +x generate-load.sh

# Run the load generation script ./generate-load.sh ```

  1. Access the monitoring dashboards:
  2. Prometheus: http://localhost:9090
  3. Grafana: http://localhost:3000 (login with admin/admin)

Deliverable: A monitoring setup for the Hyperledger Fabric network using Prometheus and Grafana, with dashboards showing key metrics such as transaction throughput, endorsement time, and resource usage.

Assessment

Multiple Choice Questions

  1. Which of the following is NOT a component of the Hyperledger Fabric network configuration? a) crypto-config.yaml b) configtx.yaml c) docker-compose.yaml d) chaincode.yaml

  2. Which tool is used to generate the cryptographic material for a Hyperledger Fabric network? a) configtxgen b) cryptogen c) peer d) orderer

  3. Which consensus mechanism is recommended for production Hyperledger Fabric networks? a) Solo b) Kafka c) Raft d) PBFT

  4. What is the purpose of the "anchor peer" in a Hyperledger Fabric network? a) To endorse transactions b) To order transactions c) To enable cross-organization communication d) To store the ledger

  5. Which of the following is NOT a valid Hyperledger Fabric peer type? a) Endorsing peer b) Committing peer c) Ordering peer d) Anchor peer

  6. What is the purpose of the "channel" in Hyperledger Fabric? a) To provide a communication path between peers b) To isolate transactions and data between a specific set of participants c) To connect to external systems d) To manage the consensus mechanism

  7. Which component is responsible for maintaining the order of transactions in Hyperledger Fabric? a) Peer b) Orderer c) CA d) Client

  8. What is the purpose of the Membership Service Provider (MSP) in Hyperledger Fabric? a) To generate transactions b) To validate transactions c) To define the organizations and their members in the network d) To store the ledger

  9. Which of the following is NOT a step in the Hyperledger Fabric chaincode lifecycle? a) Package b) Install c) Approve d) Execute

  10. What is the purpose of the "private data collection" in Hyperledger Fabric? a) To store sensitive data that only specific organizations can access b) To improve transaction performance c) To implement access control d) To enable cross-channel queries

Short Answer Questions

  1. Explain the difference between the "Solo" and "Raft" ordering services in Hyperledger Fabric and when you would use each.

  2. Describe the process of adding a new organization to an existing Hyperledger Fabric network.

  3. Explain how to implement high availability in a Hyperledger Fabric network.

  4. Discuss the security considerations when deploying a Hyperledger Fabric network in production.

  5. Explain how to monitor a Hyperledger Fabric network and what key metrics should be tracked.

Answers to Multiple Choice Questions

  1. d) chaincode.yaml
  2. b) cryptogen
  3. c) Raft
  4. c) To enable cross-organization communication
  5. c) Ordering peer
  6. b) To isolate transactions and data between a specific set of participants
  7. b) Orderer
  8. c) To define the organizations and their members in the network
  9. d) Execute
  10. a) To store sensitive data that only specific organizations can access