精华内容
下载资源
问答
  • 智能合约开发

    2019-09-12 10:31:41
    本教程将介绍如何使用以太坊的solidity编程语言开发你的第一个智能合约,我们将使用remix在线IDE来开发、编译并部署智能合约到以太坊区块链。点击这里了解什么是智能合约开发语言和开发环境选择 目前智能合约最受...

    本教程将介绍如何使用以太坊的solidity编程语言开发你的第一个智能合约,我们将使用remix在线IDE来开发、编译并部署智能合约到以太坊区块链。点击这里了解什么是智能合约

    开发语言和开发环境选择

    目前智能合约最受欢迎的编程语言为Solidity,但是并不只有Solidity。作为初学者,编写Solidity代码,我们可以使用Remix,它是一个基于浏览器的Soldity IDE,网址为:http://remix.ethereum.org/ 。Remix支持编写、测试和部署智能合约。

    以太坊智能合约开发

    编写代码

    学一门语言的第一个程序毋庸置疑都是HelloWorld,那么我们就来写一个HelloWorld的智能合约吧。合约代码如下。

    pragma solidity ^0.4.21;
    
    contract HelloWorld {
        string hello = "Hello World!!!";
        event say(string _value);
        
        function sayHello() public {
            emit say(hello);
        }
        
    }
    

    合约代码第一行指定该合约使用的Solidity版本为0.4.21,不支持高于0.4.21版本的Solidity特性。

    在Solidity中,contract关键字包含的代码段即表示一个智能合约,它拥有一些成员变量,表示该合约的数据,如我们的HelloWorld中的hello,我们可以修改操作这些成员。同时它拥有一些function,可以被他人调用。

    event是Solidity提供的一种事件和订阅机制,智能合约能够发出一些event,合约调用者能够监听这些事件并作出相应的反应。

    这个合约没有做很多事情,它只会在有人调用它的sayHello方法时,发出一个say事件。接下来让我们来部署和执行它。

    部署和运行合约

    首先我们需要编译这段代码,在Remix的右边有一个Compile的tab,点击Start to compile,编译成功,如果失败会有错误提示,改正即可。

    以太坊智能合约开发

    然后我们需要将其部署到区块链上,切换tab到Run。

    Remix支持三种环境运行合约。其中如果为JavaScript VM,则合约会在浏览器JavaScript沙箱区块链中被执行,可以理解为Remix使用了浏览器的JS环境虚拟了一个区块链虚拟机。如果为Injected Provider,则Remix将会链接Matamask或者Mist这些区块链钱包,通过它们来间接部署和调用合约。最后为Web3 Provider,Remix会链接Geth等远程区款连节点,来部署和调用合约。

    简单起见,我们将使用JavaScript VM,它将为我们初始化出五个区块链账号,使用默认账号即可。将Environment设置为JavaScript VM。如下图:

    以太坊智能合约开发

    上图除了Environment和Account依次往下,我们将能够看到Gas Limit,这是执行一个Transaction我们能够接受的最大代价。Value表示下一次调用我们将向合约账户转账多少ether。

    接下来的HelloWorld表示我们将创建的合约。点击Create既能够创建这个合约。如下图我们看到HelloWorld合约已被创建。

    以太坊智能合约开发

    我们可以点击sayHello调用。可以看到已经调用成功,在logs中打印出了我们发出的event。

    以太坊智能合约开发

    结语

    在本文中,我们编写了一个最简单的智能合约,并部署和运行了该合约。我们并没有将合约部署到实际的区块链上,只是在JS 沙箱虚拟机中执行了它。后面的文章中我们将会继续讲解如何将合约部署到真正的以太坊区块链上。

    如果你希望马上开始学习以太坊智能合约及应用开发,可以访问汇智网提供的出色的在线互动教程:

    转载:https://juejin.im/post/5ab228f5518825555c1d8ab7

    转载于:https://my.oschina.net/u/3843525/blog/1800800

    展开全文
  • 智能合约开发基础

    2018-06-09 21:16:50
    智能合约开发基础,介绍了智能合约开发工具,以太坊智能合约开发语言solidity,智能合约ERC20,ERC721接口标准等。
  • BUMO 智能合约开发(新接口) 概述 BUMO 智能合约是一段JavaScript代码,标准(ECMAScript as specified in ECMA-262)。合约的初始化函数是init, 执行的入口函数是main函数,查询接口是query。这些函数的参数字符串...

    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
    • 执行交易失败

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

    展开全文
  • EOS智能合约开发详细教程,
  • 智能合约开发用solidity编程语言部署在以太坊这个区块链平台,本文提供一个官方实战示例快速入门,用例子深入浅出智能合约开发,体会以太坊构建去中心化可信交易技术魅力。智能合约其实是“执行合约条款的计算机交易...
  • EOS智能合约开发

    千次阅读 2018-12-16 00:23:30
    EOS智能合约开发需要使用llvm和abigen来生成abi文件, 为此eos提供了一个名为eosiocpp的工具。 在这篇文章中,我们介绍如何使用这个工具来开发、部署并调用一个EOS版本的hello world智能合约。 如果你希望马上学习...

    EOS智能合约开发需要使用llvmabigen来生成abi文件, 为此eos提供了一个名为eosiocpp的工具。 在这篇文章中,我们介绍如何使用这个工具来开发、部署并调用一个EOS版本的hello world智能合约。

    如果你希望马上学习EOS智能合约的开发,可以访问这个【EOS智能合约开发教程】,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发、部署与交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。

    智能合约撰写

    首先,编写一个ahello.cpp文件 - EOS的合约开发使用C++语言:

    # mkdir /home/centos/sc/ahello
    # cd /home/centos/sc/ahello
    # vim ahello.cpp
    

    将以下内容插入到ahello.cpp文件中:

    #include <eosiolib/eosio.hpp>
    
    #include <eosiolib/print.hpp>
    using namespace eosio;
    
    class hello : public eosio::contract {
      public:
          using contract::contract;
    
    /// @abi action 
          void hi( account_name user ) {
             print( "Hello, World", name{user} );
          }
    };
    
    EOSIO_ABI( hello, (hi) )
    

    接下来,编译并创建一个wast(web程序集)文件和一个abi文件。

    # eosiocpp -o ahello.wast ahello.cpp
    
    # eosiocpp -g ahello.abi ahello.cpp
    

    智能合约的部署与交互

    在部署合约之前,我们需要创建测试用的钱包、密钥和帐户。

    首先,使用EOS客户端cleos创建一个名为scuser钱包,EOS使用钱包管理密钥:

    # cleos wallet create -n scuser
    
    Creating wallet: scuser
    Save password to use in the future to unlock this wallet.
    Without password imported keys will not be retrievable.
    "PW5JzRwAUN-----------------------------nAuCRWvHx4XnMPmGf9Kz "
    

    接下来同样使用cleos创建一个密钥对:

    # cleos create key
    
    Private key: 5KZzUHNFNvf------------------------------vuF5z7d29uAUbsdn
    Public key: EOS63ndkvF-----------------------9ZVcByP9nfZcwMLzbMpn
    

    然后将密钥保存在之前创建的钱包scuser中:

    # cleos wallet import -n scuser 5KZzUHNFNvf---------------------d29uAUbsdn
    

    还需要创建一个额外的账户进行测试:

    # cleos create key
    
    Private key: 5JbriTGYsnrpNDvL------------------LgniHVgyTnS5ommxo
    Public key: EOS8XZoG2248Gu42-------------ps7JoW8tdHQwCsV
    

    然后使用wallet子命令把这第二个密钥也存入钱包:

    # cleos wallet import -n scuser 5JbriTGYsnrpND----------HVgyTnS5ommxo
    

    接下来,使用create account子命令创建一个账户eosio —— 你需要使用账户与EOS区块链交互:

    #./cleos create account eosio scuser EOS63ndkvF---------cByP9nfZcwMLzbMpn EOS8XZo-------wJnieps7JoW8tdHQwCsV
    

    现在使用set contract子命令部署智能合约:

    # cleos set contract scuser /home/centos/sc/ahello
    
    Reading WAST/WASM from /home/centos/sc/ahello/ahello.wasm...
    Using already assembled WASM...
    Publishing contract...
    executed transaction: 053a4883d9c191c2754656544dd045da17bd869250af13a00284a613eed3d23b  1792 bytes  601 us
    #         eosio <= eosio::setcode               {"account":"scuser","vmtype":0,"vmversion":0,"code":"0061736d01000000013b0c60027f7e006000017e60027e7...
    #         eosio <= eosio::setabi                {"account":"scuser","abi":{"types":[],"structs":[{"name":"hi","base":"","fields":[{"name":"user","ty...
    warning: transaction executed locally, but may not be confirmed by the network yet
    

    合约部署成功后,使用push action子命令来执行合约方法hi

    # cleos push action scuser hi '["user1"]' -p scuser
    
    executed transaction: 9ed2894aef0f476687ad893ed16594588cc7a813c524d4b8497ba9f50793b151  104 bytes  330 us
    #        scuser <= scuser::hi                   {"user":"user1"}
    
    >> Hello, World user1
    warning: transaction executed locally, but may not be confirmed by the network yet
    

    你应该可以看到类似下图的结果:

    eos hello world

    代码分析

    以上示例代码是EOS智能合约的基本模板。 我们现在将逐步分析上面编写的代码。

    #include <eosiolib/eosio.hpp>
    #include <eosiolib/print.hpp>
    

    上述代码引入eos智能合约的头文件。

    using namespace eosio;
    

    上述代码使用eosio作为默认命名空间,因此在后续代码中可以直接使用诸如
    account_name之类的数据类型。

    class hello:public eosio :: contract { 
    

    创建一个hello类,继承自eosio预置的contract。

    public:
    using contract::contract;
    
    /// @abi action
    

    这显示了指定操作时在区块链中实际执行的功能。

          void hi( account_name user ) {
             print( "Hello, World", name{user} );
          }
    };
    
    EOSIO_ABI( hello, (hi) )
    

    EOSIO_ABI是一个包含以前版本中的apply()函数的宏。

    在这篇文章中,我们介绍了如何编写一个EOS版本的Hellow World智能合约,希望有助于你初步了解EOS智能合约的开发。

    原文链接:开发第一个EOS智能合约

    展开全文
  • 以太坊智能合约开发项目实战-投票系统。大神在课程中手把手地教大家如何构建一个基于以太坊的完整去中心化应用 —— 区块链投票系统。使用remix进行合约的开发与测试。迅速掌握智能合约的编写与运用。
  • 本文主要介绍在Ubuntu系统上搭建以太坊开发环境的过程,以及简单的智能合约开发
  • 本教程主要解决两个问题:第一,细节丰富便于复现的极简智能合约开发流程,部署到公网以太坊测试网络并运行,熟悉这个流程,可以原封不动地切换到以太坊主网上进行开发;第二,安全原则,确保在以太坊上的各种操作...
  • Truffle 智能合约开发

    2018-07-27 11:43:07
    智能合约 开发工具 下载Atom CTRL+,打开配置管理 安装插件 linter-solium autocomplete-solidity...Truffle 智能合约开发 安装 $ npm install -g ethereumjs-testrpc truffle 启动 $ testrpc Ethe...

    智能合约

    开发工具

    • 下载Atom

      • CTRL+,打开配置管理
      • 安装插件 linter-solium autocomplete-solidity linter-solidity
    • 在线工具Remix

    image

    Truffle 智能合约开发

    安装

    $ npm install -g ethereumjs-testrpc truffle
    

    启动

    $ testrpc
    EthereumJS TestRPC v6.0.3 (ganache-core: 2.0.2)
    
    Available Accounts
    ==================
    (0) 0x4927ee940390ea04396cdf45f8738efe34bc8cda
    (1) 0x620f6185921c5098484fff59de44660408949da0
    (2) 0x0948dc8f299e11947763ac5261fbec839bbe71fd
    (3) 0xfbc433617f8eaba563adf82741d0b1083c787e31
    (4) 0x33c095e2e0fdcf75d7657132f557ca68426e6e11
    (5) 0x3596f5f81ac005c2ab6f4c0656bd2a0f4580af6a
    (6) 0x98fb51da126450a6df0238addc4c3afc90c6e72d
    (7) 0xe3c6e8378165725dc40539eb062b177daf48f843
    (8) 0xfa28789a1f301d0b8d13e38d150ca84c05e834f9
    (9) 0x43c86685df60442e0c4763c41fc1c2aa42e31437
    
    Private Keys
    ==================
    (0) 13e84c6f2264596a555ecf50c075cad011f70ded50dd751e9fea8586e8c36316
    (1) be172cbc48294823ab38d263b6d846599a3c70269595e3ff9595f1463a3292fd
    (2) a8b1010b89669e654bfe3d00373410290f6eec85bf81ef915c870fd2be35aa43
    (3) 5aebf98da3414310ec1cc16327f5d073e0117e0b2018e64640d5c7c25996a6f0
    (4) 5e6482bc2c1811fc113fc45979f2300807d1708a0e4f2a003bf6e0c20439b987
    (5) 040311fcee969480e217b77d4d49ea0afe2e2c6a32a457e05dad34c54d090cc0
    (6) b7cffb5c534a3021fc4155b81e5b45139a5b4885c04e96213c4ad797a202af6c
    (7) 92db051b72d1901cdf386daa35f54ad9ae762f471133d4d0682d903b0af9d60d
    (8) 0d54ef7d404b6b876237638bb422028be2113a171e3d4630965b34fab5e8acfc
    (9) 7252563b853e3b3bf6c5d9cf819d8fb035b90a7769f86e2629d7dbd5ea0f8775
    
    HD Wallet
    ==================
    Mnemonic:      home survey unfair twenty tumble shaft verb income cigar harvest warm flash
    Base HD Path:  m/44'/60'/0'/0/{account_index}
    
    Listening on localhost:8545
    
    

    初始化工程

    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle
    $ mkdir HelloWorld
    
    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle
    $ cd HelloWorld/
    
    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle/HelloWorld
    $ truffle init
    Downloading...
    Unpacking...
    Setting up...
    Unbox successful. Sweet!
    
    Commands:
    
      Compile:        truffle compile
      Migrate:        truffle migrate
      Test contracts: truffle test
      
    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle/HelloWorld
    $ ll
    total 2
    drwxr-xr-x 1 wangxinguo 1049089   0 七月  5 16:11 build/
    drwxr-xr-x 1 wangxinguo 1049089   0 七月  5 16:06 contracts/
    drwxr-xr-x 1 wangxinguo 1049089   0 七月  5 16:36 migrations/
    drwxr-xr-x 1 wangxinguo 1049089   0 七月  5 16:01 test/
    -rw-r--r-- 1 wangxinguo 1049089 584 七月  5 16:21 truffle.js
    -rw-r--r-- 1 wangxinguo 1049089 545 七月  5 16:01 truffle-config.js
      
    

    image

    编写合约

    HelloWorld.sol

    pragma solidity ^0.4.4;
    
    contract HelloWorld {
    
      function sayHello() returns (string) {
        return "Hello world";
      }
    }
    

    编译

    生成build文件

    $ truffle compile
    

    部署合约

    修改migrations\2_deploy_contracts.js

    var HelloWorld = artifacts.require("HelloWorld");
    
    module.exports = function(deployer) {
      deployer.deploy(HelloWorld);
    };
    
    

    部署

    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle/HelloWorld
    $ truffle migrate
    Error: No network specified. Cannot determine current network.
    
    wangxinguo@EF-WANGXINGUO MINGW64 /d/DApp/truffle/HelloWorld
    $ truffle migrate
    Using network 'development'.
    
    Running migration: 1_initial_migration.js
      Deploying Migrations...
      ... 0xad0e3a65ff378250602d006be234a5f77ef649cdf62d71bacde32f71b15b7531
      Migrations: 0xf848fb353a350a2e2c4580c64b3b476938d3a985
    Saving successful migration to network...
      ... 0x49f3fab0213571cd7cab493b25f749693ef4d072be305f7f897b0a698e85e6cf
    Saving artifacts...
    Running migration: 2_deploy_contracts.js
      Deploying HelloWorld...
      ... 0x45cafe53dd0012cf62f976d37790623090cfb2fc29a186ea76641a3e5e745250
      HelloWorld: 0x1c2cfd8c56972d7c551d6bd495a03824c2589194
    Saving successful migration to network...
      ... 0xf0914d6cae838858c02bf1c6368ca083d5500fbfcb7b5f1cb10f9eb891945b36
    Saving artifacts...
    
    
    

    部署失败,需要修改文件truffle.js

    module.exports = {
        networks: {
            development: {
                host: "localhost",
                port: 8545,
                network_id: "*" // 匹配任何network id
             }
        }
    };
    

    获取合约对象

    $ truffle console
    truffle(development)> let contract
    undefined
    truffle(development)> HelloWorld.deployed().then(instance => contract = instance)
    TruffleContract {
      constructor:
       { [Function: TruffleContract]
         _static_methods:
          { setProvider: [Function: setProvider],
            new: [Function: new],
            at: [Function: at],
            deployed: [Function: deployed],
            defaults: [Function: defaults],
            hasNetwork: [Function: hasNetwork],
            isDeployed: [Function: isDeployed],
            detectNetwork: [Function: detectNetwork],
            setNetwork: [Function: setNetwork],
            resetAddress: [Function: resetAddress],
            link: [Function: link],
            clone: [Function: clone],
            addProp: [Function: addProp],
            toJSON: [Function: toJSON] },
         _properties:
          { contract_name: [Object],
            contractName: [Object],
            abi: [Object],
            network: [Function: network],
            networks: [Function: networks],
            address: [Object],
            transactionHash: [Object],
            links: [Function: links],
            events: [Function: events],
            binary: [Function: binary],
            deployedBinary: [Function: deployedBinary],
            unlinked_binary: [Object],
            bytecode: [Object],
            deployedBytecode: [Object],
            sourceMap: [Object],
            deployedSourceMap: [Object],
            source: [Object],
            sourcePath: [Object],
            legacyAST: [Object],
            ast: [Object],
            compiler: [Object],
            schema_version: [Function: schema_version],
            schemaVersion: [Function: schemaVersion],
            updated_at: [Function: updated_at],
            updatedAt: [Function: updatedAt] },
         _property_values: {},
         _json:
          { contractName: 'HelloWorld',
            abi: [Array],
            bytecode: '0x608060405234801561001057600080fd5b5061013f806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60606040805190810160405280600b81526020017f48656c6c6f20776f726c640000000000000000000000000000000000000000008152509050905600a165627a7a72305820d540aaa7d3d21783829ff5aef0e77b259d6341917f26fec070513a1f3a5a6e140029',
            deployedBytecode: '0x608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063ef5fb05b14610046575b600080fd5b34801561005257600080fd5b5061005b6100d6565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561009b578082015181840152602081019050610080565b50505050905090810190601f1680156100c85780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b60606040805190810160405280600b81526020017f48656c6c6f20776f726c640000000000000000000000000000000000000000008152509050905600a165627a7a72305820d540aaa7d3d21783829ff5aef0e77b259d6341917f26fec070513a1f3a5a6e140029',
            sourceMap: '27:100:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27:100:0;;;;;;;',
            deployedSourceMap: '27:100:0:-;;;;;;;;;;;;;;;;;;;;;;;;54:70;;8:9:-1;5:2;;;30:1;27;20:12;5:2;54:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;99:1;94:3;90:11;84:18;80:1;75:3;71:11;64:39;52:2;49:1;45:10;40:15;;8:100;;;12:14;54:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;83:6;98:20;;;;;;;;;;;;;;;;;;;;54:70;:::o',
            source: 'pragma solidity ^0.4.4;\r\n\r\ncontract HelloWorld {\r\n\r\n  function sayHello() returns (string) {\r\n    return "Hello world";\r\n  }\r\n}\r\n',
            sourcePath: 'D:\\DApp\\truffle\\HelloWorld\\contracts\\HelloWorld.sol',
            ast: [Object],
            legacyAST: [Object],
            compiler: [Object],
            networks: [Object],
            schemaVersion: '2.0.1',
            updatedAt: '2018-07-05T08:39:07.157Z' },
         setProvider: [Function: bound setProvider],
         new: [Function: bound new],
         at: [Function: bound at],
         deployed: [Function: bound deployed],
         defaults: [Function: bound defaults],
         hasNetwork: [Function: bound hasNetwork],
         isDeployed: [Function: bound isDeployed],
         detectNetwork: [Function: bound detectNetwork],
         setNetwork: [Function: bound setNetwork],
         resetAddress: [Function: bound resetAddress],
         link: [Function: bound link],
         clone: [Function: bound clone],
         addProp: [Function: bound addProp],
         toJSON: [Function: bound toJSON],
         web3:
          Web3 {
            _requestManager: [Object],
            currentProvider: [Object],
            eth: [Object],
            db: [Object],
            shh: [Object],
            net: [Object],
            personal: [Object],
            bzz: [Object],
            settings: [Object],
            version: [Object],
            providers: [Object],
            _extend: [Object] },
         class_defaults:
          { from: '0x4927ee940390ea04396cdf45f8738efe34bc8cda',
            gas: 6721975,
            gasPrice: 100000000000 },
         currentProvider:
          HttpProvider {
            host: 'http://localhost:8545',
            timeout: 0,
            user: undefined,
            password: undefined,
            headers: undefined,
            send: [Function],
            sendAsync: [Function],
            _alreadyWrapped: true },
         network_id: '1530777346103' },
      abi:
       [ { constant: false,
           inputs: [],
           name: 'sayHello',
           outputs: [Array],
           payable: false,
           stateMutability: 'nonpayable',
           type: 'function' } ],
      contract:
       Contract {
         _eth:
          Eth {
            _requestManager: [Object],
            getBalance: [Object],
            getStorageAt: [Object],
            getCode: [Object],
            getBlock: [Object],
            getUncle: [Object],
            getCompilers: [Object],
            getBlockTransactionCount: [Object],
            getBlockUncleCount: [Object],
            getTransaction: [Object],
            getTransactionFromBlock: [Object],
            getTransactionReceipt: [Object],
            getTransactionCount: [Object],
            call: [Object],
            estimateGas: [Object],
            sendRawTransaction: [Object],
            signTransaction: [Object],
            sendTransaction: [Object],
            sign: [Object],
            compile: [Object],
            submitWork: [Object],
            getWork: [Object],
            coinbase: [Getter],
            getCoinbase: [Object],
            mining: [Getter],
            getMining: [Object],
            hashrate: [Getter],
            getHashrate: [Object],
            syncing: [Getter],
            getSyncing: [Object],
            gasPrice: [Getter],
            getGasPrice: [Object],
            accounts: [Getter],
            getAccounts: [Object],
            blockNumber: [Getter],
            getBlockNumber: [Object],
            protocolVersion: [Getter],
            getProtocolVersion: [Object],
            iban: [Object],
            sendIBANTransaction: [Function: bound transfer] },
         transactionHash: null,
         address: '0x1c2cfd8c56972d7c551d6bd495a03824c2589194',
         abi: [ [Object] ],
         sayHello:
          { [Function: bound ]
            request: [Function: bound ],
            call: [Function: bound ],
            sendTransaction: [Function: bound ],
            estimateGas: [Function: bound ],
            getData: [Function: bound ],
            '': [Circular] },
         allEvents: [Function: bound ] },
      sayHello:
       { [Function]
         call: [Function],
         sendTransaction: [Function],
         request: [Function: bound ],
         estimateGas: [Function] },
      sendTransaction: [Function],
      send: [Function],
      allEvents: [Function: bound ],
      address: '0x1c2cfd8c56972d7c551d6bd495a03824c2589194',
      transactionHash: null }
    
    

    调用合约

    call只是本地调用,只读

    truffle(development)> contract.sayHello.call()
    'Hello world'
    

    需要花费gas

    truffle(development)> contract.sayHello()
    { tx: '0xbcdd3d18e262b4c5703b15ba6695280e87c29150995ae9dcbe36b257065e0f22',
      receipt:
       { transactionHash: '0xbcdd3d18e262b4c5703b15ba6695280e87c29150995ae9dcbe36b257065e0f22',
         transactionIndex: 0,
         blockHash: '0xaa7fbd9c93dfa295e295e01e6d1cd8359a7a004ad13d65459848fea2c1f785fa',
         blockNumber: 7,
         gasUsed: 21877,
         cumulativeGasUsed: 21877,
         contractAddress: null,
         logs: [],
         status: 1 },
      logs: [] }
    
    

    修改合约

    增加方法 echo

    // constant 方法只读,默认执行call方法,不需要花费gas
      function echo(string name) constant returns (string) {
        return name;
      }
    

    重新编译、部署、运行

    $ truffle compile
    
    $ truffle migrate --reset
    
    truffle(development)> contract.echo("区块链")
    '区块链'
    

    直接启动

    $ truffle develop
    
    // 编译
    truffle(develop)> complile
    
    // 部署
    truffle(develop)> migrate
    Using network 'develop'.
    
    // 运行
    truffle(development)> let contract
    undefined
    truffle(development)> HelloWorld.deployed().then(instance => contract = instance)
    
    // 调用
    truffle(development)> contract.sayHello.call()
    'Hello world'
    
    展开全文
  • 因为每个节点每次都需要大量计算,所以从Ethereum智能合约开发中进行频繁的网络请求是切不实际的。这样,智能合约就可以与链外的世界进行互动了。 但是这样有一个明显的信任问题。与信任单一外部数据源的分布式智能...
  • 智能合约开发(3) 安装Mix 集成开发环境 首先确认安装这三个软件: node nvm npm 其实现在来看,以太坊离不开这三个软件,个人认为这就已经反应了以太坊智能合约的开发核心,其实就是开发一个逻辑上的软件程序,...
  • 开发者通过智能合约去制定一套规则,然后发布到线上,人与智能合约进行交互,由机器去完成业务的部分,这样就规避了由人来做执行时可能造成的作弊行为。   静态类型的编程语言——Solidity,是以太坊的智能...
  • 智能合约开发环境搭建及 Hello World 合约 如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇。 就先学习任何编程语言一样,入门的第一个程序都是 Hello World。今天我们...
  • 派智能合约样板 智能合约开发的样板
  • 如果你对于以太坊智能合约开发还没有概念(本文会假设你已经知道这些概念),建议先阅读入门篇。 就先学习任何编程语言一样,入门的第一个程序都是Hello World。今天我们来一步一步从搭建以太坊智能合约开发环境...
  • 今天我们来一步一步从搭建以太坊智能合约开发环境开始,讲解智能合约的Hello World如何编写。 开发环境搭建 Solidity安装 强烈建议新手使用Browser-Solidity来进行开发。 Browser-Solidity是一...
  • 篇 Solidity与智能合约开发 ·第9章 Solidity初遇·第10章 Solidity数据类型·第11章 Solidity数据类型进阶·第12章 Solidity开发智能合约·第13章 Solidity开发智能合约进阶·第14章 通过web3.js与以太坊...
  • 章 智能合约开发常用工具 在介绍新的内容之前,我们先了解一些智能合约开发的常用工具,这些工具将会在以太坊智能合约开发过程中用到。 本章介绍的主要工具有: ·Git;·Nodejs;·NPM;·webpack;·Postman;·...
  • ethereum 智能合约开发

    千次阅读 2018-02-09 11:35:40
    以太坊智能合约开发有许多的概念,对于初次接触到的开发者有很多的疑惑,经过自己的总结,对以太坊智能合约相关概念有一个总结,写了一个测试的js脚步,使用remix 作为solidity开发工具,需要自己安装,作为备忘。...
  • 智能合约开发是以太坊编程的核心之一,而代币是区块链应用的关键环节,下面我们来用solidity语言开发一个代币合约的实例,希望对大家有帮助。 以太坊的应用被称为去中心化应用(DApp),DApp的开发主要包括两大部分...
  • 智能合约开发(2)基本操作 创建用户 geth account new 我们多创建几个账号,如下: 我们打开一个账户文件看看里边的内容: 包括内容如下: address 公钥地址 crypto 密码 aes-128 密码 私钥密码并没有,私钥为...
  • Nebulas实现了NVM虚拟机来运行智能合约,NVM的实现使用了JavaScript V8引擎,所以当前的开发版,我们可以使用JavaScript、TypeScript来编写智能合约。 编写智能合约的简要规范 智能合约代码必须是一个Prototype的...
  • 原文发表于:以太坊智能合约开发第七篇:智能合约与网页交互 上一篇中,我们通过truffle开发框架快速编译部署了合约。本篇,我们将来介绍网页如何与智能合约进行交互。 编写网页 首先我们需要编写一个网页。打开 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,464
精华内容 2,185
关键字:

智能合约开发