Published: 2018-06-25

搭建一个Fabric网络

注意:本文是我自己尝试本地搭建fabric的一个流程记录,可能对你没有意义

Table of Contents

1 安装编译

2 生成证书文件

2.1 生成证书配置文件目录

mkdir -p demo/crypto-dir

2.2 编辑证书配置文件

vim crypto-config.yaml

文件内容如下:

OrdererOrgs:
  - Name: Orderer
    Domain: example.com
    Specs:
      - Hostname: orderer

PeerOrgs:

  - Name: Org1
    Domain: org1.example.com
    Template:
      Count: 2
    Users:
      Count: 1

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

2.3 根据配置文件生成证书

cryptogen generate --config=crypto-config.yaml --output ./crypto-dir

2.4 查看生成的证书文件

-> tree crypto-dir/ -L 3

crypto-dir/
├── ordererOrganizations
│   └── example.com
│       ├── ca
│       ├── msp
│       ├── orderers
│       ├── tlsca
│       └── users
└── peerOrganizations
    ├── org1.example.com
    │   ├── ca
    │   ├── msp
    │   ├── peers
    │   ├── tlsca
    │   └── users
    └── org2.example.com
        ├── ca
        ├── msp
        ├── peers
        ├── tlsca
        └── users

20 directories, 0 files

3 创始块生成

3.1 创建目录

mkdir order

3.2 编辑配置文件

vim configtx.yaml

文件内容如下
Profiles:

    TwoOrgsOrdererGenesis:
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2
    TwoOrgsChannel:
        Consortium: SampleConsortium
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2

Organizations:

    - &OrdererOrg
        Name: OrdererOrg
        ID: OrdererMSP
        MSPDir: crypto-dir/ordererOrganizations/example.com/msp
    - &Org1
        Name: Org1MSP
        ID: Org1MSP
        MSPDir: crypto-dir/peerOrganizations/org1.example.com/msp
        AnchorPeers:
            - Host: peer0.org1.example.com
              Port: 7051
    - &Org2
        Name: Org2MSP
        ID: Org2MSP
        MSPDir: crypto-dir/peerOrganizations/org2.example.com/msp
        AnchorPeers:
            - Host: peer0.org2.example.com
              Port: 7051

Orderer: &OrdererDefaults

    OrdererType: solo
    Addresses:
        - orderer.example.com:7050
    BatchTimeout: 2s
    BatchSize:
        MaxMessageCount: 10
        AbsoluteMaxBytes: 99 MB
        PreferredMaxBytes: 512 KB
    Kafka:
        Brokers:
            - 127.0.0.1:9092
    Organizations:

Application: &ApplicationDefaults

    Organizations:

3.3 根据配置文件生成初始Block

configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./order/order.genesis.block

2018-06-21 15:50:41.461 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-06-21 15:50:41.472 CST [msp] getMspConfig -> INFO 002 Loading NodeOUs
2018-06-21 15:50:41.472 CST [common/tools/configtxgen] doOutputBlock -> INFO 003 Generating genesis block
2018-06-21 15:50:41.473 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Writing genesis block

3.4 查看生成文件内容

tree order
order
└── order.genesis.block

0 directories, 1 file

3.5 创建channel

➜  configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./order/alicetestchannel.tx -channelID alicetestchannel

<CeateChannelTx ./order/alicetestchannel.tx -channelID alicetestchannel
2018-06-21 16:35:23.769 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-06-21 16:35:23.781 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-06-21 16:35:23.784 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs
2018-06-21 16:35:23.811 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx

3.6 创建两个锚点文件

1). 第一个锚节点

➜  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./order/Org1MSPanchors.tx -channelID alicetestchannel -asOrg Org1MSP

<chorPeersUpdate ./order/Org1MSPanchors.tx -channelID alicetestchannel -asOrg Org1MSP
2018-06-21 16:39:03.311 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-06-21 16:39:03.321 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-06-21 16:39:03.321 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update


2). 第二个锚节点

➜  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./order/Org2MSPanchors.tx -channelID alicetestchannel -asOrg Org2MSP

