1、链码操作:Fabric 1.4 vs Fabric 2.0我们将首先快速介绍在HF 1.4和HF 2.0中的整个链码操作过程。5 j4 F2 q' b" i3 w' G2 P( y
链码操作指的是在Hyperledger fabric网络通道上部署链码的操作,这样区块链 之外的应用可以调用或查询链码方法。在链码开发完成并测试后,首先需要 将Fabric链码安装到指定的peer节点。在这个阶段链码还不能使用,直到 链码被提交(Fabric 2.0中的术语)到通道中或在通道上实例化(Fabric 1.4中的 术语),这样链码就可以被授权用户访问了。6 y/ U/ ^" v" Z* p9 K
下面是两个版本的Hyperledger Fabric中链码操作流程的对比图:9 s' J- W. x8 E. a$ h/ W
在Hyperledger Fabric 1.4中,链码操作过程包含以下步骤:打包、安装、实例化。 如果链码属于多个参与方,那么就需要打包这一环节。如果不存在多方属主的问题, 那么直接安装链码就可以(其中隐含了打包环节)。在Fabric链码安装时需要指定 要安装链码的目标节点。
在这个阶段,安装好的Fabric链码还不能使用,因为它还没有在通道上实例化。 当Fabric链码包被安装在指定的节点上之后,我们就可以执行链码实例化操作, 从而让链码在通道上可用。技术上来说,链码实例化实际上就是调用LSCC系统链码 的方法来初始化通道上的一个链码。
Fabric链码实例化之后就可以使用了,可以接受通道上的调用或查询请求。
下面我们看在Hyperledger Fabric 2.0中的链码操作步骤有何区别。4 `" N1 W- Y: x6 q; _
宽泛地来讲,在Fabric 2.0中链码操作基本遵循同样的流程,但是在命令和某些 后台处理中做了一些调整。整体的流程可以分为四个步骤:打包、安装、机构审批、 链码提交。大致可以认为前两个环节对应于Fabric 1.4中的链码安装,后面两个 环节对应于Fabric 1.4中的链码实例化,但是实例化(instantiation)这个词不再 用了。% E" ]) e0 ~2 G
链码打包这一步是创建一个打包文件(tar格式),其中包含Fabric链码以及一些元数据。 虽然不同的机构可以分别进行打包处理,更常见是由一个机构打包然后分发给其他 机构以便确保所有的机构使用相同的链码。+ W8 v0 l) A. }" l; }
安装步骤是将打包的Fabric链码文件安装在指定的peer节点上。和之前的版本一样, 只有需要接受链码调用的节点才需要安装链码。在这个节点,Fabric链码还不可用, 因为还没有提交到通道中。链码安装的结果是得到一个包标识符,其格式为.。
机构审批是在Hyperledger Fabric 2.0中增加的步骤。在之前的版本中我们可以让 一个机构实例化链码。在Fabric 2.0中,需要机构显式地审批链码。需要多少机构 审批则是由生命周期背书策略来决定,默认情况下设置为需要大多数机构(超过半数)。 如果Fabric网络中包含两个机构,那么就需要这两个机构同时批准。在审批过程中 需要排序节点的参与,因为每次审批都会生成一个新的区块,这意味着所有的peer 节点都了解审批的状态。6 \$ F H1 n$ c- k/ h& Q, u
当审批环节完成后,我们就需要指定要在哪个通道上部署链码。这需要提交一些信息, 例如背书策略、是否需要执行Init代码等等。在这里也有些与Fabric 1.4不同的地方: 在Fabric 1.4中,当链码实例化时会自动调用链码的Init方法,然而在Fabric 2.0中, 需要在提交链码后显式地调用Init方法。
在批准机构达到指定数量后,链码就可以提交了。我们现在就进入了最后一个步骤: 链码提交。! b* n0 U6 `8 r6 d2 F4 j7 ~
链码提交可以由任何机构发起。该流程首先需要批准机构的背书,然后交易提交到 排序服务并生成新的区块,最后所有的对等节点在账本中提交该区块。
现在链码就可以使用了。
2、First Network和SACC链码简介出于完整性考虑,下面给出关于First Network和SACC链码的一些信息,这些内容 都来自fabric-samples仓库。+ b& i# I+ n. g' h+ C4 ~
First Network是一个双机构设置,每个机构中包含两个peer节点。通道mychannel 创建后加入所有的4个peer节点。在byfn.sh中完整的实现了First Network的部署, 并包含一些可选的参数。在下面的演示中,我们不使用默认的链码(在Fabric 1.4 中式chaincode_example02,在Fabric 2.0中式abstore),而是使用SACC链码。
SACC式Simple Asset ChainCode的缩写,表示简单资产链码。它在账本中模拟一个 键/值存储。当初次部署后,需要一个初始的键/值对。SACC链码定义了两个方法: Set()和Get(),分别用来设置或读取某个键的值。1 ? w' }' u6 i, s' D7 S( |
好了,现在我们可以开始演示Fabric 1.4和Fabric 2.0中链码操作的不同了。 s. u) V. i! `# O+ ^/ [3 z
3、Fabric 1.4.4链码操作演示我们首先以无链码方式(使用-n选项)启动First Network,然后我们再加载 SACC链码以便聚焦链码的生命周期。
下面是演示步骤:
无链码方式启动First Network在指定的peer节点上安装SACC链码在mychannel通道上实例化SACC链码并查询结果调用set()设置新值并从另一个peer节点查询结果STEP 1:首先启动First Network:7 C3 E: R' w8 x! T; G5 m. j
1 a8 _" T; A, h6 _ 2( x; T( l7 g$ `/ W4 O4 ~ | cd fabric-samples/first-network ./byfn.sh up -n |
现在我们可以开始链码部署操作。
STEP 2:在指定peer节点上安装链码
这里我们跳过打包环节,直接在目标节点peer.org1和peer0.org2上安装链码, 因为在这个演示中我们只需要这两个节点进行链码调用和查询。
1! ]5 X" S2 n) Q" n1 ^9 E7 b! s, x 2 3 4 5 6* u) z: `. c3 V! l0 a9 v) A 78 @6 A: z* c! y& ]0 ~# j 8 9 10 | # peer0.org1& d) c8 ^2 q2 X7 D docker exec cli peer chaincode install -n mycc -v 1 \5 V* @# q, k6 t4 e -p github.com/chaincode/sacc2 D0 h1 O* {9 S! S9 @ # 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 \) @2 N7 R- ~ o1 O+ C6 J$ }/ ` cli peer chaincode install -n mycc -v 1 -p github.com/chaincode/sacc0 _+ S+ s+ J" k |
STEP 3:在通道mychannel上实例化链码并查询/ ]2 V" L( h0 M8 _
注意在sacc链码中有Init()代码。当我们实例化链码时,我们需要 提供Init()所需的参数:
1" S5 C; M, Q% _. f 27 f2 i5 G, h; @) s/ q 37 b5 X$ I" t5 w6 [- X+ e 4* S( A3 E1 e1 ?' A% _8 G3 Z | docker exec cli peer chaincode instantiate -o orderer.example.com:7050 --tls \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \ -C mychannel -n mycc -v 1 -c '{"Args":["name","kc"]}' \ -P "AND ('Org1MSP.peer','Org2MSP.peer')" |
如果现在看看peer节点的日志,我们可以看到出了新区块#3。
在链码实例化之后,我们可以查询:5 R6 ?: i4 } Z$ f
1. k: G! H( ]0 K- M: m% u | docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'' g5 c& Y9 ~- c$ u8 l0 e g3 X |
STEP 4:调用set()设置新值并从另一个节点查询( g' p" E2 o1 m1 }" \7 } o
出于演示目的,我们在peer0.org1上调用set(),然后在peer0.org2上 调用get(),以此说明链码是否工作正常。
1! n% |8 ~5 t8 ?0 E* h- }- o$ V& P 21 N2 R" h5 A( t: K 3 4 5 67 X; j7 G; H! b# d5 y: Z+ h6 w$ Y 7) n: _- w$ b# F 8( [6 w/ ?( x ~. F 97 C9 a! N3 d& N6 K7 c0 C4 U 10 11 124 ~6 W, G8 T0 p0 `7 T 134 M3 d9 I$ @; z, v4 A 14 | # peer0.org1% T$ K; `1 Y! n) C N3 b docker exec cli peer chaincode invoke -o orderer.example.com:7050 --tls \3 P; O) V {% R) O5 d I* J --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \$ f7 }' L+ ?/ U0 k) X" z z) W --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 \7 z, a' s0 d7 O3 E --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 \% M' |3 P9 ]+ f: v2 \* o7 d -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}' # 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" \; k9 y. ~8 O1 b. l: O+ i/ h -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 \: Q( T, f; p) ^4 N& J' _* t cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}' |
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:
10 K& M4 |- c' f/ f: g9 G( W 2 | cd fabric-samples/first-network+ g, g+ e& S6 j- N. e4 d ./byfn.sh up -n |
STEP 2:打包SACC链码5 d# P7 k* U/ d
首先我们处理依赖问题:
1" E, J- `; ]/ d: D0 }: p$ f: z- D 2 3. P; i: j D" P# _, ~ | cd fabric-sample/chaincode/sacc* j3 [& N! s7 B5 [7 r GO111MODULE=on go mod vendor cd fabric-sample/first-network |
1. K v. h, p1 l4 | 27 ~( a2 Q1 v$ V& y, s$ g 3 | docker exec cli peer lifecycle chaincode package sacc.tar.gz \ --path github.com/hyperledger/fabric-samples/chaincode/sacc/ \. w8 n& a& b( C+ f5 D+ O* Z+ ? --label sacc_1# w% J+ }+ i4 R3 h |
STEP 3:在指定peer节点上安装SACC链码包4 |5 y5 W- a1 X4 Q
现在我们在peer0.org1和peer0.org2上安装SACC练马报,因为在这个 演示中我们只需要使用这两个节点进行链码调用和查询。1 }! h4 ]9 H! _! A9 r, i. L, S& p
1+ W' I$ V D- N6 J 2 37 {, L! @4 c! Q8 ` 4' j$ t- }+ O0 E; P 58 V( p D3 I2 e% I# Q q 6 7$ c" N% T' F" ~/ w* E2 d' J/ g 8 91 [' ~4 Y0 ^. m1 x$ q: z 101 Y1 r8 S# O5 Z | # peer0.org1 docker exec cli peer lifecycle chaincode install sacc.tar.gz+ K) ?5 A% v2 T) K* K( Z- m # peer0.org2( t; ]& |$ }3 h2 `, T. G2 Q docker exec \' ^& X) [8 w# _ -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 \- g$ \' Z! F* Q* E5 s cli peer lifecycle chaincode install sacc.tar.gz r& J( N, |9 L7 |# o* {1 } |
我们会收到链码包的标识符,在下面的链码审批阶段会用到。我们 收到的链码标识符为:sacc_1:bf57…6399。
我们可以使用peer lifecycle chaincode queryinstalled命令随时 检查节点上的链码安装情况,如果我们需要找出链码包的标识ID,这个命令 会很有用。, h) k4 L) h9 J: b2 W; M _
1 2 3% _: L0 n1 X6 i0 v$ S6 L: I 4 5 61 `+ t6 u- @+ n/ f 7 8+ E9 E6 Q+ G' K2 ?( R" Q 9 f% i* S. c) h: j5 K6 W. j' B 102 _2 O A6 \* S; G3 g! o7 f | # peer0.org1 docker exec cli peer lifecycle chaincode queryinstalled4 S) e% y" P5 x7 v' p # peer0.org2 docker exec \# l9 N; c ], e4 t -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 \/ P+ g( G# s5 A3 @' H4 W) @ cli peer lifecycle chaincode queryinstalled |
根据默认策略,需要超过半数的机构审批链码后才能向通道提交链码, 具体可参考configtx.yaml中的Application/Policies/LifecycleEndorsement部分。 目前的设置中包含两个机构,因此需要两个机构同时批准链码。
首先是Org1批准链码:& U0 Q+ R' C3 h1 d
1 2 3 4; h$ s0 ?+ Y8 a7 M 5 | docker exec cli peer lifecycle chaincode approveformyorg \& k G& ~. ]5 T7 e3 T) i- j --tls \! p# v8 C+ E! u9 {4 Q7 o0 ^5 S: I. 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 \ --channelID mychannel --name mycc --version 1 \7 R) T0 ~& k% P6 o+ T: G1 F/ _ --init-required --sequence 1 --waitForEvent --package-id ${PACKAGE_ID} |
如果我们现在看下peer节点的日志,可以看到出了新块#3。9 X$ O) B5 \1 ]$ W ]- c: u- W0 v- X5 X5 ]
类似的,我们让Org2批准链码:$ @; l$ A$ W0 ` _- m+ T" C
18 z, v+ S% F! `6 G 2 3 4 57 F; t- j4 X8 a- z/ I) e6 b: ~ 6. z8 |3 n7 M. _6 m 7 89 ~7 `( a& A( ~: X$ e0 x& K 9) p6 ]$ A9 f( j/ o( o4 C 10 | docker exec \4 X9 f' b h; I/ I -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 \" g2 F: K" |$ k" S4 T- X -e CORE_PEER_LOCALMSPID="Org2MSP" \- ~; E- F. C: }4 s0 j -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 \ --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \7 g8 }0 ^# R/ X4 h$ \ --channelID mychannel --name mycc --version 1 --init-required \( n/ H! g% O. K7 b; i, Y& D e --sequence 1 --waitForEvent --package-id ${PACKAGE_ID} |
不出意外,可以看到出了新块block#4:
注意我们在approval命令中指定了init相关的参数,以便向SACC链码的 Init方法传入所需的参数。* T+ ~" ^8 `7 g4 i( R3 b, U
可以随时使用如下命令查看链码的提交状态:
1 2 | docker exec cli peer lifecycle chaincode checkcommitreadiness \5 n5 ~7 Y5 P9 J' f& n$ G --channelID mychannel --name mycc --version 1 --sequence 1 --output json' a; ]4 w$ w& I0 J |
两个机构都已经批准了链码,现在可以提交了。, r4 w! l5 H2 P& c
STEP 5:向通道mychannel提交链码
链码提交可以在一个peer节点上完成:! r# m! w. `- X' E/ r! N
1 2, _9 H& K" m N/ M3 G 3 E+ e' @ }+ i7 |7 ^ D 4 5 6# o4 w: h, S$ N' x2 @ 7 85 V+ L& B- _! _5 M | docker exec cli peer lifecycle chaincode commit -o orderer.example.com:7050 \ --tls \; ~, C* F5 g) ~" u! c, p0 {: y4 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 \+ J' r/ N" v8 K8 j& T* ` --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 \4 u& O7 ~% ^; E8 `0 M7 j3 U --channelID mychannel --name mycc --version 1 --sequence 1 --init-required |
可以看到出了新块#5:) o1 c+ p1 H& d6 [" I
注意我们在commit命令中已经包含了init所需的参数。
同样,我们可以使用querycommited命令来查看链码的提交状态:
1 | docker exec cli peer lifecycle chaincode querycommitted --channelID mychannel --name mycc. D. _5 S# E' y. \# T |
在链码提交到通道之后,链码的生命周期就完成了,链码已经可以访问。 现在我们回到链码的调用和查询,这和之前的版本是一致的。
STEP 6:调用链码的Init方法- i4 N6 G# a/ \" m8 F8 d! k( O
SACC链码的Init方法需要首先调用。
1 2 3) x# b" @& ^4 x" Q2 d6 x( J5 f 4 5 6: q; c! Q. j& E' P! H 7' r, q& j) ^% E& q 8 | docker exec cli peer chaincode invoke -o orderer.example.com:7050 \ --tls \, z$ U, v# j I --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/ B$ O+ z/ }( m6 E --peerAddresses peer0.org1.example.com:7051 \/ g: W- S' Z0 D/ z- Q7 K --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \! R7 A8 i7 B1 q8 z: f9 M ? --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 --isInit -c '{"Args":["name","kc"]}'8 p! V7 n6 b' s7 b |
现在可以查询 链码:
1" y/ G" I6 c6 K | docker exec cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'+ W+ ^0 y( i; U9 \* d$ I; x0 u3 a) e |
STEP 7:调用链码的set()方法并从另一个peer节点查询1 t$ |+ h" ^- G
和之前一样,我们在peer0.org1上调用链码的set()方法,在peer0.org2上 进行查询:, U* h0 M6 s8 n9 [# o2 n& R/ K
1 u7 U7 A4 L+ V* m) I- Y$ h 2 3 4 51 Y3 n9 m8 K/ d 6. {9 `$ C6 `9 R: O' }8 b, I% h 7 R& {% h+ {1 ?! k+ [ 8 9 10& w9 H. A- y% W1 m 11( L. C0 q7 K: R' e" O 12; E3 v( D* g, o. q9 n& E8 }! p 13/ l: W/ w, p [) r 146 R9 k* o0 k( [( i$ @3 J& g 150 i) W- }9 H2 N6 k& B 16 179 [# B! x! p- |/ W 18; [6 b$ |" R* A1 C6 _1 K6 H | # peer0.org1 docker exec cli peer chaincode invoke \ -o orderer.example.com:7050 \ |0 m. U: |5 X, x" g9 v, I' N( n --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 \/ c. ~. L) ^3 y/ G' d4 ^4 D# \$ v --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 \- ^4 U4 E& W9 h, U" M -C mychannel -n mycc -c '{"Args":["set","name","Peter"]}'0 u/ }4 I, w7 m& v, K" D) d - J& D# m( s- b* ? # 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$ z0 l6 t$ L T& e+ b, m -e CORE_PEER_ADDRESS=peer0.org2.example.com:9051 \9 k# F1 i. a& B! i6 m: x+ J -e CORE_PEER_LOCALMSPID="Org2MSP" \2 S6 J& T% {- S) \' y; o -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 \7 B! G+ R& ?6 a, V9 g cli peer chaincode query -C mychannel -n mycc -c '{"Args":["get","name"]}'2 l8 e# i$ h( u3 ^9 I/ R, S0 V, _ |
一切正常。