木星链 木星链
Ctrl+D收藏木星链
首页 > Fil > 正文

以太坊:EVM 深入探讨 Part 2

作者:

时间:1900/1/1 0:00:00

点击阅读:EVM深入探讨Part1

导语

在第1部分中,我们探讨了EVM如何通过被调用的合约函数知道需要运行哪个字节码,其中我们了解了调用栈、calldata、函数签名和EVM操作码指令。

在第2部分中,我们将开启内存之旅,全面了解合约的内存以及它在EVM上的工作方式。

此系列我们将引介翻译noxx的文章深入探讨EVM的基础知识。

内存之旅

我们依然使用第1部分中在remix上为大家演示的示例代码。

第1部分中我们根据合约编译后生成的字节码研究了与功能选择相关的部分。在本文中,我们将注意力放在字节码的前5个字节。

这5个字节表示初始化“空闲内存指针”操作。要完全理解这些字节码的作用,首先需要理解管理支配合约内存的数据结构。

1、内存数据结构

合约内存是一个简单的字节数组,其中数据存储可以使用32字节或1字节的数据块存储数据,但是读取时每次只能读取固定大小的32字节的数据块。下面的图片说明了此结构以及合约内存的读/写功能。

这个功能是由操作内存的3个操作码决定的。

MSTORE(x,y):从内存位置“x”开始存储一个32字节的“y”?值。

MLOAD(x):从内存位置“x”开始将32字节加载到调用栈上。

PancakeSwap V3已正式上线Polygon zkEVM主网:7月4日消息,PancakeSwap宣布其V3版本已正式上线Polygon zkEVM主网,并作为测试网生态系统合作伙伴加入Linea Voyage的DeFi Week。

此外,PancakeSwap表示,其V3总交易量升至35亿美元,较上个月环比增长3.74%,其中以太坊链上 PancakeSwap V3交易量环比增长74%。[2023/7/4 22:17:41]

MSTORE8(x,y):在内存位置“x”存储一个1字节的值“y”。

你可以将内存位置简单地看作是开始写入/读取数据的数组索引。如果想写入/读取超过1个字节的数据,只需继续从下一个数组索引写入或读取。

2、EVMPlayground

EVMPlayground有助于巩固我们这3个操作码的运行原理、作用以及内存位置的理解。单击Run和右上角的箭头进行调试来查看堆栈和内存是如何更改的。

可能会注意到一些奇怪的现象,我只添加了1个字节,为什么多了这么多零呢?

3、内存扩展

当合约写入内存时,需要为写入的字节数支付Gas,也就是扩大内存的开销。如果我们正在写入一个以前没有写入过的内存区域,那么第一次使用它会产生额外的内存扩展开销。

写入之前未触及的内存空间时,内存以32字节为增量扩展。前724个字节,内存扩展呈线性增长,之后呈二次方增长。(由以太坊黄皮书公式326扩大内存的Gas开销得出,公式为:

ConsenSys zkEVM上线测试网并更名为Linea:金色财经报道,ConsenSys宣布将Layer 2解决方案ConsenSys zkEVM更名为Linea,目前向所有开发人员、用户或协议开放测试。Linea使开发人员能够不受限制地构建可扩展的DApp。

另外,通过MetaMask和Truffle等原生集成,Linea将零知识证明与EVM等效性相结合,为开发人员提供灵活性和可扩展性,而无需ZK技术专业知识。[2023/3/28 13:30:56]

,扩展内存时为每个额外的字的开销。其中a是合约调用中写入的最大内存位置,以32字节字为单位。用1024字节内存为例,那么a=32。)

在位置32处写入1个字节之前,我们的内存是32个字节。此时我们开始往未触及的内存空间写入内容,结果,内存增加了32个字节,增加到64个字节。内存中所有位置的都初始被定义为0,这也是为什么我们会看到?2200000000000000000000000000000000000000000000000000000000000000?被添加到内存中的原因。

4、内存是一个字节数组

调试过程中,我们可能注意到的第二件事发生在我们从内存位置33(0x21)运行MLOAD时。我们将以下值返回到调用栈。

3300000000000000000000000000000000000000000000000000000000000000

内存读取可以从一个非32字节元素开始。

内存是一个字节数组,这意味着可以从任何内存位置开始读取。我们不限于32的倍数。内存是线性的,可以在字节级别进行寻址。内存只能在函数中新建。它可以是新实例化的复杂类型,如数组/结构或从存储引用的变量中复制。

现在我们对数据结构已有了一定的了解了,接下来让我们来看空闲内存指针。

5、空闲内存指针

空闲内存指针只是一个指向空闲内存开始位置的指针。它确保智能合约可以跟踪到哪些内存位置已写入,哪些未写入。这可以防止合约覆盖已分配给另一个变量的某些内存。当一个变量被写入内存时,合约将首先引用空闲内存指针来确定数据应该存储在哪里。然后,它通过记录要写入新位置的数据量来更新空闲内存指针。这两个值的简单相加将产生新的空闲内存开始的位置。

