区块链系统开发测试----链码部署开发、系统开发验证

一.检查配置环境

检查虚拟机环境,确保有正在运行的Hyperledger Fabric区块链,并且其中chaincode_basic、credit_chaincode链码可以正常调用

查看chaincode_basic、credit_chaincode链码调用

二.开发征信链码代码 

基于现有征信链码,开发征信链码的升级版,使用chaincode-init文件夹中的基础链码模板,创建完善其中lib目录以及index.js内容,在lib中创建CreditPlusContract对象,在对象中添加createCreditSubjectPlus功能,实现征信主体的保存,定义subject变量属性包括(key:征信主体主键,  organizationName:征信主体评价机构名, type:评价类型,score:征信积分,creator:创建人,datetime:评价时间),其中属性除score外其余都为string类型。将subject内容上链保存  

在链码中添加征信主体查询功能(queryCreditSubjectPlus),要求能够查询所有主体内容(包括:key:征信主体主键,  organizationName:征信主体评价机构名, type:评价类型,score:征信积分,creator:创建人,datetime:评价时间)

'use strict';
const { Contract } = require("fabric-contract-api");
class CreditPlusContract extends Contract {async createCreditSubjectPlus(ctx, key, organizationName, type, creator, datetime) {console.info('=== START:创建征信主体 ===');const subject = {key: key,organizationName: organizationName,type: type,score: 0,creator: creator,datetime: datetime};await ctx.stub.putState(key, Buffer.from(JSON.stringify(subject)));console.info('=== END:创建征信主体 ===');return subject;}// 查询征信主体async queryCreditSubjectPlus(ctx, subjectKey) {console.info('=== START : 查询征信主体 ===');const bytes = await ctx.stub.getState(subjectKey);if (!bytes || bytes.length === 0) {const msg = `${subjectKey} 征信主体不存在`;console.warn(msg);throw new Error(msg);}const subject = JSON.parse(bytes.toString());console.info('=== END : 查询征信主体 ===');return subject;}}module.exports = CreditPlusContract;

 在链码结构中test目录中添加对于createCreditSubjectPlus以及QueryCreditSubjectPlus功能的单元测试,提交测试代码和验证结果。

'use strict';
const sinon = require('sinon');
const chai = require('chai');
const sinonChai = require('sinon-chai');
const expect = chai.expect;
chai.use(sinonChai);
let assert = sinon.assert;
const { Context } = require('fabric-contract-api');
const { ChaincodeStub, ClientIdentity } = require('fabric-shim');
const CreditPlusContract = require('../lib/creditContract');
describe('Credit Chaincode Test', () => {let stub, ctx, ClientId;beforeEach(() => {ctx = new Context();stub = sinon.createStubInstance(ChaincodeStub);stub.getMspID.returns('Org1');ctx.setChaincodeStub(stub);ClientId = sinon.createStubInstance(ClientIdentity);stub.putState.callsFake((key, value) => {if (!stub.states) {stub.states = {};}stub.states[key] = value;});stub.getState.callsFake(async (key) => {let ret;if (stub.states) {ret = stub.states[key];}return Promise.resolve(ret);});stub.deleteState.callsFake(async (key) => {if (stub.states) {delete stub.states[key];}});});describe('Test CreditSubject function', () => {it('should return success on createCreditSubject', async () => {let creditContract = new CreditPlusContract();let creditSubject = await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company","Admin","2024-05-28 14:35:00");let scroe = creditSubject.score;expect(scroe).to.equals(0);});it('should return success on queryCreditSubject', async () => {let creditContract = new CreditPlusContract();await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company", "Admin", "2024-05-28 14:35:00");let creditSubject = await creditContract.queryCreditSubjectPlus(ctx, "A001");let name = creditSubject.organizationName;expect(name).to.equals("My Company");});});
})

测试代码:

 

三.部署征信链码

在虚拟机指定Hyperledger Fabric中实现对应链码的部署并验证部署情况。

将链码名修改切credit_chaincode_plus,删除node_modules目录以及对应package-lock.json文件,上传至服务器chaincode目录下:

