文章目录

  • 构建你的第一个网络(Building Your First Network)
    • 安装先决条件(Install prerequisites)
    • 想要现在运行吗(Want to run it now)?
      • 生成网络工件(Generate Network Artifacts)
      • 启动网络(Bring Up the Network)
      • 关闭网络(Bring Down the Network)
    • 加密材料生成器(Crypto Generator)
      • 它如何工作(How does it work)?
    • 配置交易生成器(Configuration Transaction Generator)
      • 它如何工作(How does it work)?
    • 运行工具(Run the tools)
      • 手工生成工件(Manually generate the artifacts)
      • 创建通道配置交易(Create a Channel Configuration Transaction)
    • 启动网络(Start the network)
      • 环境变量(Environment variables)
      • 创建和加入通道(Create & Join Channel)
      • 更新主播节点(Update the anchor peers)
      • 安装和实例化链代码(Install & Instantiate Chaincode)
      • 查询(Query)
      • 调用(Invoke)
      • 查询(Query)
      • 这个场景后面发生了什么(What’s happening behind the scenes)?
      • 这证明了什么(What does this demonstrate)?
      • 我如何看交易(How do I see these transactions)?
      • 我如何看链代码日志(How can I see the chaincode logs)?
    • 了解Docker Compose拓扑(Understanding the Docker Compose topology)
    • 使用CouchDB(Using CouchDB)
    • 为什么用CouchDB(Why CouchDB)
    • 关于数据持久性的注解(A Note on Data Persistence)
    • 故障排除(Troubleshooting)

构建你的第一个网络(Building Your First Network)

These instructions have been verified to work against the latest stable Docker images and the pre-compiled setup utilities within the supplied tar file. If you run these commands with images or tools from the current master branch, it is possible that you will see configuration and panic errors.
这些指令已经过验证,可以对付最新的稳定版Docker镜像以及提供的预编译设置实用工具tar文件。 如果使用当前主分支中的镜像或工具运行这些命令,则可能会看到配置和没有理由的错误。

The build your first network (BYFN) scenario provisions a sample Hyperledger Fabric network consisting of two organizations, each maintaining two peer nodes, and a “solo” ordering service.
构建你的第一个网络(BYFN)方案提供了一个示例Hyperledger Fabric网络,该网络由两个组织组成,每个组织维护两个对等节点,以及一个“单一”排序服务。

安装先决条件(Install prerequisites)

Before we begin, if you haven’t already done so, you may wish to check that you have all the Prerequisites installed on the platform(s) on which you’ll be developing blockchain applications and/or operating Hyperledger Fabric.
在我们开始之前,如果你还没有这样做,你可能希望检查是否已安装所有先决条件 在你将开发区块链应用程序和/或运行Hyperledger Fabric的平台上。

You will also need to Install Samples, Binaries and Docker Images. You will notice that there are a number of samples included in the fabric-samples repository. We will be using the first-network sample. Let’s open that sub-directory now.
你还需要安装样本,二进制文件和Docker镜像。 你会注意到fabric-samples存储库中包含了许多样本。 我们将使用first-network样本。 我们现在打开那个子目录。

cd fabric-samples/first-network

The supplied commands in this documentation MUST be run from your first-network sub-directory of the fabric-samples repository clone. If you elect to run the commands from a different location, the various provided scripts will be unable to find the binaries.
本文档中提供的命令必须从fabric-samples存储库克隆的first-network子目录运行。 如果你选择从其他位置运行命令,则各种提供的脚本将无法找到二进制文件。

想要现在运行吗(Want to run it now)?

We provide a fully annotated script - byfn.sh - that leverages these Docker images to quickly bootstrap a Hyperledger Fabric network comprised of 4 peers representing two different organizations, and an orderer node. It will also launch a container to run a scripted execution that will join peers to a channel, deploy and instantiate chaincode and drive execution of transactions against the deployed chaincode.
我们提供了一个完全注释的脚本 - byfn.sh - 它利用这些Docker镜像快速引导Hyperledger Fabric网络,该网络由代表两个不同组织的4个对等节点和一个排序节点组成。 它还将启动一个容器来运行脚本执行,该执行将对等节点连接到一个通道,部署和实例化链代码并根据部署的链代码驱动交易执行。

Here’s the help text for the byfn.sh script:
这是byfn.sh脚本的帮助文本:

Usage:byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-i <imagetag>] [-v]<mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'- 'up' - bring up the network with docker-compose up- 'down' - clear the network with docker-compose down- 'restart' - restart the network- 'generate' - generate required certificates and genesis block- 'upgrade'  - upgrade the network from v1.0.x to v1.1-c <channel name> - channel name to use (defaults to "mychannel")-t <timeout> - CLI timeout duration in seconds (defaults to 10)-d <delay> - delay duration in seconds (defaults to 3)-f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)-s <dbtype> - the database backend to use: goleveldb (default) or couchdb-l <language> - the chaincode language: golang (default), node or java-i <imagetag> - the tag to be used to launch the network (defaults to "latest")-v - verbose modebyfn.sh -h (print this message)Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:byfn.sh generate -c mychannelbyfn.sh up -c mychannel -s couchdbbyfn.sh up -c mychannel -s couchdb -i 1.1.0-alphabyfn.sh up -l nodebyfn.sh down -c mychannelbyfn.sh upgrade -c mychannelTaking all defaults:byfn.sh generatebyfn.sh upbyfn.sh down

If you choose not to supply a channel name, then the script will use a default name of mychannel. The CLI timeout parameter (specified with the -t flag) is an optional value; if you choose not to set it, then the CLI will give up on query requests made after the default setting of 10 seconds.
如果你选择不提供通道名称,则脚本将使用默认名称“mychannel”。 CLI超时参数(使用-t标志指定)是可选值; 如果你选择不设置它,那么CLI将在默认设置的10秒后放弃查询请求。

生成网络工件(Generate Network Artifacts)

Ready to give it a go? Okay then! Execute the following command:
准备好了吗? 好吧! 执行以下命令:

./byfn.sh generate

You will see a brief description as to what will occur, along with a yes/no command line prompt. Respond with a y or hit the return key to execute the described action.
你将看到有关将发生什么的简要说明,以及是/否命令行提示。 用y回答或按回车键执行描述的动作。

appletekiMacBook-Pro:first-network apple$ ./byfn.sh generate
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
/Users/apple/go/src/github.com/hyperledger/fabric-samples/first-network/../bin/cryptogen##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x/Users/apple/go/src/github.com/hyperledger/fabric-samples/first-network/../bin/configtxgen
##########################################################
#########  Generating Orderer Genesis block ##############
##########################################################
+ configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
2018-10-19 16:09:22.434 CST [common/tools/configtxgen] main -> WARN 001 Omitting the channel ID for configtxgen for output operations is deprecated.  Explicitly passing the channel ID will be required in the future, defaulting to 'testchainid'.
2018-10-19 16:09:22.437 CST [common/tools/configtxgen] main -> INFO 002 Loading configuration
2018-10-19 16:09:22.496 CST [common/tools/configtxgen] doOutputBlock -> INFO 003 Generating genesis block
2018-10-19 16:09:22.498 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Writing genesis block
+ res=0
+ set +x#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2018-10-19 16:09:22.576 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-10-19 16:09:22.622 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-10-19 16:09:22.628 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 003 Writing new channel tx
+ res=0
+ set +x#################################################################
#######    Generating anchor peer update for Org1MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2018-10-19 16:09:22.703 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-10-19 16:09:22.736 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-10-19 16:09:22.736 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
+ res=0
+ set +x#################################################################
#######    Generating anchor peer update for Org2MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2018-10-19 16:09:22.801 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-10-19 16:09:22.844 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-10-19 16:09:22.844 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
+ res=0
+ set +x

This first step generates all of the certificates and keys for our various network entities, the genesis block used to bootstrap the ordering service, and a collection of configuration transactions required to configure a Channel.
第一步为我们的各种网络实体生成所有证书和密钥,用于引导排序服务的genesis block,以及配置[通道](https:// hyperledger-fabric。readthedocs.io/en/release-1.3/glossary.html#channel)所需的一组配置交易。

启动网络(Bring Up the Network)

(后面准备运行node链代码,会报错,把所有.sh文件中 -v 1.0 改为 -v 1.33:-1.0改为3:-1.3,就能正常运行)

Next, you can bring the network up with one of the following commands:
接下来,你可以使用以下命令之一启动网络:

./byfn.sh up

The above command will compile Golang chaincode images and spin up the corresponding containers. Go is the default chaincode language, however there is also support for Node.js and Java chaincode. If you’d like to run through this tutorial with node chaincode, pass the following command instead:
上面的命令将编译Golang链代码镜像并加速相应的容器。 Go是默认的链代码语言,但也支持Node.js和Java 链代码。 如果你想通过node链代码运行本教程,请改为使用以下命令:

# we use the -l flag to specify the chaincode language
# forgoing the -l flag will default to Golang./byfn.sh up -l node

For more information on the Node.js shim, please refer to its documentation.
有关Node.js shim的更多信息,请参阅其文档。

For more information on the Java shim, please refer to its documentation.
有关Java shim的更多信息,请参阅其文档。

Тo make the sample run with Java chaincode, you have to specify -l java as follows:
如果使用Java链代码运行示例,则必须指定-l java,如下所示:

./byfn.sh up -l java

Do not run both of these commands. Only one language can be tried unless you bring down and recreate the network between.
不要同时运行这两个命令。 除非你关闭并重新创建网络,否则只能尝试一种语言。

Once again, you will be prompted as to whether you wish to continue or abort. Respond with a y or hit the return key:
再次,系统将提示你是继续还是中止。 回答y或点击回车键:

appletekiMacBook-Pro:first-network apple$ ./byfn.sh up -l node
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
LOCAL_VERSION=1.3.0
DOCKER_IMAGE_VERSION=1.3.0
Creating network "net_byfn" with the default driver
Creating volume "net_orderer.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating peer1.org2.example.com ... done
Creating peer0.org2.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer0.org1.example.com ... done
Creating orderer.example.com    ... done
Creating cli                    ... done____    _____      _      ____    _____
/ ___|  |_   _|    / \    |  _ \  |_   _|
\___ \    | |     / _ \   | |_) |   | |  ___) |   | |    / ___ \  |  _ <    | |
|____/    |_|   /_/   \_\ |_| \_\   |_|  Build your first network (BYFN) end-to-end testChannel name : mychannel
Creating channel...
+ peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --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
+ res=0
+ set +x
2018-10-19 08:09:39.675 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:39.730 UTC [cli/common] readBlock -> INFO 002 Received block: 0
===================== Channel 'mychannel' created ===================== Having all peers join the channel...
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2018-10-19 08:09:39.863 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:39.911 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org1 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block
+ res=0
+ set +x
2018-10-19 08:09:43.052 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:43.096 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org1 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block
+ res=0
+ set +x
2018-10-19 08:09:46.237 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:46.292 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org2 joined channel 'mychannel' ===================== + peer channel join -b mychannel.block
+ res=0
+ set +x
2018-10-19 08:09:49.437 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:49.484 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org2 joined channel 'mychannel' ===================== Updating anchor peers for org1...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --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
+ res=0
+ set +x
2018-10-19 08:09:52.629 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:52.658 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org1MSP' on channel 'mychannel' ===================== Updating anchor peers for org2...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --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
+ res=0
+ set +x
2018-10-19 08:09:55.781 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-10-19 08:09:55.809 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org2MSP' on channel 'mychannel' ===================== Installing chaincode on peer0.org1...
+ peer chaincode install -n mycc -v 1.3 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/
+ res=0
+ set +x
2018-10-19 08:09:58.970 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-10-19 08:09:58.970 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-10-19 08:09:58.986 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer0.org1 ===================== Install chaincode on peer0.org2...
+ peer chaincode install -n mycc -v 1.3 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/
+ res=0
+ set +x
2018-10-19 08:09:59.145 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-10-19 08:09:59.145 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-10-19 08:09:59.159 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer0.org2 ===================== Instantiating chaincode on peer0.org2...
+ peer chaincode instantiate -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 -l node -v 1.3 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'
+ res=0
+ set +x
2018-10-19 08:09:59.309 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-10-19 08:09:59.310 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' ===================== Querying chaincode on peer0.org1...
===================== Querying on peer0.org1 on channel 'mychannel'... =====================
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer0.org1 ...3 secs
+ res=0
+ set +x100
===================== Query successful on peer0.org1 on channel 'mychannel' =====================
Sending invoke transaction on peer0.org1 peer0.org2...
+ 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"]}'
+ res=0
+ set +x
2018-10-19 08:11:41.470 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' ===================== Installing chaincode on peer1.org2...
+ peer chaincode install -n mycc -v 1.3 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/
+ res=0
+ set +x
2018-10-19 08:11:41.622 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-10-19 08:11:41.622 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-10-19 08:11:41.642 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" >
===================== Chaincode is installed on peer1.org2 ===================== Querying chaincode on peer1.org2...
===================== Querying on peer1.org2 on channel 'mychannel'... =====================
Attempting to Query peer1.org2 ...3 secs
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
+ res=0
+ set +x90
===================== Query successful on peer1.org2 on channel 'mychannel' ===================== ========= All GOOD, BYFN execution completed =========== _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

You can scroll through these logs to see the various transactions. If you don’t get this result, then jump down to the Troubleshooting section and let’s see whether we can help you discover what went wrong.
你可以滚动浏览这些日志以查看各种事务。 如果你没有得到这个结果,那么跳到故障排除部分,让我们看看我们是否可以帮助你发现问题。

关闭网络(Bring Down the Network)

Finally, let’s bring it all down so we can explore the network setup one step at a time. The following will kill your containers, remove the crypto material and four artifacts, and delete the chaincode images from your Docker Registry:
最后,让我们把它全部放下,这样我们就可以一步一步地探索网络设置。 以下内容将终止你的容器,删除加密材料和四个文件,并从Docker Registry中删除链代码镜像:

./byfn.sh down

Once again, you will be prompted to continue, respond with a y or hit the return key:
再一次,系统将提示你继续,以y回复或点击回车键:

appletekiMacBook-Pro:first-network apple$ ./byfn.sh down
Stopping for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
Stopping cli                    ... done
Stopping orderer.example.com    ... done
Stopping peer0.org2.example.com ... done
Stopping peer0.org1.example.com ... done
Stopping peer1.org1.example.com ... done
Stopping peer1.org2.example.com ... done
Removing cli                    ... done
Removing orderer.example.com    ... done
Removing peer0.org2.example.com ... done
Removing peer0.org1.example.com ... done
Removing peer1.org1.example.com ... done
Removing peer1.org2.example.com ... done
Removing network net_byfn
Removing volume net_orderer.example.com
Removing volume net_peer0.org1.example.com
Removing volume net_peer1.org1.example.com
Removing volume net_peer0.org2.example.com
Removing volume net_peer1.org2.example.com
Removing volume net_peer0.org3.example.com
WARNING: Volume net_peer0.org3.example.com not found.
Removing volume net_peer1.org3.example.com
WARNING: Volume net_peer1.org3.example.com not found.
ecb4fdc92f08
371265c5742b
09345fac83ed
Untagged: dev-peer1.org2.example.com-mycc-1.3-382167099009df91290882e242a2f144a07c1d6ddb4a0a026f58c03c759dfd52:latest
Deleted: sha256:2cc1d46f3be5372466f85018e113b00d5e835ace9538166b298214b388225af8
Deleted: sha256:5449d6c12453181e8ac2554783e03da8ae34b4125c1eaf18271481a9b9e0da01
Deleted: sha256:04419c789a444d1224e1d462a74edb708a6ce7605f983f97a2276166b47d4ed8
Deleted: sha256:fbaf2f7733aa26c1fd20ac4e92771f3831377922acb9353263ef406a7fceae60
Untagged: dev-peer0.org1.example.com-mycc-1.3-f06095641d6dc000080874fa4076a996130733a970973834b35af14851f9a0f4:latest
Deleted: sha256:4402a7363aa40acead3bbba0d3917c77bcff6650fd88e2cb5f0cf52c75c1d80a
Deleted: sha256:fa8516c3ccbc3504e7fb826c72435219dd6c36ee18a2d55a2c2dadf914851cb9
Deleted: sha256:856305e1de606a4ab38de20e16f67f7303fc7a17101186d5ac98fdfee6562a56
Deleted: sha256:f272755391d3e5180491d0c0763e7e32a5235a8137a3c9b4b61fb1bc0237b601
Untagged: dev-peer0.org2.example.com-mycc-1.3-1eb1a770d33b0287ab46570523c2f9d1c35f2e4794920cf70d1841a20e74095b:latest
Deleted: sha256:97f4d6292ee2c37fa11e14a6f1e9692382d6ce86864c62aa48c7820910a651cb
Deleted: sha256:9c863a43d8b5e24c1a1ed197f76fcef1a7efe5e4a473e8c98d777aa76a16cb49
Deleted: sha256:713f12cc236025a9582f6f24943b45b9123cf0a1db43c23a74b70cab4f5534bd
Deleted: sha256:a47634d20eac92b4629bdb39f309bc7cf1aa5b20208f2eaa566eaf948f57c05a

If you’d like to learn more about the underlying tooling and bootstrap mechanics, continue reading. In these next sections we’ll walk through the various steps and requirements to build a fully-functional Hyperledger Fabric network.
如果你想了解有关底层工具和引导机制的更多信息,请继续阅读。 在接下来的部分中,我们将介绍构建全功能Hyperledger Fabric网络的各种步骤和要求。

