矩阵元区块链智能合约开发指南

1 适用范围

本规范描述了矩阵元区块链系统智能合约的开发约束与规范,用以指导DAPP开发者按照本规范开发基于矩阵元区块链运行的应用。

2 术语解释

术语 术语解释
DAPP 去中心化应用
Truffle 智能合约开发IDE

3 Quick Start

本章节描述一个简单的智能合约开发样例,用以描述基于矩阵元区块链的智能合约开发标准与规范。给DAPP应用的开发提供参考。

3.1 合约功能描述

此合约开发用例用来管理学生数据,并给不同用户分配不同的数据处理权限,实现数据

的访问控制。

3.2 合约规划与列表说明

3.2.1 合约存储规划

学生数据在合约的存储属性为:

id 学生id(对应于钱包地址)
name 学生名字
classId 学生所属班级id
status 标记学生数据是否开除: 0 未开除 1 已开除

3.2.2 合约接口规划

//新增学生
func addStudent(string _studentJson) public returns{}; //开除学生
func deleteStudentById0(string id) public{}; //根据Id查询用户
func findStudentById(string id) constant public returns{};

3.2.3 合约权限规划

角色列表 角色具有的权限
校长 deleteStudentById, addStudent, findStudentById
班主任 addStudent, findStudentById
学生 findStudentById

3.2.4 合约文件规划

LibStudent.sol: 学生的数据结构合约;

StudentManager.sol: 实现对学生数据的各种处理;

ModuleManager.sol: 实现对合约、角色、权限的模块化处理。

3.3 合约代码样例

LibStudent.sol:

pragma solidity ^0.4.2;

import "LibInt.sol";
import "LibString.sol";
import "LibJson.sol"; library LibStudent {
using LibJson for *;
using LibString for *;
using LibInt for *;
using LibStudent for *; //引入库的语法 //student对象结构体
struct Student{
address id; //学生Id
string name; //学生名称
string classId; //学生班级Id
uint status; //学生状态 0 未开除 1 开除
} //将student对象转换成json字符串
function toJson(Student storage _self) internal returns(string _strjson){
_strjson = "{";
string memory strAddr = "0x";
strAddr = strAddr.concat(_self.id.addrToAsciiString());
_strjson = _strjson.concat(strAddr.toKeyValue("id"), ",")
_strjson = _strjson.concat(_self.name.toKeyValue("name"), ",");
_strjson = _strjson.concat(_self.classId.toKeyValue("classId"), ",");
_strjson = _strjson.concat(uint(_self.status).toKeyValue("status"), " ");
_strjson = _strjson.concat("}");
} //从student的json字符串中提取相应值
function fromJson(Student storage _self, string _stuJson) internal returns(bool) {
_self.clear(); string memory strAddr = _stuJson.getStringValueByKey("id");
strAddr = _stuJson.getStringValueByKey("id");
_self.id= strAddr.toAddress();
_self.name = _stuJson.jsonRead("name");
_self.classId= _stuJson.jsonRead("classId");
_self.status = _stuJson.jsonRead("status").toUint();
return true;
} //将student对象置空
function clear(Student storage _self) internal {
_self.id= address(0);
_self.name = "";
_self.classId= "";
_self.status = 1;
} //重置student对象
function reset(Student storage _self) internal {
clear(_self);
_self.clear();
}
}

StudentManager.sol:

pragma solidity ^0.4.2;

