ETH 交易流程深度技术详解

1@2x-3.jpg

1.png

概述

在前面对 PolkaVM 和 Revive 的文章中,我们介绍了很多技术细节,开发工具。还对比 EVM,知道了 PolkaVM 的优势。很多同学还是对 Polkadot SDK 为什么可以运行 EVM 兼容的智能合约,以及交易处理的整个流程不太清楚。这篇文章将会带着大家梳理一下整个过程,在熟悉它之后,对于今后 Debug 代码,找到出错原因都会有很大好处。

整个处理的流程主要有下面几个模块组成,我们来逐一分析

  • RPC Server 接收交易,并转发到节点

  • Runtime 定义交易的格式扩展

  • Revive 做交易的转换,从 Eth 交易转成 Polkadot SDK 的 extrinsic

  • 最终的 bytecode 在 PolkaVM 中的执行

2.png

RPC Server

和普通的 Extrinsic 不同,也有别于之前在 Polkadot SDK 上出现的Frontier,Ink 的支持。在提交 Solidity 的交易的时候,我们会启动一个单独的RPC Server来接收交易。因此我们在配置本地的测试环境或者 Passet Hub 的时候,都需要这个 URL。

那么这个 Server 是怎么工作的呢?它的代码也在 Revive Pallet下,package 名字是 pallet-revive-eth-rpc。它主要有三个组件,一个 subxt 的客户端,一个 RPC 服务器,还有一个用来缓存数据的 sqlite 内存数据库。

subxt 主要是和 node 来交互,比如向区块链提交交易,查询数据等。 RPC 服务器来实现以太坊的 Web3 服务接口,大部分函数定义都在 EthRpc 这个 Trait 可以找到。其他还有 debug api 和 health api。

当 server 收到请求,都会转换成对区块链的请求,通过 subxt 的客户端发出,收到结果后返回给调用者。

这里分别举二个例子,一个是查询余额,一个提交交易。

截屏2025-07-21 09.49.49.png

这里的接口定义是 web3 的一致的,通过区块号或者 Hash 来查询余额。下面我们来看下它的实现。

截屏2025-07-21 09.50.42.png

这里 client 就是 subxt 的客户端,它把传进来的区块号,哈希或者 Tag,统一转换成区块哈希,进行查询,并返回结果。这里不用担心 Decimal 的问题,在 Node 一侧,当要查询的是一个Eth格式的地址时,就已经做好了转换。

下面是对发送交易的实现,它会组装一个 Pallet 是 Revive,Extrinsic 是 eth_transact 的交易,然后发给 Node。这个 Extrinsic 非常的特殊,我们接下来会在分析 Revive 代码的时候看下它是怎么处理的。

截屏2025-07-21 09.51.29.png

截屏2025-07-21 09.51.33.png

Sqlite 主要来缓存一些交易的数据,还有事件日志等。

图片

Runtime

在 Runtime 中,需要包含 Revive Pallet 才能处理Eth的交易,还有对Runtime API的实现。一个最重要的代码实现是对 UncheckedExtrinsic 的重新定义,对于不需要支持 Eth 的交易,普通的 sp_runtime::generic::UncheckedExtrinsic 就可以了。为了支持对 Eth 的交易,需要使用 Revive 里面  UncheckedExtrinsic 作为包含中 Block 中的类型。

这样区块链在处理交易池里面的 Eth 交易就可以识别他们,在验证交易的时候把它转换成普通的 Extrinsic。

4.png

Revive Pallet

Revive 当然是处理交易的核心,有些设计还比较的巧妙,我们先来看它如何转换Eth的交易。对于一个提交的 Eth 交易,下面这个函数用来对它进行转换,成为普通的 Extrinsic。

截屏2025-07-21 09.53.12.png

截屏2025-07-21 09.53.18.png

截屏2025-07-21 09.53.23.png

截屏2025-07-21 09.53.28.png

首先尝试解码 payload 成一个含有 Eth 签名的交易,并得到发送交易的以太坊地址。随后做一个基本的检查,比 如nonce,gas,chain ID 等等。

下一步就是要转换成 Call 了, 这里首先有一个特殊的地址  RUNTIME_PALLETS_ADDR,它被用来直接调用 Runtime 里面的任何交易。它把输入的数据直接解码成 Call 并调用,除此之外的都会转换成 Revive 的 Call 方法,调用某个智能合约里面的一个方法。如果没有调用的合约地址,那么只能是一个部署合约的方法,会把它尝试转换成一个 eth_instantiate_with_code 的方法。

从这里我们可以看出,从 Eth 来的交易,没有只 upload_code 的方法,当然这个也不在以太坊接口的定义里面。