The manual steps outlined below assume that the CORE_LOGGING_LEVEL in the cli container is set to DEBUG. You can set this by modifying the docker-compose-cli.yaml file in the first-network directory. e.g.
下面列出的手动步骤假定cli容器中的CORE_LOGGING_LEVEL设置为DEBUG。 你可以通过修改first-network目录中的docker-compose-cli.yaml文件来设置它。 例如。

cli:container_name: cliimage: hyperledger/fabric-tools:$IMAGE_TAGtty: truestdin_open: trueenvironment:- GOPATH=/opt/gopath- CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock- CORE_LOGGING_LEVEL=DEBUG#- CORE_LOGGING_LEVEL=INFO

加密材料生成器(Crypto Generator)

We will use the cryptogen tool to generate the cryptographic material (x509 certs and signing keys) for our various network entities. These certificates are representative of identities, and they allow for sign/verify authentication to take place as our entities communicate and transact.
我们将使用cryptogen工具为我们的各种网络实体生成加密材料(x509证书和签名密钥)。 这些证书代表身份,它们允许在我们的实体进行通信和交易时进行签名/验证身份认证。

它如何工作(How does it work)?

Cryptogen consumes a file - crypto-config.yaml - that contains the network topology and allows us to generate a set of certificates and keys for both the Organizations and the components that belong to those Organizations. Each Organization is provisioned a unique root certificate (ca-cert) that binds specific components (peers and orderers) to that Org. By assigning each Organization a unique CA certificate, we are mimicking a typical network where a participating Member would use its own Certificate Authority. Transactions and communications within Hyperledger Fabric are signed by an entity’s private key (keystore), and then verified by means of a public key (signcerts).
Cryptogen使用一个文件 - “crypto-config.yaml” - 包含网络拓扑,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。 每个组织都配置了一个唯一的根证书(ca-cert),它将特定组件(对等节点和排序节点)绑定到该组织。 通过为每个组织分配一个唯一的CA证书,我们模仿一个典型的网络,其中参与的成员会使用它自己的证书颁发机构。 Hyperledger Fabric中的交易和通信由实体的私钥(keystore)签名,然后通过公钥(signcerts)进行验证。

You will notice a count variable within this file. We use this to specify the number of peers per Organization; in our case there are two peers per Org. We won’t delve into the minutiae of x.509 certificates and public key infrastructure right now. If you’re interested, you can peruse these topics on your own time.
你会注意到这个文件中有一个count变量。 我们用它来指定每个组织的对等节点数量; 在我们的例子中,每个Org有两个对等节点。 我们现在不会深入研究x.509证书和公钥基础设施的细枝末节。 如果你有兴趣,可以在自己的时间内仔细阅读这些主题。

Before running the tool, let’s take a quick look at a snippet from the crypto-config.yaml. Pay specific attention to the “Name”, “Domain” and “Specs” parameters under the OrdererOrgs header:
在运行该工具之前,让我们快速浏览一下crypto-config.yaml的片段。 特别注意OrdererOrgs标题下的“Name”,“Domain”和“Specs”参数:

OrdererOrgs:
#---------------------------------------------------------
# Orderer
# --------------------------------------------------------
- Name: OrdererDomain: example.comCA:Country: USProvince: CaliforniaLocality: San Francisco#   OrganizationalUnit: Hyperledger Fabric#   StreetAddress: address for org # default nil#   PostalCode: postalCode for org # default nil# ------------------------------------------------------# "Specs" - See PeerOrgs below for complete description
# -----------------------------------------------------Specs:- Hostname: orderer
# -------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes# ------------------------------------------------------
PeerOrgs:
# -----------------------------------------------------
# Org1
# ----------------------------------------------------
- Name: Org1Domain: org1.example.comEnableNodeOUs: true

The naming convention for a network entity is as follows - “{{.Hostname}}.{{.Domain}}”. So using our ordering node as a reference point, we are left with an ordering node named - orderer.example.com that is tied to an MSP ID of Orderer. This file contains extensive documentation on the definitions and syntax. You can also refer to the Membership Service Providers (MSP) documentation for a deeper dive on MSP.
网络实体的命名约定如下 - “{{.Hostname}}.{{.Domain}}”。 因此,使用我们的排序节点作为参考点,我们留下一个名为 - “orderer.example.com”的排序节点,它与“Orderer”的MSP ID相关联。 该文件包含有关定义和语法的大量文档。 你还可以参考会员服务提供者(MSP)文档,深入了解MSP。

After we run the cryptogen tool, the generated certificates and keys will be saved to a folder titled crypto-config.
运行cryptogen工具后,生成的证书和密钥将保存到名为crypto-config的文件夹中。

配置交易生成器(Configuration Transaction Generator)

The configtxgen tool is used to create four configuration artifacts:
configtxgen工具用于创建四个配置工件:

  • orderer genesis block,
    排序节点genesis block
  • channel configuration transaction,
    通道configuration transaction
  • and two anchor peer transactions - one for each Peer Org.
    和两个“anchor peer transactions” - 每个对等节点的组织一个。

Please see configtxgen for a complete description of this tool’s functionality.
有关此工具功能的完整说明,请参阅configtxgen。

The orderer block is the Genesis Block for the ordering service, and the channel configuration transaction file is broadcast to the orderer at Channel creation time. The anchor peer transactions, as the name might suggest, specify each Org’s Anchor Peer on this channel.
排序节点区块是排序服务的创世区块,并且通道配置交易文件在通道创建时被广播到排序节点。 正如名称所暗示的那样,主播节点交易在此通道上指定每个组织的主播节点。

它如何工作(How does it work)?

Configtxgen consumes a file - configtx.yaml - that contains the definitions for the sample network. There are three members - one Orderer Org (OrdererOrg) and two Peer Orgs (Org1 & Org2) each managing and maintaining two peer nodes. This file also specifies a consortium - SampleConsortium - consisting of our two Peer Orgs. Pay specific attention to the “Profiles” section at the top of this file. You will notice that we have two unique headers. One for the orderer genesis block - TwoOrgsOrdererGenesis - and one for our channel - TwoOrgsChannel.
Configtxgen使用一个文件 - configtx.yaml - 包含示例网络的定义。有三个成员 - 一个排序节点的组织(OrdererOrg)和两个对等节点的组织(Org1Org2),每个对等节点的组织管理和维护两个对等节点。该文件还指定了一个联盟 - SampleConsortium - 由这两个对等节点组织组成。请特别注意此文件顶部的“配置文件”部分。你会注意到我们有两个唯一的头部。一个用于排序节点创世区块 - TwoOrgsOrdererGenesis - ,一个用于我们的通道 - TwoOrgsChannel

These headers are important, as we will pass them in as arguments when we create our artifacts.
这些头部很重要,因为我们将在创建工件时将它们作为参数传递。

Notice that our SampleConsortium is defined in the system-level profile and then referenced by our channel-level profile. Channels exist within the purview of a consortium, and all consortia must be defined in the scope of the network at large.
请注意,我们的SampleConsortium在系统级配置文件中定义,然后由我们的通道级配置文件引用。通道存在于一个联盟的范围内,所有联盟必须在整个网络范围内定义。

This file also contains two additional specifications that are worth noting. Firstly, we specify the anchor peers for each Peer Org (peer0.org1.example.com & peer0.org2.example.com). Secondly, we point to the location of the MSP directory for each member, in turn allowing us to store the root certificates for each Org in the orderer genesis block. This is a critical concept. Now any network entity communicating with the ordering service can have its digital signature verified.
此文件还包含两个值得注意的其他规范。首先,我们为每个对等节点的组织指定主播节点(peer0.org1.example.compeer0.org2.example.com)。其次,我们指出每个成员的MSP目录的位置,从而允许我们在排序节点创世区块中存储每个组织的根证书。这是一个关键概念。现在,与排序服务通信的任何网络实体都可以验证其数字签名。

运行工具(Run the tools)

You can manually generate the certificates/keys and the various configuration artifacts using the configtxgen and cryptogen commands. Alternately, you could try to adapt the byfn.sh script to accomplish your objectives.
你可以使用configtxgencryptogen命令手动生成证书/密钥和各种配置工件。 或者,你可以尝试调整byfn.sh脚本来实现目标。

手工生成工件(Manually generate the artifacts)

You can refer to the generateCerts function in the byfn.sh script for the commands necessary to generate the certificates that will be used for your network configuration as defined in the crypto-config.yaml file. However, for the sake of convenience, we will also provide a reference here.
你可以在byfn.sh脚本中引用generateCerts函数,以获取生成将用于你的网络配置的证书所需的命令,如crypto-config.yaml文件中所定义。 但是,为方便起见,我们也将在此提供参考。

First let’s run the cryptogen tool. Our binary is in the bin directory, so we need to provide the relative path to where the tool resides.
首先让我们运行cryptogen工具。 我们的二进制文件位于bin目录中,因此我们需要提供工具所在位置的相对路径。

