编写智能合约

Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScript V8引擎,所以当前的开发版,我们可以使用JavaScript、TypeScript来编写智能合约。

编写智能合约的简要规范

  1. 智能合约代码必须是一个Prototype的对象;
  2. 智能合约代码必须有一个init()的方法,这个方法只会在部署的时候被执行一次;
  3. 智能合约里面的私有方法是以_开头的方法,私有方法不能被外部直接调用;

智能合约存储区

星云链智能合约(smart contract)提供了链上数据存储功能。类似于传统的key-value存储系统(eg:redis),可以付费(消耗gas)将数据存储到星云链上。

星云链的智能合约运行环境内置了存储对象==LocalContractStorage==,可以存储数字,字符串,JavaScript对象,存储数据只能在智能合约内使用,其他合约不能读取存储的内容。

基础用法

LocalContractStorage的简单接口包括set,get,del接口,实现了存储,读取,删除数据功能。存储可以是数字,字符串,对象。

LocalContractStorage存储数据

// 存储数据,数据会被json序列化成字符串保存
LocalContractStorage.put(key, value);
// 或者
LocalContractStorage.set(key, value);

LocalContractStorage读取数据

// 获取数据
LocalContractStorage.get(key);

LocalContractStorage删除数据

// 删除数据, 数据删除后无法读取
LocalContractStorage.del(key);
// 或者
LocalContractStorage.delete(key);

高级用法

LocalContractStorage除了基本的set,get,del方法,还提供方法来绑定合约属性。对绑定过的合约属性的读写将直接在LocalContractStorage上读写,而无需调用get和set方法。

绑定属性

在绑定一个合约属性时,需要提供对象实例,属性名和序列化方法。

// SampleContract的`size`属性为存储属性,对`size`的读写会存储到链上,
// 此处的`descriptor`设置为null,将使用默认的JSON.stringify()和JSON.parse()
LocalContractStorage.defineProperty(this, "size", null);// SampleContract的`value`属性为存储属性,对`value`的读写会存储到链上,
// 此处的`descriptor`自定义实现,存储时直接转为字符串,读取时获得Bignumber对象
LocalContractStorage.defineProperty(this, "value", { // 提供自定义的序列化和反序列化方法stringify: function (obj) { // 序列化方法return obj.toString();},parse: function (str) { //反序列化方法return new BigNumber(str);}
});
// SampleContract的多个属性批量设置为存储属性,对应的descriptor默认使用JSON序列化
LocalContractStorage.defineProperties(this, {name: null,count: null
});

然后,我们可以如下在合约里直接读写这些属性。

SampleContract.prototype = {// 合约部署时调用,部署后无法二次调用init: function (name, count, size, value) {// 在部署合约时将数据存储到链上this.name = name;this.count = count;this.size = size;this.value = value;},testStorage: function (balance) {// 使用value时会从存储中读取链上数据,并根据descriptor设置自动转换为Bignumbervar amount = this.value.plus(new BigNumber(2));if (amount.lessThan(new BigNumber(balance))) {return 0}}
};

绑定Map属性

