Fabric 应用程序与部署的区块链网络交互

前言

本教程介绍了 Fabric 应用程序如何与部署的区块链网络交互。

操作内容

使用 Fabric SDK 构建的示例程序调用智能合约,用智能合约 API 查询和更新分类帐。
使用示例程序和已部署的证书颁发机构来生成应用程序与许可区块链交互所需的 X.509 证书。

运行 Fabric 应用程序

资产转移示例

示例应用程序位置

/root/go/src/github.com/fabric/fabric/scripts/fabric-samples/asset-transfer-basic/application-javascript

示例智能合约位置

/root/go/src/github.com/fabric/fabric/scripts/fabric-samples/asset-transfer-basic/chaincode-javascript

一、搭建开发环境及示例代码调用详解(含执行日志)

基础体验环境参考以下搭建教程:
https://blog.csdn.net/Bjxhub/article/details/119352058

# 除以上基础环境外,需安装以下软件
# centos7系统默认安装了python以及gcc等编译工具。{ node: '^10.15.3 || ^12.13.1 || ^14.13.1', npm: '6.4.1'}
# 安装 gcc gcc-c++ make
[root@localhost ~]# yum install gcc gcc-c++ make
# 安装nodejs(默认安装的nodejs版本补兼容Fabric,需要升级)
 [root@localhost ~]# yum install nodejs
 [root@localhost application-javascript]# npm -v