../bin/cryptogen generate --config=./crypto-config.yaml

You should see the following in your terminal:
你应该在终端中看到以下内容:

org1.example.com
org2.example.com

The certs and keys (i.e. the MSP material) will be output into a directory - crypto-config - at the root of the first-network directory.
证书和密钥(即MSP材料)将输出到first-network目录下的 - “crypto-config” - 目录。

Next, we need to tell the configtxgen tool where to look for the configtx.yaml file that it needs to ingest. We will tell it look in our present working directory:
接下来,我们需要告诉configtxgen工具在哪里查找它需要用到的configtx.yaml文件。 我们将在目前的工作目录中告诉它:

export FABRIC_CFG_PATH=$PWD

Then, we’ll invoke the configtxgen tool to create the orderer genesis block:
然后,我们将调用configtxgen工具来创建排序节点创世区块:

../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

You should see an output similar to the following in your terminal:
你应该在终端中看到类似于以下内容的输出:

2018-10-22 10:13:12.673 CST [common/tools/configtxgen] main -> INFO 002 Loading configuration
2018-10-22 10:13:12.735 CST [common/tools/configtxgen] doOutputBlock -> INFO 003 Generating genesis block
2018-10-22 10:13:12.736 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Writing genesis block

The orderer genesis block and the subsequent artifacts we are about to create will be output into the channel-artifacts directory at the root of this project.
** 排序节点创世区块和我们即将创建的后续工件将输出到该项目根目录的channel-artifacts目录中。**

创建通道配置交易(Create a Channel Configuration Transaction)

Next, we need to create the channel transaction artifact. Be sure to replace $CHANNEL_NAME or set CHANNEL_NAME as an environment variable that can be used throughout these instructions:
接下来,我们需要创建通道交易工件。 请务必替换$ CHANNEL_NAME或将CHANNEL_NAME设置为可在整个说明中使用的环境变量:

# The channel.tx artifact contains the definitions for our sample channelexport CHANNEL_NAME=mychannel  && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

You should see an output similar to the following in your terminal:
你应该在终端中看到类似于以下内容的输出:

2018-10-19 16:09:22.576 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-10-19 16:09:22.622 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-10-19 16:09:22.628 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 003 Writing new channel tx

Next, we will define the anchor peer for Org1 on the channel that we are constructing. Again, be sure to replace $CHANNEL_NAME or set the environment variable for the following commands. The terminal output will mimic that of the channel transaction artifact:
接下来,我们将在我们构建的通道上为Org1定义主播节点。 同样,请务必替换$ CHANNEL_NAME或为以下命令设置环境变量。 终端输出将模仿通道交易工件的输出:

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

Now, we will define the anchor peer for Org2 on the same channel:
现在我们将在同一个通道定义Org2的主播节点:

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

启动网络(Start the network)

If you ran the byfn.sh example above previously, be sure that you have brought down the test network before you proceed (see Bring Down the Network).
如果你之前运行过byfn.sh示例,请确保在继续操作之前已关闭测试网络(请参阅关闭网络).

We will leverage a script to spin up our network. The docker-compose file references the images that we have previously downloaded, and bootstraps the orderer with our previously generated genesis.block.
我们将利用脚本来运转我们的网络。 docker-compose文件引用我们之前下载的镜像,并引导之前生成genesis.block的排序节点。

We want to go through the commands manually in order to expose the syntax and functionality of each call.
我们希望手动完成命令,以便公开每个调用的语法和功能。

First let’s start our network:
首先让我们开始我们的网络:

docker-compose -f docker-compose-cli.yaml up -d

If you want to see the realtime logs for your network, then do not supply the -d flag. If you let the logs stream, then you will need to open a second terminal to execute the CLI calls.
如果要查看网络的实时日志,请不要提供-d标志。 如果你让日志输出,那么你将需要打开第二个终端来执行CLI调用。

环境变量(Environment variables)

For the following CLI commands against peer0.org1.example.com to work, we need to preface our commands with the four environment variables given below. These variables for peer0.org1.example.com are baked into the CLI container, therefore we can operate without passing them. HOWEVER, if you want to send calls to other peers or the orderer, then you can provide these values accordingly by editing the docker-compose-base.yaml before starting the container. Modify the following four environment variables to use a different peer and org.
要使以下针对peer0.org1.example.com的CLI命令起作用,我们需要在命令前加上下面给出的四个环境变量。 peer0.org1.example.com的这些变量被内置到CLI容器中,因此我们可以在不传递它们的情况下进行操作。 但是,如果要将调用发送给其他对等节点或排序节点,则可以在启动容器之前通过编辑docker-compose-base.yaml来相应地提供这些值。 修改以下四个环境变量以使用不同的对等节点和组织。

# Environment variables for PEER0CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
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

创建和加入通道(Create & Join Channel)

Recall that we created the channel configuration transaction using the configtxgen tool in the Create a Channel Configuration Transaction section, above. You can repeat that process to create additional channel configuration transactions, using the same or different profiles in the configtx.yaml that you pass to the configtxgen tool. Then you can repeat the process defined in this section to establish those other channels in your network.
回想一下,我们在前面使用创建通道配置交易部分中的configtxgen工具创建了通道配置交易。 你可以使用传递给configtxgen工具的configtx.yaml中相同或不同的配置文件重复该过程以创建其他通道配置交易。 然后,你可以重复本节中定义的过程,以在你的网络中建立其他通道。

We will enter the CLI container using the docker exec command:
我们将使用docker exec命令进入CLI容器:

docker exec -it cli bash

If successful you should see the following:
如果成功,你将看到如下内容:

root@f3675199c17d:/opt/gopath/src/github.com/hyperledger/fabric/peer#

If you do not want to run the CLI commands against the default peer peer0.org1.example.com, replace the values of peer0 or org1 in the four environment variables and run the commands:
如果你不想针对默认对等节点peer0.org1.example.com运行CLI命令,请在四个环境变量中替换peer0org1的值并运行命令:

# Environment variables for PEER0export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
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/peer0.org1.example.com/tls/ca.crt

Next, we are going to pass in the generated channel configuration transaction artifact that we created in the Create a Channel Configuration Transaction section (we called it channel.tx) to the orderer as part of the create channel request.
接下来,我们将传递我们在创建通道配置交易中创建的生成的通道配置事务工件作为创建通道请求的一部分(我们称之为“channel.tx”)给排序节点。

We specify our channel name with the -c flag and our channel configuration transaction with the -f flag. In this case it is channel.tx, however you can mount your own configuration transaction with a different name. Once again we will set the CHANNEL_NAME environment variable within our CLI container so that we don’t have to explicitly pass this argument. Channel names must be all lower case, less than 250 characters long and match the regular expression [a-z][a-z0-9.-]*.
我们使用-c标志指定通道名称,使用-f标志指定通道配置交易。 在这种情况下,它是channel.tx,但是你可以使用不同的名称装入自己的配置交易。 我们将再次在CLI容器中设置CHANNEL_NAME环境变量,以便我们不必显式传递此参数。 通道名称必须全部小写,长度小于250个字符,并匹配正则表达式[a-z] [a-z0-9 .-] *

export CHANNEL_NAME=mychannel# the channel.tx file is mounted in the channel-artifacts directory within your CLI container
# as a result, we pass the full path for the file
# we also pass the path for the orderer ca-cert in order to verify the TLS handshake
# be sure to export or replace the $CHANNEL_NAME variable appropriatelypeer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.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

Notice the --cafile that we pass as part of this command. It is the local path to the orderer’s root cert, allowing us to verify the TLS handshake.
注意我们作为此命令的一部分传递的--cafile。 它是排序节点的根证书的本地路径,允许我们验证TLS握手。

This command returns a genesis block - <channel-ID.block> - which we will use to join the channel. It contains the configuration information specified in channel.tx If you have not made any modifications to the default channel name, then the command will return you a proto titled mychannel.block.
该命令返回一个创世块 - <channel-ID.block> - 我们将用它来加入通道。 它包含channel.tx中指定的配置信息。如果你没有对默认通道名称进行任何修改,那么该命令将返回一个名为mychannel.block的原型。

You will remain in the CLI container for the remainder of these manual commands. You must also remember to preface all commands with the corresponding environment variables when targeting a peer other than peer0.org1.example.com.
为了这些手动命令的其余部分,你将保留在CLI容器中。 在目标是除peer0.org1.example.com以外的对等节点时,你还必须记住在所有命令前加上相应的环境变量。

Now let’s join peer0.org1.example.com to the channel.
现在让我们将peer0.org1.example.com加入通道。

# By default, this joins ``peer0.org1.example.com`` only
# the <channel-ID.block> was returned by the previous command
# if you have not modified the channel name, you will join with mychannel.block
# if you have created a different channel name, then pass in the appropriately named blockpeer channel join -b mychannel.block

