
Skandha BundlingService 深度解析从 Classic 到 Flashbots 的 6 种 Relayer 提交流程【免费下载链接】skandhaA modular typescript implementation of ERC4337 (Account Abstraction) bundler client.项目地址: https://gitcode.com/gh_mirrors/sk/skandhaSkandha 是一个模块化的 TypeScript 实现的 ERC4337账户抽象Bundler 客户端。它的核心服务 BundlingService 负责把内存池Mempool中的 UserOperation 打包成 Bundle再通过可插拔的 Relayer 提交到链上。本文将带你完整拆解 BundlingService 的打包流程以及 Classic、Flashbots、Merkle、Kolibri、Echo、Fastlane 这 6 种 Relayer 提交流程的差异与适用场景帮助你快速理解 Bundler 的工作机制。 什么是 BundlingServiceBundler 内部的“总调度台”在 ERC4337 体系中Bundler 的角色是收集 → 验证 → 打包 → 提交。BundlingService 就是“打包 提交”这一步的总调度台核心实现位于 BundlingService/service.ts。它有三个关键能力定时打包auto模式下按bundleInterval周期自动触发sendNextBundle()也可通过 API 手动触发动态调参支持运行时修改打包模式、打包间隔、最大 Bundle 大小可插拔提交根据配置relayingMode选择不同 Relayer 实现默认使用 Classic一次完整提交流程sendNextBundle 拆解以 service.ts 中的sendNextBundle()为例整个流程可以概括为 6 步抢占全局锁用async-mutex保证同一时刻只有一个打包流程在运行检查 Relayer 可用性调用canSubmitBundle()并统计空闲 Relayer 数量配置了多个签名钱包时可并行发送多个 Bundle拉取待打包 UserOp从 MempoolService 取出最新排序的条目按 sender 分组每个账户只取最新一笔清理“老赖”条目提交失败超过最大次数的条目直接标记为 Cancelled获取 Gas 费用通过 Gas Price Oracle 获取链上价格并按gasPriceMarkup加价组装 Bundle 并提交调用createBundle()做二次筛选最后交给 Relayer 发送Bundle 组装时的 6 道“安检”createBundle()是质量把关最严的地方每一笔 UserOp 都要通过以下检查否则会被跳过甚至删除检查项不通过的后果累计 Gas 超过bundleGasLimit跳过该条目Gas 价格低于 Oracle 阈值enforceGasPrice跳过防止亏本打包Paymaster / Factory 信誉被 BANNED直接 Cancelled实体被 THROTTLED或同一 Bundle 内重复出现跳过同一 sender 已在 Bundle 内跳过nonce 冲突保护二次模拟验证失败或访问了其他 UserOp 的存储槽失败则 Cancelled冲突则跳过此外还会检查Paymaster 存款是否足够支付本笔 UserOp 的预付款prefund并为 EIP-2930 / 条件交易生成 accessList 与存储哈希。通过所有检查的条目才会进入最终 Bundle并被标记为Pending状态。 6 种 Relayer 提交流程全解析所有 Relayer 都位于 relayers/ 目录统一实现IRelayingMode接口见 interfaces.ts6 种模式的定义见 types 包的 executor/index.ts。先上一张速览表Relayer提交通道核心特点超时控制Classic公共eth_sendRawTransaction最简单直接进公共 Mempool无FlashbotsBuilder / Protect 私有通道交易不上公共 Mempool防抢跑由 Builder 决定MerkleMerkle 私有池 RPC提交后轮询私有池交易状态2 分钟KolibriKolibri 私有池OFA 优化 禁止回滚由 Kolibri 返回建议等待时间EchoEcho 私有 Mempool逐块重试直到确认包含5 分钟FastlanePolygon Fastlane条件交易 验证者白名单10 分钟1️⃣ Classic最朴素的公共 Mempool 提交实现见 relayers/classic.ts。流程非常直接编码handleOps交易选择 EIP-1559 或 legacy gas 格式用eth_estimateGas做整包预执行检查validateBundle失败则取消整个 Bundle 并上报指标本地签名通过eth_sendRawTransaction广播若开启条件交易则用eth_sendRawTransactionConditional附带knownAccounts存储映射支持rpcEndpointSubmit配置单独的提交 RPC也支持 EIP-7702 授权列表交易适合场景开发测试、对 MEV 不敏感的链。缺点是交易会暴露在公共 Mempool 中理论上可被抢跑。2️⃣ Flashbots防抢跑的明星选手实现见 relayers/flashbots.ts。它在构造函数中就强制要求配置rpcEndpointSubmitFlashbots API 地址提交过程有三个亮点eth_sendBundle格式提交把签名后的交易和“生效区块 当前区块 5”打包成 JSON-RPC 负载签名防篡改用钱包对负载做 keccak 签名放入X-Flashbots-Signature请求头防止中间人篡改双模式默认走eth_sendBundle也可配置为eth_sendPrivateTransaction即 Flashbots Protect 私有交易模式适合场景以太坊主网等 MEV 激烈的环境是目前生产 Bundler 最常用的私有提交方案。3️⃣ Merkle提交 状态轮询双保险实现见 relayers/merkle.ts。需要同时配置rpcEndpointSubmit和merkleApiURL两个地址交易先通过eth_sendRawTransaction发送到 Merkle 私有池 RPC随后每 2 秒轮询{merkleApiURL}/transaction/{hash}查询私有池状态若状态为nonce_too_low、base_fee_low等可重试错误触发 rebundle 重新提交2 分钟未找到交易则超时适合场景需要私有池且想要明确失败原因的团队。4️⃣ Kolibri一次提交策略托管实现见 relayers/kolibri.ts。Kolibri 是 Polymesh 生态的私有交易池Skandha 通过其专属方法check_and_submit_bev提交并在参数里声明了明确的安全策略ofa_config启用 OFA优化防抢跑配置且allow_front_run: falsesubmit_config私有模式提交禁止回滚、不回退公共池适合场景追求“提交即托管”、不想自己处理重试逻辑的用户。5️⃣ Echo逐块重试直到上链实现见 relayers/echo.ts。需要配置echoAuthKey通过x-api-key请求头鉴权。它的提交策略非常执着监听新块每出块就向“下一个区块”发起eth_sendBundle携带awaitReceipt: true与usePublicMempool: false确保只在私有 Mempool 生效收到included状态才算成功timedOut则下块继续重试最长坚持 5 分钟适合场景要求“必须进块、绝不进公共池”的高确定性场景。6️⃣ FastlanePolygon 专属高速通道实现见 relayers/fastlane.ts。这是专为 Polygon 设计的模式门槛也最高强制要求开启条件交易conditionalTransactions并配置rpcEndpointSubmit提交前通过bor_getCurrentValidators检查配置的 Fastlane 验证者是否在当前验证者集合中不在则本轮放弃使用pfl_sendRawTransactionConditional提交附带约 10 分钟的区块窗口最新区块 180与 15 分钟的时间戳窗口每块重试一次10 分钟超时若验证者退出 Fastlane 协议会自动等待重试适合场景在 Polygon 上追求极速、私有打包的 Bundler。️ 共同的地基BaseRelayer6 种 Relayer 都继承自 relayers/base.ts 的BaseRelayer抽象类它提供了所有模式共享的能力多钱包并行从配置读取多个签名钱包config.getRelayers()每个钱包一把独立互斥锁允许同时推进多个 Bundle收款地址选择selectBeneficiary()优先使用配置的受益人地址当签名钱包余额低于minSignerBalance时自动改为自己收款保证手续费能持续支付失败处理handleUserOpFail()解析FailedOp错误——Paymaster 崩溃就记入信誉系统、Factory 的 AA1x 错误就惩罚工厂、普通回滚则标记 Reverted其余错误把 UserOp 放回 Mempool 等待重试等待确认waitForEntries()轮询 Mempool直到 EventService 处理完UserOperationEvent为止监控指标上报bundlesSubmitted、useropsSubmitted、useropsTimeToProcess等指标数据由 monitoring 包 采集⚙️ 如何切换提交流程模式由网络配置项relayingMode决定默认值为classic见 config.ts也支持通过环境变量覆盖。可选值完整列表在 types 包 中定义classic | flashbots | merkle | kolibri | echo | fastlane需要注意一个现状细节当前 BundlingService 构造函数 的运行时分支只启用了flashbots与classic未匹配到 flashbots 时一律回退 classic其余 4 种实现代码完整保留在代码库中并已纳入 RelayerClass 类型按注释中的分支逻辑即可重新启用。 总结BundlingService 是 Bundler 的打包引擎定时/手动触发从 Mempool 拉取、五重安检后组装 Bundle再委派给 Relayer6 种 Relayer 覆盖不同诉求Classic 求简单Flashbots 求防抢跑Merkle 求状态可查Kolibri 求策略托管Echo 求上链确定性Fastlane 求 Polygon 极速私有打包BaseRelayer 提供统一底座多钱包并行、失败降级、信誉惩罚、指标上报想动手实践可参考 executor 包 README 与根目录的 config.json.default 配置文件理解了这 6 条提交流程你就掌握了 Skandha 从“一笔 UserOp 进池”到“安全上链”的完整生命周期也具备了为不同链选择最优 Relayer 的能力。【免费下载链接】skandhaA modular typescript implementation of ERC4337 (Account Abstraction) bundler client.项目地址: https://gitcode.com/gh_mirrors/sk/skandha创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考