Ethereum 源码分析之EVM

以太坊EVM源码注释之数据结构 以太坊EVM源码分析之数据结构 EVM代码整体结构 EVM相关的源码目录结构: ~/go-ethereum-master/core/vm# tree . ├── analysis.go // 分析合约字节码,标记是否是跳转目标(jumpdest) ├── analysis_test.go ├── common.go ... 阅读详情
Ethereum_evm

以太坊虚拟机规定了从一个区块到另一个区块计算新的有效状态的规则. 以太坊的状态是一个大型的数据结构,它不仅保存所有账户和余额.而且还保存一个机器状态,它可以根据预定义的一组规则在不同的区块之间进行更改,并且可以执行任意的机器代码.

1. 以太坊的基本概念

外部用户对ETH的访问: 可以发送创建合约的交易,消息调用的交易或者查询世界状态的值.
在这里插入图片描述

交易的顺序:

交易必须要满足原子性(要么全部完成,要么就是部分完成). 且用户propose transactions存放到pending transaction pool中,然后miner通过某种方式获得记账权,决定了哪些交易被打包到区块中且区块中的交易执行顺序.然而区块之间的顺序(决定哪个区块先上链)是由共识算法决定的.

在这里插入图片描述

2. Ethereum虚拟机的基本概念
2.1. 以太坊虚拟机层:

在这里插入图片描述

以太坊虚拟机代码的生成方式:

在这里插入图片描述

包含有Solidity source、Viper source以及LLL source相关.

2.1 以太坊虚拟机的组成:

分为两个部分虚拟机状态以及存储状态.

  1. 虚拟机状态: 程序计数器(PC),内存,堆栈,可用燃料.

  2. 存储状态: 以太坊虚拟机代码,账户存储.

在这里插入图片描述

2.2 以太坊状态转换函数:

EVM的行为就像一个数学函数:在给定输入的情况,它会产生确定性的输出.因此,将以太坊更正式地描述为具有状态转换函数非常有帮助.

Y(S,T)=S'
给定一个旧的有效状态(S),和一组新的有效交易(T),以太坊状态转换函数Y(S,T),
产生新的有效输出状态S'
2.3 交易:

交易可以分为消息调用交易(sender:外部账户或者合约账户)和创建合约账户交易(sender:外部账户).

账户类型分为:外部账户(是由私钥控制的)和合约账户(保存有EVM代码和存储树).

外部账户的地址可以是由私钥生成公钥,然后对公钥求hash,然后生成160位的字节.

合约账户的地址可以是由创建合约的sender address+nonce进行RLP编码,然后kec求hash后取右边160位作为地址.
在这里插入图片描述

EVM说明:

EVM作为一个堆栈机运行,其栈的深度为1024个项。每个项目都是256位字.为了便于使用,使用256位加密技术(如Keccak-256哈希或secp256k1签名).

内存: 在执行期间,EVM会维护一个瞬态内存 (作为字可寻址的字节数组),该内存不会在交易之间持久存在.

2.4 EVM的操作码:

已经编译的智能合约字节码作为以EVM 操作码为单位执行标准的堆栈操作.如XOR,AND,ADD,SUB等等.

在这里插入图片描述

在以太坊中所有可编程计算都需要付费.单位是以gas为例. 上述可以知道gas的消耗来自:操作码的执行,从世界状态中读取数据到stack中以及消息调用(message call). Eth的操作是对栈直接操作的,不会访问状态树和存储树的.

EVM的操作码具体实现(go-ethereum\core\vm\contract.go): GetOp的实现实际上是读取Contract.Code[n],然后返回.那么Code中的每个字节都代表一个操作码.操作码的高四位表示操作码的类型,操作码的低四位表示操作码的该类型的具体操作.

在这里插入图片描述

2.5 Stack,Memory,Account Storage

栈是由1024个元素组成,每个元素是256位.