You can make other peers join the channel as necessary by making appropriate changes in the four environment variables we used in the Environment variables section, above.
你可以根据需要通过对上面提到的[环境变量](https://hyperledger-fabric.readthedocs.io/en/release-1.3/build_network.html# peerenvvars)章节中使用的四个环境变量进行适当更改来使其他对等节点加入通道。

Rather than join every peer, we will simply join peer0.org2.example.com so that we can properly update the anchor peer definitions in our channel. Since we are overriding the default environment variables baked into the CLI container, this full command will be the following:
我们只需加入peer0.org2.example.com,而不是加入每个对等节点,这样我们就可以正确地更新通道中的主播节点定义。 由于我们将覆盖CLI容器中的默认环境变量,因此完整命令如下:

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" 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 peer channel join -b mychannel.block

Alternatively, you could choose to set these environment variables individually rather than passing in the entire string. Once they’ve been set, you simply need to issue the peer channel join command again and the CLI container will act on behalf of peer0.org2.example.com.
或者,你可以选择单独设置这些环境变量,而不是传入整个字符串。 一旦设置完毕,你只需再次发出peer channel join命令,CLI容器将代表peer0.org2.example.com

更新主播节点(Update the anchor peers)

The following commands are channel updates and they will propagate to the definition of the channel. In essence, we adding additional configuration information on top of the channel’s genesis block. Note that we are not modifying the genesis block, but simply adding deltas into the chain that will define the anchor peers.
以下命令是通道更新,它们将传播到通道的定义。 实质上,我们在通道的创世区块之上添加了额外的配置信息。 请注意,我们不是修改genesis块,而是简单地将增量添加到将定义主播节点的链中。

Update the channel definition to define the anchor peer for Org1 as peer0.org1.example.com:
更新通道定义以将Org1的主播节点定义为“peer0.org1.example.com”:

peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./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

Now update the channel definition to define the anchor peer for Org2 as peer0.org2.example.com. Identically to the peer channel join command for the Org2 peer, we will need to preface this call with the appropriate environment variables.
现在更新通道定义,将Org2的主播节点定义为peer0.org2.example.com。 与Org2对等节点的peer channel join命令相同,我们需要在此调用前加上适当的环境变量。

CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 CORE_PEER_LOCALMSPID="Org2MSP" 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 peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./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

安装和实例化链代码(Install & Instantiate Chaincode)

We will utilize a simple existing chaincode. To learn how to write your own chaincode, see the Chaincode for Developers tutorial.
我们将使用简单的现有链代码。 要了解如何编写自己的链代码,请参阅Chaincode for Developers教程。

Applications interact with the blockchain ledger through chaincode. As such we need to install the chaincode on every peer that will execute and endorse our transactions, and then instantiate the chaincode on the channel.
应用程序通过chaincode与区块链帐本交互。 因此,我们需要在每个将执行和背书我们交易的对等节点上安装链代码,然后在通道上实例化链代码。

First, install the sample Go, Node.js or Java chaincode onto one of the four peer nodes. These commands place the specified source code flavor onto our peer’s filesystem.
首先,将示例Go,Node.js或Java链代码安装到四个对等节点之一上。 这些命令将指定的源代码放在我们的对等节点文件系统上。

You can only install one version of the source code per chaincode name and version. The source code exists on the peer’s file system in the context of chaincode name and version; it is language agnostic. Similarly the instantiated chaincode container will be reflective of whichever language has been installed on the peer.
每个链代码名称和版本只能安装一个版本的源代码。 源代码存在于对等节点基于链代码名称和版本的文件系统中; 它与语言无关。 类似地,实例化的链代码容器将反映对等节点上安装的任何语言。

Golang

# this installs the Go chaincode
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

Node.js

# this installs the Node.js chaincode
# make note of the -l flag; we use this to specify the language
peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/

Java

peer chaincode install -n mycc -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/

Next, instantiate the chaincode on the channel. This will initialize the chaincode on the channel, set the endorsement policy for the chaincode, and launch a chaincode container for the targeted peer. Take note of the -P argument. This is our policy where we specify the required level of endorsement for a transaction against this chaincode to be validated.
接下来,在通道上实例化链码。 这将初始化通道上的链代码,设置链代码的背书策略,并为目标对等节点启动链代码容器。 记下-P参数。 这是我们的策略,我们在此策略中指定针对要验证的链代码交易所需的请求级别。

In the command below you’ll notice that we specify our policy as -P "AND ('Org1MSP.peer','Org2MSP.peer')". This means that we need “endorsement” from a peer belonging to Org1 AND Org2 (i.e. two endorsement). If we changed the syntax to OR then we would need only one endorsement.
在下面的命令中,你会注意到我们将策略指定为-P "AND ('Org1MSP.peer','Org2MSP.peer')"。 这意味着我们需要来自属于Org1 和 Org2的对等节点的“背书”(即两个背书)。 如果我们将语法更改为OR,那么我们只需要一个背书。

Golang

# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as wellpeer 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 $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

Node.js

The instantiation of the Node.js chaincode will take roughly a minute. The command is not hanging; rather it is installing the fabric-shim layer as the image is being compiled.
** Node.js链代码的实例化大约需要一分钟。 命令没有挂起; 而是在编译镜像时安装fabric-shim层。**

# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well
# notice that we must pass the -l flag after the chaincode name to identify the languagepeer 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 $CHANNEL_NAME -n mycc -l node -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

Java

Please note, Java chaincode instantiation might take time as it compiles chaincode and downloads docker container with java environment.
请注意,Java链代码实例化可能需要一些时间,因为它编译链代码并下载java环境的docker容器。

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 $CHANNEL_NAME -n mycc -l java -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

See the endorsement policies documentation for more details on policy implementation.
有关策略实施的更多详细信息,请参阅背书策略文档。

If you want additional peers to interact with ledger, then you will need to join them to the channel, and install the same name, version and language of the chaincode source onto the appropriate peer’s filesystem. A chaincode container will be launched for each peer as soon as they try to interact with that specific chaincode. Again, be cognizant of the fact that the Node.js images will be slower to compile.
如果你希望其他对等节点与帐本进行交互,则需要将它们连接到通道,并将相同名称、版本和语言的链代码安装到相应的对等节点文件系统上。 一旦他们尝试与特定的链代码进行交互,就会为每个对等节点启动一个链代码容器。 再次,要认识到Node.js镜像的编译速度会慢一些。

Once the chaincode has been instantiated on the channel, we can forgo the l flag. We need only pass in the channel identifier and name of the chaincode.
一旦在通道上实例化了链代码,我们就可以放弃l标志。 我们只需传递通道标识符和链代码的名称。

查询(Query)

Let’s query for the value of a to make sure the chaincode was properly instantiated and the state DB was populated. The syntax for query is as follows:
让我们查询a的值,以确保链代码被正确实例化并填充状态数据库。 查询语法如下:

# be sure to set the -C and -n flags appropriatelypeer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

调用(Invoke)

Now let’s move 10 from a to b. This transaction will cut a new block and update the state DB. The syntax for invoke is as follows:
现在让我们将10a移动到b。 此交易将生成新区块并更新状态数据库。 调用的语法如下:

# be sure to set the -C and -n flags appropriatelypeer 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 $CHANNEL_NAME -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"]}'

查询(Query)

Let’s confirm that our previous invocation executed properly. We initialized the key a with a value of 100 and just removed 10 with our previous invocation. Therefore, a query against a should reveal 90. The syntax for query is as follows.
让我们确认我们之前的调用是否正确执行。 我们使用值100初始化了键a,并使用之前的调用去掉了10。 因此,对a的查询应该显示90。 查询的语法如下。

# be sure to set the -C and -n flags appropriatelypeer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

We should see the following:
我们将看到如下内容:

Query Result: 90

Feel free to start over and manipulate the key value pairs and subsequent invocations.
随意重新开始并操纵键值对和后续调用。

这个场景后面发生了什么(What’s happening behind the scenes)?

These steps describe the scenario in which script.sh is run by ‘./byfn.sh up’. Clean your network with ./byfn.sh down and ensure this command is active. Then use the same docker-compose prompt to launch your network again
这些步骤描述了由’./byfn.sh up’运行的script.sh场景。 使用./ byfn.sh down清理网络并确保此命令处于活动状态。 然后使用相同的docker-compose提示再次启动你的网络

  • A script - script.sh - is baked inside the CLI container. The script drives the createChannel command against the supplied channel name and uses the channel.tx file for channel configuration.
    脚本 - script.sh - 内置在CLI容器中。该脚本根据提供的通道名称驱动createChannel命令,并使用channel.tx文件进行通道配置。
  • The output of createChannel is a genesis block - <your_channel_name>.block - which gets stored on the peers’ file systems and contains the channel configuration specified from channel.tx.
    createChannel的输出是一个创世区块 - <your_channel_name> .block - 它存储在对等节点的文件系统中,并包含从channel.tx指定的通道配置。
  • The joinChannel command is exercised for all four peers, which takes as input the previously generated genesis block. This command instructs the peers to join <your_channel_name> and create a chain starting with <your_channel_name>.block.
    对所有四个对等节点执行joinChannel命令,该命令将先前生成的创世区块作为输入。此命令指示对等节点加入<your_channel_name>并创建以<your_channel_name>.block开头的链。
  • Now we have a channel consisting of four peers, and two organizations. This is our TwoOrgsChannel profile.
    现在我们有一个由四个对等节点和两个组织组成的通道。这是我们的TwoOrgsChannel配置。
  • peer0.org1.example.com and peer1.org1.example.com belong to Org1; peer0.org2.example.com and peer1.org2.example.com belong to Org2
    peer0.org1.example.compeer1.org1.example.com属于Org1; peer0.org2.example.compeer1.org2.example.com属于Org2
  • These relationships are defined through the crypto-config.yaml and the MSP path is specified in our docker compose.
    这些关系是通过crypto-config.yaml定义的,MSP路径是在我们的docker compose中指定的。
  • The anchor peers for Org1MSP (peer0.org1.example.com) and Org2MSP (peer0.org2.example.com) are then updated. We do this by passing the Org1MSPanchors.tx and Org2MSPanchors.tx artifacts to the ordering service along with the name of our channel.
    然后更新Org1MSP(peer0.org1.example.com)和Org2MSP(peer0.org2.example.com)的主播节点。我们通过将Org1MSPanchors.txOrg2MSPanchors.tx工件以及我们的通道名称传递给排序服务来实现这一目的。
  • A chaincode - chaincode_example02 - is installed on peer0.org1.example.com and peer0.org2.example.com
    链代码 - chaincode_example02 - 安装在peer0.org1.example.compeer0.org2.example.com
  • The chaincode is then “instantiated” on peer0.org2.example.com. Instantiation adds the chaincode to the channel, starts the container for the target peer, and initializes the key value pairs associated with the chaincode. The initial values for this example are [“a”,”100” “b”,”200”]. This “instantiation” results in a container by the name of dev-peer0.org2.example.com-mycc-1.0 starting.
    然后在peer0.org2.example.com上“实例化”链代码。实例化将链代码添加到通道,启动目标对等节点的容器,并初始化与链代码关联的键值对。该示例的初始值是[“a”,“100”“b”,“200”]。这个“实例化”会产生一个名为dev-peer0.org2.example.com-mycc-1.0的容器。
  • The instantiation also passes in an argument for the endorsement policy. The policy is defined as -P "AND ('Org1MSP.peer','Org2MSP.peer')", meaning that any transaction must be endorsed by a peer tied to Org1 and Org2.
    实例化也传递了背书策略的论据。该策略定义为-P "AND ('Org1MSP.peer','Org2MSP.peer')",表示任何交易必须由与Org1和Org2绑定的对等节点背书。
  • A query against the value of “a” is issued to peer0.org1.example.com. The chaincode was previously installed on peer0.org1.example.com, so this will start a container for Org1 peer0 by the name of dev-peer0.org1.example.com-mycc-1.0. The result of the query is also returned. No write operations have occurred, so a query against “a” will still return a value of “100”.
    peer0.org1.example.com发出针对“a”值的查询。链代码以前安装在peer0.org1.example.com上,因此这将为Org1 peer0启动一个名为dev-peer0.org1.example.com-mycc-1.0的容器。还将返回查询结果。没有发生写入操作,因此对“a”的查询仍将返回值“100”。
  • An invoke is sent to peer0.org1.example.com to move “10” from “a” to “b”
    调用被发送到peer0.org1.example.com以将“10”从“a”移动到“b”
  • The chaincode is then installed on peer1.org2.example.com
    然后将链代码安装在peer1.org2.example.com
  • A query is sent to peer1.org2.example.com for the value of “a”. This starts a third chaincode container by the name of dev-peer1.org2.example.com-mycc-1.0. A value of 90 is returned, correctly reflecting the previous transaction during which the value for key “a” was modified by 10.
    查询被发送到peer1.org2.example.com以获取“a”的值。这将启动名为dev-peer1.org2.example.com-mycc-1.0的第三个链代码容器。返回值90,正确反映上一个事务,在此期间,键“a”的值被修改为10。

这证明了什么(What does this demonstrate)?

Chaincode MUST be installed on a peer in order for it to successfully perform read/write operations against the ledger. Furthermore, a chaincode container is not started for a peer until an init or traditional transaction - read/write - is performed against that chaincode (e.g. query for the value of “a”). The transaction causes the container to start. Also, all peers in a channel maintain an exact copy of the ledger which comprises the blockchain to store the immutable, sequenced record in blocks, as well as a state database to maintain a snapshot of the current state. This includes those peers that do not have chaincode installed on them (like peer1.org1.example.com in the above example) . Finally, the chaincode is accessible after it is installed (like peer1.org2.example.com in the above example) because it has already been instantiated.
链代码必须安装在对等节点上才能成功对帐本执行读/写操作。 此外,对等节点不启动链代码容器,直到针对该链代码执行“init”或传统的交易 - 读/写 - (例如,查询“a”的值)。 该交易导致容器启动。 此外,通道中的所有对等节点都保持帐本的精确副本,其包括用于以区块的形式存储不可变的有序记录的区块链,以及用于维护当前状态快照的状态数据库。 这包括那些没有安装链代码的对等节点(如上例中的peer1.org1.example.com)。 最后,链代码在安装后可以访问(如上例中的peer1.org2.example.com)因为它已经被实例化了。

我如何看交易(How do I see these transactions)?

Check the logs for the CLI Docker container.
检查CLI容器的日志:

docker logs -f cli

You should see the following output:
你将看到如下输出:

2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query successful on peer1.org2 on channel 'mychannel' ========================================== All GOOD, BYFN execution completed =====================_____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

You can scroll through these logs to see the various transactions.
你可以滚动浏览这些日志以查看各种交易。

我如何看链代码日志(How can I see the chaincode logs)?

Inspect the individual chaincode containers to see the separate transactions executed against each container. Here is the combined output from each container:
检查各个链代码容器,以查看针对每个容器执行的单独交易。 以下是每个容器的组合输出:

$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

了解Docker Compose拓扑(Understanding the Docker Compose topology)

The BYFN sample offers us two flavors of Docker Compose files, both of which are extended from the docker-compose-base.yaml (located in the base folder). Our first flavor, docker-compose-cli.yaml, provides us with a CLI container, along with an orderer, four peers. We use this file for the entirety of the instructions on this page.
BYFN示例为我们提供了两种Docker Compose文件,这两种文件都是从docker-compose-base.yaml(位于base文件夹中)扩展而来的。我们第一种风格的docker-compose-cli.yaml为我们提供了一个CLI容器,以及一个排序节点,四个对等节点。我们将此文件用于此页面上的所有说明。

** the remainder of this section covers a docker-compose file designed for the SDK. Refer to the Node SDK repo for details on running these tests.**
本节的其余部分介绍了为SDK设计的docker-compose文件。有关运行这些测试的详细信息,请参阅Node SDK库。

The second flavor, docker-compose-e2e.yaml, is constructed to run end-to-end tests using the Node.js SDK. Aside from functioning with the SDK, its primary differentiation is that there are containers for the fabric-ca servers. As a result, we are able to send REST calls to the organizational CAs for user registration and enrollment.
第二种风格docker-compose-e2e.yaml构建为使用Node.js SDK运行端到端测试。除了使用SDK之外,它的主要区别在于有Fabric-ca服务器的容器。因此,我们可以向组织CA发送REST调用以进行用户登记和注册。

If you want to use the docker-compose-e2e.yaml without first running the byfn.sh script, then we will need to make four slight modifications. We need to point to the private keys for our Organization’s CA’s. You can locate these values in your crypto-config folder. For example, to locate the private key for Org1 we would follow this path - crypto-config/peerOrganizations/org1.example.com/ca/. The private key is a long hash value followed by _sk. The path for Org2 would be - crypto-config/peerOrganizations/org2.example.com/ca/.
如果你想在没有先运行byfn.sh脚本的情况下使用docker-compose-e2e.yaml,那么我们需要进行四次略微修改。我们需要指向组织CA的私钥。你可以在crypto-config文件夹中找到这些值。例如,要找到Org1的私钥,我们将遵循这条路径 - crypto-config/peerOrganizations/org1.example.com/ca/。私钥是一个长哈希值,后跟_sk。 Org2的路径是 - crypto-config/peerOrganizations/org2.example.com/ca/

In the docker-compose-e2e.yaml update the FABRIC_CA_SERVER_TLS_KEYFILE variable for ca0 and ca1. You also need to edit the path that is provided in the command to start the ca server. You are providing the same private key twice for each CA container.
docker-compose-e2e.yaml中更新了ca0和ca1的FABRIC_CA_SERVER_TLS_KEYFILE变量。你还需要编辑命令中提供的路径以启动ca服务器。你为每个CA容器提供两次相同的私钥。

使用CouchDB(Using CouchDB)

The state database can be switched from the default (goleveldb) to CouchDB. The same chaincode functions are available with CouchDB, however, there is the added ability to perform rich and complex queries against the state database data content contingent upon the chaincode data being modeled as JSON.
状态数据库可以从默认(goleveldb)切换到CouchDB。 CouchDB提供了相同的链代码功能,但是,根据链代码数据被建模为JSON,还可以根据状态数据库数据内容执行丰富而复杂的查询。

To use CouchDB instead of the default database (goleveldb), follow the same procedures outlined earlier for generating the artifacts, except when starting the network pass docker-compose-couch.yaml as well:
要使用CouchDB而不是默认数据库(goleveldb),请按照前面概述的相同步骤生成工件,除了在启动网络时用docker-compose-couch.yaml

docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d

chaincode_example02 should now work using CouchDB underneath.
chaincode_example02 现在应该使用下面的CouchDB。

If you choose to implement mapping of the fabric-couchdb container port to a host port, please make sure you are aware of the security implications. Mapping of the port in a development environment makes the CouchDB REST API available, and allows the visualization of the database via the CouchDB web interface (Fauxton). Production environments would likely refrain from implementing port mapping in order to restrict outside access to the CouchDB containers.
如果你选择将fabric-couchdb容器端口映射到主机端口,请确保你了解安全隐患。在开发环境中映射端口使CouchDB REST API可用,并允许通过CouchDB Web界面(Fauxton)可视化数据库。生产环境可能会避免实施端口映射,以限制对CouchDB容器的外部访问。

You can use chaincode_example02 chaincode against the CouchDB state database using the steps outlined above, however in order to exercise the CouchDB query capabilities you will need to use a chaincode that has data modeled as JSON, (e.g. marbles02). You can locate the marbles02 chaincode in the fabric/examples/chaincode/go directory.
你可以使用上面列出的步骤对CouchDB状态数据库使用chaincode_example02 链代码,但是为了练习CouchDB查询功能,你需要使用具有建模为JSON的数据的链代码(例如marbles02 )。你可以在fabric/examples/chaincode/go directory中找到marbles02链代码。

We will follow the same process to create and join the channel as outlined in the Create & Join Channel section above. Once you have joined your peer(s) to the channel, use the following steps to interact with the marbles02 chaincode:
我们将按照相同的流程创建和加入通道,如上面的创建和加入通道部分所述。将对等节点加入通道后,请使用以下步骤与marbles02链代码进行交互:

  • Install and instantiate the chaincode on peer0.org1.example.com:
    peer0.org1.example.com上安装并实例化链代码:
# be sure to modify the $CHANNEL_NAME variable accordingly for the instantiate commandpeer chaincode install -n marbles -v 1.0 -p github.com/chaincode/marbles02/go
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 $CHANNEL_NAME -n marbles -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org0MSP.peer','Org1MSP.peer')"
  • Create some marbles and move them around:
    创建一些弹珠并移动它们:
# be sure to modify the $CHANNEL_NAME variable accordinglypeer 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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
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 $CHANNEL_NAME -n marbles -c '{"Args":["delete","marble1"]}'
  • If you chose to map the CouchDB ports in docker-compose, you can now view the state database through the CouchDB web interface (Fauxton) by opening a browser and navigating to the following URL:
    如果你选择在docker-compose中映射CouchDB端口,现在可以通过打开浏览器并导航到以下URL,通过CouchDB Web界面(Fauxton)查看状态数据库:
http://localhost:5984/_utils

You should see a database named mychannel (or your unique channel name) and the documents inside it.
你应该看到名为mychannel(或你的唯一通道名称)的数据库及其中的文档。

For the below commands, be sure to update the CHANNELNAMEvariableappropriately.∗∗∗∗对于以下命令,请务必正确更新CHANNEL_NAME variable appropriately.** **对于以下命令,请务必正确更新CHANNELN​AMEvariableappropriately.∗∗∗∗对于以下命令,请务必正确更新CHANNEL_NAME变量。

You can run regular queries from the CLI (e.g. reading marble2):
你可以从CLI运行常规查询(例如,读marble2):

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'

The output should display the details of marble2:
输出应显示marble2的详细信息:

Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}

