Fabric: 使用InvokeChaincode实现跨通道数据访问

因为工作中遇到一些问题考虑使用Fabric的跨通道链码调用方法InvokeChaincode()来解决,这篇文章主要是记录以下在Fabric测试网络中InvokeChaincode()的使用过程及遇到的问题。

1 前期准备

1.1 认识InvokeChaincode

  InvokeChaincode的作用是调用指定的链码。而被调用的链码与执行 InvokeChaincode的链码在或不在同一个通道上时,其能发挥的作用不同。具体规则如下:

  • 如果与被调用的链码在同一个通道上,它只是将调用的链码读取集和写入集添加到调用事务中。
  • 如果与被调用的链码在不同的通道上,则只有响应返回给调用的链码;来自被调用链码的任何putState()调用都不会对账本产生任何影响(我的理解是,这种情况下只可以读数据不能写数据)。

另外,InvokeChaincode的参数及其返回值如下:

  • 参数chaincodeName: string类型,目标链码名称。
  • 参数args: [][]byte型,参数列表。
  • 参数channel: string类型,目标链码所在的通道名称。如果channel值为"",则表示当前通道。
  • 返回值peer.Response: peer.Pesponse类型的数据是对peer节点操作的响应结果,通过处理peer.Response类型的数据,可以获取操作执行的状态、事件以及返回的值。也就是说,可以从peer.Response中抽取出目标链码的返回值。peer.Response数据通常包含以下字段:
字段名含义
Status操作的状态码 ,操作成功为200
Payload操作的返回结果,其类型为:[]byte
Message操作的错误信息,仅在出错时有效
TxId操作所在的交易ID
Proposal操作所在的提案
1.2 准备工作

   为了能减少创建节点、通道等这些繁琐的工作,这里将充分利用Fabric中的测试网络test-network。在实现跨通道的数据访问之前,需要先将基本的环境搭建完成。具体包括以下:

  • 使用./network.sh up命令创建peer节点、Orderer节点和cli客户端。
  • 使用./network.sh createChannel -c命令创建两个通道channel1channel2,这两个通道将共用所有的peer和Orderer节点。
  • 配置peer CLI, 将peer CLI绑定到Org1上的peer0节点上。
  • fabric-samples中提供的go语言链码示例部署到channel1中,并使用peer chaincode invoke调用链码的InitLedger方法往链码的world state中写入数据。具体代码如下:
#将asset-transfer-basic/chaincode-go中的链码部署到channel1中
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go -c channel1
#执行InitLedger()
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" -C channel1 -n basic --peerAddresses localhost:7051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" --peerAddresses localhost:9051 --tlsRootCertFiles "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" -c '{"function":"TransferAsset","Args":["asset6","Christopher"]}'
#查询world state中的所有数据
peer chaincode query -C channel1 -n basic -c '{"Args":["GetAllAssets"]}'

Tips:以上这些工作不是本篇的重点,具体过程可以参考其他资料,这里不赘述。

以上准备工作完成后,需要编写新的链码文件的来具体引用InvokeChaincode方法,并将新的链码部署到通道channel2上。

2 实现

2.1 具体实现

  • 先编写链码文件test_invoke.go,具体代码如下:
package chaincodeimport ("github.com/hyperledger/fabric-contract-api-go/contractapi"
)type TestSmartContract struct {contractapi.Contract
}func (s *TestSmartContract) QueryData(ctx contractapi.TransactionContextInterface) (string, error) {//这里为了简单,把要传递给InvokeChaincode()的参数在函数体固定了,实际应用中需要改为从peer chaincode中接收参数chaincodeName := "basic"channelName := "channel1"chaincodeArgs := make([][]byte,1)chaincodeArgs[0]=[]byte("GetAllAssets")response := ctx.GetStub().InvokeChaincode(chaincodeName, chaincodeArgs, channelName)data := response.Payloadreturn string(data), nil
}
  • test_invoke.go文件放到fabric-samples/asset-transfer-basic/chaincode-go/chaincode目录下
  • test_invoke.go文件执行权限。
sudo chmod -R 777 test_invoke.go
  • 修改fabric-samples/asset-transfer-basic/assetTransfer.go文件。将文件中NewChaincode中的参数改为&chaincode.TestSmartContract{}即可。Tips:test_invoke.go文件的主要作用就是定义结构体类型:TestSmartContract。
    在这里插入图片描述
  • 将链码部署到channel2中,这里将这个链码命名为basic_test。
./network.sh deployCC -ccn basic_test -ccp ../asset-transfer-basic/chaincode-go -ccl go -c channel2
  • 接下来在渠道channel2上调用链码basic_test上的QueryData来实现跨通道数据访问。
peer chaincode query -C channel2 -n basic_test -c '{"Args":["QueryData"]}'

结果如下(成功返回了channel1中的world state数据了)。至此,就完成了跨通道的数据访问。
在这里插入图片描述