import "LibStudent.sol";
import "LibString.sol";
import "LibInt.sol"; contract StudentManager { using LibStudent for *;
using LibString for *;
using LibInt for *; //引入所需库合约 event Notify(uint _errno, string _info); //定义事件处理 //此mapping对象将地址映射到对象本身
mapping(address=>LibStudent.Student) studentMap;
address[] addrList;
address[] tempList; LibStudent.Student internal student;
string[] tmpArray; //错误码定义
enum StudentError {
NO_ERROR,
BAD_PARAMETER,
NAME_EMPTY,
CLASS_NOT_EXISTS,
STUDENT_NOT_EXISTS
} uint errno = 0; //构造函数
function StudentManager() {
} //新增学生
function addStudent(string _studentJson) public returns(uint) {
log("insert", "StudentManager"); if (student.fromJson(_studentJson) == false) {
log("insert bad json", "StudentManager");
errno = 9000 + uint(StudentError.BAD_PARAMETER);
Notify(errno, "insert bad json");
return errno;
} if (student.name.equals("")) {
log("student name is invalid", "StudentManager");
errno = 9000 + uint(StudentError.NAME_EMPTY);
Notify(errno, "student name is invalid");
return errno;
} if (student.classId.equals("")) {
log("student classId is invalid", "StudentManager");
errno = 9000 + uint(StudentError.CLASS_NOT_EXISTS);
Notify(errno, "student classId is invalid");
return errno;
} student.status = uint(0); studentMap[student.id] = student;
addrList.push(student.id); errno = uint(StudentError.NO_ERROR); log("add a student succcess", "StudentManager");
Notify(errno, "insert a student succcess");
student.reset();
return errno;
} //根据学生Id查找学生
function findStudentById(address _id) constant public returns(string _ret) {
_ret = "{\"ret\":0,\"data\":{"; if (studentMap[_id].status != 1) {
_ret = _ret.concat(studentMap[_id].toJson());
} else {
_ret = _ret.concat(""));
}
_ret = _ret.concat("}}");
} //根据学生Id删除学生
function deleteStudentById(address _id) public { if (studentMap[_id].status == 1) {
log("student not exists: ", _id);
errno = 9000 + uint(StudentError.STUDENT_NOT_EXISTS);
Notify(errno, "student not exists");
return;
}
delete tempList;
for (uint i = 0; i < addrList.length; i++) {
if(_id == studentMap[addrList[i]].id) {
continue;
}
else {
tempList.push(addrList[i]);
}
} delete addrList;
for (uint j = 0; j < tempList.length; ++j) {
addrList.push(tempList[j]);
} studentMap[_id].status = 1;
Notify(errno, "fire student success");
}
}

ModuleManager.sol:

pragma solidity ^0.4.2;

import "LibModule.sol";
import "LibContract.sol";
import "BaseModule.sol"; contract ModuleManager is BaseModule{ //构造module对象
LibModule.Module tmpModule; //构造contract对象
LibContract.Contract tmpContract; //构造函数,发布入链即自动执行
func ModuleManager(){
register("ModuleManager","0.0.1.0");
tmpModule.reset();
string[] memory tmpArr; tmpModule = LibModule.Module({moduleId:"systemModule001",moduleName:"系统模块",moduleVersion:"0.0.1.0",deleted:false,moduleEnable:1,moduleDescription:"系统模块管理",moduleCreateTime:nowTime,moduleUpdateTime:nowTime,moduleCreator:msg.sender,contractIdList:tmpArr,roleIds:tmpArr});
addModule(tmpModule); //添加此模块
initContractData(); //添加合约
initActionData(); //添加权限
initRoleData(); //添加角色 } //添加合约数据
func initContractData() private returns(uint){
address userAddr = rm.getContractAddress("UserManager","0.0.1.0");
tmpContract.moduleId = sysModuleId;
tmpContract.cctId = innerContractMapping["UserManager"];
tmpContract.cctName = "用户管理";
tmpContract.cctVersion = "0.0.1.0";
tmpContract.deleted = false;
tmpContract.enable = 1;
tmpContract.description = "用户管理合约";
tmpContract.createTime = nowTime;
tmpContract.updateTime = nowTime;
tmpContract.creator = msg.sender;
tmpContract.cctAddr = userAddr;
addContract(tmpContract.toJson());
return 1;
} //添加权限数据
func initActionData() private returns(uint){
string memory actionStr = ""; //权限数据对象
jsonStr="{\"id\":\"action1000\",\"moduleId\":\"module001\",\"name\":\"addStudent\",\"resKey\":\"StudentManager\",\"opKey\":\"addStudent(string)\"}";
addAction(jsonStr);
jsonStr="{\"id\":\"action1001\",\"moduleId\":\"module001\",\"name\":\"findStudentById\",\"resKey\":\"StudentManager\",\"opKey\":\"findStudentById(string)\"}";
addAction(jsonStr);
jsonStr="{\"id\":\"action1002\",\"moduleId\":\"module001\",\"name\":\"deleteStudentById\",\"resKey\":\"StudentManager\",\"opKey\":\"deleteStudentById(string)\"}";
addAction(jsonStr);
return 1;
} //添加角色数据
func initRoleData() private returns(uint){
string memory roleJsonStr=""; //角色数据对象
roleJsonStr="{\"id\":\"role1000\",\"name\":\"校长\",\"status\":1,\"moduleId\":\"systemModule001\",\"actionIdList\":[\"action1000\",\"action1001\",\"action1002\"]}";
addRole(roleJsonStr);
roleJsonStr="{\"id\":\"role1001\",\"name\":\"班主任\",\"status\":1,\"moduleId\":\"systemModule001\",\"actionIdList\":[\"action1000\",\"action1001\"]}";
addRole(roleJsonStr);
roleJsonStr="{\"id\":\"role1002\",\"name\":\"学生\",\"status\":1,\"moduleId\":\"systemModule001\",\"actionIdList\":[\"action1001\",]}";
addRole(roleJsonStr);
return 1;
}
}

3.4 合约编译发布

3.4.1 前提要求

本地矩阵元区块链平台已经启动运行。

矩阵元区块链平台搭建请参考《矩阵元区块链环境安装部署》文档;

本地已搭建好Truffle环境。

Truffle编译发布环境搭建请参考《矩阵元区块链Truffle环境搭建》文档。

3.4.2 合约编译与发布

1)Truffle环境初始化