You can retrieve the history of a specific marble - e.g. marble1:
你可以检索特定弹珠的历史记录 - 例如marble1

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'

The output should display the transactions on marble1:
输出应显示marble1上的交易:

Query Result: [{"TxId":"1c3d3caf124c89f91a4c0f353723ac736c58155325f02890adebaa15e16e6464", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}},{"TxId":"755d55c281889eaeebf405586f9e25d71d36eb3d35420af833a20a2f53a3eefd", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}},{"TxId":"819451032d813dde6247f85e56a89262555e04f14788ee33e28b232eef36d98f", "Value":}]

You can also perform rich queries on the data content, such as querying marble fields by owner jerry:
你还可以对数据内容执行丰富的查询,例如按所有者jerry查询弹珠字段:

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'

The output should display the two marbles owned by jerry:
输出应该显示jerry拥有的两个弹珠:

Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]

为什么用CouchDB(Why CouchDB)

CouchDB is a kind of NoSQL solution. It is a document-oriented database where document fields are stored as key-value maps. Fields can be either a simple key-value pair, list, or map. In addition to keyed/composite-key/key-range queries which are supported by LevelDB, CouchDB also supports full data rich queries capability, such as non-key queries against the whole blockchain data, since its data content is stored in JSON format and fully queryable. Therefore, CouchDB can meet chaincode, auditing, reporting requirements for many use cases that not supported by LevelDB.
CouchDB是一种NoSQL解决方案。它是一个面向文档的数据库,其中文档字段存储为键值映射。字段可以是简单的键值对,列表或映射。除了LevelDB支持的键/复合键/键范围查询外,CouchDB还支持全部数据丰富查询功能,例如针对整个区块链数据的非键查询,因为其数据内容以JSON格式存储,完全可查询。因此,CouchDB可以满足LevelDB不支持的许多用例的链代码,审计和报告要求。