打包测试:

export FABRIC_CFG_PATH=${PWD}/configpeer lifecycle chaincode package ./chaincode/credit_chaincode_plus.tar.gz --path ./chaincode/credit_chaincode_plus --lang node --label credit_chaincode_plus_1.0

 

查看打包结果:

安装链码:运行以下进入fabric-cli容器:

docker exec -it fabric-cli bash

1. 在org1中安装:运行以下链码安装:

. scripts/set-env.sh 1 0 7051
peer lifecycle chaincode install chaincode/credit_chaincode_plus.tar.gz

 

2. 在org2中安装,运行以下链码安装:

. scripts/set-env.sh 2 0 9051
peer lifecycle chaincode install chaincode/credit_chaincode_plus.tar.gz

 

3. 查看安装情况

peer lifecycle chaincode queryinstalled

 

批准链码
org1批准链码

1. 设置链码环境变量

export CC_PACKAGE_ID=credit_chaincode_plus_1.0:9415a0be8812a91c2e510619a4d2a6a5cd06a8cf8f9cef96ee4eec2f456ab7ec

2. 设置Org1环境变量

. scripts/set-env.sh 1 0 7051

3.批准链码

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA

 

1. 设置Org2环境变量

. scripts/set-env.sh 2 0 9051

2.批准链码

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile $ORDERER_CA

 

检查提交准备

peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.0 --sequence 1 --tls --cafile $ORDERER_CA --output json

 

提交链码

peer lifecycle chaincode commit -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.0 --sequence 1 --tls --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA

 

查询提交的链码

peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name credit_chaincode_plus --tls --cafile $ORDERER_CA

 

查看运行镜像形成容器情况

docker logs -f b1ddd21303a5

 

调用createCreditSubject功能

peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name credit_chaincode_plus --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA -c '{"function":"createCreditSubjectPlus", "Args":["A001", "My Company", "Company","Admin","2024-05-28 14:35:00"]}'

 

调用queryCreditSubject功能

peer chaincode query -C $CHANNEL_NAME --name credit_chaincode_plus -c '{"function":"queryCreditSubjectPlus","Args":["A001"]}'

 

四.部署删除和更新代码 

在链码中添加DeleteCreditSubject,实现按subject变量的key属性删除数据功能

在链码中添加UpdateSubjectScore功能,实现按key更新subject,更新subject变量中的score

