区块链NFT投资,BTC/USDT/CGPAY,虚拟加密货币交易行情分析平台
深入理解以太坊二层方案 Arbitrum 技术架构
百款NFT链游免费玩 | 数字货币支付图解教程 | 区块链游戏获利技巧 |
简单来说,Arbitrum 在 Layer 2 实现了 AVM 虚拟机,在虚拟机上再模拟 EVM 执行环境。
推荐阅读:《》
Arbitrum 是 Layer2 Rollup 的一种方案。和 Optimism 类似,状态的终局性采用「挑战」(challenge) 机制进行保证。Optimism 的挑战方法是将某个交易完全在 Layer1 模拟执行,判断交易执行后的状态是否正确。这种方法需要在 Layer 1 模拟 EVM 的执行环境,相对复杂。Arbitrum 的挑战相对轻便一些,在 Layer1 执行某个操作(AVM),确定该操作执行是否正确。Arbitrum 介绍文档中提到,整个挑战需要大概 500 字节的数据和 9w 左右的 gas。为了这种轻便的挑战机制,Arbitrum 实现了 AVM 虚拟机,并在 AVM 虚拟机中实现了 EVM 的执行。AVM 虚拟机的优势在于底层结构方便状态证明。
Arbitrum 的开发者 详细介绍了 Arbitrum 架构和设计。对 AVM 以及 L1/L2 交互细节感兴趣的小伙伴可以耐心地查看「Inside Arbitrum」章节。
整体框架
Arbitrum 的开发者文档给出了各个模块关系:
Arbitrum 的系统主要由三部分组成(图中的右部分,从下到上):EthBridge,AVM 执行环境和 ArbOS。EthBridge 主要实现了 inbox/outbox 管理以及 Rollup 协议。EthBridge 实现在 Layer1。ArbOS 在 AVM 虚拟机上执行 EVM。简单的说,Arbitrum 在 Layer2 实现了 AVM 虚拟机,在虚拟机上再模拟 EVM 执行环境。用 AVM 再模拟 EVM 的原因是 AVM 的状态更好表达,便于 Layer1 进行挑战。
EthBridge 和 AVM 执行环境对应的
ArbOS 对应的
这个模块关系图太过笼统,再细分一下:
EthBridge 主要实现了三部分功能:inbox,outbox 以及 Rollup 协议。inbox 中「存放」交易信息,这些交易信息会「同步」到 ArbOS 并执行。outbox 中「存放」从 L2 到 L1 的交易,主要是 withdrawl 交易。Rollup 协议主要是 L2 的状态保存以及挑战。特别注意的是,Arbitrum 的所有的交易都是先提交到 L1,再到 ArbOS 执行。ArbOS 除了对外的一些接口外,主要实现了 EVM 模拟器。整个模拟器实现在 AVM 之上。整个 EVM 模拟器采用 mini 语言实现,Arbitrum 实现了 AVM 上的 mini 语言编译器。简单的说,Arbitrum 定义了新的硬件(machine)和指令集,并实现了一种上层语言 mini。通过 mini 语言,Arbitrum 实现了 EVM 模拟器,可以执行相应交易。
AVM State
因为所有的交易都是在 AVM 执行,交易的执行状态可以用 AVM 状态表示。AVM 相关实现的代码在 arbitrum/packages/arb-avm-cpp 中。
AVM 的状态由 PC,Stack,Register 等状态组成。AVM 的状态是这些状态的 hash 值拼接后的 hash 结果。
AVM 使用 c++实现,AVM 表示的逻辑实现在 MachineStateKeys 类的 machineHash 函数(machinestate.cpp)中。AVM 的特别之处就是除了执行外,还能较方便的表达(证明)执行状态。深入理解 AVM 的基本数据结构,AVM 的基本的数据类型包括:
using value = std::variantTuple, uint256_t, CodePointStub, HashPreImage, Buffer>; enum ValueTypes { NUM, CODEPT, HASH_PRE_IMAGE, TUPLE, BUFFER = 12, CODE_POINT_STUB = 13 };
uint256_t - 整数类型
CodePoint - 当前代码指令表示
Tuple - 元组,由 8 个 Value 组成。元组中的某个元素依然可以是元组
Buffer - 数组,最长为 2^64
HashPreImage - 固定的 hash 类型,hashValue = hash(value, prevHashValue)
每种数据类型除了数据表示外,还能非常方便地计算其 hash 值作为状态。详细看看 CodePoint 和 Tuple 基本数据类型。
CodePoint
CodePoint 类型将多个操作「捆绑」在一起,每个 CodePoint 除了记录当前的 Operation 外,还包括前一个 CodePoint 的 hash 信息。这样所有的 Operation 可以串连起来,当前的 CodePoint 除了能表达当前的 Operation 外,还能明确 Operation 的依赖关系。CodePoint 的类型定义在:packages/arb-avm-cpp/avm_values/include/avm_values/codepoint.hpp。
struct CodePoint { Operation op; uint256_t nextHash; CodePoint(Operation op_, uint256_t nextHash_) : op(op_), nextHash(nextHash_) {} bool isError() const { return nextHash == 0 && op == Operation{static_cast(0)}; } };
Tuple
Tuple 类型由 RawTuple 实现。RawTuple 是由一组 value 组成。Tuple 限制最多 8 个 value。
struct RawTuple { HashPreImage cachedPreImage; std::vector data; bool deferredHashing = true; RawTuple() : cachedPreImage({}, 0), deferredHashing(true) {} };
Tuple 的类型定义在:packages/arb-avm-cpp/avm_values/include/avm_values/tuple.hpp。
在理解了基础类型的基础上,DataStack 可以由一系列 Tuple 实现:
总结一下,AVM 中的 PC,Stack,Register 等等的状态都能通过 hash 结果表示。AVM 整个状态由这些 hash 值的拼接数据的 hash 表示。
Rollup Challenge
在提交到 L1 的状态有分歧时,挑战双方(Asserter 和 Challenger)先将状态分割,找出「分歧点」。明确分歧点后,挑战双方都可提供执行环境,L1 执行相关操作确定之前提交的状态是否正确。L1 的挑战处理逻辑实现在 arb-bridge-eth/contracts/challenge/Challenge.sol。整个挑战机制有超时机制保证,为了突出核心流程,简化流程如下图所示:
挑战者通过 initializeChallenge 函数发起挑战。接下来挑战者 (Challenger) 和应战者 (Asserter) 通过 bisectExecution 确定不可再分割的「分歧点」。在确定分歧点后,挑战者通过 oneStepProveExecution 函数确定 Assert 之前提交的状态是否正确。
initializeChallenge
function initializeChallenge( IOneStepProof[] calldata_executors, address_resultReceiver, bytes32_executionHash, uint256_maxMessageCount, address_asserter, address_challenger, uint256_asserterTimeLeft, uint256_challengerTimeLeft, IBridge_bridge ) external override { ... asserter =_asserter; challenger =_challenger; ... turn = Turn.Challenger; challengeState =_executionHash; ... }
initializeChallenge 确定挑战者和应战者,并确定需要挑战的状态(存储在 challengeState)。challengeState 是由一个和多个 bisectionChunk 状态 hash 组成的 merkle 树树根:
整个执行过程可以分割成多个小过程,每个小过程 (bisection) 由起始和结束的 gas 和状态来表示。
turn 用来记录交互顺序。turn = Turn.Challenger 表明在初始化挑战后,首先由 Challenger 发起分歧点分割。
bisectExecution
bisectExecution 挑选之前分割片段,并如可能将片段进行再次分割:
bisectExecution 的函数定义如下:
function bisectExecution( bytes32[] calldata_merkleNodes, uint256_merkleRoute, uint256_challengedSegmentStart, uint256_challengedSegmentLength, bytes32_oldEndHash, uint256_gasUsedBefore, bytes32_assertionRest, bytes32[] calldata_chainHashes ) external onlyOnTurn {
_chainHashes 是再次分割点的状态。如果需要再次分割,需要满足分割点的个数规定:
uint256 private constant EXECUTION_BISECTION_DEGREE = 400; require( _chainHashes.length == bisectionDegree(_challengedSegmentLength, EXECUTION_BISECTION_DEGREE) + 1, "CUT_COUNT" );
简单的说,每次分割,必须分割成 400 份。
_oldEndHash 是用来验证状态这次分割的分割片段是上一次分割中的某个。需要检查分割的有效性:
require(_chainHashes[_chainHashes.length - 1] !=_oldEndHash, "SAME_END"); require( _chainHashes[0] == ChallengeLib.assertionHash(_gasUsedBefore,_assertionRest), "segment pre-fields" ); require(_chainHashes[0] != UNREACHABLE_ASSERTION, "UNREACHABLE_START"); require( _gasUsedBefore <_challengedsegmentstart.add segment length>
起始状态正确。这次分割不能超出上次分割范围,并且最后一个状态和上一个分割的结束状态不一样。
bytes32 bisectionHash = ChallengeLib.bisectionChunkHash( _challengedSegmentStart, _challengedSegmentLength, _chainHashes[0], _oldEndHash ); verifySegmentProof(bisectionHash,_merkleNodes,_merkleRoute);
通过 merkle 树的路径检查确定起始状态和结束状态是上一次某个分割。
updateBisectionRoot(_chainHashes,_challengedSegmentStart,_challengedSegmentLength);
更新细分分割对应的 challengeState。
oneStepProveExecution
当不能分割后,挑战者提供初始状态(证明),并由 L1 进行相应的计算。计算的结果应该和提供的 _oldEndHash 不一致。不一致说明挑战者成功证明了之前的计算结果不对。
(uint64 gasUsed, uint256 totalMessagesRead, bytes32[4] memory proofFields) = executors[prover].executeStep( bridge, _initialMessagesRead, [_initialSendAcc,_initialLogAcc], _executionProof, _bufferProof );
通过 executeStep 计算出正确的结束状态。executeStep 实现在 packages/arb-bridge-eth/contracts/arch/OneStepProofCommon.sol 中。核心是 executeOp 函数,针对当前的 context 读取 op,执行并更新状态。感兴趣的小伙伴可以自行查看。
rootHash = ChallengeLib.bisectionChunkHash( _challengedSegmentStart, _challengedSegmentLength, oneStepProofExecutionBefore( _initialMessagesRead, _initialSendAcc, _initialLogAcc, _initialState, proofFields ), _oldEndHash ); } verifySegmentProof(rootHash,_merkleNodes,_merkleRoute);
确定初始状态和结束状态是上一次挑战状态中的某个分割。初始状态由提供的证明(proof)计算获得。
require( _oldEndHash != oneStepProofExecutionAfter( _initialSendAcc, _initialLogAcc, _initialState, gasUsed, totalMessagesRead, proofFields ), "WRONG_END" );
确认 _oldEndHash 和计算获得结束状态不一样。不一样才说明之前提交的结束状态是错误的。
_currentWin();
计算完成后,确定胜利方。
总结
Arbitrum 是 Layer2 Rollup 的一种方案。采用挑战机制确定 Rollup 状态的终局性。为了引入轻便挑战机制,Arbitrum 定义了 AVM,一种可以方便证明执行状态的虚拟机,并设计了 mini 语言和编译器。在 AVM 上模拟了 EVM 的执行环境,兼容 EVM。挑战时将执行过程进行 400 分分割,由 L1 执行少量指令确定状态是否正确。
百款NFT链游免费玩 | 数字货币支付图解教程 | 区块链游戏获利技巧 |
相关文章
热门推荐
- 为什么说 Sushi 被低估了?
- 行情被恐慌情绪笼罩,建议以观望为主
- 四张图解读加密市场崩溃的「黑色星期三」
- 「庶民的盛宴」,Chia 挖矿全解析
- TrustBase 将于今日 21:00 上线于火币生态链建立的...
- AscendEX 将独家首发去中心化招聘平台 Freela 代币...
- 加密市场经历黑色星期三,评测 Uniswap V3 做市策略
- L2 扩容方案 zkSync 2.0 公开三项资产安全保护措施...
- 行业变奏曲 | 第三届世界数字资产峰会精华集锦
- 期货利差回归,期权波动率高涨
- 告别 PoW 之后,以太坊能耗究竟会如何?
- 比特币挖矿真的有害环境吗?Coinbase 澄清比特币挖...
- 刚刚为第三支基金募得 1.25 亿美元的 1confirmatio...
- Gitcoin vs HackerLink: 两大开源开发者资助平台有...
- DeFi 总锁仓价值半月内缩水近四成,借贷与交易所板...
- 虎符智能链 HSC「独角兽计划」优秀项目全球招募正...
最新文章
- 川普媒体公司 TMTG 要推加密币交易平台?「TruthFi...
- 币安执行长 Richard Teng 公开信:在崭新加密时代...
- 又一金融巨头入局!嘉信理财要提供「加密货币现货...
- 破产重整进入倒数!FTX 预计「明年 3 月」开始赔偿...
- 美国「Solana ETF」终于有进展!激励 SOL 飙破 260...
- 挨批「脱离比特币基本面」!「微策略」被香橼做空...
- 川普要兑现承诺!「加密顾问委员会」正成形、将推...
- 比特币首破 9.5 万美元大关!选后涨势延续,冲刺 1...
- 比特币续写历史新高之际,「ETH/BTC 汇率」跌至 3 ...
- FTX 共同创办人 Gary Wang 全身而退!配合调查免于...
- Vitalik Buterin 地址买入 3 万枚 ANON 代币,激励...
- 砸 6 百万美元拍下「胶带香蕉」、孙宇晨说「要吃掉...
- 离「10 万美元大关」只差 2.5%!比特币狂飙站上 9....
- 川普考虑设立「加密沙皇」新职位!传人选包括 Coin...
- Coinbase 宣布上架迷因币 FLOKI,引发市场热情、交...
- 发币在即,如何对 Magic Eden 进行估值?