CouchDB can also enhance the security for compliance and data protection in the blockchain. As it is able to implement field-level security through the filtering and masking of individual attributes within a transaction, and only authorizing the read-only permission if needed.
CouchDB还可以增强区块链中的合规性和数据保护的安全性。因为它能够通过过滤和屏蔽交易中的各个属性来实现字段级安全性,并且需要时只授权只读权限。

In addition, CouchDB falls into the AP-type (Availability and Partition Tolerance) of the CAP theorem. It uses a master-master replication model with Eventual Consistency. More information can be found on the Eventual Consistency page of the CouchDB documentation. However, under each fabric peer, there is no database replicas, writes to database are guaranteed consistent and durable (not Eventual Consistency).
此外,CouchDB属于CAP定理的AP类型(可用性和分区容错性)。它使用具有最终一致性的主 - 主复制模型。有关更多信息,请参见CouchDB文档的最终一致性页面。但是,在每个对等节点下,没有数据库副本,对数据库的写入保证一致且持久(不是最终一致性)。

CouchDB is the first external pluggable state database for Fabric, and there could and should be other external database options. For example, IBM enables the relational database for its blockchain. And the CP-type (Consistency and Partition Tolerance) databases may also in need, so as to enable data consistency without application level guarantee.
CouchDB是Fabric的第一个外部可插拔状态数据库,可能也应该有其他外部数据库选项。例如,IBM为其区块链启用了关系数据库。并且CP类型(一致性和分区容错性)数据库也可能需要,以便在没有应用程序级别保证的情况下实现数据一致性。

关于数据持久性的注解(A Note on Data Persistence)

If data persistence is desired on the peer container or the CouchDB container, one option is to mount a directory in the docker-host into a relevant directory in the container. For example, you may add the following two lines in the peer container specification in the docker-compose-base.yaml file:
如果在节点容器或CouchDB容器上需要数据持久性,则可以选择将docker-host中的目录安装到容器中的相关目录中。 例如,你可以在docker-compose-base.yaml文件的节点容器规范中添加以下两行:

volumes:- /var/hyperledger/peer0:/var/hyperledger/production

For the CouchDB container, you may add the following two lines in the CouchDB container specification:
对于CouchDB容器,你可以在CouchDB容器规范中添加以下两行:

volumes:- /var/hyperledger/couchdb0:/opt/couchdb/data

故障排除(Troubleshooting)

  • Always start your network fresh. Use the following command to remove artifacts, crypto, containers and chaincode images:
    始终保持网络新鲜。 使用以下命令删除工件、加密材料、容器和链代码镜像:
./byfn.sh down

