zoukankan      html  css  js  c++  java
  • 智能合约:BUMO 智能合约开发(新接口)

    BUMO 智能合约开发(新接口)

    概述

    BUMO 智能合约是一段JavaScript代码,标准(ECMAScript as specified in ECMA-262)。合约的初始化函数是 init, 执行的入口函数是 main函数,查询接口是 query。这些函数的参数字符串 input,是调用该合约的时候指定的。 下面是一个简单的例子

    "use strict";
    function init(input)
    {
      /*init whatever you want*/
      return;
    }
    
    function main(input)
    {
      let para = JSON.parse(input);
      if (para.do_foo)
      {
        let x = {
          'hello' : 'world'
        };
      }
    }
    
    function query(input)
    { 
      return input;
    }
    

    接口对象

    BUMO 智能合约内提供了全局对象 Chain 和 Utils, 这两个对象提供了多样的方法和变量,可以获取区块链的一些信息,也可驱动账号发起所有交易,除了设置门限和权重这两种类型的操作。

    注意,自定义的变量不要与内置对象重复,否则会造成不可控的数据错误。

    使用方法

    对象.方法(变量)

    • 获取账号余额

      Chain.getBalance('buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY');
      
    • 打印日志

      Utils.log('hello');
      
    • 当前区块号

      Chain.block.number;
      

    读写权限

    1. 对象里的每个函数都有固定的只读或者可写权限
    • 只读权限是指不会写数据到区块链的接口函数,比如获取余额 Chain.getBalance

    • 可写权限是指会写数据到区块链的接口函数,比如转账 Chain.payCoin

    1. 在编写智能合约的时候,需要注意的是不同的入口函数拥有不同的调用权限
    • init 和 main 能调用所有的内置函数

    • query 只能调用只读权限的函数,否则在调试或者执行过程中会提示接口未定义

    返回值

    所有内部函数的调用,如果失败则返回 false 或者直接抛出异常执行终止,成功则为其他对象。如果遇到参数错误,会在错误描述中提示参数位置出错,这里的位置指参数的索引号,即从 0 开始计数。例如 parameter 1 表示第 2 个参数错误。如下例子:

    Chain.issueAsset("CNY", 10000);
    /*
        错误描述:
        Contract execute error,issueAsset parameter 1 should be a string
    
        指第 2 个参数应该为字符串
    */
    

    Chain 对象方法

    本章节介绍 Chain 对象的一些方法,包括 Chain.load、 Chain.store、 Chain.del、 Chain.getBlockHash、 Chain.tlog、 Chain.getAccountMetadata、 Chain.getBalanceChain.getAccountAssetChain.getContractPropertyChain.payCoinChain.issueAssetChain.payAssetChain.delegateCallChain.delegateQueryChain.contractCallChain.contractQueryChain.contractCreate

    Chain.load

    • 函数描述

      获取合约账号的metadata信息。

    • 函数调用

    Chain.load(metadata_key);
    
    • 参数说明

      • metadata_key: metadata的关键字。
    • 示例

      let value = Chain.load('abc');
      /*
        权限:只读
        返回:成功返回字符串,如 'values', 失败返回false
      */
      

    Chain.store

    • 函数描述

      存储合约账号的metadata信息。

    • 函数调用

      Chain.store(metadata_key, metadata_value);
      
    • 参数说明

      • metadata_key: metadata 的关键字。
      • metadata_key: metadata 的内容。
    • 示例

      Chain.store('abc', 'values');
      /*
        权限:可写
        返回:成功返回true, 失败抛异常
      */
      

    Chain.del

    • 函数描述

      删除合约账号的metadata信息。

    • 函数调用

      Chain.del(metadata_key);
      
    • 参数说明

      • metadata_key: metadata 的关键字。
      • metadata_key: metadata 的内容。
    • 示例

      Chain.del('abc');
      /*
        权限:可写
        返回:成功返回true, 失败抛异常
      */
      

    Chain.getBlockHash

    • 函数描述

      获取区块信息。

    • 函数调用

      Chain.getBlockHash(offset_seq);
      
    • 参数说明

      • offset_seq: 距离最后一个区块的偏移量,范围:[0,1024)。
    • 示例

      let ledger = Chain.getBlockHash(4);
      /*
        权限:只读
        返回:成功返回字符串,如 'c2f6892eb934d56076a49f8b01aeb3f635df3d51aaed04ca521da3494451afb3',失败返回 false
      */
      

    Chain.tlog

    • 函数描述

      输出交易日志。

    • 函数调用

      Chain.tlog(topic,args...);
      
    • 参数说明

      • tlog会产生一笔交易写在区块上。
      • topic: 日志主题,必须为字符串类型,参数长度(0,128]。
      • args...: 最多可以包含5个参数,参数类型可以是字符串、数值或者布尔类型,每个参数长度(0,1024]。
    • 示例

      Chain.tlog('transfer',sender +' transfer 1000',true);
      /*
        权限:可写
        返回:成功返回 true,失败抛异常
      */
      

    Chain.getAccountMetadata

    • 函数描述

      获取指定账号的metadata

    • 函数调用

      Chain.getAccountMetadata(account_address, metadata_key);
      
    • 参数说明

      • account_address: 账号地址。
      • metadata_key: metadata 的关键字。
    • 示例

      let value = Chain.getAccountMetadata('buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY', 'abc');
      
      /*
        权限:只读
        返回:成功返回字符串,如 'values', 失败返回false
      */
      

    Chain.getBalance

    • 函数描述

      获取账号coin amount

    • 函数调用

      Chain.getBalance(address);
      
    • 参数说明

      • address: 账号地址
    • 示例

      let balance = Chain.getBalance('buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY');
      /*
        权限:只读
        返回:字符串格式数字 '9999111100000'
      */
      

    Chain.getAccountAsset

    • 函数描述

      获取某个账号的资产信息

    • 函数调用

      Chain.getAccountAsset(account_address, asset_key);
      
    • 参数说明

      • account_address: 账号地址。
      • asset_key: 资产属性。
    • 示例

      let asset_key =
      {
        'issuer' : 'buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY',
        'code' : 'CNY'
      };
      let bar = Chain.getAccountAsset('buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY', asset_key);
      
      /*
        权限:只读
        返回:成功返回资产数字如'10000',失败返回 false
      */
      

    Chain.getContractProperty

    • 函数描述

      获取合约账号属性

    • 函数调用

      Chain.getContractProperty(contract_address);
      
    • 参数说明

      • contract_address: 合约地址
    • 示例

      let value = Chain.getContractProperty('buQcFSxQP6RV9vnFagZ31SEGh55YMkakBSGW');
      
      /*
        权限:只读
        返回:成功返回JSON对象,如 {"type":0, "length" : 416},  type 指合约类型, length 指合约代码长度,如果该账户不是合约则,length 为0.
        失败返回false
      */
      

    Chain.payCoin

    • 函数描述

      转账

    • 函数调用

      Chain.payCoin(address, amount[, input]);
      
    • 参数说明

      • address: 发送BU的目标地址
      • amount: 发送BU的数量
      • input: 可选,合约参数,如果用户未填入,默认为空字符串
    • 示例

      Chain.payCoin("buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY", "10000", "{}");
      /*
        权限:可写
        返回:成功返回 true,失败抛异常  
      */
      

    Chain.issueAsset

    • 函数描述

      发行资产

    • 函数调用

      Chain.issueAsset(code, amount);
      
    • 参数说明

      • code: 资产代码
      • amount: 发行资产数量
    • 示例

      Chain.issueAsset("CNY", "10000");
      /*
        权限:可写
        返回:成功返回 true,失败抛异常  
      */
      

    Chain.payAsset

    • 函数描述

      转移资产

    • 函数调用

      Chain.payAsset(address, issuer, code, amount[, input]);
      
    • 参数说明

      • address: 转移资产的目标地址
      • issuer: 资产发行方
      • code: 资产代码
      • amount: 转移资产的数量
      • input: 可选,合约参数,如果用户未填入,默认为空字符串
    • 示例

      Chain.payAsset("buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY", "buQgmhhxLwhdUvcWijzxumUHaNqZtJpWvNsf", "CNY", "10000", "{}");
      /*
        权限:可写
        返回:成功返回 true,失败抛异常    
      */
      

    Chain.delegateCall

    • 函数描述

      委托调用

    • 函数调用

      Chain.delegateCall(contractAddress, input);
      
    • 参数说明

      • contractAddress: 被调用的合约地址。
      • input:调用参数。

      Chain.delegateCall 函数会触发被调用的合约main函数入口,并且把当前合约的执行环境赋予被调用的合约。

    • 示例

      let ret = Chain.delegateCall('buQBwe7LZYCYHfxiEGb1RE9XC9kN2qrGXWCY''{}');
      /*
        权限:可写
        返回:成功会返回结果,失败抛出异常
      */
      

    Chain.delegateQuery

    • 函数描述

      委托查询

    • 函数调用

      Chain.delegateQuery(contractAddress, input);
      
    • 参数说明

      • contractAddress: 被调用的合约地址。
      • input:调用参数。

      Chain.delegateQuery 函数会触发被调用的合约query函数入口,且把当前合约的执行环境赋予被调用的合约

    • 示例

      let ret = Chain.delegateQuery('buQBwe7LZYCYHfxiEGb1RE9XC9kN2qrGXWCY'"");
      /*
        权限:只读
        返回:如果目标账户为普通账户,则返回true,如果目标账户为合约,调用成功则返回字符串 {"result":"4"},其中 result 字段的值即查询的具体结果,调用失败返回 {"error":true} 字符串。
      */
      

    Chain.contractCall

    • 函数描述

      调用合约

    • 函数调用

      Chain.contractCall(contractAddress, asset, amount, input);
      
    • 参数说明

      • contractAddress: 被调用的合约地址。
      • asset : 资产类别,true代表BU,对象{"issue": buxxx, "code" : USDT} 代表资产。
      • amount: 资产数量。
      • input:调用参数。

      Chain.contractCall函数会触发被调用的合约 main 函数入口。

    • 示例

      let ret = Chain.contractCall('buQBwe7LZYCYHfxiEGb1RE9XC9kN2qrGXWCY'true, toBaseUnit("10"), "");
      /*
        权限:可写
        返回:如果目标账户为普通账户,则返回true,如果目标账户为合约,调用成功则返回main函数的返回值,调用失败则抛出异常
      */
      

    Chain.contractQuery

    • 函数描述

      查询合约

    • 函数调用

      Chain.contractQuery(contractAddress, input);
      
    • 参数说明

      • contractAddress: 被调用的合约地址。
      • input:调用参数。

      Chain.contractQuery 会调用合约的查询接口

    • 示例

      let ret = Chain.contractQuery('buQBwe7LZYCYHfxiEGb1RE9XC9kN2qrGXWCY'"");
      /*
        权限:只读
        返回:调用成功则返回字符串 {"result":"xxx"},其中 result 字段的值即查询的具体结果,调用失败返回 {"error":true} 字符串。
      */
      

    Chain.contractCreate

    • 函数描述

      创建合约

    • 函数调用

      Chain.contractCreate(balance, type, code, input);
      
    • 参数说明

      • balance: 字符串类型,转移给被创建的合约的资产。
      • type : 整型,0代表javascript。
      • code: 字符串类型, 合约代码。
      • input:init函数初始化参数。

      Chain.contractCreate 创建合约。

    • 示例

      let ret = Chain.contractCreate(toBaseUnit("10"), 0, "'use strict';function init(input){return input;} function main(input){return input;} function query(input){return input;} ", "");
      /*
        权限:可写
        返回:创建成功返回合约地址,失败则抛出异常
      */
      

     

    Chain 对象变量

    本章节介绍Chain对象的一些变量,分别区块信息(Chain.block)交易信息(Chain.tx)消息(Chain.msg)相关变量和Chain.thisAddress。区块信息的变量包括 Chain.block.timestampChain.block.number。交易信息的变量包括Chain.tx.initiator、 Chain.tx.senderChain.tx.gasPrice、 Chain.tx.hash、 chain.tx.feeLimit。消息的变量包括 Chain.msg.initiatorChain.msg.senderChain.msg.coinAmountChain.msg.assetChain.msg.nonceChain.msg.operationIndex

    区块信息(Chain.block)

    Chain.block.timestamp

    • 变量描述

      当前交易执行时候所在的区块时间戳。

    Chain.block.number

    • 变量描述

      当前交易执行时候所在的区块高度。

    交易(Chain.tx)

    交易是用户签名的那笔交易信息。

    Chain.tx.initiator

    • 变量描述

      交易最原始的发起者,即交易的费用付款者。

    Chain.tx.sender

    • 变量描述

      交易最原始的触发者,即交易里触发合约执行的操作的账户。 例如某账号发起了一笔交易,该交易中有个操作是调用合约Y(该操作的source_address是x),那么合约Y执行过程中,sender的值就是x账号的地址。

    • 示例

      let bar = Chain.tx.sender;
      /*
      那么bar的值是x的账号地址。
      */
      

    Chain.tx.gasPrice

    • 变量描述

      交易签名里的gas价格。

    Chain.tx.hash

    • 变量描述

      交易的hash值。

    Chain.tx.feeLimit

    • 变量描述

      交易的限制费用。

    消息(Chain.msg)

    消息是在交易里触发智能合约执行产生的信息。在触发的合约执行的过程中,交易信息不会被改变,消息会发生变化。例如在合约中调用 Chain.contractCallChain.contractQuery的时候,消息会变化。

    Chain.msg.initiator

    • 变量描述

      本消息的原始的发起者账号。

    Chain.msg.sender

    • 变量描述

      本次消息的触发者账号。

    • 示例

      例如某账号发起了一笔交易,该交易中有个操作是调用合约Y(该操作的source_address是x),那么合约Y执行过程中,sender的值就是x账号的地址。

      let bar = Chain.msg.sender;
      /*
      那么bar的值是x的账号地址。
      */
      

    Chain.msg.coinAmount

    • 变量描述

      本次支付操作的 BU coin

    Chain.msg.asset

    • 变量描述

      本次支付操作的资产

    • 示例

      {
          "amount": 1000, 
          "key" : {
              "issuer": "buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY", 
              "code":"CNY"
          }
      }
      

    Chain.msg.nonce

    • 变量描述

      本次交易里的发起者的nonce值,即Chain.msg.initiator账号的 nonce值。

    Chain.msg.operationIndex

    • 变量描述

      触发本次合约调用的操作的序号

    • 示例

      例如某账号A发起了一笔交易tx0,tx0中第0(从0开始计数)个操作是给某个合约账户转移资产(调用合约), 那么Chain.msg.operationIndex的值就是0。

      let bar = Chain.msg.operationIndex;
      /* bar 是一个非负整数*/
      

    Chain.thisAddress

    • 变量描述

      当前合约账号的地址

    • 示例

      例如账号x发起了一笔交易调用合约Y,本次执行过程中,该值就是Y合约账号的地址。

      let bar = Chain.msg.thisAddress;
      /*
      bar的值是Y合约的账号地址。
      */
      

    Utils 对象方法

    本章节介绍 Utils 对象的一些方法,包括 Utils.logUtils.stoI64CheckUtils.int64AddUtils.int64SubUtils.int64MulUtils.int64ModUtils.int64DivUtils.int64CompareUtils.assertUtils.sha256Utils.ecVerifyUtils.toBaseUnitUtils.addressCheckUtils.toAddress

    Utils.log

    • 函数描述

      输出日志。

    • 函数调用

      Utils.log(info);
      
    • 参数说明

      • info: 日志内容
    • 示例

      let ret = Utils.log('hello');
      /*
        权限:只读
        返回:成功无返回值,会在对应的合约执行进程里,输出一段Trace级别的日志,如 V8contract log[buQsZNDpqHJZ4g5hz47CqVMk5154w1bHKsHY:hello];失败返回 false。
      */
      

    Utils.stoI64Check

    • 函数描述

      字符串数字合法性检查。

    • 函数调用

      Utils.stoI64Check(strNumber);
      
    • 参数说明

      • strNumber:字符串数字参数
    • 示例

      let ret = Utils.stoI64Check('12345678912345');
      /*
        权限:只读
        返回:成功返回 true,失败返回 false
      */
      

    Utils.int64Add

    • 函数描述

      64位加法。

    • 函数调用

      Utils.int64Add(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Add('12345678912345', 1);
      /*
        权限:只读
        返回:成功返回字符串 '12345678912346', 失败抛异常
      */
      

    Utils.int64Sub

    • 函数描述

      64位减法。

    • 函数调用

      Utils.int64Sub(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Sub('12345678912345', 1);
      /*
        权限:只读
        返回:成功返回字符串 '12345678912344',失败抛异常
      */
      

    Utils.int64Mul

    • 函数描述

      64位乘法。

    • 函数调用

      Utils.int64Mul(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Mul('12345678912345', 2);
      /*
        权限:只读
        返回:成功返回字符串 '24691357824690',失败抛异常
      */
      

    Utils.int64Mod

    • 函数描述

      64位取模。

    • 函数调用

      Utils.int64Mod(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Mod('12345678912345', 2);
      /*
        权限:只读
        返回:成功返回字符串 '1',失败抛异常
      */
      

    Utils.int64Div

    • 函数描述

      64位除法。

    • 函数调用

      Utils.int64Div(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Div('12345678912345', 2);
      /*
        权限:只读
        返回:成功返回 '6172839456172',失败抛异常
      */
      

    Utils.int64Compare

    • 函数描述

      64位比较。

    • 函数调用

      Utils.int64Compare(left_value, right_value);
      
    • 参数说明

      • left_value: 左值。
      • right_value:右值。
    • 示例

      let ret = Utils.int64Compare('12345678912345', 2);
      /*
        权限:只读
        返回:成功返回数字 1(左值大于右值),失败抛异常
      */
      
    • 返回值

      1:左值大于右值,0:等于,-1 :小于

    Utils.assert

    • 函数描述

      64断言。

    • 函数调用

      Utils.assert(condition[, message]);
      
    • 参数说明

      • condition: 断言变量
      • message: 可选,失败时抛出异常的消息
    • 示例

      Utils.assert(1===1, "Not valid");
      /*
        权限:只读
        返回:成功返回 true,失败抛异常  
      */
      

    Utils.sha256

    • 函数描述

      sha256计算。

    • 函数调用

      Utils.sha256(data[, dataType]);
      
    • 参数说明

      • data: 待计算hash的原始数据,根据dataType不同,填不同格式的数据。
      • dataType:data 的数据类型,整数,可选字段,默认为0。0:base16编码后的字符串,如"61626364";1:普通原始字符串,如"abcd";2:base64编码后的字符串,如"YWJjZA=="。如果对二进制数据hash计算,建议使用base16或者base64编码。
    • 返回值

      成功会hash之后的base16编码后的字符串,失败会返回 false。

    • 示例

      let ret = Utils.sha256('61626364');
      /*
        权限:只读
        功能:对
        返回:成功返回64个字节的base16格式字符串 '88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589',失败返回false
      */
      

    Utils.ecVerify

    • 函数描述

      校验签名是否合法。

    • 函数调用

      Utils.ecVerify(signedData, publicKey,blobData [, blobDataType]);
      
    • 参数说明

      • signedData: 签名数据,base16编码的字符串。
      • publicKey:公钥,base16编码的字符串。
      • blobData:原始数据,根据blobDataType,填不同格式的数据。
      • blobDataType:blobData的数据类型,整数,可选字段,默认为0。0:base16编码后的字符串,如"61626364";1:普通原始字符串,如"abcd";2:base64编码后的字符串,如"YWJjZA=="。如果对二进制数据校验,建议使用base16或者base64编码。
    • 返回值

      成功会返回true,失败会返回 false

    • 示例

      let ret = Utils.ecVerify('3471aceac411975bb83a22d7a0f0499b4bfcb504e937d29bb11ea263b5f657badb40714850a1209a0940d1ccbcfc095c4b2d38a7160a824a6f9ba11f743ad80a', 'b0014e28b305b56ae3062b2cee32ea5b9f3eccd6d738262c656b56af14a3823b76c2a4adda3c', 'abcd', 1);
      /*
        权限:只读
        返回:成功会返回true,失败会返回 false
      */
      

    Utils.toBaseUnit

    • 函数描述

      变换单位。

    • 函数调用

      Utils.toBaseUnit(value);
      
    • 参数说明

      • value: 被转换的数字,只能传入字符串,可以包含小数点,且小数点之后最多保留 8 位数字
    • 返回值

      成功会返回乘以 10^8 的字符串,失败会返回 false

    • 示例

      let ret = Utils.toBaseUnit('12345678912');
      /*
        权限:只读
        返回:成功返回字符串 '1234567891200000000',失败抛异常
      */
      

    Utils.addressCheck

    • 函数描述

      地址合法性检查。

    • 函数调用

      Utils.addressCheck(address);
      
    • 参数说明

      • address 地址参数,字符串
    • 返回值

      成功返回 true,失败返回 false。

    • 示例

      let ret = Utils.addressCheck('buQgmhhxLwhdUvcWijzxumUHaNqZtJpWvNsf');
      /*
        权限:只读
        返回:成功返回 true,失败返回 false
      */
      

    Utils.toAddress

    • 函数描述

      公钥转地址。

    • 函数调用

      Utils.toAddress(public_key);
      
    • 参数说明

      • public_key 公钥,base16编码的字符串
    • 返回值

      成功,返回账号地址;失败返回false

    • 示例

      let ret = Utils.toAddress('b0016ebe6191f2eb73a4f62880b2874cae1191183f50e1b18b23fcf40b75b7cd5745d671d1c8');
      /*
        权限:只读
        返回:成功返回 "buQi6f36idrKiGrno3RcdjUjGAibUC37FJK6",失败返回false
      */
      

    异常处理

    • JavaScript异常

      当合约运行中出现未捕获的JavaScript异常时,处理规定:

      1. 本次合约执行失败,合约中做的所有交易都不会生效。
      2. 触发本次合约的这笔交易为失败。错误代码为151
    • 执行交易失败

      合约中可以执行多个交易,只要有一个交易失败,就会抛出异常,导致整个交易失败

  • 相关阅读:
    重启服务器后,托盘自启动
    【转】微服务(概念篇):什么是微服务?一篇文章让你彻底搞明白
    发送Http请求调用webService
    sqlserver查询数据库中有多少个表,多少视图,多少存储过程,或其他对象
    CDATA嵌套问题
    Mysql字符串字段判断是否包含某个字符串的3种方法[转载]
    处理jQuery选择器中的特殊符号,如(、#等
    js数组合并(一个数组添加到另一个数组里面)方法
    spring boot web项目在IDEA下热部署解决办法(四步搞定)
    javascript对数组分页
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13313249.html
Copyright © 2011-2022 走看看