3.10.10
[root@localhost application-javascript]# node -v
v6.17.1
# CentOS系统升级 Node版本(解决以下错误)
------------------------------------------------------------------------------------------------------------------------------------------------------
[root@localhost application-javascript]# node app.js
/root/go/src/github.com/fabric/fabric/scripts/fabric-samples/asset-transfer-basic/application-javascript/app.js:72
async function main() {
      ^^^^^^^^
SyntaxError: Unexpected token function
at createScript (vm.js:56:10)
at Object.runInThisContext (vm.js:97:10)
at Module._compile (module.js:549:28)
at Object.Module._extensions..js (module.js:586:10)
at Module.load (module.js:494:32)
at tryModuleLoad (module.js:453:12)
at Function.Module._load (module.js:445:3)
at Module.runMain (module.js:611:10)
at run (bootstrap_node.js:394:7)
at startup (bootstrap_node.js:160:9)

[root@localhost ~]# curl --silent --location https://rpm.nodesource.com/setup_16.x  | sudo bash
// [root@localhost ~]# sudo yum clean all
// [root@localhost ~]sudo rm -fv /etc/yum.repos.d/nodesource*
 [root@localhost ~]# sudo yum -y install nodejs
 [root@localhost application-javascript]# npm -v
7.20.3
[root@localhost application-javascript]# node -v
v16.6.1
 # 进入工作目录
 [root@localhost ~]#  cd /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network
 # 关闭之前运行的网络
 [root@localhost test-network]# ./network.sh down
 # 使用证书颁发机构来启动测试网络
 [root@localhost test-network]# ./network.sh up createChannel -c mychannel -ca
 部署链码 (指定语言和脚本位置,会运行较长时间)
 # 这个脚本使用链码生命周期来打包、安装、查询已安装的链码、批准 Org1 和 Org2 的链码,最后提交链码。
 [root@localhost test-network]# ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ -ccl javascript
 # 具体日志,参考文章最后的【部署链码日志】部分
 # 进入示例应用目录
 [root@localhost ~]# cd /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/asset-transfer-basic/application-javascript
 [root@localhost application-javascript]# ls
 app.js  package.json
 [root@localhost application-javascript]# sudo npm i --unsafe-perm
 [root@localhost application-javascript]# ls
 app.js  node_modules  package.json
 
 [root@localhost application-javascript]# node app.js
 #注册管理员和注册应用程序用户是发生在应用程序和证书颁发机构之间的交互,而不是应用程序和链码之间的交互。
 # 通过app.js中的以下函数,生成并注册管理员及应用程序用户,将用户相关凭据存放在在wallet路径下。
 # 第一步,通过await enrollAdmin(caClient, wallet, mspOrg1),生成管理员、应用程序用户凭据。
 # 第二步,通过await registerAndEnrollUser(caClient, wallet, mspOrg1, org1UserId, 'org1.department1'),生成应用程序用户凭据。
 # 注意:通过关闭并重新启动网络时,该文件夹需要删除,然后重新生成用户的公钥私钥
 # 第三步:初始化网关:const gateway = new Gateway();
 #        获取通道引用:const network = await gateway.getNetwork(channelName);
 #        获取智能合约应用:const contract = await network.getContract('chaincodeName', 'smartContractName');
 # 第四步:调用链码InitLedger函数,初始化示例数据填充分类帐,await contract.submitTransaction('InitLedger');
 # 第五步:应用程序调用各个链码函数
 #        # 1、查询所有资产:result = await contract.evaluateTransaction('GetAllAssets');
 #        # 2、创建资产:   result = await contract.submitTransaction('CreateAsset', 'asset13', 'yellow', '5', 'Tom', '1300');
 #        # 3、查询所有资产:result = await contract.evaluateTransaction('GetAllAssets');
 #        # 4、指定资产查询:result = await contract.evaluateTransaction('ReadAsset', 'asset13');
 #        # 5、判断存在、更新、再查询:
 #                          result = await contract.evaluateTransaction('AssetExists', 'asset1');
 #                          await contract.submitTransaction('UpdateAsset', 'asset1', 'blue', '5', 'Tomoko', '350');
 #                          result = await contract.evaluateTransaction('ReadAsset', 'asset1');
 #        # 6、更新一个不存在的资产(报错):await contract.submitTransaction('UpdateAsset', 'asset70', 'blue', '5', 'Tomoko', '300');
 #        # 6、将现有资产转移给新所有者并验证:await contract.submitTransaction('TransferAsset', 'asset1', 'Tom');
 #                                      result = await contract.evaluateTransaction('ReadAsset', 'asset1');
 [root@localhost application-javascript]# cd wallet/
 [root@localhost wallet]# ls
  admin.id  appUser.id

  # 注:如果凭据存在并且具有与其关联的正确权限属性,则示例应用程序用户将能够在获取对通道名称和合约名称的引用后调用链代码函数。
部署链码日志
deploying chaincode on channel 'mychannel'
executing with the following
- CHANNEL_NAME: mychannel
- CC_NAME: basic
- CC_SRC_PATH: ../asset-transfer-basic/chaincode-javascript/
- CC_SRC_LANGUAGE: javascript
- CC_VERSION: 1.0
- CC_SEQUENCE: 1
- CC_END_POLICY: NA
- CC_COLL_CONFIG: NA
- CC_INIT_FCN: NA
- DELAY: 3
- MAX_RETRY: 5
- VERBOSE: false
+ peer lifecycle chaincode package basic.tar.gz --path ../asset-transfer-basic/chaincode-javascript/ --lang node --label basic_1.0
+ res=0
Chaincode is packaged
Installing chaincode on peer0.org1...
Using organization 1
+ peer lifecycle chaincode install basic.tar.gz
+ res=0
2021-08-10 15:42:47.852 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7\022\tbasic_1.0" >
2021-08-10 15:42:47.852 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: basic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7
Chaincode is installed on peer0.org1
Install chaincode on peer0.org2...
Using organization 2
+ peer lifecycle chaincode install basic.tar.gz

+ res=0
2021-08-10 15:44:09.397 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nJbasic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7\022\tbasic_1.0" >
2021-08-10 15:44:09.397 CST [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: basic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7
Chaincode is installed on peer0.org2
Using organization 1
+ peer lifecycle chaincode queryinstalled
+ res=0
Installed chaincodes on peer:
Package ID: basic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7, Label: basic_1.0
Query installed successful on peer0.org1 on channel
Using organization 1
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7 --sequence 1
+ res=0
2021-08-10 15:44:11.507 CST [chaincodeCmd] ClientWait -> INFO 001 txid [fee76cd6d2a15cd0d28f5f348492503bb9636071a3171b731d1db96509713822] committed with status (VALID) at localhost:7051
Chaincode definition approved on peer0.org1 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
        "approvals": {
                "Org1MSP": true,
                "Org2MSP": false
        }
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
        "approvals": {
                "Org1MSP": true,
                "Org2MSP": false
        }
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'
Using organization 2
+ peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --version 1.0 --package-id basic_1.0:8c486aa50eb8b372cd7c1d5d019ba82b8f1b5614d1e9086ee239f3c27ba184a7 --sequence 1
+ res=0
2021-08-10 15:44:19.661 CST [chaincodeCmd] ClientWait -> INFO 001 txid [d9e11ee1c0037f1ddfd5ec391a275a8e55d8d4dc03443fc2a455a6cd0bf7dd3f] committed with status (VALID) at localhost:9051
Chaincode definition approved on peer0.org2 on channel 'mychannel'
Using organization 1
Checking the commit readiness of the chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
        "approvals": {
                "Org1MSP": true,
                "Org2MSP": true
        }
}
Checking the commit readiness of the chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Checking the commit readiness of the chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to check the commit readiness of the chaincode definition on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name basic --version 1.0 --sequence 1 --output json
+ res=0
{
        "approvals": {
                "Org1MSP": true,
                "Org2MSP": true
        }
}
Checking the commit readiness of the chaincode definition successful on peer0.org2 on channel 'mychannel'
Using organization 1
Using organization 2
+ peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --channelID mychannel --name basic --peerAddresses localhost:7051 --tlsRootCertFiles /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt --version 1.0 --sequence 1
+ res=0
2021-08-10 15:44:27.863 CST [chaincodeCmd] ClientWait -> INFO 001 txid [7703734bb0cbd3e6fa41c15b872bb5d228b5a0e504c9dedfc2d326661068cfd8] committed with status (VALID) at localhost:7051
2021-08-10 15:44:27.863 CST [chaincodeCmd] ClientWait -> INFO 002 txid [7703734bb0cbd3e6fa41c15b872bb5d228b5a0e504c9dedfc2d326661068cfd8] committed with status (VALID) at localhost:9051
Chaincode definition committed on channel 'mychannel'
Using organization 1
Querying chaincode definition on peer0.org1 on channel 'mychannel'...
Attempting to Query committed status on peer0.org1, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org1 on channel 'mychannel'
Using organization 2
Querying chaincode definition on peer0.org2 on channel 'mychannel'...
Attempting to Query committed status on peer0.org2, Retry after 3 seconds.
+ peer lifecycle chaincode querycommitted --channelID mychannel --name basic
+ res=0
Committed chaincode definition for chaincode 'basic' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]
Query chaincode definition successful on peer0.org2 on channel 'mychannel'
Chaincode initialization is not required

