一文了解以太坊扩容方案Rollup_ROLL:HeroesChained

译者注:原文中Rollup同时以单复数形式出现多次,在译文中统一确定为首字母大写的Rollup。

Rollup 在当前的以太坊社区已经十分著名。在可预见的未来,Rollup 是以太坊实现扩容的关键解决方案?。但 Rollup 到底是什么?你能从这项技术身上得到什么,又该如何使用它?这篇文章将尝试回答一些关键问题。

实现区块链生态系统扩容有两种方式。第一种扩容的方式是让区块链本身拥有更高的事务处理容量。比如让区块变得 “更大”,但 “大区块” 会让区块链的验证过程变得更为困难,而且可能会使节点更加中心化。为了避免这样的风险,开发者可以提高客户端软件的效率。更加具有可持续性的扩容方式是,使用分片等技术,让构建和验证区块链的工作分摊到许多不同的节点上——?“ eth2 ”?就在尝试使用这种方式升级以太坊。

第二种扩容的方式是改变使用区块链的方法。用户不需要直接把所有的活动都直接放在区块链主链上,而是在主链外的 “二层” 协议中执行大部分活动,并生成一个证明,证明链外发生的这一切活动都遵循规则。主链上部署一个智能合约,它只有两个任务:处理存取款,以及对上述证明进行验证。有多种方法实现证明和验证,但它们都有一个共同的特性,那就是在链上验证证明比在链下做原始计算的开销要小得多。

二层扩容主要有三种方案:状态通道,Plasma 和 rollup。三种方案代表了三种不同的范式,每种方案有自己的优缺点。所有的二层扩容大致都属于这三类(对于一些折衷的方案如何分类存在争议,例如?“ validium ”)(编者注:中文译本)。

另请参阅?https://www.jeffcoleman.ca/state-channels?,statechannels.org

想象一下,Alice 向 Bob 提供了网络连接服务。作为交换,Bob 为上网产生的流量支付 0.001 美元/MB 的费用给 Alice。Bob 不需要在一层主链支付每笔费用,双方使用如下二层方案。

首先,Bob 将 1 美元(稳定币,或是等值的 ETH)存入一个智能合约中。为了向 Alice 支付第一笔款项,Bob签署了一张 "票据"(一条链外消息),“票据”上写着 “0.001 美元”,并将其发送给Alice。为了支付第二笔款项,Bob 签署另一张写着 “$0.002” 的票据,并将其发送给 Alice。以此类推,每次付款都重复这个过程(译者注:状态通道参与方只需保留一个最新的状态变更,因此新的票据签署后,前一张票据作废)。当 Alice 和 Bob 完成交易后,Alice 可以将价值最高的票据包裹上自己的签名后,发布到主链上(关闭通道)。智能合约会验证 Alice 和 Bob 的签名,验证通过后,将 Bob 的票据上标注的金额支付给 Alice,剩下的金额(译者注:1 美元减去前者)返还给 Bob。如果 Alice (出于恶意或技术故障)不愿意关闭通道,Bob可以发起一个提现挑战期(例如7天)——如果 Alice 在这段时间内无法提供 Bob 支付的票据,那么 Bob 就可以拿回之前存在智能合约里的所有钱。

状态通道技术很强大:广义的状态通道可以支持双向支付、实现智能合约(例如 Alice 和 Bob 在通道中签订金融合约),并具有可组合性(如果 Alice 和 Bob 之间有一个开放的通道,Bob 和 Charlie 之间也有一个开放的通道,那么 Alice 就可以和 Charlie 进行免信任的交互)。但是通道的作用是有限制的:不能向还没有加入通道的用户在链下发送资金;不能用于没有明确逻辑所有者的对象(比如 Uniswap 智能合约)。此外,如果使用通道处理的事务比小额支付场景更复杂,需要锁定大量的资金在通道中。

另请参阅?Plasma原始白皮书,Plasma Cash

