• 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的值

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

  • 相关阅读:
    【微信小程序】实现投票功能(附源码)
    运动控制:音圈电机
    电子电气架构设计需要考虑哪些方面?
    ES6-匿名函数
    极智AI | 有趣的羊驼系列大模型
    ROS源代码阅读(1)
    【Axure】axure rp 导入元件库和使用,主流元件库下载使用
    自动化测试之路 —— Appium元素定位
    万卷书 - 欧洲的门户 [The Gates of Europe]
    python3GUI--仿做一个网易云音乐(第三弹v2.0)By:PyQt5(附下载地址)
  • 原文地址:https://blog.csdn.net/qincheng168/article/details/126334184