You will see errors if you do not remove old containers and images.
如果你不删除旧容器和镜像,你将看到错误。

  • If you see Docker errors, first check your docker version (Prerequisites), and then try restarting your Docker process. Problems with Docker are oftentimes not immediately recognizable. For example, you may see errors resulting from an inability to access crypto material mounted within a container.
    如果你看到Docker错误,请首先检查你的docker版本(先决条件),然后尝试重新启动Docker进程。 Docker的问题通常无法立即识别。 例如,你可能会看到因无法访问容器中安装的加密材料而导致的错误。

If they persist remove your images and start from scratch:
如果他们坚持删除你的镜像并从头开始:

docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -q)
  • If you see errors on your create, instantiate, invoke or query commands, make sure you have properly updated the channel name and chaincode name. There are placeholder values in the supplied sample commands.
    如果在创建、实例化、调用或查询命令中看到错误,请确保已正确更新通道名称和链代码名称。 提供的示例命令中有占位符值。
  • If you see the below error:
    如果你看到以下错误:
Error: Error endorsing chaincode: rpc error: code = 2 desc = Error installing chaincode code mycc:1.0(chaincode /var/hyperledger/production/chaincodes/mycc.1.0 exits)

You likely have chaincode images (e.g. dev-peer1.org2.example.com-mycc-1.0 or dev-peer0.org1.example.com-mycc-1.0) from prior runs. Remove them and try again.
你可能从之前的运行中拥有了链代码镜像(例如dev-peer1.org2.example.com-mycc-1.0dev-peer0.org1.example.com-mycc-1.0)。 删除它们然后再试一次。

docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
  • If you see something similar to the following:
    如果你看到类似于以下内容的内容:
Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure

Make sure you are running your network against the “1.0.0” images that have been retagged as “latest”.
确保你正在使用已被重新标记为“最新”的“1.3.0”镜像运行你的网络。

  • If you see the below error:
    如果你看到以下错误:
[configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type ""
panic: Error reading configuration: Unsupported Config Type ""

Then you did not set the FABRIC_CFG_PATH environment variable properly. The configtxgen tool needs this variable in order to locate the configtx.yaml. Go back and execute an export FABRIC_CFG_PATH=$PWD, then recreate your channel artifacts.
然后你没有正确设置FABRIC_CFG_PATH环境变量。 configtxgen工具需要此变量才能找到configtx.yaml。 返回并执行export FABRIC_CFG_PATH = $ PWD,然后重新创建通道工件。

  • To cleanup the network, use the down option:
    要清理网络,请使用down选项:
./byfn.sh down
  • If you see an error stating that you still have “active endpoints”, then prune your Docker networks. This will wipe your previous networks and start you with a fresh environment:
    如果你看到一条错误,指出你仍然有“活动端点”,那么请删除你的Docker网络。 这将擦除你之前的网络,并为你提供一个全新的环境:
docker network prune

You will see the following message:
你将看到以下消息:

WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N]

Select y.
y

  • If you see an error similar to the following:
    如果你看到类似于以下内容的错误:
/bin/bash: ./scripts/script.sh: /bin/bash^M: bad interpreter: No such file or directory

Ensure that the file in question (script.sh in this example) is encoded in the Unix format. This was most likely caused by not setting core.autocrlf to false in your Git configuration (see Windows extras). There are several ways of fixing this. If you have access to the vim editor for instance, open the file:
确保有问题的文件(本例中为script.sh)以Unix格式编码。 这很可能是因为你的Git配置中没有将core.autocrlf设置为false(参见Windows extras)。 有几种方法可以解决这个问题。 例如,如果你有权访问vim编辑器,请打开文件:

vim ./fabric-samples/first-network/scripts/script.sh

Then change its format by executing the following vim command:
然后通过执行以下vim命令更改其格式:

:set ff=unix

If you continue to see errors, share your logs on the fabric-questions channel on Hyperledger Rocket Chat or on StackOverflow.
如果你继续看到错误,请在Hyperledger Rocket Chat或StackOverflow上的fabric-questions频道上分享你的日志。

Hyperledger Fabric 1.3 官方文档翻译(五)教程 (Tutorials) - 5.2 构建你的第一个网络 (Building Your First Network)相关推荐

  1. Hyperledger Fabric 1.3 官方文档翻译(三)关键概念 (Key Concepts) - 3.7 对等节点 (Peers)

    文章目录 对等节点(Peers) 术语(A word on terminology) 账本与链代码(Ledgers and Chaincode) 多账本(Multiple Ledgers) 多链代码( ...

  2. Hyperledger Fabric(构建你的第一个网络)

    构建你的第一个网络 这些说明已经过验证,可以与最新的稳定Docker镜像和提供的tar文件中预编译的安装实用程序一起工作,如果使用当前主分支中的镜像或工具运行这些命令,则可能会看到配置和紧急错误. 构 ...

  3. Hyperledger Fabric 1.0 从零开始(五)——运行测试e2e

    3:运行测试e2e 3.1.运行fabric-samples的问题说明 该问题说明能够解决6.1.平台特定使用的二进制文件配置第一步的问题.可以选择继续阅读该说明,或者等参考到6.1小节时再反向阅读本 ...

  4. Android官方文档翻译 五 1.3Building a Simple User Interface

    Building a Simple User Interface 创建一个简单的用户界面 This lesson teaches you to 这节课将教给你: Create a Linear Lay ...

  5. Injective Protocol官方文档翻译(五) -衍生产品规范(Derivatives Specification) 概述

    文章目录 一.衍生产品规范(Derivatives Specification) 概述 拓展:什么是永续合约?永续合约特点有哪些? 拓展:头寸(position) 一.衍生产品规范(Derivativ ...

  6. Hyperledger Fabric构建第一个网络(官方教程)

    前言 官方英文:Building Your First Network 中文:构建第一个fabric网络 感谢中文翻译!不然这么长的英文以及各种名词解释实在头疼.有一些和官方英文不一样的地方我已经按官 ...

  7. Hyperledger Fabric 2.0 官方文档中文版 第6章 教程(上)

    Hyperledger Fabric 2.0 官方文档中文版第6章 教程上 总目录 6.教程(上) 将智能合约部署到通道 启动网络 Logspout设置 打包智能合约 安装链码包 批准链码定义 将链码 ...

  8. Hyperledger Fabric 2.0 官方文档中文版 第6章 教程(下)

    Hyperledger Fabric 2.0 官方文档中文版 第6章 教程下 总目录 6.教程(下) 使用CouchDB 为什么使用CouchDB? 在Hyperledger Fabric中启用Cou ...

  9. Hyperledger Fabric 1.0 从零开始(八)——Fabric多节点集群生产部署

    6.1.平台特定使用的二进制文件配置 该方案与Hyperledger Fabric 1.0 从零开始(五)--运行测试e2e类似,根据企业需要,可以控制各节点的域名,及联盟链的统一域名.可以指定单独节 ...

最新文章

  1. 推荐一个关于.NET平台数据结构和算法的好项目
  2. Java 25 岁,发展现状大曝光!程序员的机会来了
  3. 智能车竞赛技术报告 | 智能车视觉 - 中国计量大学 - 赛博-10
  4. .Net Discovery系列之十二-深入理解平台机制与性能影响(下)
  5. VC 为静态控件添加事件
  6. shp与json互转(转载)
  7. Counting Bits
  8. percona-toolkit工具包安装
  9. 用户扫描二维码进入公众号后自动发送指定消息_wetool的封杀、企业微信的崛起,我们要怎么利用企业微信进行用户增长?...
  10. Oracle 11g RAC 自动应用PSU补丁简明版
  11. hp服务器系统检测,HP服务器检测步骤
  12. CamShift算法1
  13. c# 调用浏览器打开页面
  14. STM32与S3C2440的区别
  15. 某商店规定,某商品一次购买5件以上(包含5件)打九折,一次购买10件以上(包含10件)打八折,请根据单价和数量球总价
  16. matplotlib保存图片去除白边
  17. JPG插入GPS信息
  18. html 注销 按钮,用户登录/注销时隐藏/替换菜单项
  19. FISCO BCOS 2022年度贡献者榜单
  20. Zookeeper--简介

热门文章

  1. 使用ip命令配置静态ip及网关
  2. 我的世界服务器物品不掉落,我的世界局域网服务器怎样设置死亡不掉落东西
  3. devops_DevOps:责备的后果
  4. Thinksystem SR550通过管理口收集日志的方法
  5. 4个数字计算24点java算法(附源码)
  6. 3.技术总体的工作模式和方法
  7. 以智能化为基座,城市安全发展驶入快车道
  8. 宝,运维100+服务器很头疼怎么办?用行云管家!
  9. Swin Transformer V2
  10. 今天发现猎豹浏览器的一个大坑 Request.IsAuthenticated 一直为 false;另外附加原因以及临时的解决方法...