<chorPeersUpdate ./order/Org2MSPanchors.tx -channelID alicetestchannel -asOrg Org2MSP
2018-06-21 16:39:33.978 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-06-21 16:39:33.990 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-06-21 16:39:33.990 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update

3.7 检查此时文件

➜  tree order
tree order
order
├── Org1MSPanchors.tx
├── Org2MSPanchors.tx
├── alicetestchannel.tx
└── order.genesis.block

0 directories, 4 files

4 Order节点启动

4.1 编辑Order节点配置文件

vim orderer.yaml

文件内容如下:
参考 fabric/sampleconfig/orderer.yaml to demo/orderer.yaml

General:

    LedgerType: file

    ListenAddress: 0.0.0.0

    ListenPort: 7050

    TLS:
        Enabled: false
        PrivateKey: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
        Certificate: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
        RootCAs:
          - ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt
        ClientAuthRequired: false
        ClientRootCAs:

    Keepalive:
        ServerMinInterval: 60s
        ServerInterval: 7200s
        ServerTimeout: 20s

    LogLevel: debug

    LogFormat: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

    GenesisMethod: file

    GenesisProfile: TwoOrgsOrdererGenesis

    GenesisFile: ./order/order.genesis.block

    LocalMSPDir: ./crypto-dir/ordererOrganizations/example.com/orderers/orderer.example.com/msp

    LocalMSPID: OrdererMSP

    Profile:
        Enabled: false
        Address: 0.0.0.0:6060

    BCCSP:
        Default: SW

        SW:
            Hash: SHA2
            Security: 256
            FileKeyStore:
                KeyStore:

    Authentication:
        TimeWindow: 15m

FileLedger:

    Location: ./order/production/orderer

    Prefix: hyperledger-fabric-ordererledger

RAMLedger:

    HistorySize: 1000

Kafka:

    Retry:
        ShortInterval: 5s
        ShortTotal: 10m
        LongInterval: 5m
        LongTotal: 12h
        NetworkTimeouts:
            DialTimeout: 10s
            ReadTimeout: 10s
            WriteTimeout: 10s
        Metadata:
            RetryBackoff: 250ms
            RetryMax: 3
        Producer:
            RetryBackoff: 100ms
            RetryMax: 3
        Consumer:
            RetryBackoff: 2s

    Verbose: false

    TLS:

      Enabled: false

      PrivateKey:

      Certificate:

      RootCAs:

    Version:

Debug:

    BroadcastTraceDir:

    DeliverTraceDir:

4.2 启动Order节点

orderer start

5 Peer节点启动

5.1 创建Peer节点目录

mkdir peer

5.2 创建Peer节点配置文件

vim core.yaml

文件内容如下:
logging:

    level:       info
    cauthdsl:   warning
    gossip:     warning
    grpc:       error
    ledger:     info
    msp:        warning
    policies:   warning
    peer:
        gossip: warning

    format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