'use strict';const { Contract } = require("fabric-contract-api");class CreditPlusContract extends Contract {async createCreditSubjectPlus(ctx, key, organizationName, type, creator, datetime) {console.info('=== START:创建征信主体 ===');const subject = {key: key,organizationName: organizationName,type: type,score: 0,creator: creator,datetime: datetime};await ctx.stub.putState(key, Buffer.from(JSON.stringify(subject)));console.info('=== END:创建征信主体 ===');return subject;}// 查询征信主体async queryCreditSubjectPlus(ctx, subjectKey) {console.info('=== START : 查询征信主体 ===');const bytes = await ctx.stub.getState(subjectKey);if (!bytes || bytes.length === 0) {const msg = `${subjectKey} 征信主体不存在`;console.warn(msg);throw new Error(msg);}const subject = JSON.parse(bytes.toString());console.info('=== END : 查询征信主体 ===');return subject;}async deleteCreditSubject(ctx, id) {const exists = await this.creditSubjectExists(ctx, id);if (!exists) {throw new Error(`The asset ${id} does not exist`);}return ctx.stub.deleteState(id);}async creditSubjectExists(ctx, id) {const assetJSON = await ctx.stub.getState(id);return assetJSON && assetJSON.length > 0;}async updateSubjectScore(ctx,subjectKey,inputScore) {const exists = await this.creditSubjectExists(ctx,subjectKey);if (!exists) {throw new Error(`The credit subject ${subjectKey} does not exist`);}const bytes = await ctx.stub.getState(subjectKey);if (!bytes || bytes.length ===0){const msg = `${subjectKey} 征信主体不存在`;console.warn(msg)throw new Error (msg);}var subject = JSON.parse(bytes.toString());subject.score=inputScore;return ctx.stub.putState(subjectKey, Buffer.from(JSON.stringify(subject)));}}module.exports = CreditPlusContract;

在链码结构中test目录中添加对于DeleteCreditSubject以及UpdateSubjectScore功能的单元测试 

 

'use strict';
const sinon = require('sinon');
const chai = require('chai');
const sinonChai = require('sinon-chai');
const expect = chai.expect;
chai.use(sinonChai);
let assert = sinon.assert;
const { Context } = require('fabric-contract-api');
const { ChaincodeStub, ClientIdentity } = require('fabric-shim');
const CreditPlusContract = require('../lib/creditContract');
describe('Credit Chaincode Test', () => {let stub, ctx, ClientId;beforeEach(() => {ctx = new Context();stub = sinon.createStubInstance(ChaincodeStub);stub.getMspID.returns('Org1');ctx.setChaincodeStub(stub);ClientId = sinon.createStubInstance(ClientIdentity);stub.putState.callsFake((key, value) => {if (!stub.states) {stub.states = {};}stub.states[key] = value;});stub.getState.callsFake(async (key) => {let ret;if (stub.states) {ret = stub.states[key];}return Promise.resolve(ret);});stub.deleteState.callsFake(async (key) => {if (stub.states) {delete stub.states[key];}});});describe('Test CreditSubject function', () => {it('should return success on createCreditSubject', async () => {let creditContract = new CreditPlusContract();let creditSubject = await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company","Admin","2024-05-28 14:35:00");let scroe = creditSubject.score;expect(scroe).to.equals(0);});it('should return success on queryCreditSubject', async () => {let creditContract = new CreditPlusContract();await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company", "Admin", "2024-05-28 14:35:00");let creditSubject = await creditContract.queryCreditSubjectPlus(ctx, "A001");let name = creditSubject.organizationName;expect(name).to.equals("My Company");});it('should return sucess on DeleteCreditSubject', async () => {let creditContract = new CreditPlusContract();await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company", "Admin", "2024-05-28 14:35:00");await creditContract.deleteCreditSubject(ctx,"A001");let ret = await stub.getState('A001');expect(ret).to.equal(undefined);});it('should return sucess on updateSubjectScore', async () => {let creditContract = new CreditPlusContract();await creditContract.createCreditSubjectPlus(ctx, "A001", "My Company", "Company", "Admin", "2024-05-28 14:35:00");await creditContract.updateSubjectScore(ctx, "A001",10);let ret = JSON.parse(await stub.getState('A001'));expect(ret.score).to.eql(10);});});
})

测试代码:

 

五.更新部署征信链码

在链码中重新部署开发链码,实现链码更新(要求version、sequence有迭代痕迹)

打包测试:

export FABRIC_CFG_PATH=${PWD}/configpeer lifecycle chaincode package ./chaincode/credit_chaincode_plus.tar.gz --path ./chaincode/credit_chaincode_plus --lang node --label credit_chaincode_plus_1.1

 

安装链码
运行以下进入fabric-cli容器:

docker exec -it fabric-cli bash

1. 在org1中安装 | 运行以下链码安装:

. scripts/set-env.sh 1 0 7051
peer lifecycle chaincode install chaincode/credit_chaincode_plus.tar.gz

 

2. 在org2中安装
运行以下链码安装:

. scripts/set-env.sh 2 0 9051
peer lifecycle chaincode install chaincode/credit_chaincode_plus.tar.gz

 

3. 查看安装情况

peer lifecycle chaincode queryinstalled

 

三.批准链码
org1批准链码

设置链码环境变量

export CC_PACKAGE_ID=credit_chaincode_plus_1.1:a7d65de21f706c25029b84cbbf7de2163d06d9b8e9fc33fd20a5a59cc3a18b01

2. 设置Org1环境变量

. scripts/set-env.sh 1 0 7051

3.批准链码

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.1 --package-id $CC_PACKAGE_ID --sequence 2 --tls --cafile $ORDERER_CA

 

1. 设置Org2环境变量

. scripts/set-env.sh 2 0 9051

2.批准链码

peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.1 --package-id $CC_PACKAGE_ID --sequence 2 --tls --cafile $ORDERER_CA

 

检查提交准备

peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.1 --sequence 2 --tls --cafile $ORDERER_CA --output json

 

提交链码

peer lifecycle chaincode commit -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --channelID $CHANNEL_NAME --name credit_chaincode_plus --version 1.1 --sequence 2 --tls --cafile $ORDERER_CA --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA

 

查询提交的链码

peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name credit_chaincode_plus --tls --cafile $ORDERER_CA

 

查看运行镜像形成容器情况

docker logs -f b1ddd21303a5

 

调用createCreditSubject功能

peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name credit_chaincode_plus --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA -c '{"function":"createCreditSubjectPlus", "Args":["A001", "My Company", "Company","Admin","2024-05-28 14:35:00"]}'

调用queryCreditSubject功能

peer chaincode query -C $CHANNEL_NAME --name credit_chaincode_plus -c '{"function":"queryCreditSubjectPlus","Args":["A001"]}'

调用deleteCreditSubject功能

peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name credit_chaincode_plus --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA -c '{"function":"deleteCreditSubject", "Args":["A001"]}'

 

调用updateSubjectScore功能(这边如果嫌麻烦的话可以更新功能之后再调用删除功能)

peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name credit_chaincode_plus --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles $PEER0_ORG2_CA -c '{"function":"updateSubjectScore", "Args":["A002","10"]}'

 

 


 

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

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

相关文章

Niantic利用Meta Llama让数字生物栩栩如生

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

华为机考入门python3--(26)牛客26-字符串排序

分类:字符串 知识点: 字符串是否仅由字母构成 my_str.isalpha() 字母列表按小写排序 letters.sort(keylambda x: x.lower()) 题目来自【牛客】 def custom_sort(input_str):letters []non_letters []for char in input_str:if char.isalpha…

【软件工程】【23.04】p1

关键字: 软件模型、提炼、加工表达工具、通信内聚、访问依赖、边界类交互分析、RUP核心工作流、首先测试数据流、软件验证过程、CMMI过程域分类工程类; 软件工程目的、功能需求是需求的主体、结构化方法、耦合、详细设计工具、类、类图、RUP采用用例技…

鲜花门店小程序开发流程:详细教程,让你轻松掌握

想要开发一款专属于自己鲜花门店的小程序吗?不知道从何开始?别担心,本文将为你提供详细的开发流程,帮助你轻松掌握。 1. 注册登录乔拓云网并进入操作后台 首先,你需要注册并登录乔拓云网,然后进入操作后台…

Llama模型家族之使用 Supervised Fine-Tuning(SFT)微调预训练Llama 3 语言模型(三)通过web页面方式微调

LlaMA 3 系列博客 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (一) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (二) 基于 LlaMA 3 LangGraph 在windows本地部署大模型 (三) 基于 LlaMA…

Amazon云计算AWS(一)

目录 一、基础存储架构Dynamo(一)Dynamo概况(二)Dynamo架构的主要技术 二、弹性计算云EC2(一)EC2的基本架构(二)EC2的关键技术(三)EC2的安全及容错机制 提供的…

Python自动化办公Excel数据处理实战指南

目录 一、引言 二、需求分析 三、技术选型 四、实战操作 数据读取 数据清洗 数据分析 数据输出 五、学习资源推荐: 六、结语 一、引言 在现代办公环境中,Excel数据处理是一项不可或缺的技能。然而,当数据量庞大、处理流程复杂时&a…

Linux文本文件管理003

★排序、去重、统计★ 1)排序 sort -n按照数值排序 -r降序排列 2)去重 uniq 过滤相邻、重复的行 -c 对重复行计数 3)统计 wc 统计文件中的字节数、单词数、行数 -l 显示行数 今天通过使用grep、awk、cut指令和上面几个选项提取文本文件…

专业渗透测试 Phpsploit-Framework(PSF)框架软件小白入门教程(八)

本系列课程,将重点讲解Phpsploit-Framework框架软件的基础使用! 本文章仅提供学习,切勿将其用于不法手段! 继续接上一篇文章内容,讲述如何进行Phpsploit-Framework软件的基础使用和二次开发。 现在,我们…

三十、openlayers官网示例解析Double click, Drag and Zoom——第二次点击鼠标拖拽缩放地图效果、取消地图双击放大事件

这篇展示了如何在地图上添加第二次按下鼠标移动鼠标实现拖拽缩放地图效果。 官网demo地址: Double click, Drag and Zoom 官网介绍文字的翻译如下: 示例比较简单,直接贴代码: const map new Map({//添加第二次点击拖拽缩放地图i…

一文了解等保2.0中IPS与IDS的差异

IPS(入侵防御系统) 入侵防御系统是一部能够监视网络或网络设备的网络资料传输行为的计算机网络安全设备,能够即时的中断、调整或隔离一些不正常或是具有伤害性的网络资料传输行为。 对异常的、可能是入侵行为的数据进行检测和报警&#xff…

MM模块六(收货)

接到供应商收到的货以后,进行一个收货的动作 收货:MIGO 1.消耗物料的采购订单 数量是供应商的数量 消耗物料的采购订单,收进来的货物直接进入消耗,不会增加库存,所以这里没有库存地点进行选择 点击过账 收货后在采购…

微服务架构五大设计模式详解,助你领跑行业

微服务架构设计模式详解(5种主流模式) 微服务架构 微服务,一种革命性的架构模式,主张将大型应用分解为若干小服务,通过轻量级通信机制互联。每个服务专注特定业务,具备独立部署能力,轻松融入生产环境,为系…

2005-2022年各省全体居民人均可支配收入数据(无缺失)

2005-2022年各省全体居民人均可支配收入数据(无缺失) 1、时间:2005-2022年 2、来源:国家统计局、统计年鉴 3、指标:全体居民人均可支配收入 4、范围:31省 5、缺失情况:无缺失 6、指标解释…

java多线程创建方式

1. 继承Thread类 这种方式是通过创建一个新的类继承自Thread类,并覆盖run()方法来创建线程。然后通过创建这个类的对象并调用其start()方法来启动线程。 public class MyThread extends Thread { public void run() { // 在这里定义线程的执行逻辑 …

Java—选择排序

选择排序是一种简单但高效的排序算法。它的基本思想是从未排序的部分中选择最小(或最大)的元素,并将其放置在已排序部分的末尾。 实现步骤 具体实现选择排序的步骤如下: 遍历数组:从数组的第一个元素开始&#xff0…

webpack构建流程

对webpack的理解: webpack 是一个用于现代 JavaScript 应用程序的静态模块打包工具 可以使用webpack管理模块 因为在webpack看来,项目中的所有资源皆为模块,通过分析模块间的依赖关系,在其内部构建出一个依赖图,最终编…

【MATLAB】数字滤波器的设计

一、引言 在信号处理过程中,所处理的信号往往混有噪声,从接收到的信号中消除或减弱噪声是信号传输和处理中十分重要的问题。根据有用信号和噪声的不同特性,提取有用信号的过程称为滤波,实现滤波功能的系统称为滤波器。在以往的模拟电路中用的…

OrangePi AIpro测评:智能与创新的完美结合

OrangePi AIpro上手指南 简介 香橙派与华为合作发布的香橙派AiPro为Ai主力,为边缘设备的Ai计算提供了可能。 集成图形处理器,拥有8GB/16GB LPDDR4X(我这个是8G内存版本的),可以外接32GB/64GB/128GB/256GB eMMC模块&a…

大模型备案VS算法备案:差异、要求与合规快照

​下图为最新的直至第五批深度合成服务算法备案信息的公告 根据目前公开的国内大模型算法备案统计来看,首批境内深度合成服务算法备案清单,总共通过了五批。 以第二批举例,境内深度合成服务算法备案清单,总共通过110家&#xff0…