Hi Guest

More contents, please log on!

Bitmere.com 区块链前沿 Content

以太坊进化之路:ETH2.0工程指南

fzny61226
19 0 0
关于以太坊2.0

以太坊2.0是计划中的以太坊替代方案。在接下来的几年里,以太坊2.0的设计人员打算将以太坊的共识系统和状态完全纳入其中。由于以太坊2.0的范围如此广泛,我们无法准确地说出其将包括哪些,或者不包括哪些。我们确实有了一些关于以太坊2.0的规范,并且有非常多的团队在致力于开发早期的实现。此时,以太坊2.0设计人员暂规划中的设计,包括分片、Casper、状态租赁以及eWASM虚拟机。初步的客户端测试正在进行当中,预计开发者将在三个月内(2019年第1季度)推出一款轻功能的以太坊2.0测试网。起初,以太坊2.0将从以太坊主链中获取以太币,但设计师最终计划使以太坊2.0成为主链,而以太坊1.X则作为其管理下的分片链。

这对工程师来说意味着什么?

如果你是一名Solidity或Dapp开发人员,并且希望部署以太坊2.0智能合约,那么你将需要学习很多的东西。以太坊2.0完全替代了以太坊,它将改变我们在编写智能合约时所做的很多假设。计划中的以太坊2.0多阶段推出计划,更新是产品发布周期,而不是升级周期。我们为以太坊1.X编写的工具和智能合约,可能需要为以太坊2.0完成重设计和重写。幸运的是,我们有几年的时间来准备生态系统。为了帮助大家实现这一目标,我想讨论一下当前的路线图,并介绍一些工程上的影响。

分阶段推出

目前,分片路线图(以太坊2.0路线图的2倍)列出了七个阶段。其中,只有Phase 0(阶段0)有一个充实的规范,并且定期会被更新。而 Phase 1(阶段1)规范的精确度要低得多,似乎还没有得到积极的开发。在第一阶段之后,路线图就变成了目标列表,而不是技术文档。例如,在Phase 2(阶段2),路线图链接到ethreaser.ch的次数,将是链接到github的三倍。因为任何进一步的讨论,看起来都像是推测,而不是工程,所以我们的具体讨论,仅限于阶段0、阶段1以及阶段2,并且我们已包含了一些关于后期可能方向的粗略概述。

下面我们将介绍各个阶段的发展状态。

阶段0——信标链(Beacon Chain)

阶段0引入了“信标链”。以太坊2.0的设计者希望把信标链打造成以太坊2.0生态系统的中心,并成为所有其他分片的安全和验证根源。一旦信标链被部署完成后,它将运行Casper FFG这一PoS机制。信标链的早期迭代设计得尽可能简单,这就是为什么阶段0不支持智能合约、账户、资产转移,并且不包括任何分片的原因。信标链上的以太币不能在链上转移,这意味着用户不能将其存入交易所。

BETH:新的以太币

信标ETH(BETH)是信标链上的被验证者唯一使用的新资产,它是通过两种方式创建的:1)作为验证信标链的奖励(以及阶段1之后的分片),2)任何以太坊1.x的用户都可以通过以太坊1.x合约购买BETH。合约将此称为“保证金”。工程师可能会注意到合约没有撤销功能。这是因为在第0阶段,我们无法从信标链中撤回BETH。也就是说,一旦存储在以太坊1.x验证者注册合约中,以太坊1.x的以太币就会被有效地烧掉。信标链验证者查看合约,并向信标链提交存款信息,信标链将向存款人发放新的BETH。因此,我们的目标就是:当存款人将以太币发送到验证者注册合约后不久,其就会收到信标链发布的相应数量的BETH。对存款的临时审查是可能的,但根据Casper的规则,永久审查不太可能会发生。

以太币在信标链上的传输,需要等到Phase 2(第二阶段),我相信在以太坊1.X完全折叠到分片生态系统之前,我们不会有任何办法将BETH移回到以太坊1.X。鉴于阶段0不完整,且不存在可靠的阶段1规范,我们可合理地假设,BETH作为独立且不可转让的资产的时间,将至少持续2年的时间。一旦阶段2完成,BETH将可以转移到分片上,或者从分片转移出去;然而,以太币将不会。这不太可能造成严重的经济困难。