在这里插入图片描述

  1. 栈:每个操作只能对在栈顶的的16个大小为256位的元素操作. 具体的方式:

  2. 对栈的访问只限于其顶端的16个元素(16*256bits).限制方式:允许拷贝最顶端的16个元素中的一个到栈顶,或者是交换栈顶元素和下面的16元素中的一个.所有其他对栈的操作都限制在取栈顶的两个或者1个元素,运算后,把结果压入栈顶.当然可以把栈中的元素放到存储(状态树)或者内存中. 但是无法访问栈上指定深度的那个元素,除非先从栈顶移除其他元素.

  3. EVM不是基于寄存器的,而是基于栈的,因此所有的计算都在一个称为栈的区域执行.所有的操作主要是对栈进行读取和修改的,以及消息调用.

内存: evm会为每次消息调用获取一块被重新擦拭干净的内存实例.内存是线性的,可以按照字节寻址,但读的长度被限制为256位,而写的长度可以是8位或者是256位.

  1. 每次从栈中读取和修改的以256位为单位.每次从memory中读取的单位为256位,从状态树中读取的单位也是256位

  2. 访问栈的指令有: PUSH,POP,COPY,SWAP.

访问内存的指令有: MSTORE,MSTORE8,MLOAD.

访问存储树的指令有: SSTORE/SLOAD.

在这里插入图片描述

  1. 内存字节序(Endian for Memory):

采用的是大端存储,那么意味着内存高字节放在栈的低地址. 下述介绍了内存和栈之间的数据交换:

在这里插入图片描述

内存的高位字节放在stack中放在低位上.

  1. 输入数据的字节序(Endian for input data)

采用的是大端存储,那么意味着输入数据的高字节放在内存或栈的地址处. 下述介绍了输入数据与内存/栈的数据交换:

在这里插入图片描述

  1. 在EVM中对storage trie和state trie的访问仍然使用的是go-ethereum\core\state\statedb.go中的相关接口
```go
StateDB.Empty(address)
StateDB.GetBalance(address)
StateDB.GetCode(addr)
StateDB.GetCodeHash(address)
StateDB.GetState(scope.Contract.Address(), hash)
StateDB.SetState(scope.Contract.Address(),loc.Bytes32(), val.Bytes32())
StateDB.GetBalance(scope.Contract.Address())
StateDB.AddBalance(beneficiary.Bytes20(), balance)
StateDB.Suicide(scope.Contract.Address())
evm.StateDB.AddLog(&types.Log{
            Address: scope.Contract.Address(),
            Topics:  topics,
            Data:    d,
            // This is a non-consensus field, but assigned here because
            // core/state doesn't know the current block number.
            BlockNumber: interpreter.evm.Context.BlockNumber.Uint64(),
})
 等等接口
```
2.6 消息调用(Message call)

EVM可以发送消息调用给其他账户(该账户可以是外部账户也可以是合约账户).

消息调用的发送方只能是合约账户.

  1. 在以太坊中,消息调用的深度被限制在少于1024层.

  2. 消息调用我们可以理解为EVM调用另一个EVM.

消息调用是由EVM内存中call 指令触发的,然后消息调用和返回值都是由共享内存的方式传递的.

在这里插入图片描述

其中包含了两个指令(Instruction): call instruction和return instruction.

2.7 异常(Exception):

异常的方式有: 跳转失败(invalid jump destination),指令不正确(invalid instruction),堆栈下溢(stack underflow)以及燃料用完(out-of-gas).

在这里插入图片描述

2.8 Gas的相关字段:
gasLimit:表示每笔交易所允许使用的最大燃气数量.
gasPrice:表示你愿意支付每单位燃气的费用.
gasFeeCap:表示支付给矿工的最大总费用限制.
gasTipCap:表示你愿意额外支付给矿工的最大费用.
3. Ethereum EVM源码分析:
3.1 EVM相关的各个实例:
type code []byte   //EVM code
type storage map[common.Hash]common.Hash //Account Storage
//core/vm/stack.go
type Stack struct{ //stack
    data []*big.Int  //big.Int 256位
}
//core/vm/memory.go
type Memory struct{
    store []byte //Memory,按字节寻址
    lastGasCost uint64 
}
//core/vm/instruction.go,定义了些指令的实现.
//core/vm/gas.go 定义了gas燃料.

