Bootstrap

Fabric创建联盟+channel+组织结构

注意:本文命令拷贝出去会携带一些其它内容,建议先拷贝到一个文本编辑器,去掉这些非指令内容再执行

       在fabric中联盟不能为空,必须包含一个组织机构,所有在创建联盟的时候必须有一个组织机构,能够添加进去,fabric中的联盟和通道是一对一的关系,联盟必须和通道channel并存,而所有的配置都是记录在区块中的,包括有哪些联盟,有哪些org,所以要添加联盟就必须修改区块中的数据,更新配置。

一、创建联盟

        向`configtx.yaml`的`Section: Profile`中创建Orderer创世区块的配置profile中添加新联盟(以TestConsortium联盟为例)

cd $GOPATH/src/github.com/hyperledger/fabric-samples/first-network

vi configtx.yaml

      在configtx.yaml中添加TestConsortium联盟配置

TwoOrgsOrdererGenesis:
  <<: *ChannelDefaults
  Orderer:
     <<: *OrdererDefaults
     Organizations:
        - *OrdererOrg
     Capabilities:
        <<: *OrdererCapabilities
  Consortiums:
     SampleConsortium:
         Organizations:
           - *Org1
           - *Org2
     TestConsortium:
         Organizations:
           - *Org1

```

以JSON格式输出**新联盟**的配置材料

```
# 生成包含新联盟的新创世区块
configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/sys-channel.block

   #先安装jq
    #安装EPEL源:
    yum install epel-release
    #安装完EPEL源后,可以查看下jq包是否存在:
    yum list jq
    #安装jq:
    yum install jq
# 将其内容转换成JSON并抽取出新联盟的配置材料
configtxlator proto_decode --input ./channel-artifacts/sys-channel.block --type common.Block | jq .data.data[0].payload.data.config.channel_group.groups.Consortiums.groups.TestConsortium > ./channel-artifacts/TestConsortium.json
```

1. 获取系统通道的创世区块**

- (可选)设置了`ORDERER_CA`变量:

     ```
     docker exec -it cli bash


     export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
     ```

   - 切换到`OrdererOrgs`的admin用户

     ```bash
     export CORE_PEER_LOCALMSPID="OrdererMSP"
     export CORE_PEER_TLS_ROOTCERT_FILE=$ORDERER_CA
     export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/[email protected]/msp
     ```

     原因:系统通道的相关操作必须由`OrdererOrgs`的admin用户来执行

- 使用`peer channel fetch`命令获取系统通道的创世区块

     ```bash
     peer channel fetch config ./channel-artifacts/sys_config_block.pb -o orderer.example.com:7050 -c byfn-sys-channel --tls --cafile $ORDERER_CA
     ```

     其中`-c`参数是`--channelID`的简写,此处需要使用系统通道ID,即在调用`configtxgen`创建orderer创世区块时所指定的channelID。

 - 将创世区块中的内容转换成JSON并对其进行修剪

     ```bash
     exit
     configtxlator proto_decode --input ./channel-artifacts/sys_config_block.pb --type common.Block | jq .data.data[0].payload.data.config > ./channel-artifacts/sys_config.json
     ```

   - 将新联盟TestConsortium配置定义`TestConsortium.json`添加到channel的`Consortiums`的`TestConsortium`中,并将其写入`sys_updated_config.json`

     ```bash
     jq -s '.[0] * {"channel_group":{"groups":{"Consortiums":{"groups": {"TestConsortium": .[1]}}}}}' ./channel-artifacts/sys_config.json ./channel-artifacts/TestConsortium.json >& ./channel-artifacts/sys_updated_config.json
     ```

 **创建Config Update**

     - 配置增量计算

       ```bash
       # 将原始的配置sys_config.json编码成protobuf
       configtxlator proto_encode --input ./channel-artifacts/sys_config.json --type common.Config --output ./channel-artifacts/sys_config.pb
       # 将更新后的配置sys_updated_config.json编码成protobuf
       configtxlator proto_encode --input ./channel-artifacts/sys_updated_config.json --type common.Config --output ./channel-artifacts/sys_updated_config.pb
       # 配置增量计算
       configtxlator compute_update --channel_id byfn-sys-channel --original ./channel-artifacts/sys_config.pb --updated ./channel-artifacts/sys_updated_config.pb --output ./channel-artifacts/sys_config_update.pb
       ```

     - Generating config update and wrapping it in an envelope

       ```bash
       # 将sys_config_update.pb编码成json
       configtxlator proto_decode --input ./channel-artifacts/sys_config_update.pb --type common.ConfigUpdate | jq . > ./channel-artifacts/sys_config_update.json
       # 生成sys_config_update_in_envelope.json
       echo '{"payload":{"header":{"channel_header":{"channel_id":"byfn-sys-channel", "type":2}},"data":{"config_update":'$(cat ./channel-artifacts/sys_config_update.json)'}}}' | jq . > ./channel-artifacts/sys_config_update_in_envelope.json
       # 将sys_config_update_in_envelope.json编码成protobuf
       configtxlator proto_encode --input ./channel-artifacts/sys_config_update_in_envelope.json --type common.Envelope --output ./channel-artifacts/sys_config_update_in_envelope.pb
       ```

   - **向orderer发送配置更新(<u>必须使用OrdererOrg的admin用户</u>)**

     ```bash
     docker exec -it cli bash
     

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem


     export CORE_PEER_LOCALMSPID="OrdererMSP"


     export CORE_PEER_TLS_ROOTCERT_FILE=$ORDERER_CA


     export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/[email protected]/msp
     
     peer channel update -f ./channel-artifacts/sys_config_update_in_envelope.pb -c byfn-sys-channel -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA
     ```

回顾

通过以上步骤添加了一个联盟

检查新联盟是否添加成功

- 使用`peer channel fetch`命令获取系统通道的创世区块

     ```bash
     peer channel fetch config ./channel-artifacts/sys_config_block.pb -o orderer.example.com:7050 -c byfn-sys-channel --tls --cafile $ORDERER_CA
     ```

     其中`-c`参数是`--channelID`的简写,此处需要使用系统通道ID,即在调用`configtxgen`创建orderer创世区块时所指定的channelID。

 - 将创世区块中的内容转换成JSON并对其进行修剪

     ```bash
     exit
    