RippleX:EVM兼容XRPL侧链在测试网上可用:3月15日消息,Ripple网络的开放平台RippleX昨日发推称,EVM侧链在测试网上可用,并将各种Web3应用程序带到XRP Ledger社区。其以太坊虚拟机侧链(EVM Sidechain)通过XRP Ledger(XRPL)Bridge直接连接到网络,并支持每秒处理最多1000笔交易。[2023/3/15 13:06:06]

空闲内存指针的位置+数据的字节大小=新空闲内存指针的位置

6、字节码

就像我们之前所提到的,空闲内存指针是通过这5个操作码在运行时字节码的定义的。

这些操作码声明空闲内存指针位于内存中字节0x40处,值为0x80。

Solidity的内存布局保留了4个32字节的插槽:

0x00-0x3f(64bytes):暂存空间,可用于语句之间,即内联汇编和哈希散列方法。

0x40-0x5f(32bytes):空闲内存指针,当前分配的内存大小,空闲内存的起始位置,初始化为0x80。

0x60-0x7f(32bytes):插槽0,用作动态内存数组的初始值,永远不应写入。

我们可以看到,0x40是空闲内存指针的预定义位置。而值0x80只是在4个32字节保留值插槽之后可写入的第一个内存字节。

7、合约中的内存

为了巩固我们到目前为止所学到的知识,接下来将看看内存和空闲内存指针是如何在Solidity代码中更新的。

我们创建MemoryLane合约来进行演示。合约的?memoryLane()?定义了两个长度分别为5和2的数组,并将uint256类型的1赋值给?b。

ConsenSys推出用于zkEVM扩展技术的内测测试网:金色财经报道, Metamask 和 Infura 背后的区块链基础设施平台ConsenSys为一种名为 zkEVM 的新扩展和隐私技术打开了一个私人测试网,该技术建立在以太坊之上。ConsenSys 正在使用测试网探索可能将以太坊的速度和交易成本提高 100 倍以上的潜在颠覆性技术。ZkEVM 代表零知识以太坊虚拟机。它允许开发人员使用他们在以太坊上习惯的相同工具和编码语言构建应用程序,而无需学习零知识编码所需的密码学和数学技能。

自 12 月以来,ConsenSys 测试网已收到超过 150,000 份申请。测试版的参与者可以在 Goerli 测试网和 zkEVM 之间桥接资产,以测试智能合约、dapps、基础设施和钱包。Goerli testnet 是一个流行的测试网络,用于在实时环境中启动新应用程序之前启动和试验新应用程序。[2023/1/11 11:05:03]

要查看合约代码在EVM中执行的详细信息可以将其复制到RemixIDE中编译并部署合约。调用??memoryLane()?后进入DeBug模式来逐步执行操作码(以上操作可以参考:

https://remix-ide.readthedocs.io/en/latest/tutorial_debug.html)。

将简化版操作码提取到EVMPlayground中,可通过这个链接查看具体的操作码及注释信息。

这里将操作码分成6个不同的部分依次解读,删除了JUMP以及与内存操作无关的操作码同时将注释添加了进去方便查看当前在执行什么操作。

1)空闲内存指针初始化

首先,0x80先入栈,这是由Solidity内存布局规定的值,当前内存中没有任何东西。

以太坊推出的“Shandong”测试网将对执行智能合约的EVM进行更改:金色财经报道,10月17日,以太坊的核心开发人员推出了“Shandong”测试网,用于区块链网络的上海升级。上海升级预计将在2023年进行。这将是以太坊自9月合并以来的首次升级。此次升级对执行智能合约的技术以太坊虚拟机(EVM)进行了更改。另一个预期的提议将允许通过信标链提取质押的ETH和获得的奖励。目前,持有ETH的验证者无法直接提取资金。此外,升级还将引入对第2层协议的更改,通过均衡块大小和提高网络中的呼叫数据效率来降低gas价格。[2022/10/19 16:30:10]

最后,我们调用MSTORE,它将第一项从栈0x40弹出以确定在内存中写入的位置,并将第二个值0x80作为写入的内容。这样留下了一个空栈,但已经填充了一部分到内存中。内存由十六进制字符表示,其中每个字符代表4位。例如:在内存中有192个十六进制字符,这意味着我们有96个字节。如果我们回顾Solidity的内存布局会发现,前64个字节将被分配为暂存空间,接下来的32个字节将用于空闲内存指针。

2)内存分配变量“a”和空闲内存指针更新

接下来的部分,我们将跳到每个部分的结束状态,并简洁概述。

首先,为变量“a”分配下一个内存,并更新空闲内存指针。编译器将通过数组大小和默认数组元素大小确定需要多少空间。Solidity中内存数组中的元素都是占据32字节的倍数。当前需要分配的内存为5*32字节,表示为160或0xa0。我们可以看到它被压入栈中并添加到当前空闲内存指针0x80来获取新的空闲内存指针值。这将返回0x120,我们可以看到它已被写入空闲内存指针位置。调用栈将变量“a”的内存位置保存在栈0x80上,以便以后可以在需要时引用它。0xffff代表一个JUMP位置,可以忽略,因为它与内存操作无关。

