1、链码操作:Fabric 1.4 vs Fabric 2.0我们将首先快速介绍在HF 1.4和HF 2.0中的整个链码操作过程。
链码操作指的是在Hyperledger fabric网络通道上部署链码的操作,这样区块链 之外的应用可以调用或查询链码方法。在链码开发完成并测试后,首先需要 将Fabric链码安装到指定的peer节点。在这个阶段链码还不能使用,直到 链码被提交(Fabric 2.0中的术语)到通道中或在通道上实例化(Fabric 1.4中的 术语),这样链码就可以被授权用户访问了。% I4 H8 A2 a# Z2 e$ q+ O! F$ w5 e
下面是两个版本的Hyperledger Fabric中链码操作流程的对比图:
在Hyperledger Fabric 1.4中,链码操作过程包含以下步骤:打包、安装、实例化。 如果链码属于多个参与方,那么就需要打包这一环节。如果不存在多方属主的问题, 那么直接安装链码就可以(其中隐含了打包环节)。在Fabric链码安装时需要指定 要安装链码的目标节点。
在这个阶段,安装好的Fabric链码还不能使用,因为它还没有在通道上实例化。 当Fabric链码包被安装在指定的节点上之后,我们就可以执行链码实例化操作, 从而让链码在通道上可用。技术上来说,链码实例化实际上就是调用LSCC系统链码 的方法来初始化通道上的一个链码。5 h8 B# t" e6 f# l: E# Y
Fabric链码实例化之后就可以使用了,可以接受通道上的调用或查询请求。
下面我们看在Hyperledger Fabric 2.0中的链码操作步骤有何区别。
宽泛地来讲,在Fabric 2.0中链码操作基本遵循同样的流程,但是在命令和某些 后台处理中做了一些调整。整体的流程可以分为四个步骤:打包、安装、机构审批、 链码提交。大致可以认为前两个环节对应于Fabric 1.4中的链码安装,后面两个 环节对应于Fabric 1.4中的链码实例化,但是实例化(instantiation)这个词不再 用了。
链码打包这一步是创建一个打包文件(tar格式),其中包含Fabric链码以及一些元数据。 虽然不同的机构可以分别进行打包处理,更常见是由一个机构打包然后分发给其他 机构以便确保所有的机构使用相同的链码。
安装步骤是将打包的Fabric链码文件安装在指定的peer节点上。和之前的版本一样, 只有需要接受链码调用的节点才需要安装链码。在这个节点,Fabric链码还不可用, 因为还没有提交到通道中。链码安装的结果是得到一个包标识符,其格式为.。
机构审批是在Hyperledger Fabric 2.0中增加的步骤。在之前的版本中我们可以让 一个机构实例化链码。在Fabric 2.0中,需要机构显式地审批链码。需要多少机构 审批则是由生命周期背书策略来决定,默认情况下设置为需要大多数机构(超过半数)。 如果Fabric网络中包含两个机构,那么就需要这两个机构同时批准。在审批过程中 需要排序节点的参与,因为每次审批都会生成一个新的区块,这意味着所有的peer 节点都了解审批的状态。
当审批环节完成后,我们就需要指定要在哪个通道上部署链码。这需要提交一些信息, 例如背书策略、是否需要执行Init代码等等。在这里也有些与Fabric 1.4不同的地方: 在Fabric 1.4中,当链码实例化时会自动调用链码的Init方法,然而在Fabric 2.0中, 需要在提交链码后显式地调用Init方法。
在批准机构达到指定数量后,链码就可以提交了。我们现在就进入了最后一个步骤: 链码提交。# f; a9 w) N. z: t
链码提交可以由任何机构发起。该流程首先需要批准机构的背书,然后交易提交到 排序服务并生成新的区块,最后所有的对等节点在账本中提交该区块。
现在链码就可以使用了。
2、First Network和SACC链码简介出于完整性考虑,下面给出关于First Network和SACC链码的一些信息,这些内容 都来自fabric-samples仓库。, f( ^2 j/ n" e
First Network是一个双机构设置,每个机构中包含两个peer节点。通道mychannel 创建后加入所有的4个peer节点。在byfn.sh中完整的实现了First Network的部署, 并包含一些可选的参数。在下面的演示中,我们不使用默认的链码(在Fabric 1.4 中式chaincode_example02,在Fabric 2.0中式abstore),而是使用SACC链码。- l7 ^! j6 O# u+ [
SACC式Simple Asset ChainCode的缩写,表示简单资产链码。它在账本中模拟一个 键/值存储。当初次部署后,需要一个初始的键/值对。SACC链码定义了两个方法: Set()和Get(),分别用来设置或读取某个键的值。
好了,现在我们可以开始演示Fabric 1.4和Fabric 2.0中链码操作的不同了。
3、Fabric 1.4.4链码操作演示我们首先以无链码方式(使用-n选项)启动First Network,然后我们再加载 SACC链码以便聚焦链码的生命周期。- p' [& E* X: `. A/ f0 o# G
下面是演示步骤:
无链码方式启动First Network在指定的peer节点上安装SACC链码在mychannel通道上实例化SACC链码并查询结果调用set()设置新值并从另一个peer节点查询结果STEP 1:首先启动First Network:5 m/ k# h9 u; O4 [5 Z# k
1 2 | cd fabric-samples/first-network. m7 C3 v! c# p7 u& `; c ./byfn.sh up -n |
现在我们可以开始链码部署操作。: P, T% A, b+ a! N$ c
STEP 2:在指定peer节点上安装链码
这里我们跳过打包环节,直接在目标节点peer.org1和peer0.org2上安装链码, 因为在这个演示中我们只需要这两个节点进行链码调用和查询。
1' p/ v: a3 G) F9 L% O: N) H4 D 2! K s& U& U) Y6 m 3 4* s1 x7 {1 W1 O7 ^/ F+ v3 Y& i/ \ 5 61 m- E! k3 S* S9 x; i- N 7 81 X7 e$ r# c3 L" K& {* S# F) V9 O* V 9 10 | # peer0.org1 docker exec cli peer chaincode install -n mycc -v 1 \5 t5 c* K+ b% h -p github.com/chaincode/sacc # peer0.org2 docker exec \ -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \ -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 -e CORE_PEER_LOCALMSPID="Org2MSP" \ -e 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 \- r6 L" K9 b$ ?2 C# ^ cli peer chaincode install -n mycc -v 1 -p github.com/chaincode/sacc+ v3 i9 p: |. f |
STEP 3:在通道mychannel上实例化链码并查询
注意在sacc链码中有Init()代码。当我们实例化链码时,我们需要 提供Init()所需的参数:- E5 d4 [7 G4 M9 z8 J2 {
1 2; {+ X3 H2 v" \1 d8 U1 m0 X 3 {1 f6 V3 q- @& f& V6 I) ^6 J. U- f 4: d4 P, B4 x$ c) D2 @+ r2 q5 p* U | docker exec cli peer chaincode instantiate -o orderer.example.com:7050 --tls \7 r' m; Y8 R# r/ _' q4 G --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \; d0 Y i% f$ ?2 o! i6 j, p4 Q -C mychannel -n mycc -v 1 -c '{"Args":["name","kc"]}' \* ]4 b6 R! _6 u' m$ a -P "AND ('Org1MSP.peer','Org2MSP.peer')"/ I2 g& c# x9 j0 a6 s2 }1 R0 k: q |
如果现在看看peer节点的日志,我们可以看到出了新区块#3。; e6 J @; k. ]3 s1 h
在链码实例化之后,我们可以查询:
1 | docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}' |
STEP 4:调用set()设置新值并从另一个节点查询: q* E5 j( |. W: k6 J
出于演示目的,我们在peer0.org1上调用set(),然后在peer0.org2上 调用get(),以此说明链码是否工作正常。! M, h2 d. q% a$ I7 D
12 j, L3 c- B# V/ b8 E 2 3 4) S! i! J4 F7 `/ y) Y, r 5 6, m* I& U7 S7 x. ~' O 7- b2 }3 B; }, ]) S4 [; h- Q 8 c$ u/ ], {+ W) S* f1 P 9 10 11; o' @: E/ {8 D7 a6 I6 N 12: I. J! R2 q8 R8 W8 x( e2 ` 13* E, C2 ?% j0 {1 I" D7 o! r$ p 149 ]) {& b3 U: |9 v* g | # peer0.org14 ^4 z$ A1 L& G3 ^2 D; J docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls \3 Z& ~3 j! ?1 x --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ --peerAddresses peer0.org1.example.com:7051 \ [5 i% A# |+ S% ^* u --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \" b* K8 ~& V) \% u+ \; b --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \0 M* Z3 ~/ y3 ^1 q( a) y -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}' - B0 o) Y5 Z5 q$ @* d # peer0.org20 u/ ]/ Q `# o; v9 G0 ?! g0 b docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \9 A& ^. E) h; }$ }0 C! ] -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \ -e CORE_PEER_LOCALMSPID="Org2MSP" \# |- O7 w0 f2 t -e 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 \ cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'$ ^9 o. ?+ G- a8 V |
4、Fabric 2.0链码操作演示类似的,在Fairc 2.0.0中,我们也先以无链码方式启动First Network, 然后再启动SACC链码以便聚焦链码的生命周期。
下面是演示步骤:
无链码方式启动First Network打包SACC链码在指定peer节点上安装SACC链码包机构审批链码在mychannel通道上提交链码调用SACC链码的Init方法调用SACC链码的set方法并从另一个peer节点查询结果STEP 1:以无链码方式启动First Network:3 v5 |* @/ I( x! Y; j+ b+ ~
1; e6 e" `5 d0 ]( @ X5 J1 c2 h 28 o: f( s; W @; ~4 F | cd fabric-samples/first-network8 g. d7 D# Z p7 q' I ./byfn.sh up -n |
STEP 2:打包SACC链码0 V! b [$ Z8 t# G0 O% l. N/ E7 @( L
首先我们处理依赖问题:$ `4 z9 l# P$ Z
1, a" a1 q) o# a/ A 2 3; p, a5 C( l& P. c( O | cd fabric-sample/chaincode/sacc1 C- S5 L) C# g/ x- `* k; s. q GO111MODULE=on go mod vendor cd fabric-sample/first-network |
11 S, ?3 i4 K* i! E8 h 2. W' U" o4 C# a6 \8 W 34 j, I1 s# ~. d$ l% {) b% w& z9 v | docker exec cli peer lifecycle chaincode package sacc.tar.gz \+ \+ h! w; S4 d& | --path github.com/hyperledger/fabric-samples/chaincode/sacc/ \) F1 s* A" }9 A --label sacc_1 |
STEP 3:在指定peer节点上安装SACC链码包
现在我们在peer0.org1和peer0.org2上安装SACC练马报,因为在这个 演示中我们只需要使用这两个节点进行链码调用和查询。
13 q( g9 U8 h0 Z0 T6 w 2 3 4. r' \$ p! r1 P+ K9 T- G9 T 5% [! N9 O' ^3 d R( W6 p 6 7 88 t9 @/ a' i6 ]3 \3 a1 g) C 9 10 | # peer0.org1( H1 ?( ^2 L; l N: q" A0 J docker exec cli peer lifecycle chaincode install sacc.tar.gz # peer0.org2 docker exec \3 ]$ I6 j5 b: h -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \& m4 b9 [& e8 V# N/ u$ d& }9 `# W -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \8 ^+ H; M5 e4 T. h7 {- d4 D0 D0 t! S -e CORE_PEER_LOCALMSPID="Org2MSP" \ -e 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 \/ i- q# P( n' ~2 B1 R1 |+ C cli peer lifecycle chaincode install sacc.tar.gz |
我们会收到链码包的标识符,在下面的链码审批阶段会用到。我们 收到的链码标识符为:sacc_1:bf57…6399。
我们可以使用peer lifecycle chaincode queryinstalled命令随时 检查节点上的链码安装情况,如果我们需要找出链码包的标识ID,这个命令 会很有用。
1& @9 {* D5 f4 ?7 G 28 }) @7 A7 G3 {' e0 T5 f3 n( k 3 4! U% s! _! A2 A3 N0 W. A. p O9 ] 5 6 7 8 9 10% V1 y. L6 H" h$ ?: e0 v9 C | # peer0.org1 docker exec cli peer lifecycle chaincode queryinstalled2 d: D1 ?& P# C6 H1 O& }+ ` # peer0.org2 docker exec \& i: `9 i5 G% a5 N -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \3 }) p/ K1 `' Z6 d4 P -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \1 K. b; g2 P0 J! @& U! i -e CORE_PEER_LOCALMSPID="Org2MSP" \ -e 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 \1 _* B$ l$ u! o- a cli peer lifecycle chaincode queryinstalled1 d0 Q4 E) D" u9 @- c# N# f |
根据默认策略,需要超过半数的机构审批链码后才能向通道提交链码, 具体可参考configtx.yaml中的Application/Policies/LifecycleEndorsement部分。 目前的设置中包含两个机构,因此需要两个机构同时批准链码。
首先是Org1批准链码:
19 [8 K* Y" g. ^$ n9 f 2 37 j3 y8 @$ W' G W 42 b* C3 b# L% g: \0 l 5 | docker exec cli peer lifecycle chaincode approveformyorg \8 t8 W2 |& c e% G --tls \2 m8 Z5 W0 P) s: w7 J# K --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ --channelID mychannel --name mycc --version 1 \$ X4 V( I3 ~! z9 Q --init-required --sequence 1 --waitForEvent --package-id ${PACKAGE_ID}2 Z4 x5 V [# m# V0 O& M7 z |
如果我们现在看下peer节点的日志,可以看到出了新块#3。
类似的,我们让Org2批准链码:
1 2& K) o! K" Y1 `9 C 3% P, l1 {0 J$ H3 f 4 5, z1 W7 b* z+ v 6 7 8 96 n1 d' z) F3 ^7 ] 104 _+ |0 T5 l9 ^$ h$ F- ~ | docker exec \ -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \% r8 b2 @ y; v( O4 c* W -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \( ^0 ~& `* g9 h) a! V+ o7 e% M -e CORE_PEER_LOCALMSPID="Org2MSP" \ -e 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 \ cli peer lifecycle chaincode approveformyorg \ --tls \. n1 a( m# R, L --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \, i! n. {: M1 W --channelID mychannel --name mycc --version 1 --init-required \1 S1 W; ]: h' e --sequence 1 --waitForEvent --package-id ${PACKAGE_ID} |
不出意外,可以看到出了新块block#4:
注意我们在approval命令中指定了init相关的参数,以便向SACC链码的 Init方法传入所需的参数。
可以随时使用如下命令查看链码的提交状态:
1/ P1 G$ g; s" {- d1 {: |" ]/ C 2 | docker exec cli peer lifecycle chaincode checkcommitreadiness \6 Z$ K- b& \) P! E* Q --channelID mychannel --name mycc --version 1 --sequence 1 --output json* m- w0 K0 T m1 d. B |
两个机构都已经批准了链码,现在可以提交了。2 Q6 H6 V- B5 K4 k7 Y _4 J1 S
STEP 5:向通道mychannel提交链码
链码提交可以在一个peer节点上完成:4 v, R5 X }+ t% Z! S7 o5 j, \' n6 y
1 2/ W* n1 a$ R( {' Z" m 3* k. o- b" h# }) l Z 4% d! U1 J( M" l; ^5 \- H+ f 5% Z E7 w9 l. F& O- w( E7 N- y( P 64 ~2 ^- ]2 X4 r" S3 l 7) ?; [2 K- o; v 8+ H+ o0 Z% R! g O9 f | docker exec cli peer lifecycle chaincode commit -o orderer.example.com:7050 \9 z( Q8 n! W$ s" J+ g7 C* c& X+ ` --tls \7 A( j3 K) O, {% y6 x --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \5 X" k2 h+ C( \- {) @9 d) }( e --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:9051 \5 n9 ~ T" C- }/ r( Q$ r0 P --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \+ ~6 E* ?. n/ f7 {0 ?+ m' W6 K --channelID mychannel --name mycc --version 1 --sequence 1 --init-required |
可以看到出了新块#5:& r2 K5 n0 \ M: C4 Q9 k9 P* ?
注意我们在commit命令中已经包含了init所需的参数。
同样,我们可以使用querycommited命令来查看链码的提交状态:
1: ]( g# I# v6 t* E( g | docker exec cli peer lifecycle chaincode querycommitted --channelID mychannel --name mycc |
在链码提交到通道之后,链码的生命周期就完成了,链码已经可以访问。 现在我们回到链码的调用和查询,这和之前的版本是一致的。0 x2 R X( ^: X, I( _% P! Q
STEP 6:调用链码的Init方法
SACC链码的Init方法需要首先调用。, K3 K* i: M1 O% ^1 E2 c
1 2& z6 G* L5 g+ K 38 H: a" ^! w# [7 A 4 5 6 7& Z. C' v& X( Q4 t8 k0 V, H& v 8: ^8 j0 E- L5 O; f | docker exec cli peer chaincode invoke -o orderer.example.com:7050 \9 k t1 o" e) X' V2 I --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 \/ A; z, k( Y4 D. C --peerAddresses peer0.org1.example.com:7051 \. a+ A, ^6 V* g3 P --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:9051 \1 }0 Y! h1 z" b1 ^ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \' c4 B6 U [, f% f* C) n7 q% T -C mychannel -n mycc --isInit -c '{"Args":["name","kc"]}', A4 G8 R- P2 }" k& s3 w* q |
现在可以查询 链码:
1 | docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'" M4 w" z* F7 F P4 |, d |
STEP 7:调用链码的set()方法并从另一个peer节点查询
和之前一样,我们在peer0.org1上调用链码的set()方法,在peer0.org2上 进行查询:
1 24 `! E, m! h v( K 3 4 H1 a$ ?* c5 b" w2 y$ |+ g 51 Z3 S/ f, w$ U 6 73 V( w+ q1 M8 S0 c* {) x8 f 8 9% p- r( Y [- Z6 Z, a) s5 {" ]) |+ d 10 11# J, |4 t$ l3 L( m( e4 k Q5 w# W 12) j' i' \' t; v 13! P% m+ N9 i l. u& I5 r 14 15 16( `7 N. ~$ z( r) m7 U9 N 17 185 {; Q6 E4 Q% @1 K: ^6 [& E( t | # peer0.org11 T4 [& m4 g9 p3 f* S docker exec cli peer chaincode invoke \ -o orderer.example.com:7050 \" T% f1 }' o! O$ g. ~ --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 \ --peerAddresses peer0.org1.example.com:7051 \) m$ v9 o9 ~! P' H {# @# I3 O --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:9051 \ --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \ -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}' 8 P3 R& k; p* H# N' n # peer0.org2 docker exec \ -e CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp \; z: ^$ V) s, v5 j& R$ N -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \5 {2 j% `# p% N- f+ H -e CORE_PEER_LOCALMSPID="Org2MSP" \ -e 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 \ cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'8 b( A- f3 _5 q, Q; u& n7 W5 ` |
一切正常。