peer:

    id: peer0.org1.example.com
    networkId: dev
    listenAddress: 0.0.0.0:7051
    chaincodeListenAddress: 0.0.0.0:7052
    address: 0.0.0.0:7051
    addressAutoDetect: false
    gomaxprocs: -1
    keepalive:
        minInterval: 60s
        client:
            interval: 60s
            timeout: 20s
        deliveryClient:
            interval: 60s
            timeout: 20s
    gossip:
        bootstrap: 127.0.0.1:7051
        useLeaderElection: true
        orgLeader: false
        endpoint:
        maxBlockCountToStore: 100
        maxPropagationBurstLatency: 10ms
        maxPropagationBurstSize: 10
        propagateIterations: 1
        propagatePeerNum: 3
        pullInterval: 4s
        pullPeerNum: 3
        requestStateInfoInterval: 4s
        publishStateInfoInterval: 4s
        stateInfoRetentionInterval:
        publishCertPeriod: 10s
        skipBlockVerification: false
        dialTimeout: 3s
        connTimeout: 2s
        recvBuffSize: 20
        sendBuffSize: 200
        digestWaitTime: 1s
        requestWaitTime: 1500ms
        responseWaitTime: 2s
        aliveTimeInterval: 5s
        aliveExpirationTimeout: 25s
        reconnectInterval: 25s
        externalEndpoint:
        election:
            startupGracePeriod: 15s
            membershipSampleInterval: 1s
            leaderAliveThreshold: 10s
            leaderElectionDuration: 5s
        pvtData:
            pullRetryThreshold: 60s
            transientstoreMaxBlockRetention: 1000
            pushAckTimeout: 3s
            btlPullMargin: 10

    events:
        address: 0.0.0.0:7053
        buffersize: 100
        timeout: 10ms
        timewindow: 15m
        keepalive:
            minInterval: 60s

    tls:
        enabled:  false
        clientAuthRequired: false
        cert:
            file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt
        key:
            file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key
        rootcert:
            file: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
        clientRootCAs:
            files:
              - tls/ca.crt
        clientKey:
            file:
        clientCert:
            file:

    authentication:
        timewindow: 15m

    fileSystemPath: ./peer/production

    BCCSP:
        Default: SW
        SW:
            Hash: SHA2
            Security: 256
            FileKeyStore:
                KeyStore:
        PKCS11:
            Library:
            Label:
            Pin:
            Hash:
            Security:
            FileKeyStore:
                KeyStore:

    mspConfigPath: ./crypto-dir/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp

    localMspId: Org1MSP

    client:
        connTimeout: 3s

    deliveryclient:
        reconnectTotalTimeThreshold: 3600s
        connTimeout: 3s
        reConnectBackoffThreshold: 3600s

    localMspType: bccsp

    profile:
        enabled:     false
        listenAddress: 0.0.0.0:6060

    adminService:

    handlers:
        authFilters:
          -
            name: DefaultAuth
          -
            name: ExpirationCheck    # This filter checks identity x509 certificate expiration
        decorators:
          -
            name: DefaultDecorator
        endorsers:
          escc:
            name: DefaultEndorsement
            library:
        validators:
          vscc:
            name: DefaultValidation
            library:

    validatorPoolSize:

    discovery:
        enabled: true
        authCacheEnabled: true
        authCacheMaxSize: 1000
        authCachePurgeRetentionRatio: 0.75
        orgMembersAllowedAccess: false

vm:

    endpoint: unix:///var/run/docker.sock

    docker:
        tls:
            enabled: false
            ca:
                file: docker/ca.crt
            cert:
                file: docker/tls.crt
            key:
                file: docker/tls.key

        attachStdout: false

        hostConfig:
            NetworkMode: host
            Dns:
               # - 192.168.0.1
            LogConfig:
                Type: json-file
                Config:
                    max-size: "50m"
                    max-file: "5"
            Memory: 2147483648

chaincode:

    id:
        path:
        name:

    builder: $(DOCKER_NS)/fabric-ccenv:latest

    pull: false

    golang:
        runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

        dynamicLink: false

    car:
        runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

    java:
        Dockerfile:  |
            from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-1.1.0

    node:
        runtime: $(BASE_DOCKER_NS)/fabric-baseimage:$(ARCH)-$(BASE_VERSION)

    startuptimeout: 300s

    executetimeout: 30s

    mode: net

    keepalive: 0

    system:
        cscc: enable
        lscc: enable
        escc: enable
        vscc: enable
        qscc: enable

    systemPlugins:

    logging:
      level:  info
      shim:   warning
      format: '%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}'

ledger:

  blockchain:

  state:
    stateDatabase: goleveldb
    couchDBConfig:
       couchDBAddress: 127.0.0.1:5984
       username:
       password:
       maxRetries: 3
       maxRetriesOnStartup: 10
       requestTimeout: 35s
       queryLimit: 10000
       maxBatchUpdateSize: 1000
       warmIndexesAfterNBlocks: 1

  history:
    enableHistoryDatabase: true

metrics:
        enabled: false
        reporter: statsd
        interval: 1s
        statsdReporter:
              address: 0.0.0.0:8125
              flushInterval: 2s
              flushBytes: 1432

        promReporter:
              listenAddress: 0.0.0.0:8080

5.3 启动Peer节点

# 设置环境变量为当前目录
export set FABRIC_CFG_PATH=/Users/nisen/fabric-dir/demo