configtxlator proto_decode --input ./channel-artifacts/sys_config_block.pb --type common.Block | jq .data.data[0].payload.data.config > ./channel-artifacts/sys_config.json

     ```

查看 ./channel-artifacts/sys_config.json文件中是否有新联盟信息

二、创建channel

(可选)测试联盟,创建channel,只要是联盟的成员的admin都可以创建channel

编辑configtx.yaml找到channel创建的配置文件的位置,编写channel配置文件

cd $GOPATH/src/github.com/hyperledger/fabric-samples/first-network

vi configtx.yaml

```
    TwoOrgsChannel:
        Consortium: SampleConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities:
                <<: *ApplicationCapabilities
    TestChannel:
        Consortium: TestConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
            Capabilities:
                <<: *ApplicationCapabilities

```

```

#根据上述配置文件生成新channel(testchannel)的创世区块
configtxgen -profile TestChannel -outputCreateChannelTx ./channel-artifacts/testchannel.tx -channelID testchannel
```

```
docker exec -it cli bash
```

此处我们testConsortium里面的是org1,所以无需切换环境变量,如果是其他org,则必须切换到该org的admin用户

```
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

peer channel create -o orderer.example.com:7050 -c testchannel -f ./channel-artifacts/testchannel.tx --tls --cafile $ORDERER_CA

peer channel fetch 0 testchannel.block -o orderer.example.com:7050 -c testchannel --tls --cafile $ORDERER_CA

peer channel join -b testchannel.block


peer channel list #查看

#peer0.org1添加完成,再添加peer1.org1

#切换pee1.org1环境

export CORE_PEER_LOCALMSPID="Org1MSP"


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

export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp

export CORE_PEER_ADDRESS=peer1.org1.example.com:7051

peer channel join -b testchannel.block

peer channel list #查看
```

三、添加组织机构

```
cd org3-artifacts


生成证书
../../bin/cryptogen generate --config=./org3-crypto.yaml


生成org3的json字符串
export FABRIC_CFG_PATH=$PWD && ../../bin/configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json


拷贝order证书到org3目录下
cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/
docker exec -it cli bash

#此命令拷贝到centos,会被自动加一个pem,没搞懂为什么会加pem,需要拷贝过去后自己去掉
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  && export CHANNEL_NAME=mychannel

获取mychannel的配置区块
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA

转为json
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json

将org3加入到此json中
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json

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

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

计算pb之间的增量
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb

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

加入header信息
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json

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