运行app.js日志

Loaded the network configuration located at /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/connection-org1.json
Built a CA Client named ca-org1
Built a file system wallet at /root/go/src/github.com/fabric/fabric/scripts/fabric-samples/asset-transfer-basic/application-javascript/wallet
Successfully enrolled admin user and imported it into the wallet
Successfully registered and enrolled user appUser and imported it into the wallet

--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger
*** Result: committed

--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger
*** Result: [
  {
    "Key": "asset1",
    "Record": {
      "ID": "asset1",
      "Color": "blue",
      "Size": 5,
      "Owner": "Tomoko",
      "AppraisedValue": 300,
      "docType": "asset"
    }
  },
  {
    "Key": "asset2",
    "Record": {
      "ID": "asset2",
      "Color": "red",
      "Size": 5,
      "Owner": "Brad",
      "AppraisedValue": 400,
      "docType": "asset"
    }
  },
  {
    "Key": "asset3",
    "Record": {
      "ID": "asset3",
      "Color": "green",
      "Size": 10,
      "Owner": "Jin Soo",
      "AppraisedValue": 500,
      "docType": "asset"
    }
  },
  {
    "Key": "asset4",
    "Record": {
      "ID": "asset4",
      "Color": "yellow",
      "Size": 10,
      "Owner": "Max",
      "AppraisedValue": 600,
      "docType": "asset"
    }
  },
  {
    "Key": "asset5",
    "Record": {
      "ID": "asset5",
      "Color": "black",
      "Size": 15,
      "Owner": "Adriana",
      "AppraisedValue": 700,
      "docType": "asset"
    }
  },
  {
    "Key": "asset6",
    "Record": {
      "ID": "asset6",
      "Color": "white",
      "Size": 15,
      "Owner": "Michel",
      "AppraisedValue": 800,
      "docType": "asset"
    }
  }
]

--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments
*** Result: committed
*** Result: {
  "ID": "asset13",
  "Color": "yellow",
  "Size": "5",
  "Owner": "Tom",
  "AppraisedValue": "1300"
}

--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID
*** Result: {
  "ID": "asset13",
  "Color": "yellow",
  "Size": "5",
  "Owner": "Tom",
  "AppraisedValue": "1300"
}

--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist
*** Result: true

--> Submit Transaction: UpdateAsset asset1, change the appraisedValue to 350
*** Result: committed

--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes
*** Result: {
  "ID": "asset1",
  "Color": "blue",
  "Size": "5",
  "Owner": "Tomoko",
  "AppraisedValue": "350"
}

--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error
2021-08-10T09:55:22.623Z - error: [Transaction]: Error: No valid responses from any peers. Errors:
    peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: Error: The asset asset70 does not exist
    peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: Error: The asset asset70 does not exist
*** Successfully caught the error:
    Error: No valid responses from any peers. Errors:
    peer=peer0.org2.example.com:9051, status=500, message=error in simulation: transaction returned with failure: Error: The asset asset70 does not exist
    peer=peer0.org1.example.com:7051, status=500, message=error in simulation: transaction returned with failure: Error: The asset asset70 does not exist

--> Submit Transaction: TransferAsset asset1, transfer to new owner of Tom
*** Result: committed

--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes
*** Result: {
  "ID": "asset1",
  "Color": "blue",
  "Size": "5",
  "Owner": "Tom",
  "AppraisedValue": "350"
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

A&long@2020

多一份打赏,多一份共享。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值