接着上次的分析,分析一下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. Nginx的启动过程

    主要介绍Nginx的启动过程,可以在/core/nginx.c中找到Nginx的主函数main(),那么就从这里开始分析Nginx的启动过程. 涉及到的基本函数 源码:  View Code Ngin ...

  2. PL/SQL编程接触

    1.认识PL/SQL 结构化查询语言(Structured Query Language,SQL)是用来访问和操作关系型数据库的一种标准通用语言,它属于第四代语言(4GL),简单易学,使用它可以很方便 ...

  3. PTA 03-树1 树的同构 (25分)

    题目地址 https://pta.patest.cn/pta/test/15/exam/4/question/711 5-3 树的同构   (25分) 给定两棵树T1和T2.如果T1可以通过若干次左右 ...

  4. 在mac下安装matplotlib,xlrd

    brew install freetype brew install libpng sudo easy_install pip#图形显示模块 sudo pip install matplotlib 输 ...

  5. [codevs3622] 假期(单调队列)

    传送门 首先考虑暴力做法,可以先求一遍前缀和 sum,然后ans = max(ans, sum[i] - sum[k]) (i - q <= k <= i - p) 但这个肯定会超时. 仔 ...

  6. [NOIP2003] 提高组 洛谷P1039 侦探推理

    题目描述 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先商量好由其中的一个人充当罪犯(在明明不知情的情况下),明 ...

  7. 【BZOJ2038】小Z的袜子(莫队)

    题意: 给定n个数a1, a2…… an与m个询问(L,R).对于每个询问,从aL, aL+1…… aR这R-L+1个数中随机取出两个数,求这两个数相同的概率. 数据范围:1<=n,m,ai&l ...

  8. linux date 格式化时间和日期

    [root@108test ~]# date -d today +"%Y-%m-%d" 2008-05-07   [root@108test ~]# date -d today + ...

  9. SQL SERVER 2012 第四章 连接 JOIN の INNER JOIN

    所有JOIN语句的共同点是:将一个记录与另外一个或多个记录匹配,从而生成一个新记录,这个记录是由两个记录的合并列所产生的一个超集. 内部连接: 内部连接语法结构:SELECT <select l ...

  10. HDU 5514 容斥原理

    Frogs Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submi ...