Fabric官网Commercial Paper案例chaincode的golang实现

官网上描述了Commercial Paper这个应用场景,并且提供了nodejs实现。这里补充chaincode的golang实现,保持逻辑一致,以及记录实际操作中的一些步骤和要点。实现的源码已上传github

  1. 按照官网Commercial Paper nodejs实现里的步骤,启动net_basic网络,并且启动了peer0.org1.example.com, couchdb, ca.example.com, orderer.example.com, cliDigiBank, cliMagnetoCorp这些容器(按照步骤里执行下来,docker ps能看到这些容器)。

  2. install chaincode。执行docker inspect cliMagnetoCorp,能看到/Users/ckcclc/github/fabric-samples/commercial-paper/organization/magnetocorp:/opt/gopath/src/github.com这个路径绑定。在/Users/ckcclc/github/fabric-samples/commercial-paper/organization/magnetocorp创建目录gocontract,将golang实现放在这个目录里。这时候登录到cliMagnetoCorp容器,可以看到容器内/opt/gopath/src/github.com/application下有gocontract这个目录,并且go实现在内。

    1
    peer chaincode install -n gopapercontract -v 0 -p github.com/gocontract

    同时,docker inspect cliMagnetoCorp(或者cliMagnetoCorp容器执行env查看),GOPATH=/opt/gopath, CORE_PEER_ADDRESS=peer0.org1.example.com:7051install会到${GOPATH}/src下寻找source code。然后install chaincode到${CORE_PEER_ADDRESS}

    登录peer0.org1.example.com容器。env出来FABRIC_CFG_PATH=/etc/hyperledger/fabric,查看改路径下的core.yaml配置文件,其中peer.fileSystemPath : /var/hyperledger/production。查看/var/hyperledger/production/chaincodes目录,存在文件gopapercontract.0(即${chaincodeName}.${chaincodeVersion}).

  3. instantiate chaincode。登录cliMagnetoCorp容器,执行

    1
    peer chaincode instantiate -n gopapercontract -v 0 -c '{"Args":[]}' -C mychannel -P "AND ('Org1MSP.member')"

    此时,docker ps可以看到dev-peer0.org1.example.com-gopapercontract-0这个容器。可以在cliMagnetoCorp容器执行。

    1
    2
    peer chaincode invoke -c '{"Args":["issue","MagnetoCorp", "00001", "2020-05-31", "2020-11-30", "5000000"]}' -C mychannel -n gopapercontract
    peer chaincode query -c '{"Args":["query","MagnetoCorp", "00001"]}' -C mychannel -n gopapercontract

    如果后续更新chaincode,假设更新版本为1,则执行

    1
    peer chaincode upgrade -n gopapercontract -v 1 -c '{"Args":[]}' -C mychannel -P "AND ('Org1MSP.member')"
  4. 修改fabric-samples/commercial-paper/organization/magnetocorp/application/issue.js这个文件

    1
    2
    3
    4
    5
    // 63行 const contract = await network.getContract('papercontract', 'org.papernet.commercialpaper');
    const contract = await network.getContract('gopapercontract');

    // 73行 let paper = CommercialPaper.fromBuffer(issueResponse);
    let paper = JSON.parse(issueResponse);

    然后,就可以正常调用node issue.js访问刚启动的golang commercial paper容器了。在整个流程中,可以执行./monitordocker.sh net_basic查看chaincode的日志。

