Fabric2.2.1从零开始搭建网络(非脚本)

Fabric2.2.1从零开始搭建网络(非脚本)

1. 生成证书

  • 这里使用cryptogen工具来生成证书文件
cryptogen showtemplate > crypto-template.yaml  # 生成一份模板证书配置文件
  • 生成的内容去掉英文注释后大概如下
OrdererOrgs:               # orderer组织的配置
  - Name: Orderer          # 组织名称
    Domain: example.com    # 组织的域名
    EnableNodeOUs: true    # 设置了EnableNodeOUs,会在map下生成config.yaml文件
    Specs:
      - Hostname: orderer  # 生成的证书文件会以{{Hostname}}.{{Domain}}呈现 当前的文件名就是                               
        SANS: 
          - localhost                    # orderer.example.com

PeerOrgs:                  
  - Name: Org1             
    Domain: org1.example.com
    EnableNodeOUs: true
    # template根据count来生成指定份数的证书文件
    # 我的理解是给当前这个组织中的节点生成证书文件 
    # 例如一个组织中有3个节点那么这个count就是3
    Template:
      Count: 1
      SANS: 
        - localhost
      # Start: 5   指定生成的节点从几开始,不指定就从0开始 peer0.org1.example.com
    Users:   # 组织中除了Admin之外还需要生成多少个用户,数量由count决定
      Count: 1

  - Name: Org2
    Domain: org2.example.com
    EnableNodeOUs: true
    Template:
      Count: 1
      SANS: 
        - localhost
    Users:
      Count: 1
  • 根据配置生成证书
  • 注意:这里的SANS一定要填节点真实的地址,不然会导致后面加入通道加入不进去
 cryptogen generate --config=./crypto-template.yaml --output=organizations

2. 生成创世区块

  • 生成创世区块也需要一份配置文件configtx.yaml 我这里直接复制了test-network/configtx/configtx.yaml下面的
Organizations:
    - &OrdererOrg
        Name: OrdererOrg     # 组织名称
        ID: OrdererMSP        # 组织id 用来引用组织   
        MSPDir: organizations/ordererOrganizations/example.com/msp    # 组织的msp文件目录
        Policies:         # 定义组织的一些策略
            Readers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('OrdererMSP.admin')"
                
        OrdererEndpoints:
            - orderer.example.com:7050
            
    - &Org1
        Name: Org1
        ID: Org1MSP
        MSPDir: organizations/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 # 锚节点的host地址
              Port: 7051                   # 锚节点开放的端口号地址
                 
    - &Org2
        Name: Org2
        ID: Org2MSP
        MSPDir: organizations/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

# fabric网络的能力配置部分              
Capabilities:
    Channel: &ChannelCapabilities           # Channel配置同时应用于orderer和peer
        V2_0: true
    Orderer: &OrdererCapabilities        # Orderer仅使用于orderer,无需担心升级peer     
        V2_0: true
    Application: &ApplicationCapabilities       # Application仅使用于Peer,无需担心升级Orderer   
        V2_0: true

# Application配置用来定义要写入创世区块或配置交易的应用参数        
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 锚点 也就是Application的值放在这
    Capabilities:
        <<: *ApplicationCapabilities
        
# Orderer配置用来定义要编码写入创世区块或通道交易的排序节点参数       
Orderer: &OrdererDefaults 
    OrdererType: etcdraft      # 排序节点的类型 目前有 solo kafka EtcdRaft , 不同的类型对应不同的共识算法的实现
    Addresses:     # orderer 服务的地址  
        - orderer.example.com:7050

    EtcdRaft:        # EtcdRaft排序类型的配置
        Consenters:
        - Host: orderer.example.com
          Port: 7050
          ClientTLSCert: organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
          ServerTLSCert: organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
    BatchTimeout: 1s    # 区块打包的时间,到了这个时间就打包区块
    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"

# Channel配置用来定义要写入创世区块或配置交易的通道参数
Channel: &ChannelDefaults
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ChannelCapabilities
        
# Profiles配置用来定义用于configtxgen工具生成创世区块或配置块的一些配置信息
Profiles:
    TwoOrgsOrdererGenesis:   # TwoOrgsOrdererGenesis用来生成orderer启动时所需的block,用于生成创世区块
        <<: *ChannelDefaults
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
            Capabilities:
                <<: *OrdererCapabilities
        Consortiums:
          # 这里定义了一个联盟 
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2
    # TwoOrgsChannel用来生成channel配置信息                
    TwoOrgsChannel:
        Consortium: SampleConsortium # 引用上面定义的联盟
        <<: *ChannelDefaults
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities:
                <<: *ApplicationCapabilities
  • 弄好配置文件之后就可以使用configtxgen工具来生成创世区块了
configtxgen -configPath ./ -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
选项
profile 在配置文件中配置的Profile
configPath configtx.yaml的文件夹路径注意这里是文件夹的路径而不是具体的文件的路径
channeID system-channel 这是fabric的一个默认的通道
outputBlock 要写入创世块的路径,包含文件名

3. 启动网络

  • 网络的配置如下需要和configtx.yaml中配置的对应
version: '2'