在下面就是对于 gas_price, gas_fee 的处理,还会把多给的 gas_fee 作 为tip。

最终返回一个 CheckedExtrinsic,它也在这里有了使用 Polkadot 帐号的签名,它来自发送交易者映射到 Polkadot 地址格式的帐号。

这里有一个非常有意思,和难理解的就是 eth_transact 方法,它除了给出一个错误之外没有任何其他逻辑。那么它的作用是什么呢?首先,它提供了一个接口给外部调用,比如我们在 RPC Server 里面使用 subxt 来调用它。其次,我们使用它就可以把提交来的交易解码成这个 Call,得到它的 payload 部分,在用 payload 解码成封装的 Eth 交易。

但是在从 UncheckedExtrinsic 到 CheckedExtrinsic 的转换中,它就被处理了,转换成了其他的方法。call 或者 eth_instantiate_with_code,因此在正常情况下不会有 dispatch 到这个方法里面的交易。这就是为什么它只有报错处理。

截屏2025-07-21 09.55.36.png

截屏2025-07-21 09.55.40.png

当然在 Revive 里面还有很多处理逻辑,包括我们前面文章提到的precompile,这里不再重复介绍。

5.png

交易在 VM 的执行

在 Revive 中处理交易中最核心的是一个 Stack 的数据结构,从这个名字来看,这里依然要模拟的还是 EVM 基于栈的处理模型。它的代码如下:

截屏2025-07-21 09.56.52.png

截屏2025-07-21 09.56.56.png

除去基本信息比如区块号,时间戳,还有就是对于计算和存贮的计量。通过 frames 来记录每次对合约更深一层的调用,和函数的逐层调用一样。

transient_storage 是一个在 EVM 中非常特殊的存贮,它在整个的交易中都是有效的,因此它的存贮也在 frame 之外,单独存放。

在进行完一系列繁琐的环境准备之后,代码最终在 PolkaVM 的开始执行。下面是一个非常重要的数据结构 PreparedCall,我们通过它来调用 PolkaVM 去执行合约编译后的 RISC-V 代码,或者说 PolkaVM(它和标准的 RISC-V 有着细小的差别). Module 主要包含的是编译好的程序代码, RawInstance 是一个 PolkaVM 的实例,用来运行虚拟机。Runtime 则是区块链节点提供给它的执行环境。

截屏2025-07-21 09.57.58.png

6.png

总结

在这个文章中,我们介绍了交易从发送到 RPC Server,到最终在 PolkaVM 里面运行的整个过程。希望能帮助大家在调试代码的时候有所帮助,能够根据错误信息,找到对应的模块,解决问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/93323.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/93323.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【算法训练营Day17】二叉树part7

文章目录二叉树的最近公共祖先二叉搜索树的最近公共祖先二叉搜索树中的插入操作删除二叉搜索树中的节点二叉树的最近公共祖先 题目链接:236. 二叉树的最近公共祖先 解题逻辑: 最近公共祖先的定义为:对于有根树 T 的两个节点 p、q&#xff0c…

Vue插件与组件核心区别详解

在 Vue 中,插件(Plugin) 和 组件(Component) 是两种不同层次的概念,它们的主要区别如下:1. 组件 (Component) 定义: Vue 应用的基本构建单元,是可复用的 Vue 实例&#x…

基础NLP | 02 深度学习基本原理

文章目录 深度学习基本原理 数学基础 线代 numpy 常用操作 导数, 梯度 梯度下降法 梯度下降代码 GradientDescent.py 反向传播 完整的反向传播过程 权重更新方式 pytorch 网络结构 全连接层 (线性层) 例子 - 手动实现模拟一个线性层 DNNforward.py 激活函数 激活函数-Sigmoid…

MySQL面试题及详细答案 155道(001-020)

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs&…

Ansible安装与入门

目录 Ansible ansible任务执行模式 ansible执行流程 ansible命令执行过程(背会) ansible的安装方式 ansible的程序结构(yum安装为例) ansible的配置文件查找顺序(背会) 核心配置文件 ansible的配置…

【Spring】Spring Boot启动过程源码解析

