Navigation

    Dev BBS for PRESSone & Mixin project
    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    1. Home
    2. 猪鹿蝶
    • Continue chat with 猪鹿蝶
    • Start new chat with 猪鹿蝶
    • Flag Profile
    • Block User
    • Profile
    • Following
    • Followers
    • Topics
    • Posts
    • Best
    • Groups
    Save
    Saving

    猪鹿蝶

    @猪鹿蝶

    22
    Reputation
    42
    Posts
    630
    Profile views
    0
    Followers
    3
    Following
    Joined Last Online

    猪鹿蝶 Follow

    Posts made by 猪鹿蝶

    • 解构智能合约:手把手教你拆解深入Solidity的神秘世界

      文章来源:巴比特 猎豹区块链安全
      原文链接:解构智能合约:手把手教你拆解深入Solidity的神秘世界

      第一部分·前言

      想象一下,你正在驾驶着1969年的Mustang Mach在美国西部的公路上快速行驶,阳光照耀在华丽的镀金轮辋上,整条道路只有你和沙漠,一望无际的地平线见证着你和落日的追逐... ...

      心旷神怡间,突然一身巨响,你335马力的快马被滚滚的白烟吞没,瞬间变成了蒸汽机车,于是你被迫停在路边。

      你打算看看出现了什么问题,当你翻开前车盖,发现自己完全看不懂。你根本就不知道这该死的机器是怎么工作的,于是你拿起手机准备求救,发现附近没有信号... ...

      上面描述的情形是不是和你正在做的DApp开发很像?在开发Dapp的过程中,在类比中,豪车是你的智能合约,轮辋和改造过的地方是那些经过深思熟虑的小细节。而一旦出现问题,你就需要在智能合约EVM字节码中寻找答案,大部分情况下你都完全不知道发生了什么。

      如果你是Dapp的开发者,并且遇到过上面的尴尬状况的话,那么以后再也不用担心了!

      因为,本系列文章的目的就是解构一个简单的Solidity合约,查看其字节码,并将其分解为可识别的结构,直至最低级别。我们将打开Solidity这台跑车的引擎盖。在本系列的最后,您在查看或调试EVM字节码时应该感觉很舒服。本系列的重点是揭开Solidity编译器生成的EVM字节码的神秘面纱,它真的比它看起来简单得多。

      以下是我们解构时要使用到的智能合约代码:

      pragma solidity ^0.4.24;
      
      contract BasicToken {
      
      uint256 totalSupply_;
      
      mapping(address => uint256) balances;
      
      constructor(uint256 _initialSupply) public {
      
      totalSupply_ = _initialSupply;
      
      balances[msg.sender] = _initialSupply;
      
      }
      
      function totalSupply() public view returns (uint256) {
      
      return totalSupply_;
      
      }
      
      function transfer(address _to, uint256 _value) public returns (bool) {
      
      require(_to != address(0));
      
      require(_value <= balances[msg.sender]);
      
      balances[msg.sender] = balances[msg.sender] - _value;
      
      balances[_to] = balances[_to] + _value;
      
      return true;
      
      }
      
      function balanceOf(address _owner) public view returns (uint256) {
      
      return balances[_owner];
      
      }
      
      }
      
      

      注意:此合约容易受到溢出攻击,我们只是为了说明问题,所以力求简洁。

      编译合约

      为了编译合约,我们将使用Remix(地址:https://remix.ethereum.org)。

      当你打开Remix编译器,单击文件浏览器区域上方左上角的+按钮,创建新的智能合约。将文件名设置为BasicToken.sol。创建好之后,将上面的代码粘贴到编辑器上。

      在右侧,转到“ Setting”的选项中,确保选中了“ Enable Personal Mode”。另外,要注意选择的Solidity编译器版本是

      “ version:0.4.24 +commit.e67f0147.Emscripten.clang ”。

      这两个细节非常重要,否则你将无法查看文中讨论的字节码。

      接下来,你可以进入Compile选项并单击Details按钮,你会看到一个弹出窗口,里面包含Solidity编译器生成的所有东西,其中一个是名为BYTECODE的JSON对象,它具有“object”属性,这个就是编译的合约代码,它的代码是这样的:

      608060405234801561001057600080fd5b5060405160208061021783398101604090815290516000818155338152600160205291909120556101d1806100466000396000f3006080604052600436106100565763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166318160ddd811461005b57806370a0823114610082578063a9059cbb146100b0575b600080fd5b34801561006757600080fd5b506100706100f5565b60408051918252519081900360200190f35b34801561008e57600080fd5b5061007073ffffffffffffffffffffffffffffffffffffffff600435166100fb565b3480156100bc57600080fd5b506100e173ffffffffffffffffffffffffffffffffffffffff60043516602435610123565b604080519115158252519081900360200190f35b60005490565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b600073ffffffffffffffffffffffffffffffffffffffff8316151561014757600080fd5b3360009081526001602052604090205482111561016357600080fd5b503360009081526001602081905260408083208054859003905573ffffffffffffffffffffffffffffffffffffffff85168352909120805483019055929150505600a165627a7a72305820a5d999f4459642872a29be93a490575d345e40fc91a7cccb2cf29c88bcdaf3be0029
      

      没错,这些代码完全没有可读性(至少对于正常人而言)。

      部署合约

      接下来,转到Remix中的Run部分。首先,确保您使用的是Javascript VM。这基本上是一个嵌入式Javascript EVM +网络,理想的以太坊训练场。确保在ComboBox中选择了BasicToken ,并在Deploy输入框中输入数字10000 。接下来,单击“ Deploy”按钮进行部署。这部署的是我们创建的BasicToken智能合约实例,最初提供的10000个token由当前在ComboBox帐户顶部选择的帐户拥有,该帐户会保留我们设置的所有token供应。

      在“ Run”选项卡的“Deployed Contracts”中,您可以看到已部署的智能合约,其中包含与合约进行交互的三个字段:transfer,balanceOf和totalSupply。在这里,我们能够与刚刚部署的智能合约实例进行交互。

      但在此之前,让我们来看看合同的“Deploy”(部署)究竟是什么意思:

      在页面底部的控制台区域中,你可以看到一条日志“creation of BasicToken pending ...”,然后是一个包含各种字段的事务条目:from,to,value,data,logs和hash。单击此条目以展开交易信息,你应该看到transaction的date、input,以及我们上面提到的字节码。所以,创建一个智能合约实例,其中会包含自己的地址和代码。

      我们将在下一篇文章中详细研究这transaction个过程。

      反汇编字节码

      在控制台中心,transaction框框的右侧,有个“ debug”(调试)按钮。点击这个按钮,你将激活Remix右侧区域中的Debugger选项。我们可以一起看看Instructions部分,如果向下滚动,应该是出现以下内容:

      000 PUSH1 80

      002 PUSH1 40

      004 MSTORE

      005 CALLVALUE

      006 DUP1

      007 ISZERO

      008 PUSH2 0010

      011 JUMPI

      012 PUSH1 00

      014 DUP1

      015 REVERT

      016 JUMPDEST

      017 POP

      018 PUSH1 40

      020 MLOAD

      021 PUSH1 20

      023 DUP1

      024 PUSH2 0217

      027 DUP4

      028 CODECOPY

      029 DUP2

      030 ADD

      031 PUSH1 40

      033 SWAP1

      034 DUP2

      035 MSTORE

      036 SWAP1

      037 MLOAD

      038 PUSH1 00

      040 DUP2

      041 DUP2

      042 SSTORE

      043 CALLER

      044 DUP2

      045 MSTORE

      046 PUSH1 01

      048 PUSH1 20

      050 MSTORE

      051 SWAP2

      ...(缩写)

      为了确保你前面的操作没有出错,你可以把你所操作的Remix编译器中看到的内容与上面进行比较。

      这其实就是合约的反汇编字节码。如果您按字节扫描原始字节码(一次两个字符),则EVM会识别与特定操作关联的特定操作码。例如:

      0x60 => PUSH

      0x01 => ADD

      0x02 => MUL

      0x00 => STOP

      ...

      反汇编的代码非常低级并且很难看懂,但是我们可以通过这种方式可以开始理解它。

      Opcode
      在解构智能合约代码开始之前,你将需要一个基本的工具集理解单个opcode,如PUSH,ADD,SWAP,DUP等的操作码,到最后,每个操作吗只能从EVM的堆栈,内存或属于合约的存储中压入一个项或消费一个项。

      要查看EVM可以处理的所有可用操作码,可以查看Pyethereum,上面显示了操作码列表。要了解每个操作码的工作原理,Solidity官方的汇编文档也是一个很好的参考。即使它不是与原始操作码一一对应,但是非常接近(它实际上是Yul,介于Solidity和EVM字节码之间的中间语言)。如果你能读懂技术文档,可以阅读以太坊黄皮书,其实归根结底都是上面的内容。

      虽然和大家推荐了这么多文档,现在从头到尾阅读这些资源没有什么意义,你只要记住有这么个资料就行,我们将在需要的时候使用到它们。

      指令

      上面反汇编代码中的每一行都是EVM执行的操作指令,每条指令都包含一个操作码,例如,让我们采用其中一条指令,指令88,将数字4推送到堆栈。这个特殊的反汇编程序解释说明如下:

      88 PUSH1 0x04

      | | |

      | | Hex value for push.

      | Opcode

      Instruction number

      尽管反汇编的代码能让我们更加理解底层的东西,但它还是让人摸不着头脑。我们需要一个能够解构所有问题的方法。

      策略

      任何一开始看上去不可能完成的任务,其实都可以通过不断的拆解,分解成可以解决的任务,我们遇到的问题也不例外,面对这个问题,我所采取的策略就是“分而治之”。

      我们可以试图找到反汇编代码的分叉点,并逐渐分解,直到分解成很小的块,我们将在Remix的调试器中逐步完成。

      在下图中,我们可以看到我们对反汇编代码进行的第一次拆分(我将在下一篇文章中对其进行全面分析)。

      解构智能合约
      如果你不了解图表,也不要担心,你不用一开始就什么都会,我们的系列文章将会循序渐进的介绍。现在就跟着我们的节奏,不断深入你的豪车的内部结构吧。

      本文由Alejandro Santander首发于medium,由猎豹区块链安全翻译并整理

      posted in Development and general discussion | 开发和技术相关讨论
      猪鹿蝶
    • RE: 阿里云的版权认证来了,PRESS.one就凉凉了?!

      嗯嗯,腾讯对内容的生态和理解一定是比阿里系要深刻很多,西乔的解释也很清晰了。哈哈,牛市有望。

      posted in Development and general discussion | 开发和技术相关讨论
      猪鹿蝶
    • RE: pressone文章的推荐列表

      目前我在PRS 的APP 上可以看到的推荐列表有两个,一个是PRESSone爱好者开发的PRSDigg,一个是PRS喵推荐。
      PRSDigg应该是根据文章的赞赏和点赞进行排序。PRS喵推荐前期把很多之前沉淀在平台上已有内容做了精选和推送,之前大多时候看到的都是一些长期在PRESSone上写作的人,lyric,龙姑娘,寂寞不语,行动的女巨人,比特汪,马烈,行动的女巨人等等,最近则可以看到一些新作者的推荐,也会看到比较好的图片。就我的理解,PRESSOne并不是一个中心化的分发平台,所以本身应该不会做某种具体的导向。

      我是一直也想在PRESSOne上试一试,但是每次写的都是自己琐碎的事情,关于笑来老师提到的文字的有用,我也一直没把握的太好,也就没发文字,默默的看着也挺有收获(相比之下,更加喜欢论坛,文字可以随性一点)哈哈。

      猜你是一个写作爱好者,如果真的把他单纯当作一个内容分发平台的话,现在也是早期,内容本来也不多,开始持续写出有用的东西,被看见的可能性就很大啦。

      posted in Ask for help
      猪鹿蝶
    • RE: PRESSone白皮书科普系列短文---DPoS

      期待更多楼主的更多短文

      posted in Tech Chit Chat 技术话题闲聊版
      猪鹿蝶
    • RE: 2018年,Mixin 如何在不可能三角的限制下设计一个高并发和快速确认的闪电网络

      UTXO,DAG,BFT这样三个点,就连在一起了,总而言之,是为了实现可扩展性和安全性,舍弃了去中心化。

      人们会把去中心化当作目的。但是去中心的目的是提高生存能力,去中心化越彻底,生存能力越强。

      从这个角度去理解去中心化,可能让很多密码朋克们有些难以接受吧,但技术走向商业,往往总是会要去掉一些理想主义色彩。

      posted in Development and general discussion | 开发和技术相关讨论
      猪鹿蝶
    • RE: 张首晟:区块链世界到底是如何形成的 | 经典重读

      @李大白 在 张首晟:区块链世界到底是如何形成的 | 经典重读 中说:

      社会科学一直找不到根本的数学原理,可能的确是不容易找到,因为很多经济行为建筑在人的不理性上。

      社会科学一直找不到根本的数学原理,可能的确是不容易找到,因为很多经济行为建筑在人的不理性上。

      最早看张先生演讲的时候,也是被这句话所触动,没想到知道他不到一年,他就英年早逝。

      posted in Tech Chit Chat 技术话题闲聊版
      猪鹿蝶
    • RE: PRESSone所使用的合约脚本解释器PRSC 已经开源啦

      @huoju 期待霍炬的更多讲解,哈哈。

      posted in Development and general discussion | 开发和技术相关讨论
      猪鹿蝶
    • RE: PRESSone所使用的合约脚本解释器PRSC 已经开源啦

      @coconolosky 厉害了,一直说要学习编程的本猪,表示很惭愧。

      posted in Development and general discussion | 开发和技术相关讨论
      猪鹿蝶
    • RE: 我们调查了近200人的阅读习惯,这些精选回答或许有助于你改进自己的阅读习惯

      也来说一说我的阅读习惯吧。
      微信订阅号和得到的音频是目前的主要阅读源,这是一个重要的开拓视野的渠道。一般来讲,要买什么书,都是通过这两个渠道获得了信息。

      另外我有收藏癖,所以经常会用有道云笔记收藏很多来自不同不同信息源的文字,微信订阅号为主。

      看完这个帖子,我意识到现有的阅读习惯基本限定了我在知识获取和主动学习上的能力严重不足。主动的搜索,信息的整合研究能力是一个很大的短板,这是需要不足的地方。如何连点成线是一个比较重要的课题。

      今天在PRESSOne上看到一篇文章是讲如何写出有价值的文章的,似乎可以和这个帖子结合起来:聚焦。

      聚焦某一领域,聚焦某一领域的具体问题,聚焦某一领域的某一问题,聚焦某一领域的某一问题的某一点。聚焦是建立作者快速成长的最小闭环,不断重复联系,会得到极大的个体提升,通知做到和读者的无障碍传递信息,信息单一明确。

      可以这么说当我从订阅号和得到获取的内容,大部分都是聚焦后的结果,而通过主动的搜索获取的信息,则是在海量信息获取之后的精炼。也就是当我通过订阅号和得到快速的获取内容的时候,我正在失去的一种能力实际上是聚焦的能力。

      聚焦并非是一个名词或者短暂性动作,而是一个持续性的动作。热力学第二定律在信息获取上同样成立,我们的信息获取始终会越来越发散,越来越混乱,只有在发散中不断尝试去聚焦,这个时候的阅读,可能才真正有所收获,而不只是收获的感觉。

      posted in Tech Chit Chat 技术话题闲聊版
      猪鹿蝶
    • RE: PRESSone白皮书科普系列短文---PoW

      @猪鹿蝶 找到了另外几个队哈希算法的补充,可以参考:

      在字符串后面添加一个叫做nonce的整数值,对变更后(添加nonce)的字符串进行SHA256哈希运算,如果得到的哈希结果(以16进制的形式表示)是以"0000"开头的,则验证通过。为了达到这个工作量证明的目标。我们需要不停的递增nonce值,对得到的新字符串进行SHA256哈希运算。

      Hash这个词没有对应的中文意译词,如果让我来意译的话,我会翻译为“数字摘要算法”,基本上能表达该算法的含义,就是从目标对象中提取出一个特征摘要,好像人的指纹一样。
      SHA算法从1993年发布它的第零代,一直到2015年发布第三代,二十二年间已经升级了四次。比特币用到的是第二代算法,简称为SHA-256算法,这里的“256”表示,由这个算法生成的指纹长度固定为256比特。大家可以很容易在网上找到在线生成SHA-256指纹的网页,这个算法是公开的,谁都能用。

      在实际的使用中,256位的二进制数据太长了,使用起来极不方便,还很容易看花眼。于是,指纹通常用十六进制来显示,反正二进制到十六进制是一一对应的。

      不论原始信息有多长,生成的指纹都是一样长的。而且这个指纹还有两个显著特点:一、原始信息只要改变一点点,哪怕只改动一个数字,整个指纹就会发生巨大的变化,毫无规律可循;二、截至本文写作时,世界上还没有任何公开的方法可以从指纹反向计算出原始信息,普遍认为理论上无法破解。

      哈希函数在POW中被用到,在数字签名中被用到,

      posted in Tech Chit Chat 技术话题闲聊版
      猪鹿蝶