接着上次的分析,分析一下run方法是如何执行智能合约的。至于以太币的交易,在上一篇中,已经由分析的那两个函数完成了;

合约的运行是从run开始的,go-ethereum/core/vm/evm.go 。可以分为两部分一部分是预编译,另外一部分是解释器。

预编译合约

// run runs the given contract and takes care of running precompiles with a fallback to the byte code interpreter.
func run(evm *EVM, contract *Contract, input []byte) ([]byte, error) {
if contract.CodeAddr != nil {
precompiles := PrecompiledContractsHomestead
if evm.ChainConfig().IsByzantium(evm.BlockNumber) {
precompiles = PrecompiledContractsByzantium
}
if p := precompiles[*contract.CodeAddr]; p != nil {
return RunPrecompiledContract(p, input, contract)
}
}
return evm.interpreter.Run(contract, input)
}
     在以太坊中,go-ethereum/core/vm/contracts.go,事先编译好了一组合约,具体如下:

var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{1}): &ecrecover{},
common.BytesToAddress([]byte{2}): &sha256hash{},
common.BytesToAddress([]byte{3}): &ripemd160hash{},
common.BytesToAddress([]byte{4}): &dataCopy{},
common.BytesToAddress([]byte{5}): &bigModExp{},
common.BytesToAddress([]byte{6}): &bn256Add{},
common.BytesToAddress([]byte{7}): &bn256ScalarMul{},
common.BytesToAddress([]byte{8}): &bn256Pairing{},
}
    如果要执行的contract恰好属于预编译的合约集合,那么它就可以直接运行;由于预编译的合约内容是固化在以太坊中的,所以我们输入参数即可(input),不需要输入合约内容(code)。

type PrecompiledContract interface {
RequiredGas(input []byte) uint64 // RequiredPrice calculates the contract gas use
Run(input []byte) ([]byte, error) // Run runs the precompiled contract
}
    每个预编译的合约都有两个方法,第一个是计算需要花费gas,第二个是合约的具体实现。如果是基于evm开发的公链,我们完全可以自己开发出更多的预编译合约,这样运行速度会增加很多。

解释器

不属于预编译的contract,则由Interpreter解释执行。 这里 我们需要看一下上一篇文章中的EVM框架图。

EVMInterpreter中存在一个config结构体,其中包含一个JumpTable数组,这个数组包含了256个operation对象;每个operation对象是一个指令,指令由四个函数组成——execute、gascost、validatestack、memory size;而operation执行时,会用到stack、memory,statedb。

execute:指令执行函数

gascost:gas计算

validatestack:栈深度检测

memorysize:内存消耗

contract则是智能合约对象,其中code则是合约代码,不过是已经转化为指令的代码,

从上图我可以看到,解释器的run()函数执行过程很简单;就是contract的code中的指令,依次通过jumptable找到对应operation;然后由opertation中四个函数实现指令的执行。

这是run()函数的主流程;由栈(stack)负责保存操作数,所有的操作都是运行在栈上的;内存(memory)数据结构是一个byte数组,用于一些内存操作(MLOAD,MSTORE,MSTORE8)及合约调用的参数拷贝(CALL,CALLCODE)。

每个节点都有一个EVM,为了严重交易,每一笔交易都会在每个节点的EVM都会运行一遍,很明显这样会造成计算资源的浪费。而从安全性的方面考虑,在一个区块链系统中,一但系统中节点的状态出现不同的状态,各个节点的EVM运行智能合约时,会出现错误,导致系统无法到达一致,达成共识;这就要求整个系统必须再次达成一致性。