要将资产从主链存入 Plasma 链,用户需要在主链将资产发送至管理 Plasma 链的智能合约。Plasma 链会给该资产分配一个新的唯一 ID(例如 537)。每条 Plasma 链都有一个操作者(这可能是一个中心化的角色,或者由多签控制,也可以是更复杂的东西,例如一条 PoS 链或 DPoS 链)。每隔一段时间(可以是 15 秒,也可以是一小时,或者介于两者之间的任何时长),操作者就会生成一个 “批处理”(batch),包含这段时间内所收到的所有 Plasma 链的交易。操作者生成一棵 Merkle 树,在索引为?X?的叶子节点处,如果资产 ID 为?X?的资产在这一批次中发生了交易,则叶子节点上存有对应交易,否则该叶子节点为零。操作者将这棵树的 Merkle 根发布到主链上。操作者还需要将每个索引?X?的 Merkle 分支发送给该资产的当前所有者。如果需要将资产从 Plasma 链提取至主链上,用户需要给主链的智能合约发送该资产最近一次交易对应的 Merkle 分支。智能合约随即开始了一个挑战期(例如7天),在此期间,任何人都可以尝试使用其他 Merkle 分支来证明:(i)用户在提取资产时并不拥有该资产,或者(ii)用户在某个时间点将资产发送给了其他人,从而使退出申请无效。如果在 7 天内没有人证明退出是欺诈性的,用户便可以成功取回资产。

Plasma 提供了比状态通道更强的功能:你可以将资产发送给从未加入二层的用户,锁定的资金也低得多。但这是有代价的:状态通道在 “正常运行” 时不需要将任何数据存入主链,但 Plasma 要求每条链每隔一段时间在主链发布一次哈希值。此外,Plasma 链中的交易没有即时性,即必须等待一批交易(也可称为 Plasma 区块)的证据(即那个 Merkle 根值)发到主链上。

此外,Plasma 和状态通道都有一个重要缺陷:其安全模型所对应的博弈论依赖于这样的想法:两个系统所控制的资产在逻辑层面都要有 "所有者"。只要资产所有者在乎自己的资产,那么当涉及该资产的状态变更 “无效” 时,资产所有者就会想办法出示变更 “无效” 的证明。这对一些应用来说无关紧要,但对不少其他应用来说这是个问题(例如 Uniswap)(译者注:对于 Uniswap 这样的 DEX 交易应用来说,其智能合约不属于任何人,与上述安全假设依赖的想法矛盾)。即使系统中一个对象的状态可以在未经系统所有者同意的情况下被改变(例如在基于账户的系统中,可以在未经所有者同意的情况下?增加?其余额),也不能很好地与 Plasma 兼容。这意味着,在现实中部署 plasma 或状态通道时,都需要推演 “特定应用” 的潜在逻辑设计定制化方案,不太可能做出一个能完整模拟以太坊运行环境(即 “EVM”)的 plasma 或状态通道系统。接下来让我们看看 rollup 是如何解决这个问题的。

另请参阅:EthHub 关于 optimistic rollup 的介绍,EthHub 关于 ZK rollup 的介绍

Plasma 和状态通道方案都是 “完全的” layer 2 方案,因为它们将数据和计算都转移到链下(即自己的二层系统中)。然而,数据可得性的基本博弈论原理意味着这样的系统不可能安全地实现所有应用。Plasma 和状态通道通过明确资产对象和所有者之间的关系来解决这个问题,但这使它们无法完全通用。Rollup 则与前两者不同,是一种具有 “混合性质” 的二层方案。Rollup 将计算(和完整的状态存储)转移到链下,但在链上保存了每笔交易的部分数据信息。为了提高效率,Rollup 使用了一系列花哨的压缩技巧,并尽可能地用计算替代数据。其结果是,这个系统的可扩展性仍然受限于底层区块链的数据带宽,但在此基础上实现的扩容倍数非常可观:在以太坊主链执行一笔 ERC-20 代币的转账大约消耗 45000 gas,但在 Rollup 中,每笔交易仅需要在主链上存储 16 字节数据,消耗的 gas 小于 300。

数据存储在主链是 Rollup 的关键因素(请注意:这同将数据存储在 “IPFS” 上不同,因为 IPFS 不会对存储的数据进行共识,Rollup 的数据则?必须?存储在区块链上)。将数据存储在主链并进行共识,使得任何人可以在本地处理 Rollup 中的所有操作,包括欺诈检测,发起提款,生成批处理等。因为不存在数据可得性问题,所以运营者如果作恶或者离线所造成的损失相对更少(比如他们无法造成长达 1 周的退出延迟),也在谁有权发布批处理这个问题上提供了更多的可能性,同时也使 Rollup 更易于理解。更为重要的是,不存在数据可得性问题意味着,资产无需和所有者有明确的逻辑映射关系。相比其他二层扩容方案,这是以太坊社区对 Rollup 感到更加激动的重要因素:Rollup 是具有通用性的,比如可以在 Rollup 中运行 EVM,从而使现有的以太坊应用可以在不写新代码的情况下迁移至 Rollup。

