GZ036 2023年全国职业院校技能大赛高职组 区块链技术应用赛项赛题(第7-10套)

资源下载
  1. 二一教育资源

GZ036 2023年全国职业院校技能大赛高职组 区块链技术应用赛项赛题(第7-10套)

资源简介

2023年全国职业院校技能大赛
高职组
“区块链技术应用”
赛项赛卷(8卷)



参赛队编号:
背景描述
现实中患者私密信息泄露情况时有发生,医疗部门的柜式存储和纸质记录已不再是最优选择。在2015~2016年间,美国的数家医院遭受黑客入侵,导致八千余万份医疗健康记录被盗。医疗数据泄漏占全球数据泄漏事件的15%,已经成为全球数据泄漏的第二大行业。并且医疗部门的柜式存储和纸质记录实现数据共享极为困难,造成病人看病难的问题。
区块链医疗健康平台业务流程图
相信很多人都有重复就医的经历,在一家医院做的检查,换一家医院就需要重新做一次,耗时耗钱不说,还延误病情。如果能把个人的医疗检查记录上传到区块链,在这种智能化的信任机制下,不需要医患之间的相互信任,共享医疗健康数据,安全又便捷。那也就意味着,在一家医院的检查记录,在另一家医院也能受到认可,不必重复检查,这将极大的提升患者的就医效率,减轻医院的工作负担。现有一个医疗健康数据共享平台S,患者A在S中输入身份证号后进行挂号,当A挂医院H科室C的号后,S将挂号信息显示给A。默认A去就诊,不考虑其他情况。当医生D在S中点击开始就诊后,S将根据A的身份证号查找A在C的过往所有医院的病历资料,如果有过往病历资料,调用A在对应科室过往的病历资料,授权D查看权限。默认D会在S中点击新建A的病历资料,不考虑其他情况。S调用A在H中的挂号信息、就诊医生的信息到新建的病历资料中(需要按照本顺序声明)。D需要填写病历资料,如果不填写等待填写不能点击就诊结束。当D点击就诊结束, D不可再修改本次病历资料,也不可再查看A的病历资料。如果D在12小时内不点击就诊结束,S自动结束就诊。A可以查看自己的病历资料。本案例默认S调用的信息真实,不考虑其他情况。
区块链医疗健康平台系统架构图
模块一:区块链产品方案设计及系统运维(35分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块一提交结果.docx】中对应的任务序号下。
任务1-1:区块链产品需求分析与方案设计
医疗健康平台中涉及到医院、医生、患者等参与方,他们需要在区块链医疗健康平台中完成账户注册、身份上链、挂号就诊、查询病例等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于医疗健康平台系统架构,以区块链医疗健康平台为背景,结合账户注册、登录服务、入驻上链、查询病例、新建病例等核心功能描述,撰写流程图/功能图、用例图等概要设计。本任务需要依据项目背景完成需求分析与方案设计,具体要求如下:
1. 依据给定区块链医疗健康平台的业务流程图以及用例表,编制系统业务用例图,用例图中包含系统参与角色以及用例;
表1-1-1 用例表
用例编号 用例标题 优先级 测试步骤 预期结果 测试结果
HK-TEST-01 患者在区块链医疗健康平台上挂号 高 在挂号界面,患者可以选择科室、医生、时间完成挂号,弹出挂号凭证界面 挂号成功 挂号成功
HK-TEST-02 医生在区块链医疗健康平台就诊 高 在挂号界面,拉取患者的挂号记录,在记录信息中点击就诊按钮,记录状态切换为开始就诊状态 开始就诊 开始就诊
HK-TEST-03 医生在区块链医疗健康平台检索病例 高 医生在就诊界面,通过检索当前就诊人,查询该就诊人的过往病例,可以对检索的病例进行点击查看,点击查看验证医生的身份和权限,审核通过后可弹窗查看患者病历 拉取病例记录 审核医生身份 查看成功 拉取病例记录 审核医生身份 查看成功
HK-TEST-04 医生在区块链医疗健康平台新建病例 高 在病例界面,展示当前就诊人的过往病例,可以点击新建,弹窗显示新建病例的页面,医生可在本页面输入病例信息进行创建 创建成功 创建成功
HK-TEST-05 医生在区块链医疗健康平台结束就诊 高 在就诊界面,展示当前就诊人的就诊状态以及就诊时间,点击结束就诊进行二次确认,可结束本次就诊 结束成功 结束成功
2.依据给定的背景信息、区块链医疗健康业务流程图以及区块链医疗健康平台架构图以及给出的医疗健康业务的核心流程,使用思维导图编制业务系统功能图;
表1-1-2 医疗健康平台的核心流程
过往病例检索流程 区块链医疗健康平台对医生的身份证书进行验证,判断医生的身份、查看权限等,验证通过后以当前就诊人ID作为关键字进行检索,拉取所有的过往病例
新建病例流程 区块链医疗健康平台将对医生的身份证书进行验证,判断医生的身份、写入权限等,验证通过后可以新建病例,并签名加密广播到区块链
3. 按照基础层、合约层、接口层以及应用层来设计区块链系统的架构,画出系统架构图,其中在基础层需指明需要的节点、名称、协议、存储等信息;
4. 结合案例背景将区块链医疗健康平台核心功能进行划分,完成下方表格中各个主要模块要实现的功能;
病例管理模块 请输入要实现的功能
权限管理模块 请输入要实现的功能
合约功能模块 请输入要实现的功能
5. 根据用例设计以及下方提供好的承诺集,完成区块链应用系统业务流程图;
表1-1-3 承诺集
挂号承诺 判断患者是否在平台输入正确的信息完成挂号
就诊承诺 判断医生是否在规定时间内开始就诊
病例检索承诺 判断医生是否有查看权限,是则调用过往病例,否则等待授权
新建病例承诺 判断医生是否有新建权限,以及是否为患者新建,是则填写病例,否则就诊结束
6.整合所有内容,模块调用接口编写并形成对应的需求用例文档至【区块链技术应用赛\重命名为工位号】下。
任务1-2:区块链系统部署与运维
通过给定区块链项目需求,进行区块链系统的的部署,包括系统部署、节点部署等。通过监控工具完成对网络、节点服务的监控。最终利用业务需求规范,完成系统日志、网络参数、节点服务等系统结构的维护。
子任务1-2-1:区块链网络环境搭建
在本机部署区块链网络底层环境,我们需要准备编译运行的环境,并通过区块链底层源码脚本文件编译区块链网络。
(1)使用docker安装脚本,安装docker软件,安装完成之后输出docker版本号;
(2)使用docker-compose安装脚本,安装docker-compose软件,安装完成之后输出docker-compose版本号;
(3)使用docker info命令查看docker软件相关信息,将结果中镜像源配置信息截图保存;
子任务1-2-2:区块链网络系统配置
基于原有系统配置,完成以下操作:
(1)进入区块链网络执行文件夹,使用cryptogen生产创世块文件和通道文件;
(2)进入区块链网络执行文件夹,根据docker-compose.yaml文件,通过docker容器,部署节点信息;
(3)将创建的节点加入通道中。
子任务1-2-3:区块链网络orderer集群部署
请使用区块链底层网络,基于kafka共识完成orderer集群部署方案,任务如下:
(1)进入区块链管理服务系统主目录,编写docker-orderer.yaml文件,并找到提三个order集群ip地址,写入到该文件中;
(2)找到三个order集群对应的服务器,检查当前服务器是否有防火墙权限,如有则关闭防火墙;
(3)进入区块链管理服务系统主目录,通过命令行方式,启动Orderer集群。
子任务1-2-4:区块链网络运维存储加密
(1)进入区块链存储主目录文件,运行区块链脚本,生成Key Manager管理模块,并找到生成的文件;
(2)生成Key Manager管理模块,启动Key Manager,并打印日志;
(3)启动Key Manager项目,并加密节点私钥。
任务1-3:区块链系统测试
设计对区块链系统的测试流程;结合实际业务需求,调用部署的智能合约中进行系统测试、性能测试等;根据业务需求,分析并且修复给定智能合约中的安全漏洞。利用模拟业务和测试工具来完成对区块链系统服务数据的测试。
(1)利用Truffle 编写测试智能合约,并将其部署到不同的测试网络中;
(2)使用JMeter工具发起交易操作,并发保持在其能够承受的最大范围,并查看区块链底层网络运行情况;
(3)启动区块链网络系统,将智能合约部署到ganache测试网络。
模块二:智能合约开发与测试(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块二提交结果.docx】中对应的任务序号下。
任务2-1:智能合约设计
根据医疗健康系统需求用例文档,设计合约接口,画出各需求用例的时序图。
任务2-2:智能合约开发
使用Solidity语言进行智能合约开发,根据需求用例文档在待补充源码中完成程序接口功能的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约进行业务功能的验证,成功获取合约的abi。
子任务2-2-1:信息管理合约编码
根据需求用例文档在待补充源码中完成信息管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的检索个人信息、信息管理接口功能。
1. 编写检索个人信息接口,完成患者通过身份证号检索其姓名、性别、年龄的功能;
2. 编写信息管理接口,完成允许患者与医院和科室进行信息管理,通过身份证号检索到患者的个人信息,将预约信息显示给患者,并发送到患者的账户地址中的功能;
待补充源码:
contract MedicalDataSharingPlatform {
//用于存储患者的个人信息
struct Patient {
string name; // 姓名
string gender; // 性别
uint age; // 年龄
address accountAddress; // 账户地址
}
//将患者的ID映射到其个人信息
mapping (string => Patient) patients;
// 允许患者使用其身份证号和个人信息进行注册
function register(string memory _id, string memory _name, string memory _gender, uint _age) public {
// 将患者的个人信息存储在映射中
patients[_id] = Patient(_name, _gender, _age, msg.sender);
}
/***********检索个人信息接口开发 **********/
/********** 检索个人信息接口开发 ***********/
/*********** 信息管理接口开发 **********/
/********** 信息管理接口开发 ***********/
}
子任务2-2-2:病历管理合约编码
根据需求用例文档在待补充源码中完成病历管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行新建病历、结束就诊接口功能截图保存。
1. 编写新建病历接口,实现检索病人对应科室既往病历,授权医生查看,如果没有既往病历则创建一个新的病历功能;
2. 编写结束就诊接口,实现检查病历是否已经填写,并结束病历咨询的功能。
待补充源码:
contract MedicalRecordManagement {
// 定义一个结构体用于存储病历
struct MedicalRecord {
string patientID; // 病人ID
string hospitalName; // 医院名称
string department; // 科室
string doctorName; // 医生姓名
string registrationInfo; // 信息管理信息
string pastMedicalHistory; // 既往病史
string currentMedicalHistory; // 现病史
bool isFilled; // 是否填写完毕
}
// 定义一个映射用于存储病历
mapping(string => MedicalRecord) medicalRecords;
/*********** 新建病历接口 **********/
/********** 新建病历接口 ***********/
// 定义一个函数,用于平台更新病历的信息管理和医生信息
function updateMedicalRecord(string memory patientID, string memory hospitalName, string memory department, string memory doctorName, string memory registrationInfo) public {
// 更新病历的信息管理和医生信息
medicalRecords[patientID].hospitalName = hospitalName;
medicalRecords[patientID].department = department;
medicalRecords[patientID].doctorName = doctorName;
medicalRecords[patientID].registrationInfo = registrationInfo;
}
// 定义一个函数,用于医生D填写病历
function fillInMedicalHistory(string memory patientID, string memory pastMedicalHistory, string memory currentMedicalHistory) public {
// 检查病历是否已经填写
require(bytes(pastMedicalHistory).length > 0 && bytes(currentMedicalHistory).length > 0, "a");
// 填写病历
medicalRecords[patientID].pastMedicalHistory = pastMedicalHistory;
medicalRecords[patientID].currentMedicalHistory = currentMedicalHistory;
medicalRecords[patientID].isFilled = true;
}
/*********** 结束就诊接口 **********/
/********** 结束就诊接口 ***********/
}
子任务2-2-3:病历查看合约编码
根据需求用例文档在待补充源码中完成病历查看合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的检查退款请求状态、自动批准退款请求接口功能。
编写查看病人个人信息接口,实现获取指定病人个人信息功能;
编写查看病人病情描述接口,实现获取指定病人病情描述功能。
待补充源码:
contract MedicalRecords {
// 定义一个结构体,用于存储病人信息
struct Patient {
string name; // 病人姓名
uint age; // 病人年龄
string personalInfo; // 病人个人信息
string medicalHistory; // 病人病史
string medicalContent; // 病人病情描述
}
//将病人地址映射到病人信息
mapping(address => Patient) public patients;
// 添加病人信息
function addPatient(string memory _name, uint _age, string memory _personalInfo, string memory _medicalHistory, string memory _medicalContent) public {
patients[msg.sender] = Patient(_name, _age, _personalInfo, _medicalHistory, _medicalContent);
}
/*********** 查看病人个人信息接口 **********/
/********** 查看病人个人信息接口 ***********/
// 获取病人病史
function getMedicalHistory() public view returns (string memory) {
return patients[msg.sender].medicalHistory;
}
/*********** 查看病人病情描述接口 **********/
/********** 查看病人病情描述接口 ***********/
}
子任务2-2-4:合约部署和调用
1. 解决代码错误和警告,正确编译合约,成功获取三个合约的abi,截图代码保存;
2.将三个合约形成一个文件部署至Geth中的私有链,获取部署合约的地址信息,截图编写代码保存。
任务2-3:智能合约测试
根据需求用例文档完成医疗健康合约中病例管理的功能测试以及性能测试,解决病例管理合约代码正确性的验证以及验证系统响应时间是否满足预期响应效果,编写功能测试用例,实现查询病历、填写病历的业务测试,使用性能测试工具,对查询接口进行性能测试,将编写完成的功能测试用例截图保存。
1.根据需求用例文档在以下测试用例表格中编写病历管理合约中的测试用例,依据病历管理就诊中病历查询、就诊中病历填写、就诊结束病历查询三种状态,分析在前置条件为患者在医疗平台挂号为真的情况下,医生查询病历、修改病历后,患者有既往病史、没有既往病史的情况下,产生的平台权限与医生权限的归属结果。
用例编号 用例标题 优先级 前置条件 测试步骤 测试数据 预期结果
HM-MM001 病例管理 (就诊中病历咨询) 高 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
2.利用测试工具,模拟测试查询病历接口发送200次请求,将所需HTTP请求、协议、服务器名称或IP以及路径填到工具Web服务器中,连同请求一起发送的参数,运行成功后将汇总报告提交到指定位置。
模块三:区块链应用系统开发(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块三提交结果.docx】中对应的任务序号下。
任务3-1:区块链应用前端功能开发
完成区块链应用系统的医疗健康病历页面渲染,完成服务器端(后端)与Web端(前端)的接口的联调。要求如下:
1. 按照医疗健康病历详情原型图的长度、宽度、行高、间距、文字样式、颜色等,完成医疗健康病历详情页面的样式开发,将结果截图保存;
2. 完成Vue调用医疗健康病历查询接口API,获取接口返回的姓名、性别、科别、日期等信息,填充至Vue页面中。
医疗健康病历详情页面的样式开发补充源码:
.content{ width: 100%; height: 100%; background: #EEEEEE; .contentModel{ position: absolute; top: 50%; left: 50%; box-sizing: border-box; width: 700px; padding: 41px 30px 40px; background: #fff; border-radius: 8px; box-shadow: 0 3px 12px 0 #c0c4cc; transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); -o-transform:translate(-50%, -50%); } .case_title{ text-align: center; font-size: 23px; line-height: 36px; } .personInfor{ // 此处代码补全:按原型图样式,进行长度、宽度、行高、间距、文字样式、颜色等样式设置; } .caseList{ li{ line-height: 40px; overflow: hidden; font-size: 15px; span{ float: left; width: 110px; } div{ float: left; width: calc(100% - 110px); } } } .printTime{ margin-top: 11px; padding-top: 20px; border-top: 1px solid #222222; } }
医疗健康病历详情页面的Html开发补充源码:

任务3-2:区块链应用后端功能开发
子任务3-2-1:获取区块链交易信息
区块链应用系统开发需要区块链底层网络进行支撑,开发链上数据交互功能,实现与节点建立链接,完成链上信息查询。要求如下:
(1)打开区块链网络文件目录,通过区块链启动脚本,输入bash control.sh start命令,启动区块链网络,将输出结果截图保存;
(2)打开(src/controller/BlockController.java)文件,在查询区块链信息接口中,使用Java-SDK获取区块链的最新高度和最新交易Hash,并将结果按十进制的整数和字符串类型返回。
启动区块链源码截图:
区块链的最新高度和最新交易Hash接口补充源码:
/**获取最新区块高度和最新交易Hash*/ @RequestMapping(value = "/getBlockInformation") @ResponseBody public Map getBlockInformation(FlightInformation flightInformation){ Map resMap = new HashMap<>(); try{ // 获取最新区块高度 long blockHeight = block.getLong("height"); System.out.println("最新区块高度:" + blockHeight); // 获取最新区块交易Hash String txHashes = block.getJSONArray("txHashes"); System.out.println("最新区块交易Hash:" + txHash); resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",null); } catch (ClientProtocolException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } catch (IOException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); }catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } return resMap; }
子任务3-2-2:编写查询医疗健康病历合约接口和数据库设计
(1)根据“查询医疗健康病历合约”中变量的字段,在Java项目中声明实体类(MedicalHealthCase),将声明代码结果截图保存;
包含字段:用户姓名(name)、年龄(age)、性别(sex)、科别(category)、时间(time)。
(2)请打开客户端,连接数据库,根据声明的实体类,创建数据库表(medical_health_case)与表结构字段。
医疗健康病历合约实体字段补充源码:
/** * 医疗健康病历实体实体 */ public class MedicalHealthCase { private static final long serialVersionUID = 1L; //在此处进行代码补全,声明医疗健康病历实体字段,并添加Get和Set方法 }
创建medical_health_case表补充源码:
CREATE TABLE `medical_health_case` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id', //在此处进行建表sql语句补全或使用工具创建表字段 `create_time` DATETIME NOT NULL COMMENT '创建时间', `update_time` DATETIME NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE ) COLLATE='utf8_general_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT ;
子任务3-2-3:编写调用查询医疗健康病历合约接口
通过Java-SDK完成调用查询医疗健康病历合约接口,获取医疗健康病历信息。要求如下:
(1)接收从Web端接收对应各种参数(包括病历编号)将代码截图保存;
(2)调用Java-SDK,运行调用智能合约API,接收医疗健康病历信息传递给前端页面,将代码截图保存;
(3)医疗健康病历信息查询成功后,将获取到的医疗健康病历信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中。
/**获取医疗健康病历详情接口*/ @RequestMapping(value = "/getUseMedicalHealthCase") @ResponseBody //此处代码补全:接收从Web端传输的参数(包含钱包地址) public Map getUserMedicalHealthCase(…){ Map resMap = new HashMap<>(); try{ //此处代码补全:调用Java-SDK,运行调用智能合约API,接收医疗健康病历信息传递给前端页面 //此处代码补全:医疗健康病历信息查询成功后,将获取到的医疗健康病历信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中 resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",result); } catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } return resMap; }2023年全国职业院校技能大赛
高职组
“区块链技术应用”
赛项赛卷(10卷)



参赛队编号:
背景描述
养老保险是对于老年人的最基本的生活保障。各种数据显示,当前的养老金市场规模庞大。2016年美国的养老金资产总额为19.1万亿美元;而据估计,截至2016年,全球养老金资产总额约为36万亿美元。美国是最大的养老保险市场,其占全球份额为62%;其次是英国(7.9%)和日本(7.7%)。然而,养老保险市场在各个方面存在诸多缺陷,往往会对个人造成负面影响。常见的问题包括治理不善和糟糕的绩效管理,以及在养老金缴纳过程中出现问题(因为没有标准的过程,其流程容易出现隐藏的成本、糟糕的数据管理,甚至是养老金欺诈 )。
区块链养老保险平台业务流程图
现有一个基于区块链的职工养老保险平台,当工作单位U参保人P办理职工基本养老保险时,U在养老保险管理平台S输入个人身份证号,S从公安部门调取P的基本信息,从劳动部门L调取P的U、参与工作时间、工资(需要按照本顺序声明),从A市社保局N上调取A市的缴费基数,默认调取的是真实信息,不考虑其他情况,然后生成养老保险账户。P可以拥有多个U,但S只允许一个U为其缴纳养老保险费用,如果有其他U为其缴纳,需要其他U进行减员操作才可以进行缴费。其中缴费基数是指职工在一个年度的保险缴费基数,保险基数根据月工资确定。A市规定每月P的个人缴费比例为8% ,称为个人账户,U的缴费比例为19%,称为统筹账户。A市的缴费基数上限为24000元,下限为3200元。U通过S将统筹账户的费用支付给N,P个人账户的缴费也由U代缴。若U未在30天内缴纳费用,L追究U的法律责任。P月工资为25000元,则需要个人账户每月缴纳2000元,统筹账户缴纳4750元。默认U账户金额足够,不考虑其他因素。当P在S中申请将养老保险关系从A市转移到B市时,S将授权B市的社保局M调用P的养老保险账户,M依据U是否办理停缴手续来判断是否符合转移条件。如U未办理停缴手续则复核失败。如果复核成功,则N将P的养老保险账户、全部个人账户基金和全部统筹账户基金转移到M(需要按照本顺序声明)。M建立P的参保档案,在S中接收个人账户基金、统筹账户基金、养老保险账户转移(需要按照本顺序声明)。最终将复核数据、转移数据和接收数据存储在S中(需要按照本顺序声明),方便以后调用。
区块链养老保险平台系统架构图
模块一:区块链产品方案设计及系统运维(35分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块一提交结果.docx】中对应的任务序号下。
任务1-1:区块链产品需求分析与方案设计
养老保险平台中涉及到参保人、社保局、公安局、工作单位等参与方,他们需要在区块链养老保险平台中完成账户注册、身份上链、社保代缴、信息核查等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于养老保险平台系统架构,以区块链养老保险平台为背景,结合账户注册、登录服务、入驻上链、保险转移、社保代缴等核心功能描述,撰写流程图/功能图、用例图等概要设计。
本任务需要依据项目背景完成需求分析与方案设计,具体要求如下:
1. 依据给定区块链养老保险平台的业务流程图以及用例表,编制系统业务用例图,用例图中包含系统参与角色以及用例。
表1-1-1 用例表
用例编号 用例标题 优先级 测试步骤 预期结果 测试结果
HK-TEST-01 工作单位在区块链养老保险平台上参保 高 在参保界面,工作单位可以输入员工的身份证号码,为员工办理参保 申请成功 申请成功
HK-TEST-02 区块链养老保险平台生成保险账户 高 区块链养老保险平台自动拉取参保人的基本信息、工作信息等进行核对,核对通过后,在保险账户界面为该参保人成功创建养老保险账户 创建成功 创建成功
HK-TEST-03 工作单位在区块链养老保险平台进行减员 高 工作单位在保险缴纳页面,点击减员,弹窗确认员工信息,确认无误后减员成功 减员成功 减员成功
HK-TEST-04 工作单位在区块链养老保险平台进行养老保险缴纳 高 在缴费界面,工作单位确认员工工资,点击缴费,系统判定工资与缴费基数的关系,确定缴费额度,由工作单位确认缴纳 缴纳成功 缴纳成功
HK-TEST-05 社保局在区块链养老保险平台进行保险关系转移 高 在保险管理界面,展示当前参保人的保险数据,点击转出,判断社保局的身份和权限,将参保人的保险关系转移出去 转移成功 转移成功
HK-TEST-06 社保局在区块链养老保险平台进行保险关系接收 高 在保险管理界面,展示当前参保人的转入申请数据,点击接收,为该参保人创建参保档案,将参保人的保险关系进行接收 获取申请信息 参保档案创建成功 接收成功 获取申请信息 参保档案创建成功 接收成功
2. 依据给定的背景信息、区块链养老保险业务流程图以及区块链养老保险平台架构图以及给出的养老保险业务的核心流程,使用思维导图工具编制业务系统功能图;
表1-1-2 养老保险平台的核心流程
缴纳养老保险流程 区块链养老保险平台根据缴费标准生成缴费协议,对协议合约进行平台签名,将协议代码广播到区块链。获取参保人工资数据,判断费用额度。
保险关系转移流程 区块链养老保险平台将参保人身份进行验证、参保关系、停缴状态进行核查,符合则进入保险关系转移流程,向参保人保险账户、账户基金等进行转移
3. 按照基础层、合约层、接口层以及应用层来设计区块链系统的架构,画出系统架构图,其中在基础层需指明需要的节点、名称、协议、存储等信息;
4. 结合案例背景将区块链养老保险平台核心功能进行划分,完成下方表格中各个主要模块要实现的功能;
在空白处填写主要模块要实现的功能:
参保模块 请输入要实现的功能
缴费模块 请输入要实现的功能
保险转移模块 请输入要实现的功能
合约功能模块 请输入要实现的功能
5. 根据用例设计以及下方提供好的承诺集,使用Visio工具完成区块链应用系统业务流程图;
表1-1-3 承诺集
参保承诺 判断工作单位是否在平台输入正确的身份信息完成参保
生成保险账户承诺 判断参保人基本信息、工作信息是否符合缴费基数规定,是则生成养老保险账户,否则结束
减员承诺 判断参保人是否存在多家缴费单位
缴费超时承诺 判断工作单位是否在规定时间内未参保人缴纳养老保险费用
缴费承诺 判断参保人的工资是否超出了缴纳金额的上下限
转移保险关系承诺 判断参保人是否办理了停缴
整合所有内容,模块调用接口编写并形成对应的需求用例文档至【区块链技术应用赛\重命名为工位号】下。
任务1-2:区块链系统部署与运维
子任务1-2-1:区块链网络环境搭建
操作任务如下:
(1)打开区块链源码文件,通过输入命令,检查Go语言编辑环境,并确定Go版本;
(2)打开区块链源码文件,通过输入命令,make编译区块链网络,生成区块链网络编译执行文件,请把编译执行文件截图;
(3)成功编译区块链网络后,通过输入命令,启动区块链服务;
(4)启动区块链网络后,通过输入命令,检查区块链网络状态。
子任务1-2-2:区块链运维管理
(1)通过命令行方式,使用docker启动管理台,启动成功后,使用IP在浏览器中,浏览管理台系统;
(2)使用超级管理员账号(admin)登录,申请链账户的证书文件;
(3)快速生成证书按钮,系统讲快速自动生成四个组织证书、四个节点证书、四个用户证书;
(4)查看链参数配置基础信息、共识信息、节点信息。
子任务1-2-3:区块链浏览器部署合约
(1)进行区块链管理,部署智能合约;
(2)发起上链操作;
(3)调用成功后,查看交易详情。
子任务1-2-4:搭建区块链网络监控系统
请按如下步骤,完成对系统的搭建,具体操作任务如下:
(1)通过命令行方式,在节点 env.yaml 配置中打开 metricSwitch;
(2)配置每个 target 对应 xchain 节点的 server.yaml 中的metricPort端口;
(3)进入到对应目录下,通过命令行启动启动prometheus,打开区块链监控系统项目网址。
任务1-3:区块链系统测试
(1)从源代码构建Hyperbench,并开启Hyperbench网络;
(2)在Fabric上运行HyperBench,并开启Fabric网络;
(3)使用DVWA模拟区块链环境的SQL漏登测试,使用GET方式注入、POST方式注入,分析区块链系统漏洞。
模块二:智能合约开发与测试(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块二提交结果.docx】中对应的任务序号下。
任务2-1:智能合约设计
根据职工养老保险系统需求用例文档,设计合约接口,画出各需求用例的时序图。
任务2-2:智能合约开发
使用Solidity语言进行智能合约开发,根据需求用例文档在待补充源码中完成程序接口功能的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约进行业务功能的验证,成功获取合约的abi,将合约部署至Geth中的私有链,获取部署的合约信息,将任务中编写代码、运行截图、部署至Geth截图保存至指定位置。
子任务2-2-1:账户管理合约编码
根据需求用例文档在待补充源码中完成账户管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确。需要编写生成账户接口,完成从外部部门检索姓名、年龄、雇主、开始日期、工资、缴费基数,将人员信息进行综合存储功能。
待补充源码:
contract PensionAccount {
// 定义用于存储人员信息的结构体
struct Person {
string name; // 姓名
uint age; // 年龄
string idNumber; // 身份证号码
string employer; // 雇主
uint startDate; // 开始日期
uint salary; // 工资
uint paymentBase; // 缴费基数
}
// 定义映射,使用身份证号码作为键存储人员信息
mapping(string => Person) public people;
/*********** 生成账户接口开发 **********/
/********** 生成账户接口开发 ***********/
// 从外部部门检索信息的函数
function retrieveName(string memory) private pure returns (string memory) {
// 从公安部门检索姓名的代码
return "John Doe";
}
function retrieveAge(string memory) private pure returns (uint) {
// 从公安部门检索年龄的代码
return 35;
}
function retrieveEmployer(string memory) private pure returns (string memory) {
// 从劳动部门检索雇主的代码
return "ABC Company";
}
function retrieveStartDate(string memory) private pure returns (uint) {
// 从劳动部门检索开始日期的代码
return 1625097600; // 2021年6月30日
}
function retrieveSalary(string memory) private pure returns (uint) {
// 从劳动部门检索工资的代码
return 5000;
}
function retrievePaymentBase() private pure returns (uint) {
// 从社会保障局检索缴费基数的代码
return 5000;
}
}
子任务2-2-2:费用管理合约编码
根据需求用例文档在待补充源码中完成费用管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行添加新职工账户、添加新雇主账户。
1.编写添加新职工账户接口,实现当账户不存在,只有管理员可以添加职工账户,职工新账户中账户余额为0,未被赞助的功能;
2.编写添加新雇主账户接口,实现当账户不存在,只有管理员可以添加雇主账户,雇主新账户中账户余额为0,已被赞助的功能;
待补充源码:
contract PensionInsurance {
struct Account {
uint256 personalBalance; // 个人账户余额
uint256 overallBalance; // 总账户余额
bool isSponsor; // 雇主是否为职工的管理员
uint paymentTimestamp;//缴费时间
}
// 定义合约的变量
uint256 constant MAX_INSURANCE_BASE = 24000; // 最大保险基数
uint256 constant MIN_INSURANCE_BASE = 3200; // 最小保险基数
uint256 constant PERSONAL_RATE = 8; // 个人缴费率
uint256 constant OVERALL_RATE = 19; // 总缴费率
uint256 constant SPONSOR_RATE = OVERALL_RATE - PERSONAL_RATE; // 雇主缴费率
uint256 constant PERSONAL_AMOUNT = 2000; // 每月个人缴费金额
uint256 constant OVERALL_AMOUNT = 4750; // 每月总缴费金额
uint256 constant PAYMENT_DEADLINE = 30 days; // 缴费截止日期
address public sponsor = msg.sender; // 管理员的地址
// 定义账户的映射
mapping(address => Account) public accounts;
/*********** 添加新职工账户接口 **********/
/********** 添加新职工账户接口 ***********/
/*********** 添加新雇主账户接口 **********/
/********** 添加新雇主账户接口 ***********/
// 定义设置管理员的函数
function setSponsor(address newSponsor) public {
// 只有当前管理员可以设置新的管理员
require(msg.sender == sponsor, "1");
// 新的管理员不能与当前管理员相同
require(newSponsor != sponsor, "1");
// 新的管理员必须有雇主账户
require(accounts[newSponsor].overallBalance > 0, "1");
// 设置新的管理员并更新账户的管理员状态
address oldSponsor = sponsor;
sponsor = newSponsor;
accounts[oldSponsor].isSponsor = false;
accounts[newSponsor].isSponsor = true;
}
// 定义进行缴费的函数
function makePayment(address employee) public {
// 职工账户必须存在
require(accounts[employee].personalBalance > 0 || accounts[employee].overallBalance > 0, "1");
// 雇主账户必须存在且已被赞助
require(accounts[sponsor].overallBalance > 0 && accounts[sponsor].isSponsor, "1");
// 雇主账户必须有足够的余额进行总缴费
require(accounts[sponsor].overallBalance >= OVERALL_AMOUNT, "1");
// 缴费必须在截止日期之前进行
require(block.timestamp <= accounts[sponsor].paymentTimestamp + PAYMENT_DEADLINE, "1");
// 根据职工的工资计算个人和总缴费金额
uint256 salary = 25000; // 职工的月薪
uint256 insuranceBase = salary > MAX_INSURANCE_BASE MAX_INSURANCE_BASE : (salary < MIN_INSURANCE_BASE MIN_INSURANCE_BASE : salary);
uint256 personalAmount = insuranceBase * PERSONAL_RATE / 100;
uint256 overallAmount = insuranceBase * OVERALL_RATE / 100;
// 更新职工和雇主账户的余额
accounts[employee].personalBalance += personalAmount;
accounts[sponsor].personalBalance += personalAmount;
accounts[sponsor].overallBalance -= overallAmount;
accounts[sponsor].paymentTimestamp = block.timestamp;
}
// 定义删除职工账户的函数
function removeEmployee(address employee) public {
// 只有管理员可以删除职工账户
require(msg.sender == sponsor, "1");
// 职工账户必须存在且未被赞助
require(accounts[employee].personalBalance > 0 && !accounts[employee].isSponsor, "2");
// 职工账户必须余额为零
require(accounts[employee].personalBalance == 0 && accounts[employee].overallBalance == 0, "3");
// 删除职工账户
delete accounts[employee];
}
}
子任务2-2-3:保险转移合约编码
根据需求用例文档在待补充源码中完成保险转移合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的申请转移关系、接收账户转移接口。
1.编写申请转移关系接口,实现创建申请、添加到申请列表功能,其中创建申请需要设置申请人地址、原城市、目标城市、停缴状态、批准状态;
2.编写接收账户转移接口,实现获取账户,进行账户授权状态、接收状态、个人账户基金、统筹账户基金、养老保险账户的信息设置;
待补充源码:
contract PensionInsurance {
// 定义申请结构体
struct Application {
address applicant; // 申请人地址
string fromCity; // 原城市
string toCity; // 目标城市
bool isStopped; // 是否停缴
bool isApproved; // 是否批准
}
// 定义账户结构体
struct Account {
uint personalFund; // 个人账户基金
uint overallFund; // 统筹账户基金
uint pensionInsurance; // 养老保险账户
}
// 定义社保局结构体
struct SocialSecurityBureau {
address bureauAddress; // 社保局地址
bool isAuthorized; // 是否被授权
bool hasReceived; // 是否已接收
}
// 定义申请列表
Application[] public applications;
// 定义账户映射
mapping(address => Account) public accounts;
// 定义社保局映射
mapping(address => SocialSecurityBureau) public socialSecurityBureaus;
/*********** 申请转移关系接口 **********/
/********** 申请转移关系接口 ***********/
// 社保局调用申请
function authorizeTransfer(address applicantAddress, bool isStopped) public {
// 获取申请
Application memory currentApplication;
for (uint i = 0; i < applications.length; i++) {
if (applications[i].applicant == applicantAddress) {
currentApplication = applications[i];
break;
}
}
// 判断是否停缴
if (isStopped) {
currentApplication.isApproved = false;
return;
}
// 转移账户
Account storage currentAccount = accounts[applicantAddress];
SocialSecurityBureau storage currentBureau = socialSecurityBureaus[msg.sender];
currentAccount.personalFund = 0;
currentAccount.overallFund = 0;
currentAccount.pensionInsurance = 0;
currentBureau.hasReceived = true;
// 更新申请状态
currentApplication.isStopped = false;
currentApplication.isApproved = true;
}
/*********** 接收账户转移接口 **********/
/********** 接收账户转移接口 ***********/
}
子任务2-2-4:合约部署和调用
1.解决代码错误和警告,正确编译合约,成功获取三个合约的abi;
2.将三个合约形成一个文件部署至Geth中的私有链,获取部署合约的地址信息。
任务2-3:智能合约测试
写功能测试用例,实现费用管理功能的业务测试,使用性能测试工具,对申请转移账户接口进行性能测试。
1.根据需求用例文档在以下测试用例表格中编写费用管理合约中的测试用例,依据费用管理中缴费单位的个数、与单位缴费、个人缴费的三种状态,分析在前置条件为参保人已参保、已生成养老账户的情况下,参保人有多个工作单位、有固定单位为其缴费、与工作单位不按时缴费时,不同缴费时间大于、小于规定缴费时间的情况下,产生的养老金账户和养老保险管理平台的归属结果。
用例编号 用例标题 优先级 前置条件 测试步骤 测试数据 预期结果
PI-AM001 费用管理(缴费单位个数) 高 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
2.利用测试工具,模拟测试申请账户转移接口发送100次请求,将所需HTTP请求、协议、服务器名称或IP以及路径填到工具Web服务器中,连同通请求一起发送的参数,运行成功后将汇总报告提交到指定位置。
模块三:区块链应用系统开发(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块三提交结果.docx】中对应的任务序号下。
任务3-1:区块链应用前端功能开发
完成区块链应用系统中的职工养老保险申请页面渲染,要求如下:
(1)按照生成养老保险账户原型图的长度、宽度、行高、间距、文字样式、颜色等,完成订单详情页面的样式开发,将结果截图保存;
(2)完成Vue调用添加养老保险账户API,将养老保险账户信息提交至API接口中,设计图截图保存。
押金详情页面的样式开发补充源码:
.content{ width: 100%; height: 100%; background: #EEEEEE; .contentModel{ position: absolute; top: 50%; left: 50%; box-sizing: border-box; width: 600px; padding: 41px 40px 40px; background: #fff; border-radius: 8px; box-shadow: 0 3px 12px 0 #c0c4cc; transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); -o-transform:translate(-50%, -50%); .payment_title{ font-size: 21px; font-weight: normal; text-align: center; margin-bottom: 20px; } //此处代码补全:按原型图样式,进行长度、宽度、行高、间距、文字样式、颜色等样式设置; } }
押金详情页面的Html开发补充源码:

任务3-2:区块链应用后端功能开发
子任务3-2-1: 获取区块链交易信息
区块链应用系统开发需要区块链底层网络进行支撑,完成和链上数据进行交互,并完成链上信息查询。
要求如下:
(1)打开区块链网络文件目录,通过区块链启动脚本、区块链网络;
(2)打开(src/controller/BlockController.java)文件,查询区块链信息接口。使用Java-SDK获取区块链的最新高度和最新交易Hash,并将结果按十进制的整数和字符串类型返回;
启动区块链源码截图:
区块链的最新高度和最新交易Hash接口补充源码:
/**获取最新区块高度和最新交易Hash*/ @RequestMapping(value = "/getBlockInformation") @ResponseBody public Map getBlockInformation(FlightInformation flightInformation){ Map resMap = new HashMap<>(); try{ // 获取最新区块高度 long blockHeight = block.getLong("height"); System.out.println("最新区块高度:" + blockHeight); // 获取最新区块交易Hash String txHashes = block.getJSONArray("txHashes"); System.out.println("最新区块交易Hash:" + txHash); resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",null); } catch (ClientProtocolException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } catch (IOException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); }catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } return resMap; }
子任务3-2-2: 声明生成养老保险账户实体类和数据库设计
使用Java语言,完成区块链系统数据的存储。要求如下:
(1)根据“账户管理合约”中变量的字段,在Java项目中声明实体类(PensionAccount),将声明代码结果截图保存。(2分)
包含字段:钱包地址(walletAddress)、个人账户余额(personalBalance)、总账户余额(overallBalance)、雇主是否为职工的赞助商(isSponsor)、缴费时间(paymentTimestamp)、参保人姓名(insuredPersonName)、参保人身份证(insuredPersonIdentityCard)、参保人工作单位(insuredPersonWorkUnit)、工作年限(workingYear)、薪资(salary)、缴费基数(paymentBase)
(2)请打开Navicat Premium 客户端,并连接数据库,根据第1步声明的实体类,创建数据库表(pension_account)与表结构字段。
签署房屋租赁合同合约实体字段补充源码:
/** * 养老账户实体类 */ public class PensionAccount { private static final long serialVersionUID = 1L; //在此处进行代码补全,声明养老账户实体字段,并添加Get和Set方法 }
创建pension_account表补充源码:
CREATE TABLE `pension_account` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id', //在此处进行建表sql语句补全或使用工具创建表字段 `create_time` DATETIME NOT NULL COMMENT '创建时间', `update_time` DATETIME NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE ) COLLATE='utf8_general_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT ;
子任务3-2-3: 编写调用账户管理合约添加养老保险账户接口
请使用Java语言,通过Java-SDK完成调用账户管理合约接口,添加养老保险账户。要求如下:
(1)接收从Web端对应各种参数(包括参保人姓名、身份证、工作单位、工作年限、工资、缴费基数)将代码截图保存;
(2)调用Java-SDK,运行调用智能合约API,接收养老保险账户的钱包地址、账户余额等信息传递给前端页面,将代码截图保存;
(3)养老保险账户创建成功后,将获取到的钱包信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中。
/**添加养老保险账户*/ @RequestMapping(value = "/addPensionAccount") @ResponseBody //此处代码补全:接收从Web端传输的参数(包括参保人姓名、身份证、工作单位、工作年限、工资、缴费基数) public Map addPensionAccount (…){ Map resMap = new HashMap<>(); try{ //此处代码补全:调用Java-SDK,运行调用智能合约API,创建养老保险账户的钱包地址、账户余额传递给前端页面 //此处代码补全:创建养老保险账户成功后,将获取到的钱包信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中 resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",depositInfo); } catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",200); resMap.put("message","请求失败"); } return resMap; }
(
2
)2023年全国职业院校技能大赛
高职组
“区块链技术应用”
赛项赛卷(7卷)



参赛队编号:
背景描述
2022年8月,XXX保险公司正在使用区块链为航空旅客提供自动航班延迟赔偿。
保险公司将区块链用于记录保险产品购买以及通过使用区块链上的智能合约来触发自动支付。该智能合约与记录飞行状态的飞行和空中交通数据库相连。当航班延误超过2小时时,赔偿机制将会自动执行,直接发送投保人的“信用卡”账户中,无需实际申领即可获得。这种涵盖航班延误的保险,保险条款清晰,报销程序自动。客户不必亲自去保险公司索赔。也不需要出示任何文件。所有需要的信息已经在保险订阅期间记录。
区块链航班延误险系统业务流程图
现在利用区块链技术实现航班延误险系统,将乘机人、航空公司、保险公司加入到区块链网络中,将购买、航班、保险、保单等信息存储在区块链的分布式网络中,永久有效,无法篡改。在机票延误险场景中,乘机人购买机票之后在系统上预存10元保费;保险公司再在系统上预存相应的赔偿金1000元;如果保险公司没有按时预存赔偿金,系统就直接将保费退还给用户;如果保险公司预存了赔偿金,若航班没有延误,或者延误时间少于4h,系统就将乘机人预存的保费转账给保险公司,同时退还保险公司预存的赔偿金。如果航班延误超过4h,系统也会将保费转账给保险公司,但是会将保险公司预存的赔偿金赔偿给乘机人。
区块链航班延误险系统架构图
模块一:区块链产品方案设计及系统运维(35分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块一提交结果.docx】中对应的任务序号下。
任务1-1:区块链产品需求分析与方案设计
航班延误险中涉及到乘客、航空公司、区块链系统平台、保险公司等参与方,他们需要在区块链系统平台中完成账户注册、身份上链、机票购买、保险购买等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于航班延误险系统架构,以区块链航班延误系统为背景,结合账户注册、登录服务、入驻上链、购买机票等核心功能描述,撰写流程图/功能图、用例图等概要设计。本任务需要依据项目背景完成需求分析与方案设计,具体要求如下:
1. 依据给定区块链航班延误险系统的业务流程图以及用例表,使用工具编制系统业务用例图,用例图中包含系统参与角色以及用例。
表1-1-1 用例表
用例编号 用例标题 优先级 测试步骤 预期结果 测试结果
HK-TEST-01 乘机人向航空公司购买机票 高 在航空公司页面搜索对应航班,点击购买是否能进入到下一个页面 成功跳转 成功跳转
HK-TEST-02 乘机人在0.5h内向保险公司购买航班延误险并成功预存10元保费 高 在区块链航空延误险页面选择保险公司,正常进入保险公司页面,点击投保,在规定时间内缴纳10元保费,并提示缴费成功 购买成功 购买成功
HK-TEST-03 保险公司在区块链系统中成功预存1000元赔偿金 高 保险公司保单界面展示乘机人购买保险的记录,点击预存,可成功预存1000元赔偿金 收到记录 预存成功 收到记录 预存成功
HK-TEST-04 在区块链系统中保险公司为乘机人生成保单 高 保险公司在保单界面展示所有乘机人购买保险的记录,点击生成保单,可会回显出保单的文件 记录状态变更 生成成功 记录状态变更 生成成功
HK-TEST-05 航空公司在区块链系统中上传航班的实时信息 高 航空公司在区块链系统实时航班页面拉取最新的航班动态信息,并展示到航班页面 实时展示 实时展示
HK-TEST-06 航班延误判断 高 在区块链系统理赔界面,对最新的航班延误信息进行判断,超出4个小时进行理赔处理,可以在账户中自动收取赔偿金。未超出4个小时,进行无需理赔处理,在理赔界面可查看理赔状态 理赔成功执行 理赔成功执行
2. 依据给定的背景信息、区块链航班延误险业务流程图以及区块链航班延误险系统架构图以及给出的航班延误系统的核心流程,使用思维导图工具编制业务系统功能图;
表1-1-2 航班延误系统的核心流程
发布理赔协议流程 保险公司起草航班延误险理赔协议,使用保险公司的私钥对理赔协议进行签名并广播到区块链中
生成航班延误险理赔合约流程 乘机人购买航空公司的机票后,通过乘机人节点在理赔协议中填写个人信息和航班信息,生成航班延误险理赔合约
理赔合约属性文本广播流程 乘机人对航班延误理赔合约提炼合约属性文本,使用私钥对合约属性本文以及理赔合约进行签名后,广播到区块链中
保险公司解密合约属性文本流程 保险公司使用自身私钥对加密后的理赔合约进行解密,对解密后的理赔合约提炼对照合约属性文本,并使用私钥对对照合约属性文本进行签名后广播到区块链中
航班延误赔付流程 链上节点实时监控航班时间,并在航班延误满足条件时,判断保险公司对乘机人的航班延误赔付
3. 按照基础层、合约层、接口层以及应用层来设计区块链系统的架构,画出系统架构图,其中在基础层需指明需要的节点、名称、协议、存储等信息;
4. 结合案例背景将区块链航班延误险核心功能进行划分,完成下方表格中各个主要模块要实现的功能;
机票购买模块 请输入要实现的功能
购买保险模块 请输入要实现的功能
预存赔偿金模块 请输入要实现的功能
生成保单模块 请输入要实现的功能
航班信息上传模块 请输入要实现的功能
延误判断功能模块 请输入要实现的功能
5. 根据用例设计以及下方提供好的承诺集,使用Visio工具完成区块链应用系统业务流程图;
表1-1-3 承诺集
购买机票承诺 判断乘机人是否在航空公司平台购买机票
购买保险承诺 判断乘机人是否在区块链航班延误险平台购买保险
生成保单承诺 判断保险公司是否在规定时间内预存赔偿金
理赔承诺 判断航班延误时间,是否满足理赔时间条件,满足则执行理赔,不满足则执行无需理赔
6. 整合所有内容,模块调用接口编写并形成对应的需求用例文档至【区块链技术应用赛\重命名为工位号】下。
任务1-2:区块链系统部署与运维
通过给定区块链项目需求,进行区块链系统的的部署,包括系统部署、节点部署等。通过监控工具完成对网络、节点服务的监控。最终利用业务需求规范,完成系统日志、网络参数、节点服务等系统结构的维护。
子任务1-2-1:区块链网络环境搭建
在本机部署区块链网络底层环境,我们需要准备编译运行的环境,并通过区块链底层源码脚本文件编译区块链网络。
(1)打开区块链源码文件,通过输入命令,检查Go语言编辑环境,并确定Go版本;
(2)打开区块链源码文件,通过输入命令,make编译区块链网络,生成区块链网络编译执行文件,请把编译执行文件截图;
(3)成功编译区块链网络后,通过输入命令,启动区块链服务;
(4)启动区块链网络后,通过输入命令,检查区块链网络状态。
子任务1-2-2:区块链网络服务运行
区块链网络环境成功搭建后,启动区块链网络服务,区块链网络提供了很多的命令行基础功能,满足区块链网络服务的运行,我们这些功能来满足我们日常的区块链基础运维工作。
(1)进入区块链网络执行文件夹(output),通过命令行方式,创建区块链普通钱包账户(userTest),生产区块链钱包地址,私钥,公钥;
(2)进入区块链网络执行文件夹(output),通过命令行方式,获取区块链钱包余额(data/keys);
(3)进入区块链网络执行文件夹(output),通过命令行方式,由data/keys向(userTest)转账10,并查看交易ID;
(4)进入区块链网络执行文件夹(output),通过命令行方式,使用上一步的交易ID,查询交易状态,交易源和目标账号、交易的金额等信息。
子任务1-2-3:部署区块链多节点服务
搭建一个3个节点的区块链网络,需要通过命令行创建多节点网络部署环境,并监听各个节点的RPC监听端口,并查看p2p监听渡口配置,现有任务如下:
(1)进入区块链网络主目录下,通过命令行,创建多节点网络部署环境;
(2)进入多节点网络环境目录下,创建多节点网络部署环境后,通过命令行方式,查看P2P网络配置;
(3)节点加入网络需要通过配置种子节点的网络连接地址netURL,请通过命令行方式,获取node3对应的节点netURL。
子任务1-2-4:搭建区块链网络监控系统
(1)进入区块链网络监控系统主目录,通过命令行方式,在节点 env.yaml 配置中打开 metricSwitch,[截图保存为01-04-01.png];
(2)设置endpoint服务修改 prometheus.yml 文件,添加如下配置,每个 target 对应 xchain 节点的 server.yaml 中的 metricPort 端口;
(3)进入到对应目录下,通过命令行启动启动prometheus,打开区块链监控系统项目网址。
任务1-3:区块链系统测试
设计对区块链系统的测试流程;结合实际业务需求,调用部署的智能合约中进行系统测试、性能测试等;根据业务需求,分析并且修复给定智能合约中的安全漏洞。利用模拟业务和测试工具来完成对区块链系统服务数据的测试。
(1)启动区块链浏览器系统,找到区块链最新区块列表接口,使用工具对该接口进行HTTP请求测试,并将测试保存;
(2)使用测试工具进行测试区块链网络,针对区块链网络吞吐量与时延进行性能指标分析;
(3)使用DVWA模拟区块链环境的SQL漏登测试,使用GET方式注入、POST方式注入,分析区块链系统漏洞。
模块二:智能合约开发与测试(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块二提交结果.docx】中对应的任务序号下。
任务2-1:智能合约设计
根据航空延误险系统需求用例文档,设计合约接口,画出各需求用例的时序图。
任务2-2:使用Solidity语言进行智能合约开发(20分)
使用Solidity语言进行智能合约开发,根据需求用例文档在待补充源码中完成程序接口功能的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约进行业务功能的验证。
子任务2-2-1:航班延误保险购买合约编码(5分)
根据需求用例文档在待补充源码中完成航班延误购买合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的保险购买、退保功能。
(1)编写航班保险购买上链接口,完成只有购买机票的用户可以购买保险,并且必须缴纳正确的保费金额,且购买保险的时间不能超过购买机票后的0.5小时的功能,符合条件则用户可以购买保险,将用户购买保险状态上链;(3分)
(2)编写退保接口,完成保险公司预存赔偿金后,用户无法退保,反之用户可退保的功能,将用户退保状态上链,并退还用户保费功能。(2分)
待补充源码:
contract FlightDelayInsurance {
address public platformS; // 平台S的地址
address public airlineV; // 航空公司V的地址
address public insuranceCompanyC; // 保险公司C的地址
uint public premium; // 保险费
uint public compensation; // 赔偿金额
uint public purchaseTime; // 购买保险的时间
uint public depositTime; // 存入赔偿金额的时间
bool public purchased; // 是否购买了保险
bool public deposited; // 是否存入了赔偿金额
mapping(address => bool) public insured; // 已退保的用户
mapping(address => bool) public policy; // 已生成保单的用户
mapping(address => bool) public purchasedTicket; // 已购买机票的用户
constructor(address _platformS, address _airlineV, address _insuranceCompanyC, uint _premium, uint _compensation) {
platformS = _platformS; // 初始化平台S的地址
airlineV = _airlineV; // 初始化航空公司V的地址
insuranceCompanyC = _insuranceCompanyC; // 初始化保险公司C的地址
premium = _premium; // 初始化保险费
compensation = _compensation; // 初始化赔偿金额
}
function purchaseTicket() public {
require(!purchasedTicket[msg.sender], "Ticket has already been purchased"); // 该用户已购买机票
purchasedTicket[msg.sender] = true; // 标记该用户已购买机票
purchaseTime = block.timestamp;
}
/*********** 航班保险购买上链接口开发 **********/
/********** 航班保险购买上链接口开发 ***********/
function depositCompensation() public payable {
require(msg.sender == insuranceCompanyC, "Only insurance company C can deposit compensation"); // 只有保险公司C可以存入赔偿金额
require(msg.value == compensation, "Compensation amount is incorrect"); // 赔偿金额不正确
require(block.timestamp < depositTime + 2 hours, "Deposit time has expired"); // 存入赔偿金额的时间已过期
deposited = true; // 标记已存入赔偿金额
}
/*********** 退保接口开发 **********/
/********** 退保接口开发 ***********/
function generatePolicy() public {
require(deposited, "Compensation has not been deposited"); // 赔偿金额未存入,无法生成保单
require(msg.sender == platformS, "Only platform S can generate policy"); // 只有平台S可以生成保单
require(!policy[msg.sender], "Policy has already been generated"); // 该用户已生成保单
policy[msg.sender] = true; // 标记该用户已生成保单
}
}
子任务2-2-2:航班信息存证上链合约编码
根据需求用例文档在待补充源码中完成航班延误存证上链合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的获取航班信息、判断航班是否延误接口功能截图保存为0203.png,截图编写代码保存为0204.png。
(1)编写获取航班信息接口,实现依据航班号获得航班号对应的计划起飞时间、实际起飞时间、到达时间、是否延误状态的功能;
(2)编写判断航班是否延误接口,实现依据航班号获得航班号对应的航班是否延误,得到航班是否延误的结果功能。
待补充源码:
contract FlightManagement {
// 航班结构体
struct Flight {
string flightNumber; // 航班号
uint256 scheduledDepartureTime; // 计划起飞时间
uint256 actualDepartureTime; // 实际起飞时间
uint256 arrivalTime; // 到达时间
bool delayed; // 是否延误
}
// 航班号到航班信息的映射
mapping(string => Flight) flights;
// 添加航班
function addFlight(string memory _flightNumber, uint256 _scheduledDepartureTime, uint256 _arrivalTime) public {
flights[_flightNumber] = Flight(_flightNumber, _scheduledDepartureTime, 0, _arrivalTime, false);
}
// 更新实际起飞时间
function updateActualDepartureTime(string memory _flightNumber, uint256 _actualDepartureTime) public {
flights[_flightNumber].actualDepartureTime = _actualDepartureTime;
}
/*********** 获取航班信息接口开发 **********/
/********** 获取航班信息接口开发 ***********/
/*********** 编写判断航班是否延误接口开发 **********/
/********** 编写判断航班是否延误接口开发 ***********/
}
子任务2-2-3:航班延误险理赔合约编码
根据需求用例文档在待补充源码中完成航班延误险理赔合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的客户理赔、保险公司收取保费接口功能截图保存为0205.png,截图编写代码保存为0206.png。
(1)编写客户理赔接口,实现如果航班延误超过4小时,将赔偿金赔偿给乘客的功能;
(2)编写保险公司收取保费接口,实现如果航班没有延误或者延误时间少于4小时,将保费转账给保险公司,并退还赔偿金的功能。
待补充源码:
contract Claims is FlightDelayInsurance{
// 定义航班信息结构体
struct Flight {
uint256 departureTime; // 航班出发时间
uint256 delayTime; // 航班延误时间
bool isDelayed; // 航班是否延误
bool isInsured; // 航班是否购买保险
}
// 定义保险公司地址
address public insuranceCompany;
// 定义航班信息映射
mapping(bytes32 => Flight) public flights;
// 定义购买保险事件
event BuyInsurance(bytes32 flightKey, address passenger, uint256 premium);
// 定义航班延误事件
event FlightDelay(bytes32 flightKey, uint256 delayTime);
// 定义理赔事件
event Claim(bytes32 flightKey, address passenger, uint256 amount);
// 定义保险公司预存的赔偿金
uint256 public compensationNew;
// 构造函数,初始化保险公司地址和赔偿金
constructor() FlightDelayInsurance(platformS,airlineV,insuranceCompanyC,premium,compensation){
insuranceCompany = msg.sender;
compensationNew = compensation;
}
// 更新航班信息函数
function updateFlight(bytes32 flightKey, uint256 departureTime, uint256 delayTime, bool isDelayed) payable public {
// 判断调用者是否为保险公司
require(msg.sender == insuranceCompany, "Only insurance company can update flight information");
// 更新航班信息
flights[flightKey].departureTime = departureTime;
flights[flightKey].isDelayed = isDelayed;
/*********** 客户理赔接口 **********/
/********** 客户理赔接口 ***********/
/*********** 保险公司收取保费接口开发 **********/
/********** 保险公司收取保费接口开发 ***********/
// 触发航班延误事件
emit FlightDelay(flightKey, delayTime);
}
}
子任务2-2-4:合约部署和调用
(1)解决代码错误和警告,正确编译合约,成功获取三个合约的abi;
(2)将三个合约形成一个文件部署至Geth中的私有链,获取部署合约的地址信息。
任务2-3:智能合约测试
根据需求用例文档完成航班延误险的功能测试以及性能测试,解决航空延误险合约代码正确性的验证以及验证系统响应时间是否满足预期响应效果,编写功能测试用例,实现理赔接口的业务测试,使用性能测试工具,对航班管理接口进行性能测试。
1.根据需求用例文档在以下测试用例表格中编写航班延误险合约中的测试用例,依据航空延误险有延误和没有延误的两种状态,分析在前置条件为平台运行状态为真的情况下,用户购买机票、保险以及预存赔偿金后,不同航班延误时间大于、小于、等于理赔规定时间的情况下,产生的保费和赔偿金的归属结果。
用例编号 用例标题 优先级 前置条件 测试步骤 测试数据 预期结果
HK-FM001 航空延误险(没有延误) 高 请填写 请填写 请填写 请填写
HK-FM002 航空延误险(有延误) 高 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
2.利用测试工具,模拟测试航班管理接口发送100次请求,将所需HTTP请求、协议、服务器名称或IP以及路径填到工具Web服务器中,连同通请求一起发送的参数,运行成功后将汇总报告提交。
模块三:区块链应用系统开发(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块三提交结果.docx】中对应的任务序号下。
任务3-1:区块链应用前端功能开发
使用Vue调用航班管理接口,将获取的航班号、计划起飞时间、实际起飞时间、到达时间、是否延误等信息传递给前端模板,要求如下:
1. 使用VsCode工具,按照航班管理原型图的长度、宽度、行高、间距、文字样式、颜色等,完成航班信息管理页面的开发;
(2)完成Vue调用航班管理接口API,获取接口返回的航班号、计划起飞时间、实际起飞时间、到达时间、是否延误信息,填充至Vue页面中。
航班信息管理页面样式补充源码:
航班信息展示补充源码:
任务3-2:区块链应用后端功能开发
在航班延误Dapp后端开发中,使用Java完成在区块链中实现航班信息和航班延误的管理,获取区块链交易信息、航班信息实体类设计、MySql数据库表结构创建、查询航班信息接口,与前端页面交互,形成完整的Dapp系统。
任务3-2-1:启动区块链
(1)使用Java语言编写后端代码进行交互,获取区块链的最新高度、最新交易Hash;
要求如下:
打开区块链网络文件目录,通过区块链启动脚本,输入bash control.sh start命令,启动区块链网络,将输出结果截图保存;
在IntelliJ IDEA工具中,使用Java-SDK在,查询区块链的最新高度(数字)和最新交易Hash(字符串),并将结果返回。
启动区块链源码截图:
区块链的最新高度和最新交易Hash接口补充源码:
/**获取最新区块高度和最新交易Hash*/
@RequestMapping(value = "/getBlockInformation")
@ResponseBody
public Map getBlockInformation(){
Map resMap = new HashMap<>();
try{
// 获取最新区块高度
long blockHeight = block.getLong("height");
System.out.println("最新区块高度:" + blockHeight);
// 获取最新区块交易Hash
String txHashes = block.getJSONArray("txHashes");
System.out.println("最新区块交易Hash:" + txHash);
resMap.put("code",200);
resMap.put("message","请求成功");
resMap.put("data",null);
} catch (ClientProtocolException e) {
log.error("操作失败—log:",e);
resMap.put("code",500);
resMap.put("message","请求失败");
} catch (IOException e) {
log.error("操作失败—log:",e);
resMap.put("code",500);
resMap.put("message","请求失败");
}catch (Exception e){
log.error("操作失败—log:",e);
resMap.put("code",500);
resMap.put("message","请求失败");
}
return resMap;
}
任务3-2-2:声明航班信息实体类和数据库设计
(1)根据“航班信息管理合约”中变量的字段,在Java项目中声明实体类(FlightInformation),将声明代码结果截图保存。
包含字段: 航班号(flightNumber)、计划起飞时间(departureTime)、实际起飞时间(practicalDepartureTime)、到达时间(arrivalTime)、是否延误(delayState)。
(2)请打开Navicat Premium 客户端,并连接数据库,根据第1步声明的实体类,创建数据库表(flight_information)与表结构字段。
航班信息实体字段补充源码:
/**
* 航班信息实体类
*/
public class FlightInformation {
private static final long serialVersionUID = 1L;
//在此处进行代码补全,声明航班信息实体字段,并添加Get和Set方法 }
创建flight_information表补充源码:
CREATE TABLE `flight_information` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id', //在此处进行建表sql语句补全或使用工具创建表字段 `create_time` DATETIME NOT NULL COMMENT '创建时间', `update_time` DATETIME NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE ) COLLATE='utf8_general_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT ;
任务3-2-3:编写调用航班管理合约查询航班详情接口
在航班延误Dapp中,使用Java语言调用航班管理智能合约,完成航班信息的添加和查询接口,通过Http请求与航班管理接口进行交互,并将获取航班号、计划起飞时间、实际起飞时间、到达时间、是否延误等信息传递给前端模板,要求如下:
(1)接收Web端传递的对应实体类参数(包括航班唯一标识);
(2)调用Java-SDK,运行调用智能合约API,获取航班详情传递给前端页面;
(3)订单详情查询成功后,将获取到的订单信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中。
调用查询航班智能合约接口源码截图:
/**查询工程进度信息*/
@RequestMapping(value = "/getFlightInformation")
@ResponseBody //此处代码补全:接收从Web端传输的参数(包括航班唯一标识)
public Map getFlightInformation(…){
Map resMap = new HashMap<>();
try{
//此处代码补全:调用Java-SDK,运行调用智能合约API,查询工程进度信息,并返回状态 //此处代码补全:查询到工程进度信息后,将获取到的进度信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中
resMap.put("code",200);
resMap.put("message","请求成功");
resMap.put("data",result);
} catch (Exception e){
log.error("操作失败—log:",e);
resMap.put("code",500);
resMap.put("message","请求失败");
}
return resMap;
}2023年全国职业院校技能大赛
高职组
“区块链技术应用”
赛项赛卷(9卷)



参赛队编号:
背景描述
随着异地务工人员的增多,房屋租赁成为一个广阔是市场;目前,现有技术中的房屋租赁是由房主发布租赁信息,租赁信息发布在房屋中介和/或租赁软件,租客获取租赁信息后,现场看房,并签订纸质的房屋租赁合同;房屋租赁费用通过中介或直接给房主;另外,后期的房租还需房主收取。
区块链房屋租赁平台业务流程图
现在利用区块链技术实现房屋租赁系统,将房东、房屋、租客加入到区块链网络中,将发布、租赁、合同、房租等信息存储在区块链的分布式网络中,永久有效,无法篡改。在房屋租赁场景中, 房东将房屋租出后,无法有效控制房屋的使用权,比如租客未履行租赁合约相应内容时,房东无法及时有效限制租客对房屋的使用,造成租金或房屋使用权的回收困难。租赁合约履行过程中房东如果要求租客提前搬离,也会造成租客的利益损失。现有一基于区块链的房屋租赁平台S,房东L在S中出租一套房屋,S中可以调用该房屋的电子锁E的密码。L在S中发放租房合同给租客T,默认L会发放合同,不考虑其他情况。合同中规定,房租每个月的费用是3000元,交付形式是押一付一,每个月的16号交房租。默认T会签署合同,不考虑其他情况。在T签署合同后的24小时之内,T需要在S中预存3000元保证金、3000元租金(需要按照本顺序声明),如果T未预存,交易失败。如果T预存了保证金和一个月租金,L需要在24小时内在S中预存3000元保证金,如果L未在规定时间内预存保证金,S将T的保证金与租金退回,如果L预存保证金,本交易开始执行。S自动将T的一个月房租转账给L,并将房屋E的密码发送给T。在每月16日,E会自动更换密码,如果T按时缴纳房租,S将房屋密码重新更新给T;当T到期未缴纳,S将T的保证金转账给L代替一个月的租金,S仍会将密码更新给T;如果保证金已被扣除后的月份T仍然到期未缴纳,等待补缴,T不补缴房屋密码变更会导致T进不去房屋。当未到租期L提前终止合同,S将L的保证金转给T,如果T还有保证金将保证金一并退还给T。当未到租期T提前终止合同,如果还有保证金S将T的保证金转给L,T还需赔偿L一个月租金,如果T保证金已被扣除,T需赔偿L两个月租金,S将L的保证金退还给L。默认T会赔偿租金不考虑其他情况。当合同正常到期,S将L的保证金退还,T如果还有也退还。本案例只考虑违反合同日期的情况,不考虑情况。
区块链房屋租赁平台系统架构图
模块一:区块链产品方案设计及系统运维(35分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块一提交结果.docx】中对应的任务序号下。
任务1-1:区块链产品需求分析与方案设计
房屋租赁平台中涉及到租客、房东、区块链租房平台、房屋等参与方,他们需要在区块链租房平台中完成账户注册、身份上链、出租房屋、生成合同等多种业务活动。通过对业务活动的功能分析,可以更好的服务系统的开发流程。基于房屋租赁平台系统架构,以区块链房屋租赁平台为背景,结合账户注册、登录服务、入驻上链、房屋出租、房租缴费等核心功能描述,撰写流程图/功能图、用例图等概要设计。本环节需要依据项目背景完成需求分析与方案设计,具体要求如下:
1. 依据给定区块链房屋租赁平台的业务流程图以及用例表,使用StarUML工具编制系统业务用例图,用例图中包含系统参与角色以及用例。
表1-1-1 用例表
用例编号 用例标题 优先级 测试步骤 预期结果 测试结果
HK-TEST-01 房东在区块链房屋租赁平台出租房屋 高 在房屋租赁页面,点击出租功能按钮,跳转到维护房屋信息的页面 成功跳转 成功跳转
HK-TEST-02 房东在区块链房屋租赁平台发放合同 高 在租房管理页面获取租客的租房列表信息,在租房列表中点击发放按钮,可以对该租客发放默认的房屋合同 发放成功 发放成功
HK-TEST-03 租客在区块链房屋租赁平台签署合同 高 在租房管理页面获取租房信息列表,在列表中点击签署按钮,弹窗显示租房合同,将个人信息填充到合同中 收到合同 签署成功 收到合同签署成功
HK-TEST-04 租客在区块链房屋租赁平台缴纳费用 高 在房租缴费页面,获取租房合同信息列表,在列表中点击缴费按钮,弹窗显示租金和保证金并显示缴费倒计时,在倒计时内缴费成功 合同记录 缴费成功 合同记录 缴费成功
HK-TEST-05 房东在区块链房屋租赁平台缴纳费用 高 在租房缴费页面,获取租房合同信息列表,在列表中点击缴费按钮,弹窗显示保证金和缴费倒计时,在倒计时内缴费成功 合同记录 缴费成功 合同记录 缴费成功
HK-TEST-06 区块链房屋租赁平台将房租转账给房东 高 租客、房东缴费成功后,平台自动将房租转账给房东。在房东账户管理界面,显示出收款记录。同时在租客的租赁记录里自动回显房屋的最新电子锁密码 收款成功 电子锁密码回显成功 收款成功
HK-TEST-07 租客或者房东提前终止合同 高 租客或者房东在合同信息列表页,点击终止按钮,弹窗进行二次确认是否提前终止,确认则进入违约页面 终止成功 终止成功
2. 依据给定的背景信息、区块链房屋租赁业务流程图以及区块链房租租赁平台架构图以及给出的房屋租赁业务的核心流程,使用思维导图工具编制业务系统功能图;
表1-1-2 房屋租赁平台的核心流程
发布租房合同流程 房东起草租房合同协议,填写房屋信息、租期、房租等。使用房东的私钥对租房合同进行签名并广播到区块链中进行存证
签署合同流程 租客解密租房协议,验证租房协议的来源。通过租客节点在租房协议中填写个人信息和签名信息,生成租房合约
租房合约属性文本广播流程 租客对租房合约提炼合约属性文本,使用私钥对合约属性本文以及租房合约进行签名后,广播到区块链中
房东解密合约属性文本流程 房东使用自身私钥对加密后的租房合约进行解密,对解密后的租房合约提炼对照合约属性文本,并使用私钥对对照合约属性文本进行签名后广播到区块链中
缴纳房租流程 区块链房屋租赁平台节点实时房屋到期时间,如果房屋到期时,判断房租缴纳和电子锁密码的更新
3.按照基础层、合约层、接口层以及应用层来设计区块链系统的架构,画出系统架构图,其中在基础层需指明需要的节点、名称、协议、存储等信息;
4.结合案例背景将区块链房屋租赁平台核心功能进行划分,完成下方表格中各个主要模块要实现的功能;
房屋出租模块 请输入要实现的功能
合同发放模块 请输入要实现的功能
合同生效模块 请输入要实现的功能
费用缴纳模块 请输入要实现的功能
租房合约执行模块 请输入要实现的功能
违约判断功能模块 请输入要实现的功能
5.根据用例设计以及下方提供好的承诺集,使用Visio工具完成区块链应用系统业务流程图;
表1-1-3 承诺集
房屋出租承诺 判断房东是否在房屋租赁平台发布房屋
缴纳费用承诺 判断租客是否在房屋租赁平台缴纳房租和预存保证金;判断房东是否在房屋租赁平台预存保证金
房租到期缴纳承诺 判断租客是否按时将房租转账给房东,是则发送电子密码锁,否则解锁保证金
合同到期承诺 判断合同是否到期,是则进入判断保证金是否被转账流程,是则结束,否则退还
6.整合所有内容,模块调用接口编写并形成对应的需求用例文档至【区块链技术应用赛\重命名为工位号】下。
任务1-2:区块链系统部署与运维
通过给定区块链项目需求,进行区块链系统的的部署,包括系统部署、节点部署等。通过监控工具完成对网络、节点服务的监控。最终利用业务需求规范,完成系统日志、网络参数、节点服务等系统结构的维护。
子任务1-2-1:区块链网络环境搭建
在本机部署区块链网络底层环境,我们需要准备编译运行的环境,并通过区块链底层源码脚本文件编译区块链网络。
(1)打开区块链源码文件,通过输入命令,检查Go语言编辑环境,并确定Go版本;
(2)打开区块链源码文件,通过输入命令,make编译区块链网络,生成区块链网络编译执行文件,请把编译执行文件截图;
(3)成功编译区块链网络后,通过输入命令,启动区块链服务;
(4)启动区块链网络后,通过输入命令,检查区块链网络状态。
子任务1-2-2:区块链网络服务运行
区块链网络环境成功搭建后,启动区块链网络服务,区块链网络提供了很多的命令行基础功能,满足区块链网络服务的运行。
(1)进入区块链网络执行文件夹(output),通过命令行方式,创建区块链普通钱包账户(userTest),生产区块链钱包地址,私钥,公钥;
(2)进入区块链网络执行文件夹(output),通过命令行方式,获取区块链钱包余额(data/keys);
(3)进入区块链网络执行文件夹(output),通过命令行方式,由data/keys向(userTest)转账10,并查看交易ID;
(4)进入区块链网络执行文件夹(output),通过命令行方式,使用上一步的交易ID,查询交易状态,交易源和目标账号、交易的金额等信息
子任务1-2-3:部署区块链多节点服务
搭建一个3个节点的区块链网络,需要通过命令行创建多节点网络部署环境,并监听各个节点的RPC监听端口,并查看p2p监听渡口配置,现有任务如下:
(1)进入区块链网络主目录下,通过命令行,创建多节点网络部署环境;
(2)进入多节点网络环境目录下,创建多节点网络部署环境后,通过命令行方式,查看P2P网络配置;
(3)节点加入网络需要通过配置种子节点的网络连接地址netURL,请通过命令行方式,获取node3对应的节点netURL。
子任务1-2-4:搭建区块链网络监控系统
系统集成了Prometheus开源监控框架,用户可以通过Prometheus+Grafana构建自己应用的监控系统。请按如下步骤,完成对系统的搭建:
(1)进入区块链网络监控系统主目录,通过命令行方式,在节点 env.yaml 配置中打开 metricSwitch;
(2)配置prometheus 设置endpoint服务修改 prometheus.yml 文件,添加如下配置,每个 target 对应 xchain 节点的 server.yaml 中的 metricPort 端口;
(3)进入到对应目录下,通过命令行启动启动prometheus,打开区块链监控系统项目网址。
任务1-3:区块链系统测试
设计对区块链系统的测试流程;结合实际业务需求,调用部署的智能合约中进行系统测试、性能测试等;根据业务需求,分析并且修复给定智能合约中的安全漏洞。利用模拟业务和测试工具来完成对区块链系统服务数据的测试。
1.启动区块链浏览器系统,找到区块链最新区块列表接口,使用Postman工具对该接口进行HTTP请求测试,并将测试保存;
2.使用测试工具进行测试区块链网络,针对区块链网络吞吐量与时延进行性能指标分析;
3.使用DVWA模拟区块链环境的SQL漏登测试,使用GET方式注入、POST方式注入,分析区块链系统漏洞。
模块二:智能合约开发与测试(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块二提交结果.docx】中对应的任务序号下。
任务2-1:智能合约设计
根据房屋租赁系统需求用例文档,设计合约接口,画出各需求用例的时序图。
任务2-2:智能合约开发
使用Solidity语言进行智能合约开发,根据需求用例文档在待补充源码中完成程序接口功能的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约进行业务功能的验证,成功获取合约的ABI,将合约部署至Geth中的私有链,获取部署的合约信息,将任务中编写代码、运行截图、部署至Geth。
子任务2-2-1:合同管理合约编码
根据需求用例文档在待补充源码中完成合同管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的房东签署合同、租金支付接口功能。
(1)编写房东签署合同接口,完成本合同位置只允许房东签署,通过合同中的信息生成租赁合同的链上哈希,触发协议签署合同的功能,其中合同中的信息包括房东链上账户、租客链上账户、租赁开始时间、租赁结束时间、月租金额、押金金额、交租时间;
(2)编写租金支付接口,完成只允许租客支付租金的规则,检查支付的租金金额是否正确,触发记录租金支付情况的功能。
待补充源码:
contract RentalAgreement {
address public landlord; // 房东的账户
address public tenant; // 租客的账户
uint public rentAmount = 3000; // 每月租金金额(以wei为单位)
uint public depositAmount = 3000; // 押金金额(以wei为单位)
uint public rentDueDate = 16; // 租金到期日
uint public leaseStartDate; // 租赁开始日期
uint public leaseEndDate; // 租赁结束日期
uint public leaseDuration; // 租赁期限(以秒为单位)
bytes32 public contractHash; // 租赁协议的哈希值
bytes32 public propertyHash; // 租赁物业信息的哈希值
event AgreementSigned(address indexed _signer, bytes32 _contractHash); // 租赁协议签署事件
event RentPaid(address indexed _payer, uint _amount); // 租金支付事件
event DepositPaid(address indexed _payer, uint _amount); // 押金支付事件
event LeaseTerminated(address indexed _terminator); // 租赁终止事件
constructor(address _landlord, address _tenant, uint _leaseDuration, bytes32 _propertyHash) {
landlord = _landlord;
tenant = _tenant;
leaseDuration = _leaseDuration; // 初始化租赁期限
propertyHash = _propertyHash;
}
/*********** 房东签署合同接口开发 **********/
/********** 房东签署合同接口开发 ***********/
/*********** 租金支付接口开发 **********/
/********** 租金支付接口开发 ***********/
function payDeposit() public payable {
require(msg.sender == tenant, "Only the tenant can pay the deposit."); // 仅允许租客支付押金
require(msg.value == depositAmount, "Incorrect deposit amount."); // 检查支付的押金金额是否正确
emit DepositPaid(msg.sender, msg.value); // 触发押金支付事件
}
function terminateLease() public {
require(msg.sender == landlord, "Only the landlord can terminate the lease."); // 仅允许房东终止租赁
require(block.timestamp < leaseEndDate, "Lease has already ended."); // 检查租赁是否已经结束
leaseEndDate = block.timestamp; // 更新租赁结束日期为当前时间
emit LeaseTerminated(msg.sender); // 触发租赁终止事件
}
}
子任务2-2-2:违约管理合约编码
根据需求用例文档在待补充源码中完成违约管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的房东终止合同、租客终止合同接口功能。
(1)编写房东终止合同接口,实现房东终止合同判断,如果租客已经终止合同则合同无效,如果合同有效,对合同终止状态进行标记,将剩余押金退还给租客的功能;
(2)编写租客终止合同接口,实现租客终止合同判断,如果房东已经终止合同则合同无效,如果合同有效,对合同终止状态进行标记,将剩余押金退还给房东的功能。
待补充源码:
contract RentalContract {
address payable public landlord; // 房东地址
address payable public tenant; // 租客地址
uint public rentAmount; // 租金
uint public securityDeposit; // 押金
uint public contractStartDate; // 合同开始日期
uint public contractEndDate; // 合同结束日期
uint public gracePeriod; // 宽限期
uint public terminationFee; // 终止合同费用
bool public contractActive; // 合同是否有效
bool public landlordTerminated; // 房东是否终止合同
bool public tenantTerminated; // 租客是否终止合同
bool public tenantDefaulted; // 租客是否违约
bool public securityDepositReturned; // 押金是否已退还
constructor(address payable _landlord, address payable _tenant, uint _rentAmount, uint _securityDeposit, uint _contractStartDate, uint _contractEndDate, uint _gracePeriod, uint _terminationFee) {
landlord = _landlord;
tenant = _tenant;
rentAmount = _rentAmount;
securityDeposit = _securityDeposit;
contractStartDate = _contractStartDate;
contractEndDate = _contractEndDate;
gracePeriod = _gracePeriod;
terminationFee = _terminationFee;
contractActive = true;
landlordTerminated = false;
tenantTerminated = false;
tenantDefaulted = false;
securityDepositReturned = false;
}
function payRent() public payable {
require(msg.sender == tenant, "只有租客可以支付租金。"); // 判断是否为租客
require(msg.value == rentAmount, "租金金额不正确。"); // 判断支付的租金是否正确
require(contractActive, "合同无效。"); // 判断合同是否有效
require(block.timestamp <= contractEndDate, "合同已过期。"); // 判断合同是否已过期
if (block.timestamp > contractStartDate + gracePeriod) { // 如果已经超过宽限期
tenantDefaulted = true; // 标记租客违约
if (securityDeposit >= rentAmount) { // 如果押金足够支付租金
securityDeposit -= rentAmount; // 押金减去租金
} else {
securityDeposit = 0; // 押金清零
}
if (block.timestamp > contractEndDate) { // 如果合同已经过期
contractActive = false; // 合同无效
if (securityDeposit > 0) { // 如果押金还有剩余
tenant.transfer(securityDeposit); // 将押金退还给租客
}
if (msg.value > rentAmount) { // 如果支付的租金超过了租金金额
payable(msg.sender).transfer(msg.value - rentAmount); // 将多余的租金退还给租客
}
} else {
landlord.transfer(rentAmount); // 将租金转账给房东
}
} else {
landlord.transfer(rentAmount); // 将租金转账给房东
}
}
function terminateContract() public {
require(contractActive, "合同无效。"); // 判断合同是否有效
if (msg.sender == landlord) { // 如果是房东
require(!landlordTerminated, "房东已终止合同。"); // 判断房东是否已经终止合同
/*********** 编写房东终止合同接口开发 **********/
/********** 编写房东终止合同接口开发 ***********/
/*********** 编写租客终止合同接口开发 **********/
/********** 编写租客终止合同接口开发 ***********/
}
function getSecurityDeposit() public {
require(!contractActive, "合同仍然有效。"); // 判断合同是否已经失效
require(!securityDepositReturned, "押金已经退还。"); // 判断押金是否已经退还
require(!tenantDefaulted, "租客已违约。"); // 判断租客是否违约
if (msg.sender == landlord) { // 如果是房东
securityDepositReturned = true; // 标记押金已经退还
landlord.transfer(securityDeposit); // 将押金退还给房东
} else if (msg.sender == tenant) { // 如果是租客
require(!landlordTerminated, "房东已终止合同。"); // 判断房东是否已经终止合同
require(!tenantTerminated, "租客已终止合同。"); // 判断租客是否已经终止合同
require(block.timestamp > contractEndDate, "合同尚未到期。"); // 判断合同是否已经到期
securityDepositReturned = true; // 标记押金已经退还
tenant.transfer(securityDeposit); // 将押金退还给租客
}
}
}
子任务2-2-3:押金管理合约编码
根据需求用例文档在待补充源码中完成押金管理合约的编码,解决代码错误和警告,正确编译合约,功能调试正确,运行合约中的租客缴纳押金情况查询、房东收取押金情况查询接口功能。
(1)编写租客缴纳押金情况查询接口,实现查询租客是狗已缴纳押金功能;
(2)编写房东收取押金情况查询接口,实现房东是否已收到押金的功能。
待补充源码:
contract Rent {
uint256 constant deposit = 3000; // 押金金额
uint256 constant rent = 3000; // 租金金额
uint256 constant timeLimit = 1 days; // 时间限制
struct Tenant {
bool deposited; // 是否已缴纳押金
bool rentPaid; // 是否已缴纳租金
uint256 depositTime; // 缴纳押金的时间
}
struct Landlord {
bool deposited; // 是否已收到押金
uint256 depositTime; // 收到押金的时间
}
mapping(address => Tenant) public tenants; // 租户信息
mapping(address => Landlord) public landlords; // 房东信息
function tenantDeposit() public payable {
require(!tenants[msg.sender].deposited && !tenants[msg.sender].rentPaid, "Tenant has already deposited or paid rent"); // 确保租户未缴纳押金或租金
require(msg.value == deposit + rent, "Tenant must deposit both deposit and rent"); // 确保租户缴纳的金额正确
tenants[msg.sender].deposited = true; // 标记租户已缴纳押金
tenants[msg.sender].depositTime = block.timestamp; // 记录缴纳押金的时间
}
function landlordDeposit() public payable {
require(tenants[msg.sender].deposited && tenants[msg.sender].rentPaid, "Tenant has not deposited or paid rent"); // 确保租户已缴纳押金和租金
require(!landlords[msg.sender].deposited, "Landlord has already deposited"); // 确保房东未收到押金
landlords[msg.sender].deposited = true; // 标记房东已收到押金
landlords[msg.sender].depositTime = block.timestamp; // 记录收到押金的时间
}
function checkTenantDeposit(address tenant) public view returns (bool) {
return tenants[tenant].deposited; // 返回租户是否已缴纳押金
}
/*********** 租客缴纳押金情况查询接口 **********/
/********** 租客缴纳押金情况查询接口 ***********/
/*********** 收取押金情况查询接口 **********/
/********** 收取押金情况查询接口 ***********/
function checkTenantDepositTime(address tenant) public view returns (uint256) {
return tenants[tenant].depositTime; // 返回租户缴纳押金的时间
}
function checkLandlordDepositTime(address landlord) public view returns (uint256) {
return landlords[landlord].depositTime; // 返回房东收到押金的时间
}
function checkTimeLimit() public view returns (bool) {
return block.timestamp <= tenants[msg.sender].depositTime + timeLimit; // 返回是否在时间限制内
}
function refund() public {
require(!landlords[msg.sender].deposited && block.timestamp > tenants[msg.sender].depositTime + timeLimit, "Landlord has already deposited or time limit has not been reached"); // 确保房东未收到押金且时间限制已到期
payable(msg.sender).transfer(deposit + rent); // 将押金和租金退还给租户
}
}
子任务2-2-4:合约部署和调用
(1)解决代码错误和警告,正确编译合约,成功获取三个合约的ABI;
(2)将三个合约形成一个文件部署至Geth中的私有链,获取部署合约的地址信息。
任务2-3:智能合约测试
根据需求用例文档完成违约管理的功能测试以及性能测试,解决违约管理合约代码正确性的验证以及验证系统响应时间是否满足预期响应效果,编写功能测试用例,实现违约管理的业务测试,使用JMeter性能测试工具,对合同管理接口进行性能测试。
1.根据需求用例文档在以下测试用例表格中编写违约管理合约中的测用例,依据违约管理中租客违约、房东违约、合同违约的三种状态,分析在前置条件为签署合同、缴纳保证金、押金的情况下,租客提前解除合同、房东提前解除合同、合同失效等情况下,产生的保证金和押金的归属结果;
用例编号 用例标题 优先级 前置条件 测试步骤 测试数据 预期结果
FW-RC0001 违约管理(租客违约) 高 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
请填写 请填写 请填写 请填写 请填写 请填写 请填写
2.利用测试工具,模拟测合同管理接口发送150次请求,将所需HTTP请求、协议、服务器名称或IP以及路径填到工具Web服务器中,连同通请求一起发送的参数,运行成功后将汇总报告提交到指定位置。
模块三:区块链应用系统开发(30分)
选手完成本模块的任务后,将任务中设计结果、运行代码、运行结果等截图粘贴至客户端桌面【区块链技术应用赛\重命名为工位号\模块三提交结果.docx】中对应的任务序号下。
任务3-1:区块链应用前端功能开发
完成区块链应用系统的构建、服务器端(后端)与Web端(前端)的接口的联调。要求如下:
1.使用VsCode工具,按照押金详情原型图的长度、宽度、行高、间距、文字样式、颜色等,完成押金详情页面的样式开发;
2.使用VsCode工具,完成Vue调用押金查询接口API,获取接口返回的租房人、房屋位置、楼号、押金金额、收款人、收款日期信息,填充至Vue页面中。
押金详情页面的样式开发补充源码:
.content{ width: 100%; height: 100%; background: #EEEEEE; .contentModel{ position: absolute; top: 50%; left: 50%; box-sizing: border-box; width: 560px; padding: 41px 40px 40px; background: #fff; border-radius: 8px; box-shadow: 0 3px 12px 0 #c0c4cc; transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -webkit-transform: translate(-50%, -50%); -o-transform:translate(-50%, -50%); } // 此处代码补全:按原型图样式,进行长度、宽度、行高、间距、文字样式、颜色等样式设置; }
押金详情页面的Html开发补充源码:

任务3-2:区块链应用后端功能开发
子任务3-2-1:区块链网络环境启动
区块链应用系统开发需要区块链底层网络进行支撑,完成和链上数据进行交互,与节点建立链接,完成链上信息查询。要求如下:
(1)打开区块链网络文件目录,通过区块链启动脚本,输入bash control.sh start命令,启动区块链网络;
(2)使用IntelliJ IDEA工具,打开(src/controller/BlockController.java)文件,在查询区块链信息接口中,使用Java-SDK获取区块链的最新高度和最新交易Hash,并将结果按十进制的整数和字符串类型返回。
启动区块链源码截图:
区块链的最新高度和最新交易Hash接口补充源码:
/**获取最新区块高度和最新交易Hash*/ @RequestMapping(value = "/getBlockInformation") @ResponseBody public Map getBlockInformation(FlightInformation flightInformation){ Map resMap = new HashMap<>(); try{ // 获取最新区块高度 long blockHeight = block.getLong("height"); System.out.println("最新区块高度:" + blockHeight); // 获取最新区块交易Hash String txHashes = block.getJSONArray("txHashes"); System.out.println("最新区块交易Hash:" + txHash); resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",null); } catch (ClientProtocolException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } catch (IOException e) { log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); }catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } return resMap; }
子任务3-2-2:编写签署房屋租赁合同合约接口和数据库设计
(1)根据“签署房屋租赁合同合约”中变量的字段,在Java项目中声明实体类(HouseLeasingContract),将声明代码结果截图保存;
包含字段:房东的账户公钥(landlord)、租客的账户公钥(tenant)、每月租金金额(rentAmount)、押金金额(depositAmount)、租金到期日(rentDueDate)、租赁开始日期(leaseStartDate)、租赁结束日期(leaseEndDate)、租赁期限(leaseDuration)、租赁协议的哈希值(contractHash)、租赁物业信息的哈希值(propertyHash)。
(2)请打开Navicat Premium 客户端,并连接数据库,根据第1步声明的实体类,创建数据库表(house_leasing_contract)与表结构字段。
签署房屋租赁合同合约实体字段补充源码:
/** * 签署房屋租赁合同实体 */ public class HouseLeasingContract { private static final long serialVersionUID = 1L; //在此处进行代码补全,声明签署房屋租赁合同实体字段,并添加Get和Set方法 }
创建house_leasing_contract表补充源码:
CREATE TABLE `house_leasing_contract` ( `id` INT NOT NULL AUTO_INCREMENT COMMENT '主键id', //在此处进行建表sql语句补全或使用工具创建表字段 `create_time` DATETIME NOT NULL COMMENT '创建时间', `update_time` DATETIME NOT NULL COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE ) COLLATE='utf8_general_ci' ENGINE=InnoDB ROW_FORMAT=COMPACT ;
子任务3-2-3:编写调用查询押金合约接口
已将押金管理合约部署至区块链,通过Java-SDK完成调用押金管理合约接口,获取租房押金信息。要求如下:
(1)接受从Web端接收对应各种参数(包括钱包地址);
(2)调用Java-SDK,运行调用智能合约API,接收租房押金信息传递给前端页面;
(3)租房押金信息查询成功后,将获取到的押金信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中。
/**获取押金详情接口*/ @RequestMapping(value = "/getBlockCashPledgeInformation") @ResponseBody //此处代码补全:接收从Web端传输的参数(包含钱包地址) public Map getBlockCashPledgeInformation(…){ Map resMap = new HashMap<>(); try{ //此处代码补全:调用Java-SDK,运行调用智能合约API,接收租房押金信息传递给前端页面 //此处代码补全:租房押金信息查询成功后,将获取到的押金信息进行解析,并通过数据库依赖包(mysql-connector-java-bin.jar)存储到数据库中 resMap.put("code",200); resMap.put("message","请求成功"); resMap.put("data",depositInfo); } catch (Exception e){ log.error("操作失败—log:",e); resMap.put("code",500); resMap.put("message","请求失败"); } return resMap; }
(
1
)

展开更多......

收起↑

资源列表