另外,在peer0.org1.example.com节点上可以使用peer chaincode list命令查询channel内instantiated的chaincode以及peer上installed的chaincode。

  1. 查询channel内instantiated的chaincode。
    1
    2
    3
    4
    5
    $ peer chaincode list -C mychannel --instantiated

    Get instantiated chaincodes on channel mychannel:
    Name: gopapercontract, Version: 1, Path: github.com/gocontract, Escc: escc, Vscc: vscc
    Name: papercontract, Version: 0, Path: /opt/gopath/src/github.com/contract, Escc: escc, Vscc: vscc
  2. 查询peer上installed的chaincode。
    1
    2
    3
    $ peer chaincode list  -C mychannel --installed

    Error: Bad response: 500 - access denied for [getinstalledchaincodes]: Failed verifying that proposal's creator satisfies local MSP principal during channelless check policy with policy [Admins]: [This identity is not an admin]
    从返回结果可以看出,当前使用的角色并非Admin(这与MSP相关,使用的非Admin的X509证书)。因此可以指定使用Admin。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # 默认使用的MSP config
    $ echo $CORE_PEER_MSPCONFIGPATH
    /etc/hyperledger/msp/peer/

    # 区别在于keystore存放的用来签名请求的私钥。
    $ ls $CORE_PEER_MSPCONFIGPATH
    admincerts cacerts keystore signcerts tlscacerts

    # 设置使用Admin的MSP config
    $ CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp

    $ peer chaincode list -C mychannel --installed

    Get installed chaincodes on peer:
    Name: gopapercontract, Version: 0, Path: github.com/gocontract, Id: 44777e9463329c5b03a93abd48975980a795152907d0c6226b0b85589f4a0ca7
    Name: gopapercontract, Version: 1, Path: github.com/gocontract, Id: d000a5b0e4ed415ae1739e716c13a481096b947cb31dd5f25ab1d67633d18bb0
    Name: papercontract, Version: 0, Path: /opt/gopath/src/github.com/contract, Id: f09e75abcf455f6fb83257080ebd739f1d2397cf50ce2e52cd805d992a64bc03
  3. 使用openssl查看X.509证书。下面是Admin证书的示例
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    $ openssl x509 -noout -text -in Admin\@org1.example.com-cert.pem

    Certificate:
    Data:
    Version: 3 (0x2)
    Serial Number:
    15:2c:67:2c:01:ac:bb:4e:33:ac:59:00:13:0c:e7:eb
    Signature Algorithm: ecdsa-with-SHA256
    Issuer: C=US, ST=California, L=San Francisco, O=org1.example.com, CN=ca.org1.example.com
    Validity
    Not Before: Aug 31 09:14:32 2017 GMT
    Not After : Aug 29 09:14:32 2027 GMT
    Subject: C=US, ST=California, L=San Francisco, CN=Admin@org1.example.com
    Subject Public Key Info:
    Public Key Algorithm: id-ecPublicKey
    Public-Key: (256 bit)
    pub:
    04:57:57:5f:98:ac:6c:14:a5:a8:ee:8e:83:34:12:
    1a:21:57:9b:08:23:c0:33:d0:bf:b0:b0:6d:e2:92:
    51:ad:ef:69:58:4f:7c:ec:38:d7:66:86:77:82:57:
    38:f8:3a:0f:32:d4:e6:05:1a:9b:3d:5c:18:71:4b:
    e9:6d:86:3c:a7
    ASN1 OID: prime256v1
    NIST CURVE: P-256
    X509v3 extensions:
    X509v3 Key Usage: critical
    Digital Signature
    X509v3 Basic Constraints: critical
    CA:FALSE
    X509v3 Authority Key Identifier:
    keyid:42:39:AA:0D:CD:76:DA:EE:B8:BA:0C:DA:70:18:51:D1:45:04:D3:1A:AD:1B:2D:DD:DB:AC:6A:57:36:5E:49:7C

    Signature Algorithm: ecdsa-with-SHA256
    30:44:02:20:5c:cc:b6:e8:01:14:fc:65:0c:3d:f0:8c:b3:f9:
    d0:8d:03:04:d5:9c:41:1c:06:19:b4:a1:2e:45:1d:fa:d4:9b:
    02:20:48:3d:04:e6:5d:22:88:a8:46:2b:c9:0b:e6:54:ce:f2:
    54:9e:45:ee:a3:61:e4:5a:2b:b1:2e:c8:9b:1b:1b:44