optimistic Rollup方案的主要特点:

  1. 在 Rollup 方案中,交易数据被写入 L1 (作为 calldata),但合约的实际计算和存储则是在 L2 上完成,以此来实现扩容;
  2. 某个验证者(Validator),会将一个断言提交到 L1,可以理解为该断言就是将一个 Rollup 区块内的所有交易、结果打包到了 L1 的一笔交易里;
  3. 而 Optimistic 主要是指系统对待断言的态度是乐观的,即当一个断言发布时,它不需要包含任何保证其有效性的附带证明,相反,会有一个时间窗口供任何质疑的人去挑战。挑战成功,则这个断言包含的所有交易都将被回撤,发布断言的验证者将被没收所有押金;挑战失败 / 无人挑战,则断言被接受并获得终局性.

Arbitrum 是多轮交互式 Rollup 方案,方案会首先乐观的认为验证者提出的断言是正确的,直到在挑战期内由其他验证者提出挑战或反驳。大多数情况下并不会出现挑战,因此整个系统得以更快速和低成本的推进执行

安全机制:

首先,数据可用性确保了用户在二层的资产、数据随时可以从 L1 恢复,永远不会丢失;

其次,任何用户都可以将交易请求发送到 L1 的 Inbox 合约中,来强制发起提现;

最后,AnyTrust 机制确保了用户自己就可以强制 L2 正确的处理这笔提现交易。

AnyTrust 是 Rollup 协议的关键安全属性,它表示任何一个诚实的验证者都可以强制确认 L2 链的正确执行,也就是说无论有多少想作恶的人试图阻止你,你或你雇佣的人都可以强制正确处理你自己的交易,你无须信任任何第三方。

1 Rollup的核心思路是在L1上保存能够验证交易过程的凭证,而将交易过程(计算过程)还有状态存储运行在L2中。

在 L2 上执行的所有交易,首先都会被提交到 L1 上运行的 Inbox 智能合约中,即作为 calldata 写入 L1。任何人都可以通过这些数据,还原 L2 上的所有交易,并将 L2 恢复到中断之前的正确状态。这些数据的可用性是通过 L1 来保证的,也因此人们完全不用担心 L2 的故障或者下线会导致自己在 L2 上的资产受损。

何为交易过程的凭证,交易执行的过程就是由1个状态转移到另外1个状态的过程,如果L1知道了一组交易前的状态和一组交易后的状态还有这一组交易,自然可以验证这组交易对应的状态转移是否正确。

理解Arbitrum Layer2方案_算法

如上图所示,发布者将交易前状态树的根hash 和交易后状态树的根hash以及交易发布到L1上,L1智能合约确认交易前状态树根hash是否和存储的根hash一致。交易前的根hash一致说明起始状态正确,那么本次交易过程是否正确如何验证呢?最安全的做法肯定是我们每次都在L1上重新执行L2的交易树,进行状态转移,但这样L2失去了意义,还是会面临不可能三角中处理速度的问题。

如何去验证状态转移是否正确也引出了2种不同的Layer2 Rollup机制。

第一种是欺诈证明,即默认相信存入的状态是正确的,等待其他参与者提出欺诈证明挑战,每一次L2发布到L1时的节点都要缴纳一定的保障金,当欺诈被证明后 回滚到前一状态,发布者保证金会被全部扣除,部分给到挑战者,部分直接销毁。如何证明欺诈,根据和L1交互程度的不同,分为交互式欺诈证明和非交互式欺诈证明,下面会详细解释。

第二种是零知识证明,每次存入状态都需要给出证明,证明会在L1进行验证,如果验证根hash值是正确的,代表发布者的发布无误,这里的证明用到了零知识证明相关研究。

欺诈证明

刚刚上面说到欺诈证明本着默认相信的原则。当没有挑战的时候,流程较为简单, 即将状态树的根hash 交易信息存入L1中。核心在于有挑战者发起挑战时,如何证明交易前状态树的根hash经过这一组交易可以变为新的状态根hash。这里有2种思路。

