Optimism Bedrock是当前版本的OP Stack,提供了启动生产质量的Optimistic Rollup区块链的工具。它包括op-batcher和op-proposer两个服务,负责从sequencer读取交易内容并rollup到链上,以及将交易状态rollup到合约。文中介绍了如何使用recordL1Tip和l1Tip来获取最新的L1BlockRef,以及如何收集和提交交易数据。每个事务仅使用一帧,如果通道已满,则仅返回剩余帧,直到成功发送到L1。sendTransaction将交易发送到一层,并更新交易发送状态。FetchNextOutputInfo获取L2上的区块output,NextBlockNumber获取下一批次需要提交的区块区间,SyncStatus获取L2块的状态和块信息,OutputAtBlock根据块高获取output,sendTransaction使用output构建stateRoot提交交易到一层链。
原文作者:Rayer
原文来源:登链社区
Optimism Bedrock 是 OP Stack 的当前版本。Bedrock 版本提供了用于启动生产质量的 Optimistic Rollup 区块链的工具。此时,OP Stack 不同层的 API 仍然与 Stack 的 Rollup 配置紧密耦合。
Op-stack 主要的 rollup 由两个服务来承担。
op-batcher 执行流程图
loadBlocksInfoState 执行逻辑
loadBlocksInfoState 负责读取,从前一次读取的块开始的所有块,即还未读取的块。
其整体流程如下
代码如下:
loadBlocksIntoState 完成了以下动作
1、获取 sequencer 中的同步状态
2、153 行,调用calculateL2BlockRangeToStore函数
3、164 行,拿到提交的开始块和结束区块之后,从起始区块开始获取区块信息,调用loadBlockIntoState 函数获取区块
4、165 行至 168 行,校验区块是否需要重新提交,若需要,将 l.lastStoredBlock 置成 eth.BlockID{};173 行,否则就将 l.lastStoredBlock 置成 eth.ToBlockID(block);latestBlock 置成 block;
5、177 行,L2BlockToBlockRef 从 L2 块引用源中提取基本的 L2BlockRef 信息,根据区块号判断必要时回退到创世信息
publishStateToL1 执行逻辑
publishStateToL1 将队列中的所有交易提交到 L1,直到队列中没有交易或者出现错误为止。
代码如下:
1、publishStateToL1 会循环将队列里的交易发送到 Layer1 网络。
2、377 行调用publishTxToL1。
publishTxToL1 是提交单个交易到 L1 的逻辑,publishTxToL1 方法获取要提交的数据数据构建交易发送到 Layer1 网络,并将发送出去的交易扔到 receiptCh chan TxReceipt[T] channel 里面。
handleReceipt
handleReceipt 获取从 channel 处理交易的状态,并将成功处理的交易从 channel 里面移除。
代码如下:
op-proposer
FetchNextOutputInfo
FetchNextOutputInfo: 获取 L2 上的区块的 output,方便后续组装提交。返回的 output 结构如下:
type OutputResponse struct {Version Bytes32 json:"version"OutputRoot Bytes32 json:"outputRoot"BlockRef L2BlockRef json:"blockRef"WithdrawalStorageRoot common.Hash json:"withdrawalStorageRoot"StateRoot common.Hash json:"stateRoot"Status *SyncStatus json:"syncStatus"}
代码如下:
FetchCurrentBlockNumber 代码如下:
1、254 行,SyncStatus:获取 L2 块的 SafeL2 和 FinalizedL2 的状态和块信息,
FetchOutput 代码如下:
2、279 行,OutputAtBlock: 根据块高获取 output, 里面包含 stateRoot,这里最终是调用 eth_getProof 去计算并获取 stateRoot,代码调用流程可以参考上图。提示: 这里并不是一个块提交一次 stateRoot, 而是根据 SUBMISSION_INTERVAL 配置的值来计算一批块的 stateRoot,最终将 stateRoot 提交到 L2OutputOracle 合约
return abi.Pack( "proposeL2Output", output.OutputRoot, new(big.Int).SetUint64(output.BlockRef.Number), output.Status.CurrentL1.Hash, new(big.Int).SetUint64(output.Status.CurrentL1.Number))
代码如下: