7.7 Creating a channel

Делаю:

28.08.2020


Все удаляю

$ cd ~/projects/dev/hyperledger/
$ sudo rm -rf *


$ {
    docker stop $(docker ps -aq)
    docker rm $(docker ps -aq)
    docker system prune -a
}


$ curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s


In order to create and transfer assets on a Hyperledger Fabric network, an organization needs to join a channel. Channels are a private layer of communication between specific organizations and are invisible to other members of the network. Each channel consists of a separate ledger that can only be read and written to by channel members, who are allowed to join their peers to the channel and receive new blocks of transactions from the ordering service. While the peers, nodes, and Certificate Authorities form the physical infrastructure of the network, channels are the process by which organizations connect with each other and interact.


Setting up the configtxgen tool

Channels are created by building a channel creation transaction and submitting the transaction to the ordering service. The channel creation transaction specifies the initial configuration of the channel and is used by the ordering service to write the channel genesis block. While it is possible to build the channel creation transaction file manually, it is easier to use the configtxgen tool. The tool works by reading a configtx.yaml file that defines the configuration of your channel, and then writing the relevant information into the channel creation transaction. Before we discuss the configtx.yaml file in the next section, we can get started by downloading and setting up the configtxgen tool.

$ cd fabric-samples/test-network
$ export PATH=${PWD}/../bin:$PATH
$ export FABRIC_CFG_PATH=${PWD}/configtx


Start the network

$ ./network.sh down && ./network.sh up

Our instance of the test network was deployed without creating an application channel.


Creating an application channel

$ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel1.tx -channelID channel1


$ export FABRIC_CFG_PATH=$PWD/../config/


$ {
    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org1MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
    export CORE_PEER_ADDRESS=localhost:7051
}


// create the channel
$ peer channel create \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com \
-c channel1 \
-f ./channel-artifacts/channel1.tx \
--outputBlock ./channel-artifacts/channel1.block \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


Join peers to the channel

// Org1

$ peer channel join -b ./channel-artifacts/channel1.block

// verify that the peer has joined the channel
$ peer channel getinfo -c channel1

// Org2

$ {
    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org2MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/[email protected]/msp
    export CORE_PEER_ADDRESS=localhost:9051
}


// get the genesis block for Org2
$ peer channel fetch 0 ./channel-artifacts/channel_org2.block -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


$ peer channel join -b ./channel-artifacts/channel_org2.block


Set anchor peers

We will use the configtxlator tool to update the channel configuration and select an anchor peer for Org1 and Org2.

// Org1

$ {
    export FABRIC_CFG_PATH=$PWD/../config/
    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org1MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/[email protected]/msp
    export CORE_PEER_ADDRESS=localhost:7051
}


// fetch the channel configuration
$ peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


$ cd channel-artifacts


Утилита jq должна быть установлена для выполнения следующих команд.


$ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

$ jq .data.data[0].payload.data.config config_block.json > config.json

$ cp config.json config_copy.json


// add the Org1 anchor peer to the channel configuration
$ jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' config_copy.json > modified_config.json


Convert both the original and modified channel configurations back into protobuf format and calculate the difference between them

$ 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 config_update.pb


$ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

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

$ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb


$ cd ../


// add the anchor peer by providing the new peer
$ peer channel update \
    -f channel-artifacts/config_update_in_envelope.pb \
    -c channel1 \
    -o localhost:7050  \
    --ordererTLSHostnameOverride orderer.example.com \
    --tls \
    --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


// Org2

set the anchor peers for Org2

$ {
    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org2MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/[email protected]/msp
    export CORE_PEER_ADDRESS=localhost:9051
}


// pull the latest channel configuration block, which is now the second block on the channel
$ peer channel fetch config channel-artifacts/config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c channel1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


$ cd channel-artifacts

$ configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json

$ jq .data.data[0].payload.data.config config_block.json > config.json

$ cp config.json config_copy.json


// Add the Org2 peer that is joined to the channel as the anchor peer in the channel configuration:
$ jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' config_copy.json > modified_config.json


We can now convert both the original and updated channel configurations back into protobuf format and calculate the difference between them.

$ 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 config_update.pb

Wrap the configuration update in a transaction envelope to create the channel configuration update transaction:

$ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json

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

$ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output config_update_in_envelope.pb


$ cd ..

Update the channel and set the Org2 anchor peer by issuing the following command:

$ peer channel update -f channel-artifacts/config_update_in_envelope.pb -c channel1 -o localhost:7050  --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

// confirm that the channel has been updated successfully
$ peer channel getinfo -c channel1


Deploy a chaincode to the new channel

$ ./network.sh deployCC -ccn basic -c channel1 -cci InitLedger

// confirm the data was added with the below query
$ peer chaincode query \
    -C channel1 \
    -n basic \
    -c '{"Args":["getAllAssets"]}' \
    | python -m json.tool
[
    {
        "ID": "asset1",
        "color": "blue",
        "size": 5,
        "owner": "Tomoko",
        "appraisedValue": 300
    },
    {
        "ID": "asset2",
        "color": "red",
        "size": 5,
        "owner": "Brad",
        "appraisedValue": 400
    },
    {
        "ID": "asset3",
        "color": "green",
        "size": 10,
        "owner": "Jin Soo",
        "appraisedValue": 500
    },
    {
        "ID": "asset4",
        "color": "yellow",
        "size": 10,
        "owner": "Max",
        "appraisedValue": 600
    },
    {
        "ID": "asset5",
        "color": "black",
        "size": 15,
        "owner": "Adriana",
        "appraisedValue": 700
    },
    {
        "ID": "asset6",
        "color": "white",
        "size": 15,
        "owner": "Michel",
        "appraisedValue": 800
    }
]