1.非交互式欺诈证明,即在L1上将这组交易重新执行一遍,看看执行过后的状态树 根hash值和传入的根是否一致即可。

2.交互式欺诈证明,由挑战者和发布者在L2上进行多轮挑战,最终挑战者锁定具体哪条指令具有欺诈性,由L1进行裁决。L1只需要执行存在争议的最小指令即可。

非交互式欺诈证明

非交换式欺诈,欺诈证明实现较为简单,将L2中执行的交易在L1中再完整执行一次,以确定状态根的hash是否一致来判断欺诈行为。

理解Arbitrum Layer2方案_智能合约_02

如上图所示,发布者发布信息到L1上,携带交易信息和新旧整体根hash, L1中的智能合约收到后会默认变更state为新的根hash,这时挑战者提出挑战,挑战者需要提供符合旧根hash的merkle状态树,L1智能合约通过旧的状态树执行完整的交易流程得到根hash和发布者提供的新根hash比较,不相等则说明有欺诈行为。

重新执行就会遇到一个问题,区块相关的属性会因为执行环境不同而发生变化。

理解Arbitrum Layer2方案_验证者_03

如上图所示block.timestamp会获取当前区块的时间戳,但由于合约执行的环境不同得到的时间戳大概率是不一样的。我们看看Optimism是如何设计OVM来解决这一问题的。

OVM

为了解决在L2和L1运行智能合约时所处环境不一致的问题,Optimism使用了虚拟化技术(实际上就是使用封装方法屏蔽)的方式,让智能合约直接获取一些状态变为经过OVM封装后调用。

上面的那个例子,将不能直接调用block.timestamp,改为调用ovm封装的1个方法ovm_getTimestamp(非真实 随意命名)

contract OVM_ENV {
uint timestamp; //L1重新执行前调用该方法设置正确的L2 timestamp即可
funtion ovm_setTimestamp(t:uint) {
timestamp=t;
}

funtion ovm_getTimestamp() returns(uint) {
return timestamp;
}
}

交互式欺诈证明

智能合约执行的过程就是推进状态变化的过程我们再次回顾状态机的概念

理解Arbitrum Layer2方案_数据_04

如图所示,无论上L1上的状态树还是L2上的状态树,都是由一系列的交易(智能合约的执行也是一次交易的调用),推动状态转换的,而由于智能合约,交易又可以拆分为更小的步骤指令。所以就变成了下面的样子

理解Arbitrum Layer2方案_验证者_05

我们的问题转化为证明状态树从状态A 经过N个指令变成了状态B,那么这个证明过程是否是可分解的呢?我们用分治的方式不难想到二分法,将1个大问题拆两个子问题,问题就变为证明状态A 经过前N/2个指令变成状态X和状态X经过后N/2个指令变成状态B。逐步二分最终定位到存在问题的指令,交由L1执行验证即可。

让我们完整描述整个运行过程,假设X是发布者 发布从状态A经过N条指令转移到状态B Y是挑战者。

Y向X提出挑战,要求给出经过 N/2条指令处的状态,X给出状态后,Y会自行验证是否正确。如果验证正确,则代表前N/2指令执行无问题,问题在后N/2,如果验证错误,则代表前N/2条指令执行就有问题。Y继续向X询问存在问题的指令区间N/2处状态,循环往复,直至找到有问题的指令(这里不是指令有问题,是执行指令前的状态无法通过执行指令得到执行指令后的状态)。

在实际应用中Arbitrum不是使用二分的方式,而是使用了K分,即每次将N个指令分为N/K组去寻找欺诈指令,效率更高

Arbitrum 使用一种链下争议解决方式来将争议缩减为交易中的一个单一步骤。然后协议会将这个单一步骤断言发送给 EVM 以做最终的验证,而不是发送整个交易到 EVM 中

理解Arbitrum Layer2方案_验证者_06

理解Arbitrum Layer2方案_数据_07

arbitrum如何应对审查攻击: 分叉攻击,拒绝服务攻击,阻塞攻击,饱和攻击

分叉攻击: 矿工串通(或被贿赂)弃置包含正常挑战的区块,并通过分叉,使另一条没有包含任何挑战的区块链被接受。

首先,由于挑战者的存在,一旦发生分叉攻击,必然会被某个挑战者发现。而当大家发现所处的区块链存在算力垄断者(这是分叉攻击的前提条件),并且会为了利益不受约束的破坏规则时,对于这个区块链将会是毁灭性的打击,Arbitrum 是否采取挑战期设计模式已经无关紧要了。

拒绝服务攻击: 矿工密谋(或被贿赂)在出块时不打包正常的挑战。

我们假设垄断者控制了 90% 的算力,挑战窗口期为 50 个区块,那么需要连续 50 个区块都由垄断者打包才能完成攻击,其概率为 0.9 的 50 次方,仅为 0.5%,而实际的挑战期远远多于 50 个区块,因此攻击成功概率极小。而在 Arbitrum 的设计中,每次攻击失败,攻击者都将支付大量的罚金,所以发起拒绝服务攻击对垄断者而言是相当不经济的。

阻塞攻击: 攻击者通过传统的拒绝服务攻击(DoS),使得其他人无法提出挑战(无法发出包含挑战的交易)

由于只要出现一个正直的挑战者,攻击就会失败,所以攻击者必须阻止“所有”可能的挑战者,如果挑战者足够多,这是很难完成的。更进一步的,利益相关方可能会雇佣暗中监视者,它们作为后备方案,只有在参与方来不及或难以发出挑战时才介入,攻击者根本无法提前辨别这些潜伏的挑战者,自然也没办法对其发起 DoS 攻击。【让executor也是challenger,只有所有的执行者质押完成,才算完成一轮验证。为保证自己的资产安全,所有的执行者都会去验证区块状态的有效性】

饱和攻击: 攻击者在很短的时间内提出大量的链上断言,让其他人来不及在时间窗口内对所有断言进行检查和挑战。

Arbitrum 防御饱和攻击的方法是对提出断言的频率进行限制,保证协议在设定的挑战窗口期内的任何时间点,全网都有足够的能力去检查待处理的断言和挑战。具体来说,会针对一条 Rollup 区块链的智能合约处理能力实施速度限制,使得即使存在某个能快速提出大量断言的人,最终也不得不慢下来。

排序者的优势:

Sequencer Mode 是 Arbitrum 的一个可选特性,主网上线的初期,官方(Offchain Labs)会运营唯一的 Sequencer 节点。

Sequencer 被赋予权利,可以控制每笔交易在 Inbox 中的顺序,从而确保它可以立即确定客户交易的结果,而无须等待以太坊上 5 分钟左右的区块确认时间,甚至也不需要等待 15 秒的区块创建时间。

同时,一个正直的 Sequencer 可以有效的防御抢跑攻击(Front-Running Attack)。

因此,由官方运营一个中心化的正直的 Sequencer 节点,对项目早期的发展可能是非常有益的,可以减少很多麻烦,但安全风险也显而易见(虽然很难想象官方会去自己作恶)。所幸官方承诺,会在技术成熟后,尽快切换至去中心化的多 Sequencer 节点方案。

除此以外,Inbox 会被一分为二,一个接受 Sequencer 提交的交易,一个接受常规的 Aggregator 或者用户提交的交易,这也给不信任中心化 Sequencer 的用户提供了另一个选择。

Arbitrum