在主链上有一个智能合约,存有一个状态根?—— 表征 Rollup 状态的 Merkle 根。(状态内容包括 Rollup 中的账户余额,合约代码等)

任何人都可以在主链上对该智能合约发起一个批处理事务(transaction),这个批处理是对一批 Rollup 内部事务的高度压缩,还包括旧的状态根和新的状态根(在旧状态根基础上执行批处理交易之后生成的新状态根)。主链合约会检验旧的状态根与新的状态根是否匹配(译者注:即新的状态根是否可以由这一批交易集触发状态转换生成)。如果检验通过,主链上的旧状态根会更新为新状态根。

为了支持存款(译者注:将资产从主链的其他地方存入 Rollup 合约)和取款(译者注:解除 Rollup 合约对自己资产的控制,使之返回到链上其他地方),批处理中的事务的输入或输出可以是 Rollup “外部”(译者注:即主链其他地方)的状态。如果批处理中有交易的输入来自 Rollup 之外,那么这个批处理操作会将主链其他地方的资产转移至 Rollup 合约中。如果批处理中有交易的输出来自 Rollup 之外,那么这个批处理会触发智能合约中的取款操作,将资产从 Rollup 取回主链。

整个过程就这么简单!不过还有一个细节。如何知道批处理执行完成之后的状态根是正确的??如果有人可以提交一个伪造的状态根,而不产生任何后果,他们就可以把所有的资产转移给自己。这个问题很关键,因为这个问题有两种截然不同的解决办法,从而形成了两种类型的 Rollup。

Rollup 的两种类型包括:

Optimistic Rollup,使用?欺诈证明解决上述问题:主链的 Rollup 合约记录了该 Rollup 内部状态根变更的完整记录,以及每个(触发状态根变更的)批处理的哈希值。如果有人发现某个批处理对应的新状态根是错误的,他们可以在主链上发布一个证明,证明该批处理生成的新状态根是错误的。合约校验该证明,如果校验通过则对该批处理之后的所有批处理交易全部回滚。