新建合约目录DAPP
在新建的合约目录DAPP下执行truffle init初始化目录结构 修改truffle.js文件中RPC地址为平台地址
删除示例合约ConvertLib.sol,MetaCoin.sol,Migrations.sol

2)上传应用智能合约

将编写的上述智能合约上传到truffle init生成目录结构下的contract中

3)合约编译

在新建的Dapp目录下执行命令truffle compile完成合约的编译

4)合约发布

修改部署配置文件:
在migrations目录下修改migrations/1_initial_migration.js
注释掉deployer.deploy(Migrations); 在migrations目录下修改migrations/2_deploy_contracts.js
添加自己要发布的合约,例:
module.exports = function(deployer) {
deployer.deploy(StudentManager);
deployer.deploy(ModuleManager);
}; 在新建的Dapp目录下执行命令truffle migrate完成合约的发布。

3.4.3 合约测试

进入truffle控台: truffle console

实例化待测合约对象,如StudentManager.sol

> var stu = StudentManager.deployed();
undefined

或者:

> var stu = StudentManager.at(“0x002b4f09741a896e757f276d8f5f0c24bca870bf”);
undefined

注:该处此地址为合约发布时输出的对应地址。

调用合约函数:

> stu.addStudent(‘{“id”: “0x006d8f5f0c24bca870bf2b4f09741a896e757f27”, “name”: “juzix”,     “classId”: “SuperClass”,“status”: 0}’);
“0x00aa1676c77bb7861ef115652715671880aa1677”
> stu.findStudentById(“0x006d8f5f0c24bca870bf2b4f09741a896e757f27”);
‘{“id”: “0x006d8f5f0c24bca870bf2b4f09741a896e757f27”, “name”: “juzix”, “classId”: “SuperClass”,“status”: 0}’
> stu.deleteStudentById(“0x006d8f5f0c24bca870bf2b4f09741a896e757f27”);
“0x5652715671880aa00aa1676c77bb7861ef11ba21”

4 系统合约接口说明

系统Library库合约以及系统合约接口说明请参考智能合约开发指南_矩阵元区块链文档

4.3 系统角色与权限说明

系统内置四种角色以及每个角色对应的权限,分别为:节点管理员、链管理员、系统管理员、权限管理员,每个角色为相关合约下的所有接口,四大角色所有权限如下:

角色名称 节点管理员
角色权限 权限描述 四大合约权限以及节点信息管理权限
所有权限 UserManager, DepartmentManager, ActionManager, RoleManager, NodeInfoManager
角色名称 链管理员
角色权限 权限描述 四大合约权限、链文件以及节点申请权限
所有权限 UserManager, DepartmentManager, ActionManager, RoleManager, NodeApplyManager, FileInfoManager, FileServerManager
角色名称 系统管理员
角色权限 权限描述 四大合约权限以及系统配置权限
所有权限 UserManager, DepartmentManager, ActionManager, RoleManager, SystemConfig
角色名称 权限管理员
角色权限 权限描述 机构、用户、角色权限管理员,四大合约权限以及权限控制
所有权限 UserManager, DepartmentManager, ActionManager, RoleManager, RoleFilterManager

5 合约业务开发流程介绍

使用智能合约开发业务,需按照以下5个步骤进行:

1)完成合约基础数据的处理;

2)实现注册合约;

3)定义业务数据的结构,并实现对业务数据的处理;

4)根据接口文档实现业务合约的业务逻辑;

5)模块化管理。

流程详情请参考智能合约开发指南_矩阵元区块链文档