3)内存初始化变量“a”

已经分配好了内存并且更新了空闲内存指针,接下来需要为变量“a”初始化内存空间。由于该变量只是被声明并没有被赋值,它将被初始化为零值。

EVM通过使用了?CALLDATACOPY操作码来进行操作,其中存在3个变量。

memoryOffset/destOffset?

calldataOffset/offset

size/length

表达式:

memory=msg.data

在这个例子中,memoryOffset(destOffset)?是变量“a”的内存位置。calldataOffset(offset)?是实际calldata的大小,因为并不需要复制任何calldata,所以初始化内存为零。最后,传入的变量为0xa0。

这是可以看到我们的内存已经扩展到288字节,并且调用栈再次保存了变量的内存位置和以及栈上的JUMP地址。

这与变量“a”的内存分配和空闲内存指针更新相同,只是这次是针对“bytes32memoryb”。内存指针更新为0x160,等于先前的空闲内存指针288加上新变量的大小64。空闲内存指针已在内存中更新为0x160,那么现在在栈上就拥有变量“b”的内存位置。

与变量“a”的内存初始化相同。现在内存已增加到352字节,栈内仍然保存2个变量的内存位置。

最后,我们开始为数组“b”索引0赋值。代码指出?b?的值应该为1。该值被压入栈0x01。接下来发生向左移位,但是移位的输入为0,这意味着我们的值不会改变。接下来,要写入0x00的数组索引位置被压入堆栈,并检查该值是否小于数组0x02的长度。如果不是,则执行跳转到处理此错误状态的字节码的不同部分。MUL和ADD操作码用于确定需要将值写入内存中的哪个位置以使其对应于正确的数组索引。

0x20(10进制为32)*0x00(10进制为0)=0x00

需要记住,内存数组是32字节的元素,因此该值表示数组索引的起始位置。鉴于我们正在写入索引0,没有偏移量,也就是从0x00开始写入。

0x00+0x120=0x120

ADD用于将此偏移值添加到变量“b”的内存位置。偏移量为0,直接将数据写入分配的内存位置。最后,MSTORE将值0x01存储到这个内存位置0x120。

下图显示了函数执行结束时的系统状态。所有栈项都已弹出。请注意,实际上在remix中还有一些项目留在堆栈上,一个JUMP位置和函数签名,但是它们与内存操作无关,因此在EVMplayground中被省略了。

内存已更新为包含?b=1?赋值,在我们内存的倒数第三行,0值变成了1。可以验证该值位于正确的内存位置,b?应占用位置0x120-0x13f。

我们现在对合约内存的工作原理有了一定程度的了解。在后续需要编写代码时,将为我们提供很好理解与帮助。当你跳过一些合同操作码,看到某些内存位置不断弹出(0x40),现在就知道他们的确切含义了。

在本系列下一篇文章中,我们将在EVM深入探讨系列第3部分深入探讨合约存储的工作原理,了解存储插槽包装,揭开存储插槽的神秘面纱。

标签:以太坊0X0FFSOFF比特币以太坊最新价格行情0X0价格PUFFSMinimal Initial SushiSwap Offering

Fil热门资讯
区块链:我们为什么投资公链 Shardeum:分片的另一种可能

作者:Beam2022年9月15日,以太坊合并。这是一个历史性的时刻,以太坊为此准备了5年、推迟了6次,由于反复的调试与长期的开发、万众瞩目的晕轮效应,很多人误以为合并会自然而然地带来更高的可扩.

1900/1/1 0:00:00
MAN:Mango Market黑客事件与预言机的局限性

来源:Medium编译:比推BitpushNewsDerrickChen预言机是将有关某些链上或链下事件的信息传输到区块链上的工具.

1900/1/1 0:00:00
数字货币:联储最大噩梦来临:另一些离转向越来越近的因素

原文作者:David,W3.Hitchhiker??进入九月以来,地缘、金融市场的风险次第展开,全球市场在美联储超级鹰派政策的带领下走向越来越未知的领域.

1900/1/1 0:00:00
LUNA vs. LUNC: 哪个是更糟糕的投资

Luna于2018年推出,最初被开发为Terra的第一个本土代币。他们把它称为LUNA。它的目的是作为一种补充代币,吸收加密货币基于智能合约的稳定币terraUSD的任何价格波动.

1900/1/1 0:00:00
元宇宙:元宇宙热潮退去?去年工程师年入150万 有人跳槽薪资翻倍 如今薪资收紧

元宇宙行业正经历从野蛮生长到规范发展的阵痛期。从求职者、猎头到公司,都明显感受到了市场的变化。“去年整个行业有大量的投资方涌入,不缺资金,招聘也很火热,主力是研发.

1900/1/1 0:00:00
ETH:公链生态"吸金"七件套 缺一不可

还记得当初刚进加密行业那会,公链这个词是个很高大上的东西。因为人们一提公链,往往首先想到的ETH这种“通用智能合约型”,或者说平台型公链,而非类似BTC,LTC这种“一币一公链”的公链,这些,我.

1900/1/1 0:00:00