# 启动
peer node start

6 创建Channel

6.1 创建Channel

# 设置环境变量
➜  export set CORE_PEER_LOCALMSPID=Org1MSP
➜  export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

# 应当运行:
peer channel create -t 50 -o orderer.example.com:7050 -c alicetestchannel -f /Users/nisen/fabric-dir/demo/order/alicetestchannel.tx

# 但因为都在本地部署,实际上没有域名,所以实际运行:
peer channel create -t 50 -o 127.0.0.1:7050 -c alicetestchannel -f /Users/nisen/fabric-dir/demo/order/alicetestchannel.tx


2018-06-21 17:31:20.399 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-06-21 17:31:20.462 CST [channelCmd] InitCmdFactory -> INFO 002 Endorser and orderer connections initialized
2018-06-21 17:31:20.683 CST [main] main -> INFO 003 Exiting.....


# 运行完后会在当前目录生成alicetestchannel.block

6.2 让已经运行的peer加入channel

➜  export set CORE_PEER_LOCALMSPID=Org1MSP
➜  export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
➜  export set CORE_PEER_ADDRESS=peer0.org1.example.com:7051
➜  peer channel join -b ./alicetestchannel.block
Error: Error getting endorser client channel: endorser client failed to connect to peer0.org1.example.com:7051: failed to create new connection: context deadline exceeded

域名不可用,修改为
➜  export set CORE_PEER_ADDRESS=localhost:7051
➜  peer channel join -b ./alicetestchannel.block
2018-06-21 17:36:02.053 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-06-21 17:36:02.106 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
2018-06-21 17:36:02.106 CST [main] main -> INFO 003 Exiting.....

6.3 更新锚节点peer

➜  export set CORE_PEER_LOCALMSPID=Org1MSP
➜  export set CORE_PEER_MSPCONFIGPATH=/Users/nisen/fabric-dir/demo/crypto-dir/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
➜  export set CORE_PEER_ADDRESS=peer0.org1.example.com:7051  # 域名不可用,需要修改

➜  peer channel update -o localhost:7050 -c alicetestchannel -f ./order/Org1MSPanchors.tx
2018-06-21 17:39:03.820 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-06-21 17:39:03.884 CST [channelCmd] update -> INFO 002 Successfully submitted channel update
2018-06-21 17:39:03.885 CST [main] main -> INFO 003 Exiting.....

7 部署chancode

7.1 显示peer所加入的channel

➜  peer channel list

2018-06-21 17:40:16.125 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
alicetestchannel
2018-06-21 17:40:16.132 CST [main] main -> INFO 002 Exiting.....

7.2 部署chancode

➜  peer chaincode install -n examplechaincode -v 1.1 -p simpledemo
2018-06-21 17:49:58.103 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-06-21 17:49:58.103 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-06-21 17:49:59.043 CST [main] main -> INFO 003 Exiting.....

7.3 实例化chaincode

➜  peer chaincode instantiate -o localhost:7050 -C \
         alicetestchannel -n examplechaincode -v 1.1 -c '{"Args":["init","a","100","b","200"]}' \
         -P "OR ('Org1MSP.member','Org2MSP.member')"
2018-06-21 17:52:25.318 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-06-21 17:52:25.318 CST [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-06-21 17:52:48.665 CST [main] main -> INFO 003 Exiting.....

7.4 查看运行的容器

➜  docker ps
CONTAINER ID        IMAGE                                                                                                               COMMAND                  CREATED             STATUS              PORTS               NAMES
47d28c47b6eb        dev-peer0.org1.example.com-examplechaincode-1.1-d2b990146ffe74fcdfcdc76dbb4ad69ae46eb0a557d438972c6b66673ce3517e   "chaincode -peer.add…"   9 seconds ago       Up 8 seconds                            dev-peer0.org1.example.com-examplechaincode-1.1

7.5 调用chaincode

➜  peer chaincode invoke -o localhost:7050 -C alicetestchannel -n examplechaincode -c '{"Args":["invoke","a","b","1"]}'

Author: Nisen

Email: imnisenATgmailDOTcom

Emacs 25.2.1 (Org mode 8.2.10)