在过去,很多交易所通过IOU(欠条)的方式,将类似BETH的token预先进行了交易。例如,在Tezos众筹期间,Hitbit和BitMEX交易所就推出了相应的期货市场。如果市场对BETH有交易需求,我们可能会看到一些交易所会支持BETH的托管交易和投资。然而,市场对BETH的需求似乎存在着一些问题。因为ETH到BETH的单向1:1挂钩,使得BETH有了最高限价,这并不是一个好的投资标的。也就是说,BETH 的价值永远不可能超过以太币,并可能会低于以太币。

阶段0+——分片

用户可在信标链上押入 32 BETH,然后成为一名验证者。在阶段0中,验证者将只管理信标链。从第一阶段开始,验证者还将管理1024条分片链。信标链(以及每个分片链)将使用 Casper FFG机制来确定区块。Casper FFG是一种针对链中止和审查等不良行为实施权益削减惩罚的一种PoS算法。敏锐的读者会注意到,FFG的"表兄"Casper CBC,列在了分片路线图的“以太坊3.0”部分。(全面讨论FFG以及CBC不在本文的范畴,我建议大家阅读一下Vitalik关于混合PoW和FFG的笔记,以及他撰写的关于最小化削减条件和FFG论文的 medium文章。

验证者(staker)做些什么?

分片的目的,在于跨节点分割状态信息,而不需要任何节点拥有网络的完整图像。因此,没有验证者会验证所有分片。相反,信标链将协调所有其他分片的验证,所有验证者将验证这一信标链。每个时间段(64个区块或6.4分钟),信标链将洗牌验证者,并将其分配给一个分片。分配给分片的一组验证者,被称为委员会。委员会会有128名成员。在阶段0中,这意味着每6分钟,信标链将选择可用的验证者,而在接下来的6分钟内组成一个委员会。在阶段一,信标链将为1024个分片指定一个验证者委员会。精确的方法是复杂的。它包括一个多阶段随机数生成过程以及一个可验证的延迟函数,以进一步挫败操纵委员会选择过程的尝试。

以太坊2.0随机选择委员会,并且经常因关键工作而轮换委员会。各委员会负责维护其分片的安全、活性及完整性,并在信标链上证明分片状态。它们是信标链了解分片状态的唯一方法,反之亦然。从所有验证者池中随机地选择它们,可最大限度地降低整个委员会说谎或作弊的可能性。而轮换他们,往往是为了减轻一个坏委员会可能造成的伤害。换句话说,存有恶意或寻求利润最大化的验证者,很难成为委员会成员,并对网络发起攻击。此外,即便他们有机会能够控制一个分片委员会,这个控制的时间也不会超过64个区块(6.4分钟)。

对于工程师的PoS证明

虽然以太坊1.x的工作量证明(PoW)和以太坊2.0的权益证明之间的哲学差异是一个持续的过程,但值得注意的是,一些些pow/pos特性差异,确实直接会影响到工程师。例如,虽然PoW链支持无状态SPV证明,以及NiPoPow总结的远程状态跟踪,但PoS禁止了任何低状态通信。主观性阻碍了轻状态认证。换言之,关于PoS的远程状态证明,将包含与POW无状态SPV证明大致相同数量的数据,但需要预先验证整个PoS历史。相反,无状态SPV证明不需要其他信息来验证。这意味着在主观的PoS环境中,交叉分片或交叉链应用降低了功能性,并增加了管理开销。

阶段0+——分片

用户可在信标链上押入 32 BETH,然后成为一名验证者。在阶段0中,验证者将只管理信标链。从第一阶段开始,验证者还将管理1024条分片链。信标链(以及每个分片链)将使用 Casper FFG机制来确定区块。Casper FFG是一种针对链中止和审查等不良行为实施权益削减惩罚的一种PoS算法。敏锐的读者会注意到,FFG的"表兄"Casper CBC,列在了分片路线图的“以太坊3.0”部分。(全面讨论FFG以及CBC不在本文的范畴,我建议大家阅读一下Vitalik关于混合PoW和FFG的笔记,以及他撰写的关于最小化削减条件和FFG论文的 medium文章。

验证者(staker)做些什么?

分片的目的,在于跨节点分割状态信息,而不需要任何节点拥有网络的完整图像。因此,没有验证者会验证所有分片。相反,信标链将协调所有其他分片的验证,所有验证者将验证这一信标链。每个时间段(64个区块或6.4分钟),信标链将洗牌验证者,并将其分配给一个分片。分配给分片的一组验证者,被称为委员会。委员会会有128名成员。在阶段0中,这意味着每6分钟,信标链将选择可用的验证者,而在接下来的6分钟内组成一个委员会。在阶段一,信标链将为1024个分片指定一个验证者委员会。精确的方法是复杂的。它包括一个多阶段随机数生成过程以及一个可验证的延迟函数,以进一步挫败操纵委员会选择过程的尝试。

以太坊2.0随机选择委员会,并且经常因关键工作而轮换委员会。各委员会负责维护其分片的安全、活性及完整性,并在信标链上证明分片状态。它们是信标链了解分片状态的唯一方法,反之亦然。从所有验证者池中随机地选择它们,可最大限度地降低整个委员会说谎或作弊的可能性。而轮换他们,往往是为了减轻一个坏委员会可能造成的伤害。换句话说,存有恶意或寻求利润最大化的验证者,很难成为委员会成员,并对网络发起攻击。此外,即便他们有机会能够控制一个分片委员会,这个控制的时间也不会超过64个区块(6.4分钟)。

对于工程师的PoS证明

虽然以太坊1.x的工作量证明(PoW)和以太坊2.0的权益证明之间的哲学差异是一个持续的过程,但值得注意的是,一些些pow/pos特性差异,确实直接会影响到工程师。例如,虽然PoW链支持无状态SPV证明,以及NiPoPow总结的远程状态跟踪,但PoS禁止了任何低状态通信。主观性阻碍了轻状态认证。换言之,关于PoS的远程状态证明,将包含与POW无状态SPV证明大致相同数量的数据,但需要预先验证整个PoS历史。相反,无状态SPV证明不需要其他信息来验证。这意味着在主观的PoS环境中,交叉分片或交叉链应用降低了功能性,并增加了管理开销。

阶段2——智能合约

第二阶段最终会给我们带来一个类似我们所熟悉的以太坊系统。随着第二阶段的发布,分片链会从简单的数据容器过渡到结构化的链状态。届时,BETH将成为可转让的,智能合约将被重新引入。每个分片将基于eWASM(我们称之为“EVM2”)管理一个虚拟机,我们希望EVM2能够支持我们在Solidity当中所熟悉的账户、合约、状态以及其他抽象内容。然而,大量的幕后变化可能会破坏现有的大多数工具。幸运的是,eWASM团队为solc、truffle和ganache做了一些基础工作。我们可期望看到在阶段二的测试网推出前或期间,将我们所熟悉的一些工具移植到EVM2。

状态租赁(State rent),很有可能会出现在阶段二,这对当前的Solidity工程师提出了一些有趣的挑战。状态租赁将要求合约开发者和用户支持一段时间的EVM2存储费用,而不是无限期地存储代码和数据。这可通过确保未使用的信息随着时间的推移而脱离状态来防止状态膨胀。目标是让用户(而不是整个节点)支付状态成本。开发者们提出了很多不同的模型,但目前没有明确的赢家。

有趣的是,随着一些以太坊升级计划的发布,并且卓越的以太坊核心开发者推荐它,状态租赁可能是不同路线图中唯一有重叠的部分。因此,我强烈建议在当前部署的合约中纳入对状态租赁的支持,并设计模型,以便将来将状态租赁传递给用户。我们不知道状态租赁的精确设计,但我们应该为成本做计划。

除此之外,我们并不知道阶段二还会发生什么。它仍处于研究的早期阶段,包括几个尚未解决的主要问题。考虑到非正式规范和开发过程,以及阶段二在阶段一的扩展范围,似乎在2020年之前,阶段二都不太可能会落地。也就是说,尽管以太坊2.0今年可能会推出,但至少在2020年之前,我们不要指望以太坊2.0能够支持资产转让或智能合约。

阶段3 ——链下状态存储

为了更多地讲述智能合约的相关问题,第3阶段的内容我们会简单地提一下。阶段3通过尽可能多将状态转移到链下来尽可能减少链上状态。链上不用存储整个状态,而是存储一些状态信息和聚合器(聚合器是表示长数据列表的短数据; Merkle树就是一种聚合器)。用户将负责在链下存储完整的状态。当用户想要与状态进行交互时,他们会在交易中包含当前状态的证明。这样,运行验证节点的资源要求可以低得多。现在已经有一些聚合器的设计了,它们有不同特性和性能特征,但目前还没做出具体的选择。在这个阶段,我们停止使用链上通信来协调用户,因此我们必须计划通过其他系统来同步状态。链上事件对工程师的有用性降低,因为链不再能够保证数据的可用性。在阶段3中,维护和获取链下状态将成为限制dapp设计的关键性因素。

阶段4 ——分片智能合约

然而,一个无法逾越的问题仍然存在:ETH2.0合约,虽然它们将与以太坊合约一样强大,但它们必然会被绑定到一个分片碎片(shard),无法与另一个分片碎片上的合约直接交互。这是分片的直接结果。分片的目的是将状态分割开并放在不同分片碎片中,而不需要直接了解其他分片碎片。它通过分割状态和尽可能减少验证者的工作量来实现扩容。直接的交互需要直接的知识。但根据设计,一个分片碎片不具有其他分片碎片的直接知识。它仅通过与信标链的跨链通信来了解其他分片碎片。因此,每当我们想要跨分片交互时,我们就必须等待信标链。具体来说,这意味着如果在分片碎片A上部署SafeMath,分片碎片 B上的用户将不得不等待一些时间来访问它,或者在分片碎片 B上部署新的SafeMath。

像SafeMath这样的简单实用程序将被部署到每个分片碎片——1024个分片碎片上有1024个SafeMath ——但是像Maker或Compound这样的市场呢? #DeFi可组合金融的目标在跨越分片碎片边界时就显得很有挑战性。CDP激活与DAI收取之间的长时间延迟会导致无法接受的经济损失。如果市场发生变化,CDP在用户收到DAI之前被清算,那该怎么办?在实践中,这可能意味着用户需要在每个包含智能合约的分片上拥有帐户,并且跨分片的结构完全没了用武之地。 Maker和0x只有在它们都部署在同一个分片上时才能进行交互,并且0x用户还要在该分片上拥有资产。

根本性的权衡:同步还是扩容

ETH2.0设计人员不知道跨分片通信系统最终将会是什么样子。通过阅读许多提案,似乎在即时反馈和可预测性之间存在根本性的权衡。分片的本质不会改变:无论如何用户都必须等待跨分片通信。但是,我们可以紧密地或松散地将交易的本地和远程执行阶段耦合到每个分片上。

紧密耦合让等待优先。在分片通信之前,交易不执行任何操作。相比之下,我们可以通过现在执行部分,稍后执行部分来松散地耦合交易。交易在本地分片上执行,然后在跨分片通信之后在远程分片上执行。松散耦合为用户提供了更好的体验。他们能立即看到他们的交易在本地执行,并且知道远程执行将在未来的某个时刻发生。不幸的是,他们无法在不需要等待的情况下知道松散耦合交易远程阶段的结果。紧密耦合的交易更具可预测性。用户更了解结果,因为远程状态不会在本地和远程执行阶段之间转换。但是,紧耦合需要用户在看到任何结果之前等待。

我们关于ETH2.0通信模型的信息非常少。我们知道它不能在不牺牲几乎所有扩容优势的情况下提供跨分片合约调用。如果你在这里停止阅读,我不会责怪你,因为第4阶段只有思维导图和一些模糊的链接。这种情况的一个非显性的结果就是,ETH2.0在第4阶段之前不会为复杂的智能合约系统带来明显的扩容优势。在此之前,希望与其他合约交互的智能合约必须与一个分片共存,并且受限于那个分片的速度和扩容效果。与ETH1.X相比,我们预计分片最多只能获得一个小的常数因子的加速量。这意味着在第4阶段发布(2025年左右)之前,几乎没有理由将智能合约代码或用户迁移进来,因为优势很小。与此同时,为了更好地理解工程师和dapp用户的权衡,我研究了一些社区或者开发者建议的模型。我认为这些都不会被采纳,但我相信它们有助于理解这里所涉及的权衡。再说一遍:下面所有的内容都是推测性的。

基本模型:收据(receipt)和证明(proof)

所有形式的跨链通信都利用了信标链。因为信标链可以检索所有分片的状态,并且每个分片会影响信标链的状态,所以我们可以将它用作分片链生态系统中的中心。消息从某个链到另一个链在某种意义上必须通过信标链传输。我们不会想要发送完整的消息,因为这需要信标链来处理每个交易本身,完全无法实现扩容的效果。

相反,每当分片A上的用户或合约想要与分片B交互时,我们都会让分片 A生成带有该消息的“收据”。分片A在其区块头中提交其所有收据。信标链等待A最终确认,然后提交到A的区块头(包括对收据的提交)。分片B必须等待信标的最终确认,然后提交到信标区块头。这时,可以向B提交新的交易,包含收据和证明。证明显示收据包含在A中,A包含在信标中,并且信标包含在B中。这样,B上的合约可以信任从A发送的消息。如果B上的合约想要发送回复(返回值或错误),我们反过来重复整个过程:分片B发出一个收据,最终收据一路到分片 A。

很容易理解为什么这个过程需要花费很多时间。四个通信步骤中的每一个都需要等待几分钟才能完成!不幸的是,我们完全无法避免等待。如果我们想确定远程状态,那么我们必须在每一步都等待最终结果。往返通信的最佳情况是四个最终确认周期。也就是说,用户可以在三个周期后获得信心,因为用户可以在分片 A看到分片B的收据之前看到它们。使用ETH2.0的6.4分钟时间段(epoch)长度,用户必须等待19分钟才能看到结果,并且需要26分钟才能获得链上结果。

具体收据(concrete receipts):分片之间的代币迁移

ERC20代币的多功能性使它们在今天的以太坊中无处不在。但是,ETH2.0给代币带来了一些逻辑问题。因为智能合约管理所有代币余额,并且智能合约仅存在于单个分片上,所以分片 B上根本不存在来自分片 A的代币。但是,通过一些聪明的跨分片通信,我们可以在多个分片上部署相同的代币并允许在分片之间迁移代币——有效地在代币合约之间建立双向挂钩。

该方案非常简单:在部署代币时(让我们称之为“酷酷的跨分片代币”或“CCT”),我们将使用ERC20添加两个小的附加功能:migrateSend和migrateReceive函数。我们将使用migrateSend销毁代币并生成收据。收据将包括已销毁的代币数和接收的分片。我们将使用migrateReceive验证收据并生成相同数量的CCT。然后我们将在每个分片上部署相同的代币合约。现在我们可以通过调用migrateSend来销毁一个分片上代币,然后在另一个上调用migrateReceive来有效地生成代币。我们需要在每个分片上重新部署我们的代币合约,但这似乎是值得的。迁移是单向的,至少需要两个跨分片通信的最终确认。因此,在我们调用migrateSend之后,将在我们的CCT在接收分片上可以运行之前大约需要10分钟。

Yank(拉拽)

收据是跨分片传递信息的一般方式。我们可以在收据中放置任何链上信息。这包括整个智能合约。 Yanking是一种通过将合同的代码和收据中的存储信息囊括在内来跨分片迁移合约的提议。合约将从分片 A中删除(yanked),然后在收据到达之后在分片B上重新部署。一旦该合约在分片B上了,它可以直接与分片 B的合约进行通信,并与分片 B的状态进行交互。它甚至可以被yank回分片 A。

这将允许任何一个智能合约与任何其他智能合约进行通信(在跨分片等待时间之后)。很遗憾,由于收据包括整个合约及其所有存储,因此迁移大型或者用户量大的合约花费会很高。收据在传输过程中,合约完全无法使用。它已从分片 A中抽出但尚未到达分片B。这意味着所有其他用户都无法使用该合约,直到它到达分片 B。而且,只有已经在分片 B上的用户才能与之交互。因此,yanking最适合用户很少的小合约。它使紧密耦合的执行成为可能,但远非通用的解决方案。

分片配对

从这里我们转而谈谈更有创意的一些构建想法。收据旨在使异步(松散耦合)通信成为可能。但是,我们也可能想要进行同步通信。为此,我们必须更有创意。分片配对是一个简单的设计,可以让我们在进行紧密耦合执行时为我们带来尽可能小的麻烦。

碎片配对是一个简单的方案。在这篇文章的第三段中我们讲到过,我们在每个高度将分片排序成同步对。每次一个分片与另一个分片配对时,任一分片的用户都可以跨越这两个分片执行紧密耦合的状态更新。这意味着如果分片A和B在高度7处配对,则A和B的所有验证者必须都知道A和B的所有状态,并且分片必须一起前进或根本不前进。在此模型中,如果你需要在A和B之间进行跨链交易,则需要等待A和B的随机配对。但是Vitalik提出了100分片的情况。有1,024个碎片,我们预计它需要512个区块——大约一个小时——但由于配对是随机的,它所需的时间可能更长或更短。正如Vitalik所说,当你想要与多个分片交互时,这种扩容效果很差。

分片区域(zone)

这是配对的更广泛版本。每个时间段(epoch)我们将分片分成几个由多个分片组成的“区域”。区域内的分片必须同步进行,这意味着区域中的所有分片一起更新其本地状态。通过同步进行,区域保证了分片之间的自由迁移,以及与区域中的任何合约的直接交互,但与区域外的任何分片进行通信则没有任何优势。此外,由于区域需要验证者来了解区域中所有分片的状态,因此它们否定了分片的许多扩容优势。如果一个区域由16个分片组成,我们牺牲了大约15/16(= 94%)的扩容优势,同时获得总网络15 / 1,024(= 1%)的紧密耦合执行。

产权负担(Encumbrances)

跨分片(和跨链)通信的一个非显性的特性是,用户可以比所涉及的链更快地获得对消息的信任。Alice从分片 A向分片 B发送5 BETH,知道它会在发送后立即到达。Bob看到交易的发送,知道一旦发送到分片 A上确认,BETH将到达分片 B。然而,分片 B及其合约必须等待几分钟才能使信标链对分片 A的最终确认进行最终确认。这意味在资金于分片A上花费以后,一个钱包可以很快在分片 B上接收和花费这些资金。换句话说,Bob将从分片 B上的Alice的钱包中获得可执行的IOU(欠条),因为Bob很有信心Alice已经发送了足够的ETH。如果分片B足够多的用户愿意观察分片 A并接受标准化的IOU,那么分片 A ETH可能会在发送后很快在分片 B上花费。然而,当应用于智能合约时,这种方案变得异常复杂,因为状态是不可替代的,所以状态的欠条是不可能实施的,故而它不适合通用交互。这意味着我们应该将产权负担视为松散耦合中的用户体验改进。它允许松耦合模拟紧密耦合,快速执行某些交易。

共识和状态分离

更复杂和更让人感兴趣一种方案是将共识过程和状态更新过程分离。当前以太坊矿工和完整节点只有在执行了区块中包含的所有状态更新后才接受区块。其实不必这样。相反,他们可以先接受区块,稍后更新状态。在这种情况下,我们不会像在以太坊中那样就系统状态达成共识,而是会对所有分片中所有交易的总历史(或“总顺序”)达成共识。这样做意味着每个分片都可以快速添加区块而无需知道任何其他分片的状态,这就是如何用分片扩容的原理。但是,在所有分片完成之前,交易对分片状态和整个网络的影响将不会被知道。换句话说,状态的最终确认落后于分片内容的最终确认。

从用户的角度来看:我们会立即提交交易,并且我们知道它们已被包含在内,但我们必须等待一些时间来确定该交易的结果。随着分片的最终确定,我们逐渐获得有关状态的更多信息,但在所有分片达到最终确认之前无法完全确定。与产权负担相似,在某些情况下,用户可以提前确定交易的结果并相应地采取行动。

结论与工程方向

ETH2.0将是与以太坊完全不同的系统。它们将并行存在多年并具有非常不同的特征集。在不久的将来,我们预计会出现从ETH到BETH的单向挂钩。如果你经营交易所或托管服务,请考虑如何在BETH在链上可转移之前支持你的用户进行BETH托管交易和staking(押注)。从长远来看,我们需要考虑智能合约如何在有和没有跨分片通信的情况下适应分片。最重要的是,密切关注研发过程。 ETH2.0是一个复杂且不断发展的系统。所有dapp工程师都需要清楚地了解ETH2.0计划和进度。
BitMere.com is Information release platform,just provides information storage space services.
The opinions expressed are solely those of the author,Does not constitute advice, please treat with caution.
You have to log in before you can reply Login | 立即注册

Points Rules

Write the first review

fzny61226 初中生
  • Follow

    0

  • Following

    0

  • Articles

    12

59600
Promoted