//core/vm/interpreter.go 
func (in *Interpreter) Run(contract *Contract, input []byte) (ret []byte, err 
error)
//core/state_processor.go 定义交易的执行(ApplyTransaction)
func ApplyTransaction(config *params.ChainConfig, bc *BlockChain, author 
*common.Address, gp *GasPool, statedb *state.StateDB, header *types.Header, tx 
*types.Transaction, usedGas *uint64, cfg vm.Config) (*types.Receipt, uint64, error)
定义消息的执行:
func ApplyMessage()
3.2 Bootstrap of EVM in Geth

根据下述的调用关系,我们可以知道一笔交易就会创建一个EVM.

处理区块的接口是:go-ethereum\core\state_processor.go Process方法其中会遍历block中的交易,为每个交易调用ApplyTransaction函数.

在go-ethereum\core\state_processor.go applyTrasanction前必须要先将交易转化为消息.其代码部分为:go-ethereum\core\types\transaction.go AsMessage 消息的数据结构在下述的代码块中.

在这里插入图片描述

根据上述代码中Run[core/vm/interpreter.go]的方法

func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (ret []byte, err error) 

传入的是contract,因此为每一次智能合约的执行都会创建一个memory和stack.

//EVM的数据结构
type EVM struct {
    // Context provides axiliary blockchain related information
    Context BlockContext
    TxContext
    // StateDB gives access to the underlying state
    StateDB StateDB
    // Depth is the current call stack
    depth int

    // chainConfig contains information about the current chain
    chainConfig *params.ChainConfig
    // chain rules contains the chain rules for the current epoch
    chainRules params.Rules
    // virtual machine configuration options used to initialise the
    // evm.
    Config Config
    // global (to this context) ethereum virtual machine
    // used throughout the execution of the tx.
    interpreter *EVMInterpreter
    // abort is used to abort the EVM calling operations
    // NOTE: must be set atomically
    abort int32
    // callGasTemp holds the gas available for the current call. This is needed because the
    // available gas is calculated in gasCall* according to the 63/64 rule and later
    // applied in opCall*.
    callGasTemp uint64
}
//Message is a fully derived transaction and implements core.Message
type Message struct {
    to         *common.Address //消息调用交易的目的地址
    from       common.Address //消息调用交易的sender
    nonce      uint64 //消息调用交易的sender账户nonce
    amount     *big.Int //消息调用交易的sender账户的amount
    gasLimit   uint64 //此消息调用交易的所能花费的最大gas量(wei)
    gasPrice   *big.Int //此消息调用交易的每wei gas的价格
    gasFeeCap  *big.Int //此消息调用交易的愿意支付的最大eth
    gasTipCap  *big.Int //此消息调用所需要额外支付的eth
    data       []byte
    accessList AccessList //访问的列表
    isFake     bool
}

core/state_transaction.go:TransactionDb方法实现了什么?

func (st *StateTransition)TransitionDb()(*ExecutionResult,error)
 在这个接口中我们可以知道当msg.To为nil时,该消息就是创建合约交易.
    //TODO the code module to process the msg
    if contractCreation {
        ret, _, st.gas, vmerr = st.evm.Create(sender, st.data, st.gas, st.value)
    } else {
        // Increment the nonce for the next transaction
        st.state.SetNonce(msg.From(), st.state.GetNonce(sender.Address())+1)
        ret, st.gas, vmerr = st.evm.Call(sender, st.to(), st.data, st.gas, st.value)
    }

上述接口主要做了6个方面的检查:

在这里插入图片描述

3.3 如何获得每笔交易访问和修改StateTrie的账户地址以及StorageTrie的Key
  1. 在EVM层面的修改: 在go-ethereum\core\vm\evm.go的EVM结构体加入两个字段(readSetIncludeStorage []state.SItems;writeSetIncludeStorage []state.SItems)

