环境
fisco-bcos 2.8
ubuntu 20
solidity 0.4.25[版本有点老,也可以用0.6的版本 ]
前言
大家可以阅读上篇对于这个系统的介绍
上一篇 基于fisco-bcos的共享病例智能合约的设计与实现【1】
这篇将介绍共享病历系统智能合约的 角色实体
Roles 库合约
pragma solidity^0.4.25;
library Roles{
struct Role{
mapping(address=>bool) bear;
mapping(address=>address) bearDetail;
address[] bearList;
}
function addRole(Role storage _role,address amount ,address amountDetail) internal {
require(!hasRole(_role,amount),"该用户已经加入");
_role.bear[amount] = true;
_role.bearList.push(amount);
_role.bearDetail[amount] = amountDetail;
}
// 返回一个角色实体细节
function getRoleDetail(Role storage _role,address amount) internal view returns(address){
require(hasRole(_role,amount),"该用户不存在");
return _role.bearDetail[amount];
}
function hasRole(Role storage _role,address amount) internal view returns(bool){
return _role.bear[amount];
}
function removeRole(Role storage _role,address amount) internal{
require(hasRole(_role,amount),"该用户不存在");
_role.bear[amount] = false;
_role.bearDetail[amount] = address(0);
removeRoleByList(_role,amount);
}
function removeRoleByList(Role storage _role,address amount) private{
for(uint i = 0;i< _role.bearList.length;i++){
if(amount == _role.bearList[i]){
for(uint j = i; j<_role.bearList.length-1;j++){
_role.bearList[j] = _role.bearList[j+1];
}
_role.bearList.length--;
break;
}
}
}
function getRoleList(Role storage _role) internal returns(address[]){
return _role.bearList;
}
}
这个库合约非常常见,当系统上有角色的业务逻辑需要设计的时候,可以结合这个库进行设计【请不要重复造轮子[○・`Д´・ ○]】。
这个在WeBase-Front 的合约仓库里面的工具箱里的Roles,我写的Roles库合约,只是 对其进行增加了一些功能,比如删除功能和结构体的修改然后我在原来的基础上,对于Role 这个结构体进行修改
struct Role{
mapping(address=>bool) bear;
mapping(address=>address) bearDetail;
address[] bearList;
}
对于为啥增加这两个字段 mapping(address=>address) bearDetail; address[] bearList;
-
bearList
我来做出个解释,因为这个系统设计的时候考虑到在前端展示的时候,需要展示整个系统的患者列表或者医生列表等,则需要有一个数组进行统计,所以我在Role结构体里面放了address[]
。
但是这种方式非常消耗gas,特别是删除的时候,如果让我再设计这个系统的时候,我会考虑结合链上链下相结合的方法,在mysql 上一对一的保留链上的信息,当我们实现列表展示的业务时候,我们可以用mysql查出列表的【比如存的是患者合约的地址】,然后再拿着数据去链上拿数据。这样就能做到性能和资源平衡。 -
bearDetail
这是个mapping ,而且是地址映射着地址,这是由于系统的特性而设计,因为我们设计的时候,医生和患者这样的角色实体,是一个合约,这样的话,每注册一个医生,就会产生合约地址。
但是,我们在使用系统,在链子上发送交易的时候,使用的是用户合约,所以我选择拿一个mapping来将其绑定在一起,用户A 在链子上有自己的地址,他注册成为医生,用户A的地址与医生合约地址
绑定,这样才有医生权限在这个系统上。
这样子使用合约来做实体,而不是用Struct来做实体,是考虑维护和扩展的角度来设计的,所有数据都在一个合约里会影响交易的自动并行化,影响区块链系统的交易效率
当然,如果数据总量[如医生的数量]不大的话,怎么方便维护怎么来,哈哈
结语
接下来的文章我将介绍如何用Roles库合约将医生合约和患者合约结合起来。