org1签名
peer channel signconfigtx -f org3_update_in_envelope.pb

切换到org2签名
export CORE_PEER_LOCALMSPID="Org2MSP"
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/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

上传新配置
peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA

exit

cd $GOPATH/src/github.com/hyperledger/fabric-samples/first-network

编写docker-compose文件
docker-compose -f docker-compose-org3.yaml up -d

进入容器
docker exec -it Org3cli bash

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel

获取第0个区块
peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA

加入到channel里边
peer channel join -b mychannel.block

切换到另一peer
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls/ca.crt && export CORE_PEER_ADDRESS=peer1.org3.example.com:7051

加入到channel里边
peer channel join -b mychannel.block

#查看区块

peer channel getinfo -c mychannel

四、合约

实例化合约
peer chaincode instantiate -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 mychannel -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

invoke合约上块
peer chaincode invoke -o orderer.example.com:7050 --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 -C mychannel -n mycc --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:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
#'{"Args":["delete","a"]}'

查询合约
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

## 常用命令:

### channel相关

#### 获取某一channel区块信息:

```
peer channel getinfo -c mychannel(区块的最新高度,hash值)
```

#### 获取最新的区块

```
peer channel fetch newest -c mychannel channel-artifacts/new.pb --orderer orderer.example.com:7050 
```

#### 获取最新的channel配置区块

```
peer channel fetch config -c mychannel channel-artifacts/config.pb --orderer orderer.example.com:7050
```

#### peer加入channel

```
peer channel join -b ./mychannel.genesis.block
```

#### 查看peer已经加入的channel

```
peer channel list
```

#### 将pb区块转换为json

```
configtxlator proto_decode --input ./channel-artifacts/new.pb --type common.Block | jq . > ./channel-artifacts/new.json (将生成的区块转换成json格式)
```

#### 创建channel

```
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx channel-artifacts/mychannel1.tx -channelID mychannel1

peer channel create -o orderer.example.com:7050 -c mychannel1 -f ./channel-artifacts/mychannel1.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

peer channel join -b mychannel1.block

peer channel list
```

#### 切换peer环境变量

```
export CORE_PEER_LOCALMSPID="Org1MSP"
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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org1.example.com:7051
```

### 合约相关

#### 安装合约

```
peer chaincode install -n emr -v 1.0 -p github.com/chaincode/emr/

peer chaincode install -n javabasic -l java -v 5.0 -p /opt/gopath/src/github.com/chaincode/java/
```

#### 实例化合约

```
peer chaincode instantiate -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 mychannel -n emr -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org1MSP.peer')"


peer chaincode instantiate -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 mychannel -n javabasic -v 6.0 -l java -c '{"Args":["init"]}' -P "OR ('Org1MSP.peer')"
```

#### 升级合约

```
peer chaincode upgrade -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 mychannel -n emr -v 2.0 -c '{"Args":["init"]}' -P "OR ('Org1MSP.peer')"
```

#### invoke合约

```
peer chaincode invoke -o orderer.example.com:7050 --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 -C mychannel -n basicinfo --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 -c '{"Args":["save","110115","{\"name\":\"zhangsan\",\"identity\":\"110115\",\"mobile\":\"18910012222\"}"]}'


peer chaincode invoke -o orderer.example.com:7050 --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 -C mychannel -n javabasic --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 -c '{"Args":["invoke","110115","{\"name\":\"zhangsan\",\"identity\":\"110115\",\"mobile\":\"18910012222\"}"]}'
```

#### 查询合约

```
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'

peer chaincode query -C mychannel -n javabasic -c '{"Args":["query","110115"]}'
```

#### 查看已安装合约

```
peer chaincode list --installed
```

#### 查看已经实例化合约

```
peer chaincode list --instantiated -C mychannel
```

配置锚节点(可选)
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c mychannel --tls --cafile $ORDERER_CA

configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json

jq '.channel_group.groups.Application.groups.Org3MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org3.example.com","port": 11051}]},"version": "0"}}' config.json > modified_anchor_config.json

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

configtxlator proto_encode --input modified_anchor_config.json --type common.Config --output modified_anchor_config.pb

configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_anchor_config.pb --output anchor_update.pb

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

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

configtxlator proto_encode --input anchor_update_in_envelope.json --type common.Envelope --output anchor_update_in_envelope.pb

peer channel update -f anchor_update_in_envelope.pb -c mychannel -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
```

11111111

;