2.2 补充说明

  在编写test_invoke.go文件时,中途遇到一些错误信息。整理如下:

  • 使用deployCC命令部署链码时若出现错误,一般都是go语言的语法错误,这里直接根据提示信息修改代码即可。
  • 即使 deployCC命令成功了也不代表链码能运行成功。后续链码的编译和执行错误信息可以通道命令docker查看。先运行docker ps -a命令,如果出现如下情况,则说明链码依然有错。
    在这里插入图片描述
    这种情况下,可以通过docker日志来查看具体的错误信息。命令如下:
docker logs --details <CONTAINER-ID>

代码修改之后需要重新使用 deployCC部署。

  • 开始test_invoke.go文件中只有一个名为queryData的方法时遇到这样一种错误: Contracts are required to have at least 1 (none-ignored) public method.
    错误原因:go语言中的方法名如果第一个字母为小写,则说明其他包无法使用这个方法,即为私有。所以这个错误只需要将方法名的首字母大写即可,即QueryData。这里建议,链码中的方法名都尽可能首字母大写。
  • InvokeChaincode方法的返回值类型为peer.Response,如果QueryData直接返回peer.Response,比如采用如下写法:
func (s *TestSmartContract) QueryData(ctx contractapi.TransactionContextInterface) peer.Response {chaincodeName := "basic"channelName := "channel1"chaincodeArgs := make([][]byte,1)chaincodeArgs[0]=[]byte("GetAllAssets")response := ctx.GetStub().InvokeChaincode(chaincodeName, chaincodeArgs, channelName)return response
}

这种写法会提示错误:Cannot use metadata. Metadata did not match schema。为了解决这个错误,在最终的代码中将QueryData的返回值类型改为了(string,error)

参考资料

  1. https://blog.csdn.net/weixin_41946008/article/details/123044664
  2. https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/186679.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++之旅(学习笔记)第6章 基本操作

C之旅&#xff08;学习笔记&#xff09;第6章 基本操作 6.1 基本操作 class X{ public:X(Sometype); // "普通的构造函数": 创建一个对象X(); // 默认构造函数X(const X&); // 拷贝构造函数X(X&&); // 移动构造函数X& operator(const …

微信小程序将后端返回的图片文件流解析显示到页面

说明 由于请求接口后端返回的图片格式不是一个完整的url,也不是其他直接能显示的图片格式&#xff0c;是一张图片 后端根据模板与二维码生成图片,返回二进制数据 返回为文件流的格式,用wx.request请求的时候&#xff0c;就自动解码成为了下面这样的数据数据格式,这样的数据没…

Go-服务注册和发现,负载均衡,配置中心

文章目录 什么是服务注册和发现技术选型 Consul 的安装和配置1. 安装2. 访问3. 访问dns Consul 的api接口go操作consulgrpc下的健康检查grpc的健康检查规范动态获取可用端口号 负载均衡策略1. 什么是负载均衡2. 负载均衡策略1. 集中式load balance2. 进程内load balance3. 独立…

SOLIDWORKS软件提供了哪些特征造型方法?硕迪科技

SOLIDWORKS作为一款三维设计软件&#xff0c;为用户提供了多种特征造型方法&#xff0c;以下是其中几种常用的&#xff1a; 实体建模特征&#xff1a;SOLIDWORKS使用实体建模技术来创建和编辑三维几何体。通过使用基本几何体&#xff08;如立方体、圆柱体、圆锥体等&#xff09…

计算机视觉驾驶行为识别应用简述

一、什么是计算机视觉识别&#xff1f; 计算机视觉识别是一种基于图像处理和机器学习的人工智能应用技术&#xff0c;可以用于多个场景。常见应用场景包括人脸识别、场景识别、OCR识别以及商品识别等。今天以咱们国产系统豌豆云为例&#xff0c;为大家梳理一下在车辆驾驶行为中…

docker部署redis6

前言&#xff1a;在离线服务器上&#xff08;无联网&#xff09;&#xff0c;部署redis的方式&#xff0c;采用docker是比较方便的。下面将描述如何使用docker部署单机版redis 环境&#xff1a;centos 7 redis&#xff1a;6.2.14 docker&#xff1a;20.10.9 1.下载 redis 镜像…

工业相机基本知识理解:工业相机IO接口,功耗和供电方式

I-input 相机接收外部信号&#xff0c;可用于触发相机&#xff08;硬触发&#xff09;&#xff0c;也可用于定制不同的 功能&#xff0c;例如使用不同信号宽度来改变相机的曝光时间。主要用于现场设 备控制相机使用&#xff0c;常常配合各种传感器使用 O-output 相机输出信号&a…

单链表(增删改查)【超详细】

目录 单链表 1.单链表的存储定义 2.结点的创建 3.链表尾插入结点 4.单链表尾删结点 5.单链表头插入结点 6.单链表头删结点 7.查找元素&#xff0c;返回结点 8.在pos结点前插入一个结点 ​编辑 9.在pos结点后插入一个结点 10.删除结点 11.删除pos后面的结点 12.修改…

