EVM有一个基于栈的架构,在一个栈中保存了所有内存数值。EVM的数据处理单位被定义为256位的“字”(这主要是为了方便处理哈希运算和椭圆曲线运算操作)
这里所说的内存数值是指那些EVM字节码运行所需要的输入、输出参数数据和智能合约程序运行中所需要的局部变量等数据,而不是指下文中所提到的“内存”数据;下文中的“内存”是一个与栈共同存在的、独立的临时存储空间。
以太坊EVM的架构和执行上下文

目前市面上比较主流的是BTC脚本引擎和以太坊虚拟机(Ethereum Virtual Machine, EVM)。
图灵完备的计算环境——以太坊虚拟机(EVM)。这就意味着在EVM上可以做所有的能想得到计算,包括无限循环。EVM指令包括一个JUMP的跳转指令,可让程序跳回前面的程序代码,也可以像条件判断语句那样做条件跳转,当满足一定条件时将程序跳转到另一个地方执行。另外,一个合约可以调用其他合约,这提供了潜在的递归调用的功能。
EVM模块主要分为三大模块:编译合约模块、Ledger模块和EVM执行模块。
EVM指令由很多标准机器码指令组成,包含:
EVM执行事务的流程如图所示

(1) EVM接收到Transaction信息,然后判断Transaction类型是部署合约还是执行合约。如果是部署合约,执行指令集,来存储合约地址和编译后的代码;如果是执行合约或是调用合约,则使用EVM来执行输入指令集。
(2) 执行上一条指令集之后,判断EVM是否停机,如果停机则判断是否正常停机,正常停机则更新合约状态到区块链,否则回滚合约状态。如果不停机则回到上一步(1)进行判断。
(3) 执行完的合约会返回一个执行结果,EVM会将结果存储在Receipt回执中,调用者可以通过Transaction的哈希来查询结果。
每轮执行时,通过调出代码的第pc(程序计数器)个字节,每个指令如何影响元组都有定义。例如,ADD将两个元素出栈并将它们的和入栈,将Gas减1并将pc加1; stack将顶部的两个元素出栈,并将第2个元素插入由第1个元素定义的合约存储位置,同样减少最多200的Gas值,并将pc加1。虽然有许多方法通过即时编译去优化以太坊,但以太坊的基础性的实施可以用几百行代码实现。
以太坊合约的代码是使用低级的基于堆栈的字节码的语言写成的,被称为“以太坊虚拟机代码”或者“EVM代码”。代码由一系列字节构成,每一个字节代表一种操作。一般而言,代码执行是无限循环,程序计数器每增加一(初始值为零)就执行一次操作,直到代码执行完毕或者遇到错误、STOP或者RETURN指令。
EVM不是基于寄存器的,而是基于栈的虚拟机。因此所有的计算都在一个称为栈的区域内执行。栈最大有1024个元素,每个元素有256位。对栈的访问只限于其顶端,允许复制最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面16个元素中的一个。所有其他操作都只能取最顶的一个或几个元素,并把结果压在栈顶。当然可以把栈里的元素放到存储或者主存中。但是无法只访问栈里指定深度的那个元素,在那之前必须把指定深度之上的所有元素都从栈中移除才行。
EVM的指令集被刻意保持在最小规模,以尽可能避免可能导致共识问题的错误。所有的指令都是针对256位这个基本的数据单位进行的操作,具备常用的算术、位、逻辑和比较操作,也可以进行条件和无条件跳转。
虚拟机(EVM)执行指令部分的Gas计算是最为复杂的。虚拟机(EVM)事务执行期间的所有操作,包括数据库读写、消息发送以及虚拟机采取的每个计算步骤都要消耗一定量的燃料,并且在不同参数和缓存影响的情况下都会对应有不同的燃料标价。图2-15是取自以太坊官方黄皮书中的非指令部分的燃料标价示例图。
黄皮书链接:https://ethereum.github.io/yellowpaper/paper.pdf
以太坊的高级语言最后会编译成在EVM中执行的EVM字节码(bytecode),部署在以太坊区块链上。以太坊提供3种编程语言:Solidity、Serpent和LLL。
我在使用omniauth/openid时遇到了一些麻烦。在尝试进行身份验证时,我在日志中发现了这一点:OpenID::FetchingError:Errorfetchinghttps://www.google.com/accounts/o8/.well-known/host-meta?hd=profiles.google.com%2Fmy_username:undefinedmethod`io'fornil:NilClass重要的是undefinedmethodio'fornil:NilClass来自openid/fetchers.rb,在下面的代码片段中:moduleNetclass
我遵循了教程http://gettingstartedwithchef.com/,第1章。我的运行list是"run_list":["recipe[apt]","recipe[phpap]"]我的phpapRecipe默认Recipeinclude_recipe"apache2"include_recipe"build-essential"include_recipe"openssl"include_recipe"mysql::client"include_recipe"mysql::server"include_recipe"php"include_recipe"php::modul
我在用Ruby执行简单任务时遇到了一件奇怪的事情。我只想用每个方法迭代字母表,但迭代在执行中先进行:alfawit=("a".."z")puts"That'sanalphabet:\n\n#{alfawit.each{|litera|putslitera}}"这段代码的结果是:(缩写)abc⋮xyzThat'sanalphabet:a..z知道为什么它会这样工作或者我做错了什么吗?提前致谢。 最佳答案 因为您的each调用被插入到在固定字符串之前执行的字符串文字中。此外,each返回一个Enumerable,实际上您甚至打印它。试试
如何检查Ruby文件是否是通过“require”或“load”导入的,而不是简单地从命令行执行的?例如:foo.rb的内容:puts"Hello"bar.rb的内容require'foo'输出:$./foo.rbHello$./bar.rbHello基本上,我想调用bar.rb以不执行puts调用。 最佳答案 将foo.rb改为:if__FILE__==$0puts"Hello"end检查__FILE__-当前ruby文件的名称-与$0-正在运行的脚本的名称。 关于ruby-检查是否
目录一.加解密算法数字签名对称加密DES(DataEncryptionStandard)3DES(TripleDES)AES(AdvancedEncryptionStandard)RSA加密法DSA(DigitalSignatureAlgorithm)ECC(EllipticCurvesCryptography)非对称加密签名与加密过程非对称加密的应用对称加密与非对称加密的结合二.数字证书图解一.加解密算法加密简单而言就是通过一种算法将明文信息转换成密文信息,信息的的接收方能够通过密钥对密文信息进行解密获得明文信息的过程。根据加解密的密钥是否相同,算法可以分为对称加密、非对称加密、对称加密和非
//1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json
我从Ubuntu服务器上的RVM转移到rbenv。当我使用RVM时,使用bundle没有问题。转移到rbenv后,我在Jenkins的执行shell中收到“找不到命令”错误。我内爆并删除了RVM,并从~/.bashrc'中删除了所有与RVM相关的行。使用后我仍然收到此错误:rvmimploderm~/.rvm-rfrm~/.rvmrcgeminstallbundlerecho'exportPATH="$HOME/.rbenv/bin:$PATH"'>>~/.bashrcecho'eval"$(rbenvinit-)"'>>~/.bashrc.~/.bashrcrbenvversions
我有一个使用SeleniumWebdriver和Nokogiri的Ruby应用程序。我想选择一个类,然后对于那个类对应的每个div,我想根据div的内容执行一个Action。例如,我正在解析以下页面:https://www.google.com/webhp?sourceid=chrome-instant&ion=1&espv=2&ie=UTF-8#q=puppies这是一个搜索结果页面,我正在寻找描述中包含“Adoption”一词的第一个结果。因此机器人应该寻找带有className:"result"的div,对于每个检查它的.descriptiondiv是否包含单词“adoption
我写了一个非常简单的rake任务来尝试找到这个问题的根源。namespace:foodotaskbar::environmentdoputs'RUNNING'endend当在控制台中执行rakefoo:bar时,输出为:RUNNINGRUNNING当我执行任何rake任务时会发生这种情况。有没有人遇到过这样的事情?编辑上面的rake任务就是写在那个.rake文件中的所有内容。这是当前正在使用的Rakefile。requireFile.expand_path('../config/application',__FILE__)OurApp::Application.load_tasks这里
如果names为nil,则以下中断。我怎样才能让这个map只有在它不是nil时才执行?self.topics=names.split(",").mapdo|n|Topic.where(name:n.strip).first_or_create!end 最佳答案 其他几个选项:选项1(在其上执行map时检查split的结果):names_list=names.try(:split,",")self.topics=names_list.mapdo|n|Topic.where(name:n.strip).first_or_create!e