state.SItems的结构体组成为:

在这里插入图片描述

以太坊源码分析 账户管理 本文分析以太坊的账户管理的源码,主要包括两个部分: 获取钱包列表、订阅钱包事件。 阅读详情

相关推荐

以太坊虚拟机EVM介绍,智能合约详解

指的是“一套以数字形式指定的承诺,包括合约参与方可以在上面执行这些承诺的协议”。早在1994年,美国计算机科学家尼克·萨博(Nick Szabo)就提出了智能合约的概念。智能合约是一种基于区块链技术的自动执行合约的计算机程序。它们是一组以代码形式编写的、在区块链上运行的规则和逻辑。智能合约定义了在满足特定条件时应该执行的操作,而无需中介方的干预。以太坊是最为著名的支持智能合约的区块链平台之一。在以太坊中,智能合约是用一种称为Solidity的编程语言编写的。

ydl1128的博客 5727

以太坊:源码解读

源码解读是深入了解一个产品最好的方式,通过以太坊源码可以理解以太坊的基本设计思想,智能合约的实现过程;本教程由浅入深为你讲述以太坊区块链的实现过程,如何实现交易,如何实现EVM等关键技术

读懂以太坊源码(3)-详细解析genesis.json

要想搞懂以太坊的源代码逻辑,必须要了解以太坊创世区块配置文件(genesis.json)的结构,以及每个配置参数的意义,创世配置文件,主要作用是设置链的ID,指定以太坊网络中硬分叉发生的区块高度,以及初始ETH数量的初始分配,以下的json代码是以太坊主网的创世配置文件的原始文件和简要说明,本文后续有更详细的说明,由于genesis.json文件包含了大量的众筹地址和数量,实在是太长了,所以这里省略了其中大量的众筹地址和分配数量,其它参数保持不变。

曹昆的技术博客 1730

以太坊EVM源码分析学习记录

EVM源码简单分析

weixin_43563956的博客 3975

利用ANSYS随机振动分析功能实现随机疲劳分析

本文介绍了ANSYS随机振动分析功能,以及利用该功能,按照Steinberg提出的基于高斯分布和Miner线性累计损伤定律的三区间法进行ANSYS随机疲劳计算的具体过程。在工程应用中,汽车、飞行器、船舶以及其它各种机械或零部件,大多是在随机载荷作用下工作,当它们承受的应力水平较高,工作达到一定时间后,经常会突然发生随机疲劳破坏,往往造成灾难性的后果。因此,预测结构或零部件的随机疲劳寿命是非常有必要的。在工程界,疲劳计算广泛采用名义应力法,即以S-N曲线为依据进行寿命估算的方法,可以直接得到总寿命。

qq_38220914的博客 7607

【安徽理工大学】一文带你高分拿下计算机考研复试(85+的秘密)

一文带你高分拿下安徽理工大学计算机考研复试(85+的秘密)

猫天意的博客 1523

以太坊地址和公钥_秘密!以太坊安全之 EVM 与短地址攻击

前言以太坊(Ethereum)是一个开源的有智能合约功能的公共区块链平台,通过其专用加密货币以太币(ETH)提供去中心化的以太坊虚拟机(EVM)来处理点对点合约。EVM(Ethereum Virtual Machine),以太坊虚拟机的简称,是以太坊的核心之一。智能合约的创建和执行都由EVM来完成,简单来说,EVM是一个状态执行的机器,输入是solidity编译后的二进制指令和节点的状态数据,输出...

weixin_39639965的博客 944

计算机视觉——多视图几何

