{"content":{"title":"Optimism和OP Stack学习","body":"# 整体流程：\r\n**deposit和发交易：**\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/bfb772b0-43ec-4b93-9b77-210516f3d5fe.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/JhkeOgzj65ebd80dd0dad.png)\r\n**withdraw:**\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/07756daf-7959-438e-a407-c3c7ebc4dfbf.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/c059cy2o65ebd820c96fe.png)\r\n\r\n**OP主网安全模型**：\r\n目前OP主网的安全性依赖于多签，由几个匿名人士掌握着这些钱包。\r\n在 OP 主网中，区块每两秒生成一次，即使没交易也会生成空区块。每个L2区块都归属于epoch，epoch是指L2区块归属于的L1块，这个L1块一般是几分钟前的某个L1块。epoch的编号等于L1上对应块的号。L2块一般由epoch和它在epoch中的序号标识。\r\nepoch的第一个块中包含了所有从L1发往L2的交易（统称deposit）。如果Sequencer忽略了某个deposit交易，这也算是作恶，会被抓出来。\r\n**OP交易处理流程**：\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/c9d9ec26-3dba-4f66-b790-e53a1f388164.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/aFeaEJ6k65ebd84be4a93.png)\r\n**交易压缩**：\r\n由op-batcher完成。它有两个功能：\r\n● 将交易压缩成批次。\r\n● 将这些批次发布到 L1 \r\n当通道满了，或者超时时，就会把压缩交易发布到L1。\r\n超时时间：\r\n以L1的区块时间来计算，5个块，5*12=60s \r\n压缩：\r\n有两个参数可以控制压缩：\r\n    ○ L1上的目标大小。--target-l1-tx-size-bytes\r\n    ○ 预期的压缩比：--approx-compr-ratio\r\n**交易发布**\r\n当通道已满时，它会作为单个事务或多个事务（取决于数据大小）发布到 L1。\r\n已处理的 L2 事务存在以下三种状态之一：\r\n● 不安全：交易已被处理，但尚未写入 L1。某些情况可能会导致这些事务被丢弃。\r\n● 安全：交易已被处理并写入 L1。此时如果L1区块重组，还是有可能会被删除。\r\n● 最终确定：交易被写入 L1 ，且已经足够老以完成确定。\r\n**交易处理**\r\n交易处理分为两步：\r\n1. op-geth处理交易，获得新的世界状态\r\n2. 由op-proposer将merkle根提交到L1\r\n**Deposit**\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/9ac20a6b-fb72-49db-ab3e-6dfe2958422f.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/DbjsBYgO65ebd87607c23.png)\r\n**L1上的处理**\r\n1. EOA或者合约，调用L1CrossDomainMessenger的sendMessage，有3个参数（例子）\r\n    a. _target，L2上的目标地址\r\n    b. _message，L2交易的calldata，ABI编码\r\n    c. _minGasLimit，这个需要注意，这是最小值。在L2上执行时，gasLimit比这个值只大不小，因为还有一些前置工作要做。\r\n2. L1CrossDomainMessenger调用自己的_send函数，参数如下：\r\n    a. _to，目标地址，对deposit来说，始终是0x4200000000000000000000000000000000000007\r\n    b. _gasLimit\r\n    c. _value，发送到L2的ETH，取自msg.value\r\n    d. _data，要中继的数据\r\n3. _sendMessage，调用portal的depositTransaction接口。注意其他合约也可以调用depositTransaction，但这样会绕过一些数据审查，所以不推荐。\r\n4. depositTransaction做一些安全检查，然后发出TransactionDeposited事件。\r\n**L2上的处理**\r\n1. op_node检查收到的TransactionDeposited事件，有的话就解析它\r\n2. op_node将事件depositedTransaction.\r\n3. 多数情况下，调用 L2CrossDomainMessenger的relayMessage处理\r\n4. relayMessage做一些安全检查，没问题的话，使用relay的calldata,调用真正的目标合约。\r\n**DOS处理**\r\ndeposit交易是在L1发起，L2执行的。所以L1上的费用由用户支付，L2上的费用由OP节点支付。因此需要引入一个gasLimit来防止DOS攻击。这个gasLimit是在TransactionDeposited事件里写入的，在L1上完成收费。\r\nhttps://github.com/ethereum-optimism/optimism/blob/62c7f3b05a70027b30054d4c8974f44000606fb7/packages/contracts-bedrock/contracts/L1/ResourceMetering.sol#L162\r\n**Withdraw**\r\n从L2发往L1的交易统称withdraw。withdraw需要发3笔交易：\r\n1. 在L2上发起提款交易\r\n2. 在L1上提交提款证明，这是一个基于L2ToL1MessagePasser的merkle根证明\r\n3. 挑战期结束后，在L1上执行交易，取走资产。\r\n具体交易流程见https://community.optimism.io/docs/protocol/withdrawal-flow/#withdrawal-initiating-transaction\r\n\r\n# OVM和欺诈证明\r\n参考：https://medium.com/taipei-ethereum-meetup/optimistic-rollup-%E7%9A%84%E6%8C%91%E6%88%B0%E6%A9%9F%E5%88%B6-%E4%B8%80-optimism-ovm-1-0-2b6a8e9d64cd\r\n这部分是OP的核心，即如何在L1上完成欺诈证明挑战。\r\nOptimism出过两个版本，V1和V2，分别看下。\r\n## OVM V1\r\n核心思想是：交易是在L2运行的，状态根提交到了L1上。当有人发现提交到L1的状态根不对（某笔交易的执行结果不对）时，需要在L1上发起挑战。挑战就是在L1上把这笔交易重新执行一遍，看是谁错了，如果挑战成功，就得回滚。\r\n所以这里的重点是：从L1重新部署L2上的合约，然后执行挑战的那笔交易，比较结果。\r\n难点是：在L1上，Context都跟L2上执行时不一样，如何在L1上重现L2的执行环境+上下文？这里上下文包括如：block.time，block.height, msg.sender等，其中最关键的是:SLOAD，也就是执行中用到的状态。这些如何处理？\r\nOP修改了编译器，把这些相关的opcode的处理做了定制化。所以同一套solidity代码，在OP上部署时，需要用OVM compiler重新编译，里面所有跟Context相关的都变了。\r\n以SLOAD为例，它会加载storage里的状态，实际上这个状态需要提前在L1上先用一笔交易填上去，然后下次执行挑战交易的时候，SLOAD执行的时候就能读出正确数据了。注意交易里所有SLOAD要用到的值全都得加载进去。\r\n提前加载的交易是否能加载错误数据来影响挑战结果呢？不行。因为这个是有merkle证明的，要符合merkle证明的才能被加载进去。\r\n使用这些被OP改过的opcode，就可以在L1上完美执行来自L2的交易，完成裁决。这种方法也叫EVM in EVM。\r\n这种方案是有很多代价的：\r\n● 需要修改编译器，所以有的工具在OP没法直接用，得重新编写才行。geth等很多东西都得改。\r\n● 合约大小限制。目前合约限制24kb左右，OP的编译器会导致编译结果变大约15%，所以实际合约大小限制是20.8kb左右。对于本就受此限制影响的合约来说，更难了。\r\n● 为了防止SLOAD需要在L1加载的数据过多，导致挑战消耗的gas过大，L2上一个交易一个块。\r\n\r\n## OVM V2\r\n这个新的OVM方案叫做Cannon，文档：https://medium.com/ethereum-optimism/cannon-cannon-cannon-introducing-cannon-4ce0d9245a03\r\nV1的缺点是：需要修改编译器，geth等，导致很多工具都得改，对开发者不友好，维护也很困难。而且一个交易一个块。\r\n所以对以上重新思考后，推出了OVM V2，即Cannon。Cannon的主要价值是：可以在L2上运行跟L1上完全一样的EVM。即实现了EVM等效性。\r\nOVM的出发点还是如何进行作恶挑战。这是个交互式的挑战过程。在V1里，挑战的是一个交易，在V2里，挑战的是一个opcode。因此首先需要考虑要解决哪些问题：\r\n1. 如何定位到要挑战的opcode。\r\n2. 要挑战一笔opcode，应该需要哪些数据\r\n3. 如何在L1挑战一笔opcode。\r\n执行opcode时，有哪些内容会影响到它的执行呢？\r\n● 一些全局变量，如op, pc, gas, depth等\r\n● stack\r\n● memory\r\n● storage\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/fd4a1d09-2acc-412f-ba2e-faf6f9c94c46.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/de6ck2P865ebd8ddc33c5.png)\r\n这些在执行时都是确定性的。因此如果我们把一笔交易拆开细化来看，每一个opcode执行完之后，都会有个确定的状态，这个状态可以被提取出来，形成merkle树，用树根就可以表达这个状态。\r\n然后，我们通过比较挑战者和守护者的这个状态树根，用二分法来查找哪个opcode出现分歧。这应该很快，但它是交互式的，所以。。。未必很快。\r\n\r\n这里有几个问题：\r\n1. 用EVM来表达上面这些状态方便吗？不方便的，用go方便，因为是现成的，就是geth。而且用geth的话，升级很方便。\r\n2. 在L1里，用EVM来模拟EVM，即V1的那种EVM in EVM，是必须的吗？能不能otherthing IN EVM？其实是可以的。\r\n因此，考虑一种新的方案：MIPS in EVM 。所以最终结果是：\r\nOP对geth进行了裁剪，只留下了执行opcode相关的部分，称为mini geth。把minigeth编译成了MIPS opcode代码。用合约实现了MIPS opcode（才不到400行）。\r\n烧脑开始：\r\nCannon官方的解释是：\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/60576c9a-6b3b-477f-acf1-6abe3ab0d46f.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/1neutKSW65ebd8f46d519.png)\r\n所以在L2上，是：\r\ngo代码执行mini geth,  mini geth里运行EVM， EVM上运行MIPS的合约，合约里模拟的是mini geth， 上面运行的是EVM。\r\n在L1上，是：\r\nEVM上运行MIPS合约，合约里模拟mini geth，上面运行EVM。\r\n这样，在L1和L2上，就统一起来了，从以前的EVM兼容，变成了EVM等效。这样也不必再改编译器那些东西了，L1和L2上运行的是一样的合约，因为这个合约是从相当于一个mini geth模拟器里执行的。\r\n**preImage Oracle**\r\n但上面的东西只是完成了执行层面的一致性，L1上挑战时，还是得加载L2上的状态值才行。这通过preImage Oracle完成。\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/714528ca-f543-4b4b-9291-7ecf00edea15.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/rNpLHFDg65ebd9141d1d1.png)\r\n以太坊里的状态存在一棵树里，其实底层是通过一个个key-value对存储的。\r\n例如要取node4的值，就先拿到root，然后node1，然后node4，是个递归过程。minigeth通过不停询问preImage Oracle最终获得需要的值。这个方式在链上和链下都可以做。\r\n对链上，需要挑战者和被挑战者先把这些需要的值load到oracle里，后续在执行中就会通过oracle获取。在链下时就是通过rpc服务获取。\r\n另外，对一些区块context的oracle可以直接在L1的块头中获得。例如可以把L2的一个epoch的块，其context都设置为一个L1上的块，这样在执行这个epoch内的所有交易时，对Context的获取都可以直接从L1块头中，而不需要用oracle专门写入了。\r\n**扩展**：\r\n既然EVM能模拟MIPS，那也可以模拟其他指令集，所以L2上就可以执行非EVM的虚拟机了。\r\n\r\n# OP Stack\r\nOP Stack 是一套为 Optimism 提供支持的软件——即当前 Optimism 主网使用的软件。它最终将以 Optimism 超级链及其治理的形式出现。\r\n随着超级链概念的出现，对于 Optimism 来说，轻松创建可在超级链生态系统中互操作的新链变得越来越重要。因此，OP Stack 主要专注于创建一个共享的、高质量的、完全开源的系统，用于创建新的 L2 区块链。通过协调共享标准\r\n随着Optimism的发展，OP 堆栈也会发展。尽管 OP Stack 目前的核心是运行 L2 区块链的基础设施，但 OP Stack 理论上可以扩展到底层区块链之上的层，包括区块浏览器、消息传递机制、治理系统等工具。\r\n**现状**\r\nOptimism Bedrock 是 OP Stack的当前迭代。Bedrock 提供了用于启动 Optimistic Rollup 的工具。\r\n今天的 OP Stack是为了支持Optimism Superchain 构建的，这是一个拟议的 L2 网络，共享安全性、通信层和通用开发堆栈（OP Stack本身）。OP Stack 的 Bedrock 版本可以轻松启动 L2，该 L2 启动时将与超级链兼容。OP 堆栈是一个不断发展的概念。它随着Optimism的增长而增长。\r\n**架构**\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/e2736c1d-70d1-46a6-ab50-40369dbcd617.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/hbA54QMr65ebd93fd920c.png)\r\n并不是所有东西都已经是生产状态。上图中的部分内容不是最新的。例如cannon已经被部署了。\r\n**Derivation**\r\nDerivation层用来对DA层的数据进行解释，将其翻译为可以直接用标准以太坊API作为执行输入的参数。Derivation层一般与DA层紧密耦合，因为它们配合在一起工作。\r\n**结算层**\r\n结算层用于在外部链（如L1 以太坊）上建立对OP链的视图（view），从而了解当前OP链的状态情况。结算层对外部链来说是只读的，可以让外部链通过这个view来做出决定，如从L2到L1的提款请求。\r\n## 超级链\r\n一个去中心化的区块链平台，由许多共享安全性和技术堆栈（OP Stack）的链组成。互操作性和标准化使工具和钱包能够同等对待各个链。\r\n超级链是一个 L2 链网络，其中每条链称为 OP 链，它们共享安全性、通信层和开源技术堆栈。然而，与多链设计不同，这些链是标准化的，旨在用作可互换的资源。这使得开发人员能够构建以整个超级链为目标的应用程序，并抽象出应用程序运行的底层链。\r\n\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/677c2815-ec64-40c0-ac00-879597dc2931.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/kzS1bImr65ebd95ccaf24.png)\r\n\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/e8da20c0-3863-48c1-a47d-cc3d346c5ac8.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/69BtPXVu65ebd96d7a24d.png)\r\n## 将OP升级为超级链需要做哪些事（概述）\r\n以下内容，需要逐一确认是否已经ready，可能已经好了，但是文档没更新。\r\n**将BedRock桥升级成为链工厂**\r\nBedRock在L1上部署合约用来定义L2链。包括链id，key定义，gas Limit等。\r\n（这应该是待实现的）一旦链的定义数据在链上了，我们就可以创建一个工厂合约，为每条链来部署链配置，以及其他所需的合约。用CREATE2，就可以在有了链配置后，就把链桥的地址确定下来。这可以让链继承标准安全性。\r\n**使用链工厂导出OP Chain的数据**\r\n通过L1链，可以获得所有标准OP Chain的数据。OP节点应该可以在给定单个 L1 地址和到 L1 的连接的情况下确定性地同步任何OP 链。\r\n当OP链同步时，链状态在本地计算。这意味着确定 OP 链的状态是完全无需许可且安全的。链推导不需要证明系统，因为所有无效交易都会被节点执行的本地计算过程忽略。然而，仍然需要一个证明系统来启用超级链withdraw。\r\n**用来withdraw的无需许可的证明系统**\r\n在Bedrock中，有一个permissioned的提款交易提交者，并且用户提款需要在L1上规定时间内提交特定交易。在未来，这将被修改。特定permissioned的提款交易提交者将被消除，任何人都可以提交提款申请。\r\n**每个链可配置的Sequencer**\r\n**所有链共享升级路径**\r\n为了使初始超级链对安全性和去中心化充满信心，引入去中心化的安全委员会来管理升级。安全委员会应该能够更新链证明者集，延迟启动合约升级，并按下紧急桥暂停按钮，这也会取消待处理的升级。\r\n在紧急情况下暂停桥梁的能力意味着，在最坏的情况下，即安理会参与者的私钥泄露的必要阈值，结果将是无限期暂停提款，桥梁升级将永久取消。换句话说，L1资金将被冻结。\r\n## Bedrock\r\n组成：\r\n\r\n● op-node\r\n● op-geth\r\n● op-batcher\r\n● op-proposer\r\n● contracts-bedrock\r\n● fault-detector\r\n● sdk\r\n● chain-mon\r\n数据可用性来自两个来源：\r\n1. Sequencer发布到L1上的rollup数据\r\n2. L1上调用deposit发往L2的交易。\r\n协议包括以下主要部分：\r\n● deposit通过直接与 L1 上的智能合约交互而写入canonical L2 链。\r\n● withdraw是写入canonical L2 链，隐式触发与 L1 上的合约和账户的交互。\r\n● Batches是与汇总上的批次相对应的数据写入。\r\n● 区块Derive是如何解释 L1 上的数据以理解canonical L2 链。\r\n● 证明系统定义了L1 上发布的输出根的最终性，以便它们可以被执行（例如，执行withdraw）。\r\n**BlockDerivation**\r\n协议保证在L1上deposit的时间顺序，在L2上也能被重现。\r\n在L2上，每个epoch的开头第一个块必须包含从L1上发来的deposit交易。L2区块的交易时间戳与L1的保持一致。\r\n**RollUp Node**\r\nBedRock上没有共识。共识是由Derivation完成的。执行客户端连接到定义block derivation的客户端，称为Rollup node。\r\nrollup node是没有状态的。它负责通过从L1上读取data和deposite交易来导出系统状态。在bedrock里，rollupnode既可以为用户或其他rollupnode发来的交易排序，也可以通过单独依赖 L1 来验证在 L1 上发布的已确认交易。\r\n下面是它的用途：\r\n验证L2 canonical chain:\r\n运行rollup node的最简单方式是仅follow L2 canonical chain。此方式下不需要连接到其他的rollup node，仅仅从L1读取calldata，并且通过derivation规则来解析数据。\r\n此类节点的目的是为了验证L1上的输出根是否正确。\r\n看起来这像是L2的轻节点。\r\n**参与L2网络**\r\n最常见的用法是参与L2的网络，跟踪 L2 的进度和状态。 在此模式下，汇总节点不仅从 L1 读取数据和deposite交易，并将其解释为块；而且接受其他rollup node网络的用户和peer的交易。\r\n此网络的roll up 节点使用安全或者不安全的块头。安全的块头指来自L1的块头，无论它是否已终结；不安全的块头是指还没有提交到L1的块头，它来自sequencer或其他rollup node。当出现分歧的时候，总是相信L1的安全块头。对大部分dapp来说，可能它们用的是不安全的块头，因为这些块头更新。\r\n**L2交易排序**\r\nRollup node的第三个用法是对L2的交易排序。也就是在不安全的块头上出新块，即Sequencer。注意当前OP网络里只有一个Sequencer。Sequencer也负责把L2块rollup到L1。\r\n**Batcher**\r\nBatcher和rollup node都是sequencer的组件，Batcher从rollup node读取tx数据并将其解释为要写入 L1 的批处理事务。 批处理程序组件负责读取由排序器运行的rollup node的不安全 L2 头、创建批处理程序事务并将其写入 L1。\r\n**Standard Bridge Contracts**\r\n就是L1和L2之间的桥，负责ETH和ERC20代币的转移。一边是原生代币，另一边是包装币。\r\n\r\n## BedRock和L1的差异\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/75fc69d4-5993-4768-8f9f-9429a8e2b93f.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/qTboZbXI65ebda4219361.png)\r\n如果在L2想获得最近的L1的数据（也就是下次打包用的L1的Context，即这些L2交易被“认为打入”的L1的Context），可以用getter函数访问合约L1Block。是个预置合约，0x4200000000000000000000000000000000000015\r\n● number: The latest L1 block number known to L2\r\n● timestamp: The timestamp of the latest L1 block\r\n● basefee: The base fee of the latest L1 block\r\n● hash: The hash of the latest L1 block\r\n● sequenceNumber: The number of the L2 block within the epoch (the epoch changes when there is a new L1 block\r\n**地址别名**\r\n由于CREATE操作码的特性，用户可以在L1和L2上创建相同地址的合约，这可能会引入作恶行为。因此对tx.origin和msg.sender的行为，在L1和L2上有一定差异。\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/770665ae-72e0-45d5-b6b3-66f75f72d511.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/F0NwCwtl65ebda5c87939.png)\r\n即，如果是EOA调用的话，在L2上跟L1是一样的。但是如果是L1的合约调用的话（即用L1合约调用deposite），tx.origin是L1合约地址加一个固定字符串。\r\nmsg.sender在第一层调用时，总是等于tx.origin，所以也会受上面规定的影响。一般来说，不能用tx.origin作为授权的检测。\r\n**块生产**：\r\n<!--StartFragment-->\r\n\r\n![](https://alidocs.oss-cn-zhangjiakou.aliyuncs.com/res/2M9qPmLJrm1kO015/img/36f86143-5223-4a4f-8d53-d67966547843.png)\r\n\r\n<!--EndFragment-->\r\n\r\n![image.png](https://img.learnblockchain.cn/attachments/2024/03/dt5aWiDS65ebda694e876.png)\r\n**其他**：\r\n● JSON RPC：OP的JSON RPC除了完全支持以太坊部分外，还引入了一些针对OP的特定接口。\r\n● EIP-155：在EIP-155之前的交易不支持链id，这可能引入重放攻击，所以OP默认不支持EIP155之前的交易。\r\n● 交易成本：OP的执行成本包括在L2上的执行成本和L1的数据成本。"},"author":{"user":"https://learnblockchain.cn/people/13806","address":null},"history":null,"timestamp":1709955803,"version":1}