Arbitrum 协议利用其 L1、L2 之间的通信能力,理论上可以无须信任的将任意形式的以太坊资产(包括 Ether、ERC20、ERC721 等)在 L1、L2 之间转移。当将资产从 L1 转入 L2 时,资产被存入一个 L1 上的 Arbitrum 桥合约中,之后一笔相同数量的资产在 L2 上被铸造并存入指定地址;而将资产从 L2 转回 L1 时,资产将在 L2 上被销毁,随后等量的资产将在 L1 的桥合约中变为可用。此外,从 L2 赎回资产到 L1 时,有一个关键性的区别是,用户发送交易后,必须等待一个挑战期的结束,才能最终在 L1 上执行。这是由 Optimistic Rollup 安全模型决定的。

值得注意的是,官方建议使用「可重试票据 Retryable Tickets」机制进行 L1、L2 之间的通信。可重试票据的运作方式大致如下:L1 向 L2 发起的交易首先被存入 inbox 中,并附带 calldata、callvalue、gas info 等交易参数。当这笔交易首次执行失败后,它将被放入 L2 的「重试缓冲区(retry buffer)」中,这意味着在一段时间内(通常为一个挑战期,即大约一周),任何人都可以通过重新执行这笔交易来赎回票据。L2 至 L1 的重试交易没有时间限制,争议期结束后的任何时间点都可进行。

这种机制设计主要是为了应对这样的场景:当某个用户希望将某笔 token 从 L1 存入 L2,首先会将这些 token 存入 L1 的桥合约中,同时在 L2 上铸造等量的 token。假设 L1 上的交易已经完成,但是 L2 上的交易却因为手续费不足失败了,这会导致一个严重问题:用户在 L1 上的 token 已经转出,但是在 L2 上却没收到 token,实际上,这些 token 被锁在了 L1 的合约里。通过可重试票据机制,用户(或者其他任何人),可以在一周内,使用足够的手续费重新执行这笔交易,并最终在 L2 上获得 token。

理解Arbitrum Layer2方案_验证者_08

以下是 Arbitrum 原生桥的基本步骤:

L1 ->L2

用户从 L1 发起 Deposit 交易

资产存入 L1 合约,交易被批量存入 Inbox 中

交易在 L2 被执行,铸造资产转入指定地址

如果交易失败,则交易被存入 L2 的重试缓冲区,用户可以在一个挑战期内发起重试

L2 -> L1

用户在 L2 发起 Withdraw 交易

L2 链将在一定时间内收集到的交易打包,生成默克尔树,并将根节点作为 OutboxEntry 发布到 L1 的 Outbox 中

用户或者任何人可以对根节点和交易信息进行默克尔验证

挑战期结束后,用户即可在 L1 完成交易,如果交易失败,则用户可以发起重试

理解Arbitrum Layer2方案_智能合约_09

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模拟器,可以执行相应交易。

ZK-Rollup

零知识证明的含义

零知识即在参与者解出问题结果但不告知验证者结果的情况下,让验证者相信参与者解出的问题结果是正确的。我们举2个比较有名的例子。

我们以starkware为例介绍zk-rollup的机制,starkware流程图如下图所示。

理解Arbitrum Layer2方案_算法_10

当发布者发布交易到L1上时,需要将交易以及L2上状态打包交给一个证明生成服务,证明生成服务经过大量运算,生成这次发布的证明。证明服务将证明发送给L1的验证服务。同时发布者将状态根hash值提交到L1,L1中接收到根hash值会询问L1上的验证服务,验证服务根据证明验证根hash值是否正确,如果正确L1会将状态根切换成新的hash值。

在这个过程中本来验证状态树的根hash是需要前一次完整状态树执行这次发布的所有交易得到新的交易树,从而计算新的根hash值,最终根据发布者提供的根hash值和新的hash值进行比较判断发布是否合法。由于引入了zk证明,我们不需要知道具体的状态和交易就可以判断hash值是否正确。这就是zk证明在以太坊扩容的应用。

理解Arbitrum Layer2方案_算法_11

理解Arbitrum Layer2方案_验证者_12