ZK Rollup, 使用有效性证明解决上述问题: 每个批处理中包含一个称为 ZK-SNARK 的密码学证明(例如使用PLONK协议, 证明新状态可以由旧状态经此批处理操作后转换而来(译者注:在 ZK Rollup 中,提交的密码学证明只需要具有尺寸小,验证快的特性即可,无需具有零知识性,所以只需要 SNARK 即可实现 ZK Rollup,不是一定需要 ZK-SNARK。事实上,在 ZK Rollup 中,因为批处理交易信息存储在主链上,而这些信息恰是密码学证明系统中所证明的内容,因此 ZK Rollup 本身并不具有零知识性,具有零知识性的 ZK Rollup 被称为 ZK ZK Rollup)。无论批处理的计算量多大,都可以在主链上高效对证明进行验证。

这两种 Rollup 之间的设计权衡比较复杂

总的来说我自己的观点是,短期内 Optimisitc Rollup 很可能在实现具有通用性的 EVM 中胜出,ZK Rollup 很可能在简单的支付、转账和其他特定应用中胜出。但从中长期来看,随着 ZK-SNARK 技术的改进,ZK Rollup 将在所有应用场景中胜出。

Optimistic Rollup 的安全性取决于这样的想法:如果有人将一个无效的批处理发布到 Rollup 中,任何?同步了该链的人只要发现欺诈行为便可以向主链上的合约发布欺诈证明,证明该批处理是无效的,应该被回滚(译者注:不清楚作者这里的 “该链(the chain)” 到底是指主链,还是指 Rollup,虽然都是对的)。

一个断言某个批处理无效的欺诈证明需要包括上图中以绿色标识的数据:该批处理本身(可与存储在链上的哈希值进行核对)以及证明该批处理读取或修改了特定账户的默克尔树路径。黄色的节点可以通过绿色的节点重建,所以无需包含在证明中。这些数据足以执行批处理并计算新的状态根(请注意,这与无状态客户端验证单个区块的方式完全相同)。如果计算出的新状态根和批处理中提供的新状态根不一样,那么就证明了该批处理是欺诈的。

可以确保的是,如果一个批处理中存在错误,而在此之前的所有批处理都是正确的,那么就可以创建一个欺诈证明,证明该批处理的构造是错误的。注意如果在 Rollup 中有多个无效的批处理,那么最好尽量证明最早的那个批处理无效。当然可以确保的是,如果一个批处理是正确的,那么永远不可能创建一个欺诈证明,证明该批处理是无效的。

一笔最简单的以太坊转账(发送 ETH)大约需要 110 字节,但是在 Rollup 中实现 ETH 转账只需要大约 12 字节:

Nonce:这个参数的目的是为了防止重放。如果一个账户状态当前的 nonce 是 5,那么该账户的下一笔交易的 nonce 参数必须是5,但是一旦交易被处理,账户状态中的 nonce 就会被递增为 6,这样 nonce 为 5 的交易就不会再被打包。在 Rollup 中,我们可以完全省略 nonce,因为我们只需要从更新前状态中恢复 nonce;如果有人试图用较早的 nonce 重放交易,签名将无法通过验证,因为签名校验将使用 nonce 更大的数据。这其中的部分原因是 Rollup 可以采用更简单的高级编码技巧,而目前以太坊的 RLP 在每个值的长度上浪费了1个字节。同时 Rollup 还运用了一些非常聪明的压缩技巧。

Gas Price:我们可以允许用户使用固定范围的 Gas 价格进行支付,例如范围是 0 - 2 的 16 次幂。另外,我们也可以只为每个批处理收取固定的费用,甚至可以将 gas 支付完全移到 Rollup 之外,让交易者通过特定渠道向批处理创建者支付费用。

Gas:我们同样可以只是将 Gas 总量范围选择为 2 的幂。另外,我们也可以只在批处理层面设置 Gas 限制。(译者注:这里的 Gas Price 和 Gas,都是为了比较通过 rollup 合约和以太坊网络来转账所产生的数据量。并不代表一个 rollup 协议一定要包含这些概念。比如 Fuel 作为一种 Optimistic Rollup 协议,就是基于 UTXO 的,完全不包含这些概念。)

To:我们可以用?索引?代替 20 字节的地址(例如,如果一个地址是添加到树上的第 4527 个地址,我们就用索引 4527 来表示。我们会在状态中添加一个子树来存储索引到地址的映射)。

Value:我们可以用科学计数法来存储 Value。在大多数情况下,转账只需要 1-3 个有效位。

Signature:我们可以使用 BLS 聚合签名,使许多签名聚合成一个约 32 - 96 字节(具体大小取决于所使用的协议)的签名。然后,这个签名可以一次性对整个消息集和发送者进行批处理的签名校验。表中的 ~0.5 表示在一个主链区块中可以验证的聚合签名数量是有限的,因此如果批处理中的交易较多,需要约每 100 笔交易生成一次聚合签名。(译者注:大意是,验证聚合签名的计算量会随被聚合的原始签名的数量增加而增加,而以太坊主链区块可以使用的 Gas 数量是有上限的,因此聚合签名不能一次性聚合太多原始签名。)

ZK Rollup 有一个特殊的重要压缩技巧:如果交易的一部分只用于验证,与计算状态更新无关,那么这部分数据可以不存储在主链上。这在 Optimisitc Rollup 中是做不到的,因为该数据仍然需要存储在链上,以备后续欺诈证明校验的不时之需,而在ZK Rollup 中,证明某批处理数据正确性的 SNARK 证明,已经证明了相关方提供了所有验证所需的数据。一个重要的例子是实现具有隐私保护性质的 Rollup:在 Optimisitc Rollup 中实现隐私保护,每笔交易中用于保护隐私的约 500 字节的 ZK-SNARK 需要上链,而在 ZK Rollup 中实现隐私保护,覆盖整个批处理的 ZK-SNARK 已经可以证明 "内部 "的 ZK-SNARK 是有效的。(译者注:由于 SNARK 可以嵌套,故在 ZK Rollup 中实现隐私保护,只需将最终生成的最外层的 SNARK 提交上链即可,在验证外层 SNARK 时,内层的 SNARK 的有效性同时可以得到验证。)

这些压缩技巧是 Rollup 实现扩容的关键,如果没有这些技巧,Rollup 或许只能在主链的扩容基础上实现大约 10 倍的扩容(尽管在一些特定的大计算量的应用中,简单的 Rollup 实现的扩容已经很强大),但在使用了压缩技巧之后,几乎所有应用的扩容系数都可以超过 100 倍。

对于哪些人可以在 Optimistic Rollup 或 ZK Rollup 中提交批处理这个问题,已经存在许多流派。一般来说,大家都认为提交批处理的用户必须质押一大笔押金,如果某用户曾经提交过一个具有欺诈性的批处理(例如提交一个无效的状态根),那么这笔押金的一部分将被燃烧销毁,另一部分奖励给提交欺诈证明的用户。但除此之外,还存在许多可能:

(译者注,可以将批处理发布到主链上的用户称为 sequencer(排序者),该术语得名原因是该角色需要对批处理中的交易进行排序)

完全无许可的排序者:任何人都可以在任何时候提交批处理。这个方法最简单,但有一些严重的缺点,比如存在这样的问题:多个参与者同时生成并试图提交批处理,而其中仅有一个批处理可以成功被收录。这将导致在生成证明的计算开销或提交证明时的 Gas 开销有大量被浪费。

中心化的排序者:通过排序者这样的角色提交批处理(提现操作除外:在提现操作中,首先由用户自己提交提现请求,如果排序者在下一个批处理中没有处理该笔提现交易,那么用户可以亲自提交一个仅包含一笔提现交易的批处理申请)。这种方法“效率”最高,但需要依赖一个中心化的角色。

排序者拍卖:通过拍卖(比如每天)来决定谁有权利成为第二天的排序者。这种方案的优点是可以筹集资金,而这些资金可以通过 Rollup 的 DAO 来分配(参考MEV 拍卖)。

从 PoS 集合中随机选择:任何人都可以将 ETH(或者 Rollup 协议设定的代币)存入 Rollup 合约中,每一个批处理的排序者都会在这些存款人中随机选取,被选中的概率与存款金额成正比。这种方案的主要缺点是需要锁定大量资产。

DPoS 投票:某些排序者通过拍卖选取后执行批处理,但如果他们表现不佳,那么代币持有者可以投票将其踢出,并举行新的拍卖来替代他们。

目前正在开发的一些 Rollup 采用的是 “分割-批处理”("split batch")模式,即提交一批二层交易批处理的行为和提交一个状态根的行为是分开进行的。这其中有一些关键的优势。

你可以允许许多排序者并行发布批次,以提高抗审查能力,减轻对于某些批处理会因为其他一些批处理提前打包而无效的担心。

如果一个状态根存在欺诈,无需回滚整个批处理,可以只回滚状态根,并等待有人为同一批处理提供新的状态根。这样可以更好地确保交易发送者的交易不会被还回滚。

总的来说,这是一个相当复杂的技术组合,还在涉及效率,简单性,抗审查性和其他目标的复杂权衡中找到平衡。现在说这哪种组合最有效还为时过早,时间会证明一切。

在现有的以太坊主链上,每个区块的 Gas 上线是 1250 万,而交易的每个字节存储在链上花费 16 Gas。这意味着,如果一个区块中只包含一个批处理(这里假设使用 ZK Rollup,校验证明花费 50 万 Gas),那么这个批处理可以包含 1200 万 / 16 = 75 万字节的数据。而如上文所述,Rollup 中的每一笔 ETH 转账只需要 12 字节的存储空间,这意味着每个批处理中可以包含 62500 笔交易。目前以太坊主链的区块间隔是 13 秒,也就是说实现的 TPS 约为 4807(相比之下,以太坊主链上实现 ETH 转账的 TPS 约为 1250000 / 21000 / 13 = 45)。

下表中包含了其他一些应用场景的扩容效率。

需要说明的是,出于某些原因,这些数字其实是过于乐观的。最重要的原因是,一个区块中几乎不可能只包含一个批处理,因为到时会有多个不同的 Rollup 系统。第二个原因是,存款和提现操作始终将会存在。第三个原因是,短期内?Rollup 的使用量可能较低,因此固定成本的收费模式会占据主导。不过即使考虑了这些因素,超过 100 倍的扩容应该不难实现。最大扩容倍数计算方法:以太坊主链对应操作的 Gas 消耗 / (Rollup 中对应操作需上链的字节数 * 16) * 1200万 / 1250 万

那如果我们想要实现 1000-4000 TPS(取决于具体的应用场景)呢?这就需要 eth2 数据分片了。在这个提案中,每 12 秒开辟一个 16MB 的存储空间,这个存储空间可以被任何数据填满,系统将确保对这些数据的可用性达成共识。这个数据空间可以被 Rollup 使用。这个约 1398kB/秒的数据吞吐量比当前以太坊主链的约 60 kB/秒提高了 23 倍,从长远来看,数据容量有望进一步增长。因此,使用 eth2 数据分片实现的 Rollup 的 TPS 可以高达 10万,在未来甚至会更大。

虽然现在 Rollup 的基本概念已经被人们所熟知,我们也很确定 Rollup 从本质上说上是可行的、安全的,而且已经有多个 Rollup 在以太坊主网部署,但 Rollup 在设计层面仍有许多地方没有被很好地探索,如果要将以太坊生态系统的大部分都完全引入 Rollup 从而利用其扩容性,这方面仍存在不少挑战。一些关键的挑战包括:

用户和生态系统的入驻:目前使用 Rollup 的应用不多,用户对 Rollup 不熟悉,很少有钱包开始整合 Rollup。商家和慈善机构还不接受它们用于支付。

跨 Rollup 交易:有效地将资产和数据(如预言机输出)从一个 Rollup 转移到另一个 Rollup 中,而不需要通过主链中转并产生相应费用。

审计激励:如何最大限度地提高至少有一个诚实节点会完全验证 Optimistic Rollup 的概率,从而确保在出现问题时有人发布欺诈证明?对于小规模的 Rollup(TPS 几百以下)来说,这不是一个重要的问题,可以简单地依靠利他主义实现,但对于更大规模的 Rollup 来说,需要把激励问题研究清楚。

探索在 Plasma 和 Rollup 两者之间设计的可能性:是否有技术可以把?部分?与状态更新相关的数据放在链上,但不把?全部?数据放在链上?通过这种技术是否会诞生出新的有用的工具?

最大限度地提高预确认的安全性:很多 Rollup 为了让用户体验更好,提供了一个 “预确认” 的概念,即在交易完成后,排序者即刻提供一个承诺:某笔交易将被包含在下一批处理中,如果排序者食言,他们的押金将被销毁。但是这种方案在经济层面的安全性是有限的,因为排序者可能同时向非常多的用户做出很多承诺。这个机制是否可以改进?

提高对缺席排序器的响应速度:如果一个 Rollup 的排序者突然离线,那么如何最大限度地快速以及低成本地从这种情况中恢复,要么快速和低成本地大规模退出到另一个 Rollup,要么更换排序者。快速响应这是非常有价值的。

高效的 ZK-VM:生成一个ZK-SNARK证明,证明具有通用性的 EVM 代码(或现有合约可以编译到的另一种 VM)已经正确执行,并有一个确定的结果。

Rollup 是一种新的强大的二层扩容范式,预计将成为以太坊未来短期和中期(也可能是长期)实现扩容的基石。以太坊社区对于 Rollup 非常兴奋,因为与之前的二层扩容尝试不同,Rollup 可以支持通用的 EVM 代码,允许现有的应用程序轻松迁移过来。Rollup 通过做出一个关键的妥协来实现这一目标:不试图完全搬到链下,而是将每笔交易的少量数据保留在链上。(译者注:即上文所说的没有数据可得性问题)

Rollup 有很多种,设计上也有很多选择:使用欺诈证明的 Optimisitc Rollup,使用有效性证明的ZK Rollup。排序者可以是一个中心化的角色,也可以是一个去中心化的自由角色,或者是介于两者之间的许多其他选择。Rollup 仍然是一项早期阶段的技术,开发正在快速地继续,但它们是有效的,一些(特别是 Loopring、ZKSync 和 DeversiFi)已经运行了几个月。期待在未来的几年里,Rollup 领域会有更多令人兴奋的成果出现。

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

金宝趣谈

[0:15ms0-6:476ms