多视图几何1.前言1.1 多视图几何概念2. 基本原理2.1 对极几何2.2 基础矩阵2.2.1 基础矩阵推导2.2.2 求解基础矩阵3. 实验过程3.1 实验数据准备3.2 实验代码3.3 实验结果及分析4. 实验中遇到的问题 1.前言 1.1 多视图几何概念 多视图几何是利用在不同视点所拍摄图像间的关系,来研究照相机之间或者特征之间关系的一门科学。 多视图几何(Multiple View ...

RuiMa的博客 7715

go-ethereum代码阅读环境搭建

go-ethereum源码解析 因为go ethereum是最被广泛使用的以太坊客户端, 所以后续的源码分析都从github上面的这份代码进行分析。 搭建go ethereum调试环境 windows 10 64bit 首先下载go安装包进行安装,因为GO的网站被墙,所以从下面地址下载。 https://studygolang.com/dl/golang/go1.9.1.windows-amd64...

Show something 586

如何利用PREEvision和MATLAB开发AUTOSAR软件组件

在业界,比较著名的电子电气架构开发工具要属德国Vector公司开发的PREEvision工具了,而MATLAB/Simulink软件是非常高效且实用的基于模型的应用软件开发工具。利用PREEvision与Simulink联合开发AUTOSAR应用软件组件的开发流程有三种,分别是:“自上而下”开发流程(从PREEvision开始),“自下而上”开发流程(从Simulink开始),以及“双向”开发流程。如下图所示,无论哪一种开发流程,PREEvision与Simulink工具都是通过arxml文件进行信息交互的

怿星科技的博客 5395

基于单片机负载控制的无人机电气设备监测系统设计

为深入分析无人机电气设备的电子负载性能,实现对传输电子量的合理性监管与控制,设计基于单片机负载控制的无人机电气设备监测系统;利用电气信号发生电路,构建负载网络控制器与以太网模块运行所需的电气设备负载环境,借助PCB监控板建立PLC扩展负载模块与核心监控主机之间的物理连接关系,实现无人机电气设备监测系统的硬件执行环境搭建;在此基础上,通过STM32型单片机移植协议,确定无人机电气设备通信主机的现有组态形式,联合已设定的监控任务有线级条件,实现监测系统的软件执行环境搭建,完成基于单片机负载控制的无人机电气设备监

weixin_45905610的博客 1300

以太坊源码分析(1)go-ethereum的设计思路及模块组织形式

 版权声明:本文为博主尹成联系QQ77025077,微信18510341407原创文章,欢迎转载侵权不究。 https://blog.youkuaiyun.com/yincheng01/article/details/80304070 go-ethereum的设计思路及模块组织形式 =================================== 以太坊的目标是基于区块链技术打造一个运行智能合约的去中...

u012149181的博客 663

Fluent求解器——湍流参数的设置

Fluent湍流参数的介绍和设置。

Ronko_G的博客 4万+

Ethereum源码分析—账号解锁

Ethereum源码分析—账号解锁测试用例 测试用例 keystore.NewKeyStore: 创建一个对象,第一个参数是生成的keystore文件保存路径 k.NewAccount: 创建账号,参数是密码 点击进入getDecryptedKey方法,再进入getKey方法 进入Decryptkey函数 ...

weixin_43883839的博客 328

【DexGraspNet与多指手抓取算法详解】第三章 DexGraspNet数据集构建机理

抓取姿态描述多指手与物体的相对空间关系,包含手掌位姿与手指关节配置。

VectorShift的博客 497

【超详细】计算机组成原理总结及思维导图

计算机组成 第一章 计算机系统概论 冯诺依曼型计算机特点 1.计算机由运算器,控制器,存储器,输入和输出设备5部分组成 2.采用存储程序的方式,程序和数据放在同一个存储器中,并以二进制表示。 3.指令由操作码和地址码组成 4.指令在存储器中按执行顺序存放,由指令计数器(即程序计数器PC)指明要执行的指令所在的储存单元地址,一般按顺序递增,但可按运算结果或外界条件而改变 5.机器以运...

圣三一 10万+

go-ethereum evm b11r 区块构建指南:如何将 ommer 叔块组装进规范区块

本文以 go-ethereum 仓库中 [cmd/evm/testdata/22/readme.md](https://link.gitcode.com/i/06a6d4a517b3a1ce8f63c1af3d850d2c) 这份测试用例说明为骨架,深入讲解 `evm b11r`(block builder)工具如何将叔块(ommer / uncle)头组装进一个规范区块。读者将掌握:b11r 的

gitblog_00513的博客 8

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

goland环境配置_Ethereum以太坊源码分析(一)前言与环境搭建

本文参考:Github - go-ethereum-code-analysis前言之前在Github看到一个很棒的Ethereum源码分析笔记,所以想跟着这个笔记把Ethereum的代码过一遍,希望通过这个已有的笔记和自己的分析,能总结出一些自己的东西,并以此方式记录下来,用输出来激励自己的输入。因为之前有过fabric的开发经历,所以,我选择了go-ethereum这个项目来对ethereum的...

weixin_35558751的博客 414

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

go-ethereum(通常简称为 Geth)源码解释

go-ethereum 是一个工程杰作,代码质量很高,但体量巨大。分层思想:它清晰地分离了核心协议 (core)、网络通信 (p2p) 和应用服务 (rpc, eth)。模块化设计:每个部分都相对独立,通过接口(如 consensus.Engine)进行交互,具有很好的扩展性。数据结构是基础:不理解 Block、Transaction 和 Merkle Patricia Trie,就很难理解上层逻辑。希望这个导览能为你探索 Geth 的代码世界提供一张清晰的地图!

u011091936的博客 790

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Ethereum概念理解

*** 必读 : Ethereum White Paper** Externally owned account(EOA) VS. Contract account 两者都使用20字节的地址。EOA外部拥有账户是由用户通过公钥/私钥秘钥对控制的,通过以太坊客户端创建,由秘钥对生成的账户地址。而Contract account则是EOA通过调用创建合约的方法创建的账户,账户内包含合约代码,由...

ckcclc的博客 1290

optimizerDuck Windows 优化完整指南:42 项优化移除预装应用、关闭遥测,全部改动一键还原

optimizerDuck 是一款免费、开源、完全离线的 Windows 优化工具,支持 Windows 10/11。不用打开注册表(Windows 的系统参数数据库),就能关闭遥测、精简后台服务、移除预装应用,而且每处改动都会先备份,随时一键还原。适合刚装好系统、想让机器更干净流畅,却不敢也没时间手改注册表的人。 [![optimizerDuck Windows 优化工具主界面,性能分类优化卡

gitblog_00030的博客 738

02.以太坊源码分析(2)go ethereum 目录大概介绍

go-ethereum项目的组织结构基本上是按照功能模块划分的目录,下面简单介绍一下各个目录的结构 accounts 实现了一个高等级的以太坊账户管理 bmt 二进制的默克尔树的实现 build 主要是编译和构建的一些脚本和配置 cmd 命令行工具,又分了很多的命令行工具,下面一个一个介绍 /abigen S...

boss2967的博客 446

Go Ethereum源码学习笔记 001 Geth Start

首先读者需要具备Go语言基础,至少要通关菜鸟教程,知道Go语言的基本语法,这些基础教程网络上非常多,请大家自行学习。安装Go SDK,即Go语言的开发环境;安装GoLand,即Go语言的IDE,当然也可以选择VSCode等其他IDE;克隆源码;克隆源码(可选);以太坊基础知识,Ethereum 协议(黄皮书 )做好这些准备工作,就可以打开源码了,如下图所示:以太坊是以区块链作为基础的应用,所以我们必须具备区块链相关的基础知识,否则很难读懂源码究竟在做什么。

CloudHuCoding 1280

以太坊源码分析(四) - 以太坊整体架构和核心概念

1

yzpbright的博客 2256
上一篇: Fabric 搭建测试网络并部署智能合约
下一篇: Ethereum 源码分析之ethdb
Blockchain410
博客等级 码龄5年 3230粉丝 36原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Blockchain410

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值