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

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. Memcache随笔

    Tip01: Memcache 中记录的缓存如果你设置了失效时间,之后如果你在系统时间中将时间修改为超过失效时间,再次访问之前你设置的资源,Memcache 会认为你设置的缓存已失效: Tip02: ...

  2. DZNSegmentedControl和XLForm联合使用

    前言: 可能我还没有掌握IOS开发的精髓, 总感觉写ios代码像调bug, 任何一个功能开发完成之后总会有莫名其妙的问题, 最终这些问题很大概率会归结为"系统特性". 正文: 问题 ...

  3. SQLite 如何取出特定部分数据

    如果我要取11-20的Students表的数据,则为: Select * From Students  Limit 9 Offset 10; 表示从Students  表获取数据,跳过10行,取9行 ...

  4. OC录制小视频

    OC录制小视频 用 AVCaptureSession + AVCaptureMovieFileOutput 来录制视频,并通过AVAssetExportSeeion 手段来压缩视频并转换为 MP4 格 ...

  5. fis3 安装(Linux)

    Linux安装fis3 1,首先安装node环境 https://segmentfault.com/a/1190000004245357 2,安装fis3 http://blog.csdn.net/g ...

  6. 如何编写及运行JS

    JS也是一种脚本语言,他可以有两种方式在HTML页面进行引入,一种是外联,一种是内部.       外联JS的写法为: <script src="相对路径"></ ...

  7. Ubuntu更换国内源

    打开终端,输入:sudo gedit /etc/apt/sources.list 在文件最底部输入以下内容: deb http://mirrors.ustc.edu.cn/ubuntu/ xenial ...

  8. react-router-dom实现全局路由登陆拦截

    相比与vue的路由集中式管理,能够很好的进行统一的路由操作,react的路由看起来更乱,想要进行像vue的全局路由管理不是那么得心应手.在我们的项目中,有很多页面是需要登陆权限验证的,最好的方式就是能 ...

  9. hadoop 部署配置

    配置hadoop: 第一个:hadoop-env.sh export JAVA_HOME=/usr/java/jdk1.7.0_65 选择修改日志文件目录(默认目录内日志文件太多易混): export ...

  10. MQTT的学习之Mosquitto安装&使用(1)

    Mosquitto是一个实现了MQTT3.1协议的代理服务器,由MQTT协议创始人之一的Andy Stanford-Clark开发,它为我们提供了非常棒的轻量级数据交换的解决方案.本文的主旨在于记录M ...