以太坊 EVM内交易执行分析(二)的更多相关文章

  1. 以太坊 EVM内交易执行分析(一)

    以太坊上交易最终都会由EVM进行解析存入数据库,今天就来探讨一下,一笔交易是如何别EVM执行的.我们可以把交易分为三种.(注意,和交易相关的模块很多,交易的生命周期存在于整个以太坊中,我们这次只是分析 ...

  2. 以太坊 layer2: optimism 源码学习(二) 提现原理

    作者:林冠宏 / 指尖下的幽灵.转载者,请: 务必标明出处. 掘金:https://juejin.im/user/1785262612681997 博客:http://www.cnblogs.com/ ...

  3. 以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程

    作者:林冠宏 / 指尖下的幽灵 掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8 博客:http://www.cnblogs.com/linguan ...

  4. 以太坊EVM在安全性方面的考虑

    以太坊上用户编写的合约是不可控的,要保证这些合约能够正确执行并且不会影响区块链的稳定,虚拟机需要做安全方面的考虑. 1 在程序执行过程中采取的每个计算步骤都必须提前支付费用, 从而防止DoS攻击.先消 ...

  5. c#实战开发:以太坊钱包对接私链 (二)

    上一篇讲了 以太坊私链搭建 首先下载Ethereum Wallet 钱包 可以直接百度 下载如果直接打开它会默认连接公链 所以我们要通过命令打开 "F:\Program Files\Ethe ...

  6. 以太坊go-ethereum客户端docker安装(二)开发(dev)环境搭建

    在上一篇博客中,讲述了基于docker怎么搭建一个go-ethereum节点.作为开发人员,如果只是单纯的拥有一个Full node,还无法满足正常的开发.比如说,进行转账交易,你要考虑是否拥有一定的 ...

  7. ethereum(以太坊)(基础)--容易忽略的坑(二)

    pragma solidity ^0.4.0; contract EMath{ string public _a="lin"; function f() public{ modif ...

  8. 死磕以太坊源码分析之txpool

    死磕以太坊源码分析之txpool 请结合以下代码阅读:https://github.com/blockchainGuide/ 写文章不易,也希望大家多多指出问题,交个朋友,混个圈子哦 交易池概念原理 ...

  9. 以太坊中的账户、交易、Gas和区块Gas Limit等概念

    什么是账户 以太坊账户与我们所知的账户概念有一定相似之处,却又有很大的区别,更不同于比特币中UTXO. 账户分两类: - 外部拥有账户(EOA),也就是普通账户 - 合约账户 普通账户 所谓的普通账户 ...

随机推荐

  1. xtu summer individual 2 C - Hometask

    Hometask Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on CodeForces. Origin ...

  2. tarjan求割边割点

    tarjan求割边割点 内容及代码来自http://m.blog.csdn.net/article/details?id=51984469 割边:在连通图中,删除了连通图的某条边后,图不再连通.这样的 ...

  3. C++中,什么叫类,结构,联合?

    在C++中 class 和 struct 本质上一样 可以互用class的成员默认是private的,struct的成员默认是public的但一般习惯把成员变量隐藏的用class申明, 成员变量可以公 ...

  4. jsonp跨域请求实现示例

    网上看了很多关于jsonp的资料,发现在本机运行后实现不了,有的是有错漏,有的是说的比较含糊,接合自己的情况,整了一个可运行的示例: 前言: ajax请求地址:http://192.168.1.102 ...

  5. SpringBoot配置Bean的两种方式--注解以及配置文件

    一.注解方式 编写实体类: package com.example.bean; import org.springframework.boot.context.properties.Configura ...

  6. 【收藏】实战Nginx与PHP(FastCGI)的安装、配置与优化

    拜读南非蚂蚁大牛的文章真是有所收获 http://ixdba.blog.51cto.com/2895551/806622 一.什么是 FastCGI FastCGI是一个可伸缩地.高速地在HTTP s ...

  7. iOS - 设置系统类似的方法弃用警告的方式

    在开发过程中,调用系统方法时,经常可以看xCode 提示 该方法已弃用,如下图: 觉得特别炫,查一下资料,如果自己也想实现如下的效果,只需要采用系统的如下几个关键字加在方法名后面就可以了: NS_DE ...

  8. ***apache做301重定向的方法

    将不带www的定向到带www去 方法一:加在httpd.conf 1.这里我使用mod_rewrite重写URL的方式来做,做之前朋友记得检查一下你的apache是否已经加载了rewrite模块.如图 ...

  9. BZOJ——2563: 阿狸和桃子的游戏

    http://www.lydsy.com/JudgeOnline/problem.php?id=2563 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit:  ...

  10. CF821E(多次矩阵快速幂)

    题意: 冈伦从二维平面上(0,0)走到(k,0),(k<=1e18),每次有三个行动方向:右上一格.右方一格.右下一格,问一共有多少种走的方案 限制:每段x都有一个天花板,一共有n段天花板(n& ...