区块链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链游免费玩 | 数字货币支付图解教程 | 区块链游戏获利技巧 |
相关文章
热门推荐
- 欧易 OKEx 推出 Avalanche 的锁仓挖矿服务
- Purpose 旗下比特币 ETF 近一月增持约 2000 BTC
- 巨额融资再现,Revolut 完成 8 亿美元融资 | 投融...
- 高盛、摩根大通、瑞银……监管高压下华尔街银行如何...
- 共持有超 10.5 万枚 BTC,CEO 称将继续在数字资产...
- 国际权威评级机构 Moody's 下调萨尔瓦多长期外币发...
- 比特币重返高峰,特斯拉比特币持仓盈利超 10 亿美元
- Coinbase Pro 将上线 KRL、LCX、SUKU 和 TRAC
- Decentraland、The Sandbox……
- MetaBlox推出圣诞神秘盲盒活动:探索DePIN的新奇之旅
- 比特币 1 月链上交易爆量!连续两个月超过 1 兆美元
- 80 倍漲幅面臨市場拋壓,幣安 Launchpool 新項目 P...
- 聚焦愿景和使命:OKX Web3 举办的 The Future is N...
- AVS 时代到来:EigenLayer 上线主网影响几何?
- 比特币 6 个月涨幅近 100%,分析师:令其他资产看...
- 规范稳定币、加密货币,英国预计 6 、 7 月出台新立法
最新文章
- 说好的商品又变证券?Consensys 怒告 SEC 对以太币...
- Arkham 统计币圈 Top 10 个人大户:孙宇晨位居榜首...
- OKX 第 18 期 PoR:BTC 、 ETH 、 USDC 和 USDT 储...
- 知情人士:摩根士丹利考虑让 1.5 万经纪人主动推销...
- 消息:预计美国 SEC 将否决以太币现货 ETF 申请,...
- Meson Network 代币 MSN 上线「OKX Jumpstart」新...
- 当年「乱入」与叶伦同框而爆红!「Buy Bitcoin」笔...
- 美国又出手打击混币器,Samourai Wallet 两位创办...
- 香港首批「加密币现货 ETF」名单出炉:4/29 首次发...
- MICA Daily|Glassnode:比特币减半后,投资人应降...
- BitMEX 创办人 Arthur Hayes:印钞将加速,加密货...
- 改口称「以太币现货 ETF 过关渺茫」!渣打仍看好 E...
- 特斯拉今年 Q1 未出售比特币,连续 7 个季度「没卖...
- Block 宣布「3 纳米挖矿晶片」完成开发,目标打造...
- 比特币 200 天移动平均线接近新高,牛市最激烈阶段...
- 赵长鹏遭美检方求刑 3 年,辩护律师争取缓刑