目录 一、启动入口 二、SpringApplication的构造过程 2.1 设置应用类型 2.2 设置初始化器(Initializer) 2.2.1 获取BootstrapRegistryInitializer对象 2.2.2 获取ApplicationContextInitializer对象 2.3 设置监听器(Listener&#xff…

CDN架构全景图

CDN架构全景图 CDN(内容分发网络)是一种通过在全球范围内部署边缘节点服务器,将内容缓存至离用户最近的位置,从而加速内容分发、降低延迟并减轻源站压力的分布式网络架构。其核心设计目标是优化互联网内容传输效率,提升…

【pytest高阶】源码的走读方法及插件hook

一、pytest源码走读方法 依赖库认知篇 📦这是理解 pytest 源码的 “前菜”,先认识 3 个超重要的小伙伴:iniconfig 📄:像个 “文件小管家”,专门负责读取 ini 配置文件(比如 pytest 的配置&#…

算法训练营day32 动态规划理论基础、509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯

今天开始动态规划的部分! 其实说白了,动态规划我感觉就是找类似递归的规律, 动态规划理论基础 动态规划,英文:Dynamic Programming,简称DP,如果某一问题有很多重叠子问题,使用动态规…

基于神经网络的手写数字识别系统

基于神经网络的手写数字识别系统 结合模板匹配和神经网络两种方法进行手写数字识别。这个系统包括图像预处理、特征提取、神经网络训练和可视化分析。 %% 基于神经网络的手写数字识别系统%% 清理工作区 clear; clc; close all;%% 加载手写数字数据集 % 使用MATLAB自带的手写数字…

机器学习?一文看懂这门热门技术

🌟 什么是机器学习?一文看懂这门热门技术在人工智能(AI)的大潮中,机器学习(Machine Learning, ML) 无疑是最耀眼的明星之一。它让计算机具备了 “自我学习” 的能力,让自动驾驶、智能…

Spring的初始化钩子

1. PostConstruct JSR-250 标准注解(不是 Spring 独有),用来标记 Bean 初始化完成后要执行的方法。会在 Bean 的构造方法执行完、依赖注入完成后执行。 使用实例: Component public class Demo {PostConstructpublic void init() …

【AI】Java生态对接大语言模型:主流框架深度解析

文章目录1. Deep Java Library (DJL)2. LangChain4j(LLM)3. HuggingFace Inference API4. OpenAI Java Client技术对比矩阵架构设计建议在人工智能浪潮下,大语言模型(LLM)已成为技术核心。Java生态通过以下框架实现高效…

【06】C#入门到精通——C# 多个 .cs文件项目 同一项目下添加多个 .cs文件

文章目录1 单个 .cs文件2 创建 多个 .cs文件2.1 添加Hero类2.1 添加ShowInfo类2.3 关于命名空间的引用2.4 所有.cs文件代码3 test3项目文件下载1 单个 .cs文件 上一讲中 描述游戏中英雄的角色 所有代码在一个.cs文件中, 如果代码很多,类很多&#xff0…

【MySQL基础篇】:MySQL常用数据类型的选择逻辑与正确使用

✨感谢您阅读本篇文章,文章内容是个人学习笔记的整理,如果哪里有误的话还请您指正噢✨ ✨ 个人主页:余辉zmh–CSDN博客 ✨ 文章所属专栏:MySQL篇–CSDN博客 文章目录数据类型1.数据类型分类2.数值类型int整形类型bit位类型float小…

三、搭建springCloudAlibaba2021.1版本分布式微服务-springcloud loadbalancer负载均衡

什么是负责均衡 Spring Cloud LoadBalancer是一个客户端负载均衡器,类似于Ribbon,但是由于Ribbon已经进入维护模式,并且Ribbon 2并不与Ribbon 1相互兼容,所以Spring Cloud全家桶在Spring Cloud Commons项目中,添加了Sp…

Oracle不完全恢复实战指南:从原理到操作详解

核心提示:当误删表、日志损坏或控制文件丢失时,Oracle的不完全恢复是DBA最后的救命稻草。掌握关键恢复技术,可在数据灾难中力挽狂澜。一、不完全恢复核心概念 1. 核心特点 必须关闭数据库:在MOUNT状态下执行重做日志恢复权限要求&…

Linux之shell脚本篇(二)

一、shell编程之if语句引言Linux在shell编程中,通常都是以自上而下运行,但是为了提高其代码严谨性,我们即引入了多条件 控制语句例如:if、for、while、case等语句,有时候针对条件我们还会结合正则表达式去运用。将这些…

如何在android framewrok dump camera data

实现dump 函数 实现1 void dumpBufferToFile(buffer_handle_t* buffer, int width, int height, int frameNum) {void* data NULL;GraphicBufferMapper::getInstance().lock(*buffer, GRALLOC_USAGE_SW_READ_OFTEN, Rect(width, height), &data);char filename[128];sprin…

机器学习中的可解释性:深入理解SHAP值及其应用

机器学习可解释性的重要性在人工智能技术快速发展的2025年,机器学习模型已经深度渗透到医疗诊断、金融风控、司法量刑等关键领域。然而,随着模型复杂度的不断提升,一个根本性矛盾日益凸显:模型预测性能的提升往往以牺牲可解释性为…