最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 过渡到Web3 - 02 智能合约

    正文概述 掘金(众成翻译)   2021-02-03   615

    译者:海洋饼干

    原文链接


    从web2转向web3 值得开发者信赖的教程 第二期

    ?

    欢迎回到这个系列博客,该博客旨在帮助web开发者以尽可能简单的方法基于Ethereum(以太坊)构建分布式应用和智能合约。

    本系列的第一篇博客为-过渡到Web3 - 01 分布式开发介绍.第二篇(也就是本篇)会讨论如何编写Ethereum(以太坊)智能合约,并附上了一个示例项目。


    什么是智能合约?

    正如第一篇博客提到的:

    **合约**是“双方或多方间的自愿约定”([Wikipedia][10])。

    **智能合约**是""一种推动谈判,校验谈判,或强制谈判,抑或执行合约的计算机协议""([Wikipedia][11])。

    作为90年代的密码员,[Nick Szabo第一个提出了智能合约的概念][12],这个概念在许多以加密货币为基础的项目中都有抢眼表现,其中最引人注目的就是Ethereum(以太坊)。

    现在可以给出基于Ethereum背景的定义:智能合约可被用于程序化和自动化执行合约。智能合约的意义在于取消了集中式中介,因此在分布式软件中可以发挥作用。

    搭建

    直接下载示例项目:

    git clone https://github.com/lukehedger/todoeth.git
    
    cd todoeth
    
    git checkout issue#2-smart-contracts
    

    我们将会看到**一个加密经济诱因的Todo List** — 它叫Todoeth。之后的两篇博客,我们会开始构建一个Todo List app,它通过扣掉用户的钱来推动大家完成自己的Todo List!

    过渡到Web3 - 02 智能合约

    线框圈出的就是Todoeth。图标由[Hea Poh Lin][13]提供。

    安装项目依赖需执行以下命令,接下来我们正式开始:

    npm install
    

    设计

    每个健壮的程序都以清晰完整的结构设计开始,这对编写智能合约尤其关键。鉴于部署到Ethereum区块链的合约不可改变,所有可能的情况必须考虑到。

    在client-server式的web应用中,如果出现了一个bug,我们可以简单地给生产服务器打个补丁,这样我们网站的所有未来浏览者都会访问修补后的版本。考虑到Ethereum中数据具有永久性,可验证性以及防篡改性,很明显合约不能用这种方式简单升级 — 否则,所有记录都会丢失!

    设计一个可更新的合约系统关键要**将存储合约与代理合约分离**(接下来会详细介绍)。

    我们的分布式Todo app需要三个合约:

    • 一个用来存储每个用户以及用户Todo的初级合约
    • 一个追踪Todo存款的二级合约
    • 一个促进web应用交互的代理合约

    编写

    让我们以经典的“Hello,World”作为开始,当然,这里的实现是只对函数调用者说hello: )

    pragma solidity ^0.4.18;
    
    // import './SomeContract.sol';
    
    contract HelloYou {
    
      event Hello(address you);
    
      
    
      function sayHello() public {
    
        address _person = msg.sender;
    
        
    
        Hello(_person);
    
      }
    
    }
    

    合约顶端的**pragma**是一个[指令][16],用于告知Solidty编译器我们使用了哪个版本。

    这个合约没有任何输入,如果有的话,我们会在pragma下面用相关的文件路径来定义输入。

    接下来是**合约声明**。为了声明一个合约,要为合约名称使用contract关键字 — 例子中,合约名称是'Hello You'。

    合约包括一个**eventfunction**。事件用event关键字和一个函数签名(事件名称以及被括号括起来的类型参数)简单地声明。上例中事件名是‘Hello’,该事件接受一个类型为'address'的参数‘you’(address是Solidty中用来描述一个Ethereum公共地址的特殊类型)。

    sayHello函数使用了Solidty中的一个[全局命名空间的变量][17]msg.sender。这个值以及其他有用的值可被任何合约方法访问。因此,我们把这个值存入_person变量(不需使用var关键字,只需一个类型,变量名称和=),并把变量传递给Hello事件,它就可以触发EVM上的事件。

    这样我们就通过一个智能合约对某个人说了hello。这个函数可以被调用,并且在web应用中这个事件可以被监听,下一篇文章中还会讲到!正如早先的Ethereum谚语所说:""如果没人在听,EVM上的事件还会发出声音吗?""

    模式

    就像之前提到的,我们必须用一种**允许代码更新并且数据不会因此损失**的方式构建我们的合约。实现方法是将包含永久状态(任何时候数据都存储在合约中)的代码与代理分离,而流入这些合约的数据都源自外部,比如web应用。这个存储合约可以保持很轻量的状态,并为一个不需要更新的操作提供服务。我们会在后面详细介绍存储合约。

    过渡到Web3 - 02 智能合约

    添加一个新的Todo产生的数据流

    **Todo.sol**

    ToDo合约是我们对应存储合约的‘代理’,它也是唯一一个与我们的web app关联的合约。它不会保存任何数据。这样**所有操作都与这个合约关联**,并且任何更新都不会造成数据损失。

    来看以下三种方法:

    • addTodo(todold) 把todo ID和msg.sender作为用户ID传递给ToDoStorage合约,并且把msg.value(一些token值)作为存款账户传递给ToDoBank
    • addToDo(index)TodoStorage合约中通过用户Todo数组获得一个Todo
    • getTodoCount() 获得一个用户存储的Todo数目

    从存储中检索一个Todo被分为两步的原因是Solidty会限制返回动态长度的值,比如数组。因此,我们第一步要得到Todo数组的长度,接下来利用索引逐一获取Todo。但不必担心,这个限制在下一个版本0.5.0中会被移除。

    存储

    基于Ethereum区块链智能合约可以被用来存储不可变更的,可验证的数据。这是一个很棒的工具,可以应用于许多有趣的领域例如数字交易和协议。

    在Todo示例中,我们会存储一个对应每个任务的永久引用!我们也会存储一些对应每个Todo的Ether(Ethereum的原生token)。

    **TodoStorage.sol**

    The TodoStorage contract simply contains methods for getting and setting todos. Metadata about the todo will be stored on Swarm and, so, the only data we actually store in the contract will be the Swarm reference to this metadata (an address of where to find the data in the Swarm network). TodoStorage 合约简单包括了获取和设置Todo的方法。关于Todo的元数据会存储在Swarm,因此我们实际存储于合约中的数据会是对应元数据的Swarm引用(即在Swarm网络中数据对应的地址)。

    这些引用,我们会作为todoId存储在一个数组中,并且会在TodoStore对象中用userId锁上(Todo所有者的Ethereum地址)。

    其数据结构如下:

    TodoStore: {
    
      userId: [
    
        todoId
    
      ]
    
    }
    

    **TodoBank.sol**

    存储使用的另一个合约是TodoBank。我们在这里存储对应每个Todo的Ether存款 - 这些存款在这里会被一直加密直到正常取消。当然,这个合约值包含获得和设置存款的方法。

    数据结构如下:

    TodoVault: {
    
      todoId: deposit
    
    }
    

    这已经不在示例的作用域之内,但你可以了解到激励机制是如何融入这个系统中的。例如,如果一个待办事项在特定时间被完成,钱就会退回所有者的地址,如果错过了截止日期,钱会被发送到另外一个对应用户未完成待办事项的地址。

    因此,你必须完成Todo,否则就会失去你的钱。下篇文章会继续这方面的内容。

    安全

    当软件涉及个人数据和资金时安全就变得至关重要。鉴于智能合约的固有经济生态,以及编写合约所用的语言刚问世不久,他们的安全性极为重要 — 在设计和编写一个合约时必须建立安全机制。

    当测试Solidty时,有必要警惕一些可能面对的针对合约的攻击。当你需要研究安全时,[Ethereum智能合约安全最佳实践][20]教程是个很棒的选择。

    检查

    你可以使用 [solium][21]检查你的合约,它是一个和ESLint类似的小工具。

    在示例项目中检查合约需要运行以下命令:

    npm run lint
    

    文档

    Solidty合约能以[Ethereum默认指定的格式]22使用注释作为文档,和JSDoc相似。

    /*
    
     * @notice TodoAdded event
    
     * @param {bytes32} todoId
    
     */
    
    event TodoAdded(bytes32 todoId);
    

    编译

    合约需要被Solidty编译器编译为可以被EVM读取的字节码

    可以直接通过一个名为[solc-js][25]的JavaScript工具来使用Solidty编译器,该工具已经被Ethereum Foundation开发者使用。

    编译器获得合约名称对象以及合约的字符化内容, [返回编译后的字节码][26] 和 [一个接入合约代码的接口,叫做ABI]27。

    我发觉这个过程可以简化,办法是对重复任务进行抽象(解析合约输入,将输出写入硬盘),集成为一个库,利用配置文件控制输入、输出。这个工具叫[Sulk][28] ?!

    Sulk的配置文件很简洁,下面是配置文件的最简形式:

    module.exports = {
    
      contracts: [
    
        'Todo',
    
      ],
    
      inputPath: './path/to/contracts',
    
    }
    

    此外还需在项目中编写一个[contracts.json][29]文件,该文件包含了字节码和ABI,当‘应部署’你的合约时它就会派上用场。

    编译项目示例中的合约需要运行以下命令:

    npm run compile
    

    应用

    要想公开你的合约以及合约方法,你需要将合约部署到Ethereum区块链。这和部署一项微服务到服务器类似,Ethereum同样拥有生产,开发,以及本地网络的概念。生产网络 - 当然,只有一个生产网络-通常被视为‘主网络’;而开发网络-每个开发网络拥有不同的性质和能力-它们被称为‘测试网络’。

    要开始与你合约的互动,最简单的方式就是将它部署到一个本地Ethereum网络。[**ganache-cli**][30](之前与testrpc齐名)是一个基于Node.js的“为Ethereum开发而生的个人区块链”,它简化了部署过程。

    在项目示例中你可以运行以下命令,它会运行一个本地二进制安装的ganache-cli,且不需任何参数(没有比这更棒的了不是吗)

    npm run 
    

    一旦ganache开始运行,你就可以使用包含在项目示例中的部署脚本将合约部署到本地Ethereum节点:

    npm run deploy
    

    [部署脚本][31]使用了[Web3.js][32]库来与Ethereum节点实现交互。通读代码和注释,这样才能了解部署一项合约所需的步骤。要了关注工具是如何简化部署过程的。

    部署脚本同样会在JSON文件中存储部署合约的地址,以便之后使用([addresses.json][35])。每个已部署的合约都拥有一个Ethereum地址(就像一个API拥有一个HTTP端点),当实例化的合约通过测试和应用实现互动时这些地址是必须的。

    Gas

    你可能在部署脚本和示例代码中见过‘gas’这个词或者是对它的引用。Gas只是为Ethereum操作收取的交易费用;是EVM的资金来源。最终,gas需要避免虚拟机器的过度使用。

    [https://github.com/ethereum/wiki/blob/master/Glossary.md][36]

    测试

    用JavaScript编写智能合约的单元测试是可行的。但是,不易让人接受的是在习惯于编写传统的client-server应用单元测试的程序员看来这有点违背常理:你必须运行一个本地Ethereum节点计算JavaScript测试中的合约方法。

    关于模拟或存储网络响应的工具(比如适用于Ethereum的 [Sinon.JS][37])非常棒,一定会优先得到开发 - Go 和 Python已经有了类似的工具。现在,我们必须打破单元测试的根本限制并触发网络活动。

    项目示例测试可以这样运行:

    npm test
    

    下一篇文章会详细介绍利用智能合约实现应用间的交互,现在你可以读读这些测试,以便了解如何使用Web3.js计算合约方法。

    调试

    更新合约代码,编译,部署以及运行单元测试的过程太过臃肿,debug效率很低。你可以使用Remix来debug,它是一个编写,编译,部署以及执行方法的IDE。

    有个CLI工具也叫remixd,它可以与Remix IDE共享你的本地合约。项目示例中有执行共享操作的命令 - 然后点击 Remix工具栏中的?按钮进行连接:

    npm run remix
    

    你也可以 [将合约从Gist载入Remix][38]。


    下一篇

    我们会介绍如何构建一个与待办Todo List智能合约交互的分布式web应用。


    拓展阅读

    • ? [Official Solidity docs][39]
    • ? [Deeper dive into Solidity][40]
    • ? [Solidity CRUD][41]
    • ☝️ [Writing upgradeable contracts][42]

    项目更新

    对非集中式应用痴迷的人运行了一个非常棒的副项目,项目的绝大部分代码已经开源。你可以深入挖掘并实践repo中的问题—我可没说一定要贡献你的代码 : )

    在Jakk我们正在构建 [元网络和协议][43],最近在[一个私有alpha中实验][44],我们使用了合作伙伴的数据来填充网络。看下我们的代码[链接][45],在[Slack channel][46]和我们聊聊你发下的任何东西!

    在[Twitter][48] 和 [Facebook][49] 上搜索 [我们][47]

    感谢 [JAAK][50] 以及 [FRΞÐ Tibbles][51].

    • [Ethereum][52]
    • [Web3][53]
    • [Development][54]
    • [Dapp][55]
    • [Blockchain][56]

    快给我们点赞吧,赞数的高低可以让我们判断哪篇文章更受欢迎。

    [3]: twitter.com/jaak_io ""Visit “JAAK” on Twitter"" [4]: blog.jaak.io//facebook.c… ""Visit “JAAK” on Facebook"" [5]: medium.com/m/signin?re… [6]: medium.com/m/signin?re… [7]: blog.jaak.io/@level_out?… [8]: blog.jaak.io/@level_out?… [9]: blog.jaak.io/crossing-ov… [10]: en.wikipedia.org/wiki/Contra… [11]: en.wikipedia.org/wiki/Smart_… [12]: www.fon.hum.uva.nl/rob/Courses… [13]: thenounproject.com/charlenehea… ""View Profile"" [14]: atom.io/packages/la… [15]: packagecontrol.io/packages/Et… [16]: en.wikipedia.org/wiki/Direct… [17]: solidity.readthedocs.io/en/develop/… [18]: swarm-gateways.net/bzz:/theswa… [19]: ipfs.io/ [20]: consensys.github.io/smart-contr… [21]: github.com/duaraghav8/… [22]: github.com/ethereum/wi… [23]: twitter.com/notice ""Twitter profile for @notice"" [24]: twitter.com/param ""Twitter profile for @param"" [25]: github.com/ethereum/so… [26]: solidity.readthedocs.io/en/develop/… [27]: solidity.readthedocs.io/en/develop/… [28]: github.com/lukehedger/… [29]: github.com/lukehedger/… [30]: github.com/trufflesuit… [31]: github.com/lukehedger/… [32]: github.com/ethereum/we… [33]: github.com/L4ventures/… [34]: github.com/ethjs/ethjs [35]: github.com/lukehedger/… [36]: github.com/ethereum/wi… [37]: sinonjs.org/ [38]: gist.github.com/lukehedger/… [39]: solidity.readthedocs.io/en/develop/… [40]: github.com/androlo/sol… [41]: medium.com/@robhitchen… [42]: blog.colony.io/writing-upg… [43]: github.com/meta-networ… [44]: cointelegraph.com/news/jaak-a… [45]: github.com/meta-networ… [46]: community.meta-network.io/ [47]: jaak.io [48]: twitter.com/jaak_io [49]: www.facebook.com/JAAK.io/ [50]: medium.com/@jaak_io?so… [51]: medium.com/@Tibbles?so… [52]: blog.jaak.io/tagged/ethe… [53]: blog.jaak.io/tagged/web3… [54]: blog.jaak.io/tagged/deve… [55]: blog.jaak.io/tagged/dapp… [56]: blog.jaak.io/tagged/bloc… [57]: blog.jaak.io/@level_out?… ""Go to the profile of Luke Hedger"" [58]: blog.jaak.io/@level_out ""Go to the profile of Luke Hedger"" [59]: blog.jaak.io?source=footer_card ""Go to JAAK"" [60]: blog.jaak.io?source=footer_card [61]: blog.jaak.io ""Go to JAAK"" [62]: medium.com/@Medium/per…


    起源地下载网 » 过渡到Web3 - 02 智能合约

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元