一文读懂RestCloud AppLink

RestCloud AppLink是什么&#xff1f; RestCloud AppLink 是一种应用程序集成解决方案&#xff0c;它提供了一套工具和技术&#xff0c;用于实现不同应用程序之间的无缝集成和交互。平台旨在解决企业中应用程序之间数据孤岛、信息孤立和业务流程不畅的问题&#xff0c;提高企业…

每次重启完IDEA,application.properties文件里的中文变成?

出现这种情况&#xff0c;在IDEA打开Settings-->Editor-->File Encodings 然后&#xff0c;你需要将问号改为你需要的汉字。 重启IDEA&#xff0c;再次查看你的.properties文件就会发现再没有变成问号了

XOR Construction

思路&#xff1a; 通过题目可以得出结论 b1^b2a1 b2^b3a2 ....... bn-1^bnan-1 所以就可以得出 (b1^b2)^(b2^b3)a1^a2 b1^b3a1^a2 有因为当确定一个数的时候就可以通过异或得到其他所有的数&#xff0c;且题目所求的是一个n-1的全排列 那么求出a的前缀异或和arr之后…

网页分析和xml.etree库

源代码&#xff1a; Lib/xml/etree/ElementTree.py 该xml.etree.ElementTree模块实现了一个简单高效的 API&#xff0c;用于解析和创建 XML 数据。 一、说明 这是一个简短的使用教程xml.etree.ElementTree&#xff08;ET简而言之&#xff09;。目标是演示该模块的一些构建块和基…

送水服务预约小程序内容该如何做

无论小区还是办公楼等场景&#xff0c;送水服务往往有较高需求&#xff0c;同时该服务属于长期稳定性的&#xff0c;因此对品牌来说&#xff0c;如何打造品牌获取更多用户及转化非常重要&#xff0c;然而在实际订水过程中&#xff0c;又会面临着一些难题&#xff1a; 1、品牌传…

代码随想录算法训练营第四十六天|139. 单词拆分、多重背包问题、总结

第九章 动态规划part08 139. 单词拆分 给你一个字符串 s 和一个字符串列表 wordDict 作为字典。请你判断是否可以利用字典中出现的单词拼接出 s 。 注意&#xff1a;不要求字典中出现的单词全部都使用&#xff0c;并且字典中的单词可以重复使用。 关于字符串类型的题目还是…

ElementUI之el-progress动态修改进度条里面文本颜色与进度条色块统一

1.效果&#xff1a; 2.实现方式 通过行内style样式动态给整个progress赋颜色 再在样式里给进度条文字单独设置颜色为默认继承父级颜色就ok啦 <el-progress class"custom-progress" stroke-linecap"square" :style"{color:item.color}" :colo…

使用电阻检测仪是否能满足生产车间防静电要求

在现代工业生产中&#xff0c;静电对产品质量和人员安全造成的影响越来越受到重视。特别是在电子、半导体、化工等领域&#xff0c;静电问题可能导致产品损坏、人员触电等严重后果。因此&#xff0c;生产车间的防静电工作显得尤为重要。而电阻检测仪作为一种常用的防静电工具&a…

Java后端开发——JDBC入门实验

JDBC&#xff08;Java Database Connectivity&#xff09;是Java编程语言中用于与数据库建立连接并进行数据库操作的API&#xff08;应用程序编程接口&#xff09;。JDBC允许开发人员连接到数据库&#xff0c;执行各种操作&#xff08;如插入、更新、删除和查询数据&#xff09…

OpenAI开发者大会大模型圈开卷AI Agent? 实在智能布局前瞻已下“先手棋”

“平地起惊雷&#xff0c;至今有余音。” 去年的11月&#xff0c;OpenAI发布ChatGPT给科技圈劈下了一道惊雷&#xff0c;引爆了全世界的AI大模型热潮&#xff0c;全球科技巨头公司争先恐后地推出通用大模型&#xff0c;探索产业应用的可能。 短短一年后&#xff0c;北京时间1…

汇编-DUP操作符

DUP操作符使用整数表达式作为计数器&#xff0c; 为多个数据项分配存储空间。 在为字符串或数组分配存储空间时&#xff0c;这个操作符尤其有用&#xff0c;并且可以使用初始化或非初始化数据&#xff1a; .data BYTE 20 DUP(0) ;20个字节&#xff0c;都等于0 BYTE 20 …

电商项目之Java8函数式接口落地实践

文章目录 1 问题背景2 前言3 多处重复的重试机制代码4 优化后的代码5 进一步优化 1 问题背景 在电商场景中&#xff0c;会调用很多第三方的云服务&#xff0c;比如发送邮件、发起支付、发送验证码等等。由于网络存在抖动&#xff0c;有时候发起调用后会拿到500的状态码&#xf…