基于星云链的智能合约与Dapp(五)——智能合约存储区

论坛 期权论坛 区块链     
古川不爱笑   2018-11-20 23:29   3621   0
            星云链智能合约(smart contract)提供了链上数据存储功能。类似于传统的key-value存储系统(eg:redis),可以付费(消耗gas)将数据存储到星云链上。
LocalContractStorage星云链的智能合约运行环境内置了存储对象
  1. LocalContractStorage
复制代码
,可以存储数字,字符串,JavaScript对象,存储数据只能在智能合约内使用,其他合约不能读取存储的内容。
基础用法
  1. LocalContractStorage
复制代码
的简单接口包括set,get,del接口,实现了存储,读取,删除数据功能。存储可以是数字,字符串,对象。
  1. LocalContractStorage
复制代码
存储数据
  1. // 存储数据,数据会被json序列化成字符串保存LocalContractStorage.put(key, value);// 或者LocalContractStorage.set(key, value);
复制代码
  1. LocalContractStorage
复制代码
读取数据
  1. // 获取数据LocalContractStorage.get(key);
复制代码
  1. LocalContractStorage
复制代码
删除数据
  1. // 删除数据, 数据删除后无法读取LocalContractStorage.del(key);// 或者LocalContractStorage.delete(key);
复制代码
  1. LocalContractStorage
复制代码
在具体的合约中使用的实例
  1. 'use strict';var SampleContract = function () {};SampleContract.prototype = {    init: function () {    },    set: function (name, value) {        // 存储字符串        LocalContractStorage.set("name",name);        // 存储数字        LocalContractStorage.set("value", value);        // 存储对象        LocalContractStorage.set("obj", {name:name,value:value});    },    get: function () {        var name = LocalContractStorage.get("name");        console.log("name:"+name)        var value = LocalContractStorage.get("value");        console.log("value:"+value)        var obj = LocalContractStorage.get("obj");        console.log("obj:"+JSON.stringify(obj))    },    del: function () {        var result = LocalContractStorage.del("name");        console.log("del result:"+result)    }};module.exports = SampleContract;
复制代码
高级用法
  1. LocalContractStorage
复制代码
除了基本的
  1. set
复制代码
,
  1. get
复制代码
,
  1. del
复制代码
方法,还提供方法来绑定合约属性。对绑定过的合约属性的读写将直接在
  1. LocalContractStorage
复制代码
上读写,而无需调用
  1. get
复制代码
  1. set
复制代码
方法。
绑定属性在绑定一个合约属性时,需要提供对象实例,属性名和序列化方法。
绑定接口
  1. // define a object property named `fieldname` to `obj` with descriptor.// default descriptor is JSON.parse/JSON.stringify descriptor.// return this.defineProperty(obj, fieldName, descriptor);// define object properties to `obj` from `props`.// default descriptor is JSON.parse/JSON.stringify descriptor.// return this.defineProperties(obj, descriptorMap);
复制代码
  1. LocalContractStorage
复制代码
绑定属性的例子:
  1. 'use strict';var SampleContract = function () {    // 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    });};module.exports = SampleContract;
复制代码
然而,我们可以如下在合约里直接读写这些属性。
  1. 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设置自动转换为Bignumber        var amount = this.value.plus(new BigNumber(2));        if (amount.lessThan(new BigNumber(balance))) {            return 0        }    }};
复制代码
绑定Map属性
  1. LocalContractStorage
复制代码
还提供了对合约中map属性的绑定方法。
下面是一个绑定map属性的例子:
  1. '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遍历。
提示:由于Map遍历性能开销比较大,不建议对大数据量map进行遍历,建议按照limit,offset形式进行遍历,否者可能会由于数据过多,导致调用超时。
[code]##### 遍历map数据"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
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:50
帖子:9
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP