Solidity智能合约开发 — 5.2 -理解EVM虚拟机交易执行、合约创建、区块上链

1 EVM概述

一个交易数据中附加了合约创建代码或者合约函数调用代码,以太坊客户端就会相应的使用EVM来运行这些代码。所有智能合约代码最终反映为EVM机器码,以下是常有的EVM操作码.

1.1 EVM操作码

  • 栈和内存操作码

       POP PUSH  MLOAD MSTORE JUMP PC MSIZE GAS DUP SWAP

  • 通用系统操作码

      CREATE CALL RETURN REVERT SELFDESTRUCT

  • 算数操作码

       ADD MUL SUB DIV SDIV MOD SMOD ADDMOD MULMOD EXP STOP

  • 环境数据操作码

      ADDRESS BALANCE CALLVALUE ORIGIN CALLER CODESIZE GASPRICE EXTCODESIZE RETURNDATACOPY 

1.2 EVM代码执行

在EVM中,从逻辑上讲有两类程序代码

一类叫做“运行时字节码”,他们保存在ROM中,由各节点维护,且基于账户地址标识。

一类叫做“字节码”,仅在合约创建时执行一次,用来生成合约的“运行时字节码”的代码,不会持久化保存。

2 合约创建

合约创建可以由一个外部用户签名的交易执行触发,也可以在合约代码中由特定的合约代码所触发。对于EVM中执行合约,他需要若干输入参数。

  • 发送者:直接发起合约创建操作的账户地址
  • 原始交易发起人:触发当前执行、最初由外部用户签名的交易数据的发送者地址
  • 可用gas: 创建过程中使用的最大gas数量
  • gasPrice:触发当前执行、最初由外部用户签名的交易数据中指定的gas价格
  • 初始捐款:发送到新创建合约的一定量以太币。
  • EVM初始化代码:用来创建合约的“运行时字节码”
  • 当前的运行栈深度
  • 对状态进行修改的许可标志。

如果合约初始化代码的执行没有发生任何异常,那么由其所生成的合约“运行时字节码”会被保存到EVM的ROM中。此外还需要从发送者账号的balance中扣除执行这些初始化代码所消耗的gas费用和代码保存费用。

如果合约初始化代码的执行发生异常,那么将不会创建任何账户和任何金额转移。

3 消息调用

与合约创建一样,可以由一个外部用户签名的交易执行触发,也可以在合约代码中由特定的合约代码所触发。对于在EVM执行消息调用而言,也需要执行若干输入数据。

  • 发送者:直接发起合约创建操作的账户地址
  • 原始交易发起人:触发当前执行、最初由外部用户签名的交易数据的发送者地址
  • 接收者:消息调用的目标地址
  • 要执行的代码所在的账号地址:通常与接收者地址相同
  • 可用gas: 创建过程中使用的最大gas数量
  • gasPrice:触发当前执行、最初由外部用户签名的交易数据中指定的gas价格
  • 初始捐款:发送到新创建合约的一定量以太币。
  • 转账金额:发送到被调合约函数的以太币数量
  • 当前的运行栈深度
  • 对状态进行修改的许可标志。

在EVM中有4个操作码可以发起消息调用。

表3-1 消息调用操作码
操作码 说明
CALL 向某个接受者发起消息调用,recipient与sender可以相同,也可以不同
CALLCODE 与CALL基本等价,但recipient与sender相同且与code address相同
DELEGATECALL 与CALL基本等价,但recipent与sender相同且与code address不同
STATICCALL 与CALL基本等级,但不允许转账,且不允许对状态进行任何修改

4 区块上链

看看区块如何最终定稿并添加到区块链中。

  • ommer验证

要求ommer区块的父区块必须是当前区块6代(含)以内的祖先区块。

  • 交易验证

对于生成区块的矿工而言,他需要从本地维护的交易池中选择哪些gasPrice合适的交易来顺序执行,同时更改相应的状态和存储并生成交易收据数据。

对于非矿工全节点而言,除了顺序执行所有交易,同时更改本地维护的状态树、存储树,生成交易收据,并计算累计的gas消耗量与区块头中给定的gasUsed相符。

  • 奖励发放

前期区块的beneficiary最多可获得1+2/32的基础区块奖励。

  • 状态验证

对于生成区块的矿工而言,所有交易执行所导致的状态变动以及奖励发放之后的最终‘状态树’根节点哈希值保存到区块头的stateRoot字段。

对于非矿工全节点,则需要验证按区块中包含交易数据列表顺序执行完所有交易,并发放区块奖励之后的“状态树”根节点哈希值是否与区块头的stateRoot相符。

  • 验证区块头数据的nonce和mixHash字段

对于矿工节点,就是基于Ethhas算法获得nonce和mixHash的值

对于非矿工节点,就是验证区块头中保存的这两个数据的一致性。

猜你喜欢

转载自blog.csdn.net/qincheng168/article/details/126334184