volumes:
  orderer.example.com:
  peer0.org1.example.com:
  peer0.org2.example.com:

networks:
  test:

services:

  orderer.example.com:
    container_name: orderer.example.com
    image: hyperledger/fabric-orderer:latest
    environment:
      - FABRIC_LOGGING_SPEC=INFO
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # 监听地址
      - ORDERER_GENERAL_LISTENPORT=7050       # 监听端口号
      - ORDERER_GENERAL_GENESISMETHOD=file   # 指定账本类型(可选file、RAM、json三种)
      - ORDERER_GENERAL_GENESISFILE=/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]        # 可信任的根CA证书
      - 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]
    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
    networks:
      - test

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    image: hyperledger/fabric-peer:latest
    environment:
      # Generic peer variables
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock   # vm管理系统的端点
      # 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=my-network_test
      - FABRIC_LOGGING_SPEC=INFO
      #- FABRIC_LOGGING_SPEC=DEBUG
      # TLS设置 
      - 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
      # Peer specific variabes
      - CORE_PEER_ID=peer0.org1.example.com   # 指定节点ID
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051   # 节点对外的服务地址
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7051       # 侦听本地网络接口上的地址。
      - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052  # 如果没有指定chaincodeListenAddress,则从其中选择address 
      - 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
    volumes:
        - /var/run/:/host/var/run/
        - ./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
    networks:
      - test

  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    image: hyperledger/fabric-peer:latest
    environment:
      #Generic peer variables
      - 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=my-network_test
      - FABRIC_LOGGING_SPEC=INFO
      #- FABRIC_LOGGING_SPEC=DEBUG
      - 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
      # Peer specific variabes
      - 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_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
      - CORE_PEER_LOCALMSPID=Org2MSP
    volumes:
        - /var/run/:/host/var/run/
        - ./organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
        - ./organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org2.example.com:/var/hyperledger/production
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    ports:
      - 9051:9051
    networks:
      - test
  • 启动网络
  • 这里需要注意CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE需要设置当前docker网络名称默认是 当前文件夹名称_test
docker-compose -f {{你的文件名}} up -d

4. 生成通道和锚节点更新交易配置

  • 使用configtxgen 不仅可以生成创建创世区块还可以生成一些交易的配置,他们的关系如下
configtx.yaml 生成 genesis.block channel.tx *anchors.tx
  • 生成通道交易配置
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputCreateChannelTx ./channel-artifacts/mychannel.tx
  • 生成两个组织的锚节点更新交易配置
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -asOrg Org1
configtxgen -configPath ./ -profile TwoOrgsChannel -channelID mychannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -asOrg Org2
## 这里的 -asOrg 的值是configtx中配置的组织的Name

5. 创建通道加入组织并更新锚节点

  • 先配置组织身份环境变量
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_ADDRESS=localhost:7051
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/Admin@org1.example.com/msp
export CORE_PEER_TLS_ENABLED=true
  • 使用我们之前生成的通道交易配置来创建通道证书的路径需要配置绝对路径使用相对路径会读不到
peer channel create -o localhost:7050 -c mychannel --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/mychannel.tx --outputBlock ./channel-artifacts/mychannel.block --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • Org1加入通道并更新锚节点
peer channel join -b ./channel-artifacts/mychannel.block

peer channel update -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • Org2加入通道并更新锚节点
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_ADDRESS=localhost:9051
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/Admin@org2.example.com/msp
export CORE_PEER_TLS_ENABLED=true

peer channel join -b ./channel-artifacts/mychannel.block

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

6. 安装链码测试

1. 打包链码 这里以fabric的asset-transfer-basic/chaincode-go 为例子

peer lifecycle chaincode package basic.tar.gz --path ./chaincode-go --lang golang --label basic_1

2. Org1和Org2安装链码

export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_ADDRESS=localhost:7051
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/Admin@org1.example.com/msp
export CORE_PEER_TLS_ENABLED=true

peer lifecycle chaincode install basic.tar.gz

export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_ADDRESS=localhost:9051
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/Admin@org2.example.com/msp
export CORE_PEER_TLS_ENABLED=true

peer lifecycle chaincode install basic.tar.gz

3. 审议链码定义

先获取链码的package_id

peer lifecycle chaincode queryinstalled

# 这串就是packageid每个人都不一样的
# basic_1:d612c5afb52543307c8d75b79da3de6b3b8d2f984e005a92db9528d0d9176f7d

用Org1和Org2的身份执行下面的命令来审议链码定义 环境变量在上面

peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --package-id Package ID: {{你的packageId}} --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

可以使用checkcommitreadiness来查询链码审议情况通道中大部分的组织同意即可提交

peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json

4. 提交链码定义

使用一个组织身份提交即可

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name basic --version 1.0 --sequence 1 --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

使用querycommitted可以查询当前通道中提交的链码

peer lifecycle chaincode querycommitted -C mychannel

5. 调用链码

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"InitLedger","Args":[]}'

查询链码

 peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'

如果能够查到初始化的数据,那么恭喜你网络搭建成功了!

上一篇:区块链学习——HyperLedger-Fabric v1.0 启动过程分析


下一篇:Fabric网络升级(二)