truffle框架快速开发合约步骤的更多相关文章

  1. 使用 CodeIgniter 框架快速开发 PHP 应用(三)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(三) 分析网站结构既然我们已经安装 CI ,我们开始了解它如何工作.读者已经知道 CI 实现了MVC式样. 通过对目录和文件的内容进行分 ...

  2. 使用 CodeIgniter 框架快速开发 PHP 应用(七)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(七) CodeIgniter 和对象这是玩家章节.它讲述的是 CodeIgniter 的工作原理,也就是揭开CI头上'神秘的面纱'.如果 ...

  3. 使用 CodeIgniter 框架快速开发 PHP 应用(六)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(六) 简化使用 Session 和安全理论说得够多了! 现在让我们开始写我们自己的应用. 在这一章里,我们将会大致描述一下我们要建立的一 ...

  4. 使用 CodeIgniter 框架快速开发 PHP 应用(五)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(五) 简化 HTML 页面和表格设计这一章介绍了又一个节约你的时间而且使你的代码更具安全性和逻辑性的领域.第一,我们将会介绍创建视图的各 ...

  5. 使用 CodeIgniter 框架快速开发 PHP 应用(四)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(四) 使用 CI 简化数据库开发你学习CI 是因为你想要使编程更容易和更有生产力.这一章讲述CI的Active Record类. 如果C ...

  6. 使用 CodeIgniter 框架快速开发 PHP 应用(二)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(二) 二分钟: 建立一个 CodeIgniter 网站用CI建一个网站很容易. 这一章很短,解释了用CI制作网站时发生了些什么,哪些文件 ...

  7. 使用 CodeIgniter 框架快速开发 PHP 应用(一)

    原文:使用 CodeIgniter 框架快速开发 PHP 应用(一) 对 CodeIgniter 的介绍大多数PHPer都想写出运行状态良好的应用程序,而且希望尽可能做得简单且不费事.这篇文章是有关 ...

  8. Scut游戏服务器免费开源框架--快速开发(2)

    Scut快速开发(2) Python脚本开发 1   开发环境 Scut Lib版本:5.2.3.2 需要安装的软件 a)        IIS和消息队列(MSMQ) 进入控制面板,程序和功能 b)  ...

  9. Scut游戏服务器免费开源框架--快速开发(3)

    Scut快速开发(3) 1     开发环境 Scut Lib版本:5.2.3.2 需要安装的软件 a)        IIS和消息队列(MSMQ) b)        数据库,Sql2005以上版本 ...

随机推荐

  1. Knowledge Point 20180305 详解精度问题

    1.1 精度与基本数据类型运算的深度解析 我们在探讨Java基本数据类型时多次提到过精度的问题,那么计算机中的精度究竟是什么样的,为什么我们有时候的计算和我们预期的不同呢?下面我们通过精度来了解: 1 ...

  2. 09 OCP知识点讲解 之 LRU链与脏LRU链

    OCP知识点讲解 之 LRU链与脏LRU链 分类: Oracle 2012-06-30 10:49:26   一.LRU链: 任何缓存的大小都是有限制的,并且总不如被缓存的数据多.就像Buffer c ...

  3. LeetCode 中级 - 组合总和(105)

    给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重复被选 ...

  4. ExcludeClipRect区域裁剪问题

    CPaintDC dc(this); CRect rt1; CPen newPen; newPen.CreatePen(PS_SOLID,1,RGB(0,0,0)); CPen *pOldPen = ...

  5. java8的新特性,Collections.sort(排序的List集合)的使用,对list封装Map里面的某个值进行排序

    --------------------------对简单list的排序---------------------------------- List<Integer> list = ne ...

  6. 前端模块化小总结—commonJs,AMD,CMD, ES6 的Module

    随着前端快速发展,需要使用javascript处理越来越多的事情,不在局限页面的交互,项目的需求越来越多,更多的逻辑需要在前端完成,这时需要一种新的模式 --模块化编程 模块化的理解:模块化是一种处理 ...

  7. Jmeter的实例应用

    目标: 获取城市的天气数据: 第一步: 发送request 获取城市的城市代号http://toy1.weather.com.cn/search?cityname=上海 从这个请求的response ...

  8. Spring Boot在反序列化过程中:jackson.databind.exc.InvalidDefinitionException cannot deserialize from Object value

    错误场景 用Spring boot写了一个简单的RESTful API,在测试POST请求的时候,request body是一个符合对应实体类要求的json串,post的时候报错. 先贴一段error ...

  9. css:url链接去下划线+点击前黑色+点击时灰色+点击后黑色

    一般的文章列表 加了样式之后的效果 附上css代码 /*点击前*/ a:link{ color: black; } /*点击后*/ a:visited{ color: black; } /*点击时*/ ...

  10. 虚拟机(unbutun16.04)设置静态ip

    电脑上装了虚拟机,想用xshell连接,无奈按照默认的网络设置方式每次重启了虚拟机后都要修改ip才能访问,这怎么能忍,经过一番折腾终于搞定这个问题了,解决步骤如下: 大步骤分为两步:其一是主机的设置, ...