'use strict';var SampleContract = function () {// 为`SampleContract`定义`userMap`的属性集合,数据可以通过`userMap`存储到链上LocalContractStorage.defineMapProperty(this, "userMap");// 为`SampleContract`定义`userBalanceMap`的属性集合,并且存储和读取序列化方法自定义LocalContractStorage.defineMapProperty(this, "userBalanceMap", {stringify: function (obj) {return obj.toString();},parse: function (str) {return new BigNumber(str);}});// 为`SampleContract`定义多个集合LocalContractStorage.defineMapProperties(this,{key1Map: null,key2Map: null});
};SampleContract.prototype = {init: function () {},testStorage: function () {// 将数据存储到userMap中,并序列化到链上this.userMap.set("robin","1");// 将数据存储到userBalanceMap中,使用自定义序列化函数,保存到链上this.userBalanceMap.set("robin",new BigNumber(1));},testRead: function () {//读取存储数据var balance = this.userBalanceMap.get("robin");this.key1Map.set("robin", balance.toString());this.key2Map.set("robin", balance.toString());}
};module.exports = SampleContract;

Map数据遍历

在智能合约中如果需要遍历map集合,可以采用如下方式:定义两个map,分别是arrayMap,dataMap,arrayMap采用严格递增的计数器作为key,dataMap采用data的key作为key,详细参见set方法。遍历实现参见forEach,先遍历arrayMap,得到dataKey,再对dataMap遍历。Tip:由于Map遍历性能开销比较大,不建议对大数据量map进行遍历,建议按照limit,offset形式进行遍历,否者可能会由于数据过多,导致调用超时。

"use strict";var SampleContract = function () {LocalContractStorage.defineMapProperty(this, "arrayMap");LocalContractStorage.defineMapProperty(this, "dataMap");LocalContractStorage.defineProperty(this, "size");
};SampleContract.prototype = {init: function () {this.size = 0;},set: function (key, value) {var index = this.size;this.arrayMap.set(index, key);this.dataMap.set(key, value);this.size +=1;},get: function (key) {return this.dataMap.get(key);},len:function(){return this.size;},forEach: function(limit, offset){limit = parseInt(limit);offset = parseInt(offset);if(offset>this.size){throw new Error("offset is not valid");}var number = offset+limit;if(number > this.size){number = this.size;}var result  = "";for(var i=offset;i<number;i++){var key = this.arrayMap.get(i);var object = this.dataMap.get(key);result += "index:"+i+" key:"+ key + " value:" +object+"_";}return result;}
};module.exports = SampleContract;

智能合约实例

下面通过实现一个非常简单的功能,来说明智能合约的开发。

功能简要说明

  1. 提交文字信息存储到星云链,包括:标题和内容
  2. 根据作者地址查看提交的信息

    智能合约代码

'use strict';// 定义信息类
var Info = function (text) {if (text) {var obj = JSON.parse(text); // 如果传入的内容不为空将字符串解析成json对象this.title = obj.title;                     // 标题this.content = obj.content;                 // 内容this.author = obj.author;                  // 作者this.timestamp = obj.timestamp;            // 时间戳} else {this.title = "";this.content = "";this.author = "";this.timestamp = 0;}
};// 将信息类对象转成字符串
Info.prototype.toString = function () {return JSON.stringify(this)
};// 定义智能合约
var InfoContract = function () {// 使用内置的LocalContractStorage绑定一个map,名称为infoMap// 这里不使用prototype是保证每布署一次该合约此处的infoMap都是独立的LocalContractStorage.defineMapProperty(this, "infoMap", {// 从infoMap中读取,反序列化parse: function (text) {return new Info(text);},// 存入infoMap,序列化stringify: function (o) {return o.toString();}});
};// 定义合约的原型对象
InfoContract.prototype = {// init是星云链智能合约中必须定义的方法,只在布署时执行一次init : function () {},// 提交信息到星云链保存,传入标题和内容save : function (title, content) {title = title.trim();content = content.trim();if (title === "" || content === "") {throw new Error("标题或内容为空!");}if (title.length > 64) {throw new Error("标题长度超过64个字符!");}if (content.length > 256) {throw new Error("内容长度超过256个字符!");}// 使用内置对象Blockchain获取提交内容的作者钱包地址var from = Blockchain.transaction.from;// 此处调用前面定义的反序列方法parse,从存储区中读取内容var existInfo = this.infoMap.get(from);if (existInfo) {throw new Error("您已经发布过内容!");}var info = new Info();info.title = title;info.content = content;info.timestamp = new Date().getTime();info.author = from;// 此处调用前面定义的序列化方法stringify,将Info对象存储到存储区this.infoMap.put(from, info);},// 根据作者的钱包地址从存储区读取内容,返回Info对象read : function (author) {author = author.trim();if (author === "") {throw new Error("地址为空!");}// 验证地址if (!this.verifyAddress(author)) {throw new Error("输入的地址不存在!");}var existInfo = this.infoMap.get(author);return existInfo;},// 验证地址是否合法verifyAddress: function (address) {// 1-valid, 0-invalidvar result = Blockchain.verifyAddress(address);return {valid: result == 0 ? false : true};}
};
// 导出代码,标示智能合约入口
module.exports = InfoContract;

部署智能合约

可以在命令行下进行部署,本文介绍在web钱包下的部署方法,操作更简单。

第一步

第二步

第三步

执行智能合约方法

执行save方法,发布信息

注意:目的地址为合约地址

执行read方法,查看信息

转载于:https://blog.51cto.com/634435/2114749

星云链智能合约开发(六):智能合约开发与部署相关推荐

  1. android系统开发(六)-HAL层开发基础

    Android HAL层,即硬件抽象层,是Google响应厂家"希望不公开源码"的要求推出的新概念 1,源代码和目标位置 源代码: /hardware/libhardware目录, ...

  2. Nebulas 101 - 03 编写并运行智能合约 ---》星云链开发

    Nebulas 3200 万奖金的 DApp 开发激励计划 注册地址:https://incentive.nebulas.io/cn/signup.html?invite=58jke 时间: 2018 ...

  3. 10本区块链热门图书(应用开发、智能合约等)免费送!

    欢迎访问网易云社区,了解更多网易技术产品运营经验. "互联网之后就是区块链时代,区块链是实现未来跟踪经济的关键技术."世界上真的存在 100% 去中心化的系统吗?区块链到底是什么? ...

  4. 区块链应用开发(智能合约的开发和WeBASE合约IDE的使用)

    文章目录 四.智能合约的开发和WeBASE合约IDE的使用 一.实验概述 二.实验目标 三.实验环境及建议 四.实验步骤 4.1 启动Webase 4.2 智能合约开发 4.2.1 合约功能设计 4. ...

  5. 基于星云链的智能合约与Dapp(四)——编写并运行智能合约

    一般智能合约需要以下几个步骤: 1.编写智能合约 2.部署智能合约 3.调用智能合约,验证合约执行结果 编写智能合约 Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScri ...

  6. Zeppelin:用于区块链应用的开源安全智能合约架构

    9月15日,Zeppelin的路线图建议发布.Zeppelin是一种构建安全智能合约的开源架构,遵循MIT许可.该建议的推出正是时候,从DevCon2大会上围绕着智能合约形式验证的报告和讨论的次数上就 ...

  7. solidity payable_以太坊区块链搭建与使用(五)-智能合约Solidity

    一.智能合约Solidity开发工具 1.remix-ide http://remix.ethereum.org/ 在线版本,也可以去github下载安装到本地.开发.编译.发布.执行.测试 2.re ...

  8. c++ eos智能合约开发_十分钟教你开发EOS智能合约

    EOS环境搭建和启动节点 下面从EOS入门的环境搭建.编译运行一个智能合约.发送一些Aigsen,给大家做一些展示,希望能让非技术人员也有一些收获. 首先下载EOS环境搭建和启动节点.这一步其实还是比 ...

  9. 十分钟教你开发EOS智能合约

    十分钟教你开发EOS智能合约 在CSDN.柏链道捷(PDJ Education).HelloEOS.中关村区块链产业联盟主办的「EOS入门及最新技术解读」专场沙龙上,柏链道捷(PDJ Educatio ...

最新文章

  1. openstack安装在虚拟机上重启之后无法启动问题
  2. windows AD/DNS服务器搭建
  3. Android Studio调试功能使用总结
  4. 动作游戏老是卡?试试从这些方面提升流畅度
  5. 一名拿到阿里offer的Java程序员分享三轮面试经验
  6. JVM参数设置、分析
  7. %@ taglib prefix=c uri=http://java.sun.com/jsp/jstl/core %会报错
  8. 吴恩达深度学习5.1笔记_Sequence Models_循环序列模型
  9. 使用 XML Schema 定义元素的基本知识--1
  10. 用c语言编电话薄系统,求助 哈稀表编电话薄程序(c语言) 算法
  11. latex中设置标题左对齐
  12. java第14次作业
  13. Why does getView return wrong convertView objects on BaseAdapter?
  14. 【你离诺贝尔奖也就20米】记一次诺奖得主讲座聆听感受
  15. 噬菌体疗法减缓细菌耐药性进化
  16. MacBook软件安装和更新与卸载
  17. Android 系统剪贴板的使用 - 复制、获取和清空
  18. Mockito verify Junit5集成 Mockito
  19. windows扩充C盘容量(删除Ubuntu分区)
  20. yo搭建nodejs项目脚手架

热门文章

  1. 移动老总上厕所!!!让你爽歪歪!!
  2. 基于Bmob从零开始写一个博客小程序
  3. SylixOS启动读取配置文件
  4. oracle报错注入的一些函数
  5. JavaScript-常用正则函数(适合忘记时看)
  6. 流行歌曲演唱的风格与技巧
  7. cocos2dx视频教程进阶篇--第1天--吃西瓜游戏。
  8. 数据结构研究 ----单链表的按序号查找
  9. Ruby命令之gem操作
  10. 主题:spring集成quartz,出现2次重复调用的问题