Storj 白皮书 v3 最全面解读, Docker 创始人的加入能否扳倒 AWS S3 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
omnigeeker
V2EX    程序员

Storj 白皮书 v3 最全面解读, Docker 创始人的加入能否扳倒 AWS S3

  •  
  •   omnigeeker
    omnigeeker 2018-12-18 16:31:40 +08:00 2372 次点击
    这是一个创建于 2493 天前的主题,其中的信息可能已经有所发展或是发生改变。

    Storj 新发了白皮书 v3,地址是:https://storj.io/storjv3.pdf

    这次白皮书一共有 90 页,看完还真要费不少时间。如果你没有时间看,可以看一下我这篇快速技术解读。

    上次 Storj 发布白皮书 v2 的时候,是 2016 年 12 月 15 日;这次 v3 版白皮书的发布时间,是 2018 年 11 月,距离上次发布白皮书时隔 2 年时间。

    这次白皮书 V3 相对于白皮书 v2 来说,务实了很多,给我的整体感觉是:解密了不少实现的细节。全篇白皮书在说 Storj 去中心化存储的架构细节,区块链部分依然提到的很少。

    看了 Storj 的白皮书之后,大致可以明确几点:

    • Storj 依然是 ERC20 通证,它没有将存储数据写入区块链,写入区块链是只有资产,简单地说,就是“钱”。因为白皮书 V3 很少提到区块链的内容,所以预计 Storj 的 ERC20 状态还会持续很久。
    • Storj 仍然采用中心化记账,每个月“发工资”的形式。工资就是 Storj 的 ERC20 的通证。
    • 白皮书 V2 里面的农场主,在白皮书 V3 全部改成了存储节点。这也能感受到 Storj 采用了去区块链化的路线,Storj 变得更靠近传统古典项目,对标 AWS S3。
    • 国内不少“矿圈”的人,抱怨在 Storj 上面种田没有收益,白皮书 v3 做了揭秘,说明了原因,后面我会详细解释。( Storj 上的种田,就类似于 FileCoin 上挖矿。)

    下面我完整地解读一下 Storj。

    Storj 历史

    Storj 历史上几个重要的时间点:

    2014 年 7 月,Storj 项目首次亮相,并且做了第一次通证的众筹,筹集了 910 个比特币,当时的价值是 50 万美金。后面经过差不多 2 年的开发,终于在 2016 年 4 月上线了 Beta 版; 2016 年底,发布了 Storj 的第二版白皮书。2017 年 2 月-7 月,又发起了一次众筹,这次相当于 ICO,这次筹集了价值 3000 万美金左右。2018 年 3 月,Docker 的创始人兼 CEO, Ben Golub, 加入了 Storj 担任新 CEO。最后就是在不久前发布了这篇白皮书 v3。

    Storj 设计原则

    这次白皮书 V3 里面,首先提到的就是设计原则。设计原则有以下几个关键词:安全与隐私;去中心化;市场和经济; AWS S3 兼;耐用率, 硬件故障, 和 流失;延迟;带宽;对象大小;拜占庭容错;局部协作。

    解读出以下几点重要信息:

    1. 可以看出“安全和隐私”是 Storj 设计的第一原则。其他原则如果与这个原则冲突,都按照这条原则来执行。

    基于这个第一原则,数据必须在进入 Storj 网络之前完成加密,而且加密算法是可插拔的,也就是可以使用不同加密算法加密。

    2. 要想办法降低维护成本和带宽消耗

    3. Storj 白皮书 V3 首次提出了 AWS S3 的兼容。这样开发者就能快速将之前基于 ASW S3 编写的程序移植到 Storj 上。对中国开发者来说,兼容了 AWS S3,就兼容了阿里云 OSS。

    这次 Storj 支持了 AWS S3 的 7 个最核心的 API。Bucket(Create, Delete, List), Object(Get, Put, Delete, List)。

    1. Storj 定义了一系列的 Qos,特别关注了延迟。之前在 Storj 社区有人反馈:把数据存入 Storj 网络有时需要几个小时。现在看起来,Storj 很关注这些反馈意见了。当然,除了延迟外,还定义了一个非常重要的参数:耐用性。耐用性是保证数据不丢失的概率,即使在大量硬件故障或者大量存储节点离线后,数据不丢失的概率。耐用性,一般是用 9 的数量来衡量的。如 99.99%, 就是 4 个 9 的耐用性,表示有万分之一的数据可能会丢失。

    2. Storj 白皮书 v3 完整讲述了 Storj 的经济体系。一共设计了 4 个角色: 终端用户, 存储节点运营商, 需求供应商, 网络运营商(现在是 Storj Labs)。

    3. 定义了 Object 的大小,最小为 4M。如果大小不到 4M,会按照 4M 收费,这样鼓励存入大点的文件。

    4. 存储节点一般归为 3 类:

    • 拜占庭节点:有主观意愿作恶的节点。
    • 利他节点:抛开不可避免的硬件故障,完全遵守规则并且无私地给他人奉献的好节点。
    • 理性节点:在遵守规则的前提,追求自己利润最大化的节点。
    1. 为了达到整体的规模最大,局部协议的最小化协调是 Storj 非常提倡的。

    角色

    Storj 的系统中有以下这些角色:

    • 客户端:在网络中上传和下载数据的用户或应用程序
    • 节点的类型:
    • 存储节点: 用于存储数据,获得收益
    • Uplinks 节点:用于实现库 libuplink,并希望存储和检索数据的任何应用程序或服务。 预计此类节点不会像其他两类一样保持在线状态,并且相对轻量。
    • Libuplink (一个库)
    • Gateway (网关)
    • Uplink CLI (控制台命令)
    • 卫星节点:用于缓存节点地址,存储对象元数据,维护存储节点信誉,聚合计费数据,支付存储节点,执行审计和修复,以及管理授权和用户帐户。

    用户拥有帐户并信任特定的卫星节点。任何用户都可以运行他们自己的卫星节点,Storj 希望许多用户选择使用其他卫星节点,避免操作复杂。有了卫星节点,Storj 整体架构就非常灵活。

    注意:中国不少自媒体,我就不点名,宣称 Storj 采用了天上的卫星传输技术,因为白皮书里面写了 Satellite。其实卫星节点根本就不是天上的卫星,而是分布式系统中一个角色。

    框架

    Storj 的设计,框架内的都将执行以下操作:存储数据; 检索数据; 维护数据; 支付费用。

    独立的模块有:存储节点; P2P 的通讯和发现;冗余;元数据;加密;审计和信誉;数据修复;支付。

    存储节点

    存储节点的作用是存储和返回数据。选择存储节点以基于各种标中和评估:ping 时间,延迟,吞吐量,带宽上限,足够的磁盘空间,地理位置,正常运行时间,准确响应审计的历史记录等等。这点和传统 P2P 项目选择节点的方式非常接近。

    • 可以存储具有特定 TTL 到期的片段,其中期望在到期之后删除数据。
    • 存储节点必须另外跟踪已签名的带宽分配,以便发送到卫星节点以后进行结算和支付。
    • TTL 和带宽分配都存储在 SQLite 数据库中。
    • 存储节点可以选择使用哪些卫星节点。 如果它们使用多个卫星节点(默认行为),那么付款可能来自不同的付款时间表上的多个来源。
    • 未通过随机审核的存储节点将从池中删除,可能会损失托管中的资金以支付额外费用,并且将来只会收到付款。
    • 存储节点将支持三种方法:get,put 和 delete。 每种方法都将采用分片 ID,卫星节点 ID,来自相关卫星节点实例的签名以及带宽分配。
    • 存储节点将允许管理员在过去 30 天内配置允许的最大磁盘空间和每个 Satellite 的带宽使用量。

    P2P 的通讯和发现

    网络上的所有节点都通过一个标准儿协议通信。这个协议支持以下几点:

    • P2P 的可达性,即使面对防火墙和 NAT。这需要 STUN,UPnP,NAT-PMP 等技术。
    • 提供 S/Kademlia 中的身份验证,其中每个参与者以加密方式证明与其通话节点的身份,以免中间人攻击。
    • 提供完全隐私,默认情况下所有通信都是私密的。
    • 可以在我们选择的对等通信协议之上构建各种重叠网络覆盖,例如 Chord,Pastry 或 Kademlia,以提供发现服务。

    冗余

    Storj 白皮书 v2 中就提到了冗余,但那时采用的是简单冗余。Storj 白皮书 v3 说明了简单冗余的缺陷,改用了纠删冗余。下面我想说下简单冗余和纠删冗余的优缺点。

    简单冗余

    在存储系统的不同位置创建数据副本,这个副本和之前数据一模一样。

    • 通常为 2 或 3 份,可根据风险等级进行配置
    • 如果驱动器发生故障,则会在副本的另一个驱动器上重新创建数据
    • CPU 计算资源占用更低 = 写入性能更快
    • 简单恢复 = 更快的重建性能
    • 需要 2 倍或更多的原始存储空间和带宽

    纠删编码

    基于奇偶校验的保护技术

    • 数据分成碎片并编码
    • 使用可配置数量的冗余部件,且不用部件存储在不同位置
    • 比简单冗余消耗更少的存储空间 - 适合廉价 /深度存储
    • 允许存储系统的两个或多个元素发生故障
    • 奇偶校验计算是消耗 CPU 计算资源的
    • 会增加延迟,也可能会减慢生成,写入和重建的速度

    里德-所罗门 纠删码

    Storj 使用的就是里德-所罗门 纠删编码

    • 如果用 (k,n) 纠删码编码数据块,则总共有 n 个纠删片段,其中只需要任何 k 个就能完全恢复原始数据块。
    • 如果数据块是 s 字节,则每个纠删片段的大小大约是 s/k 字节。
    • 当 k = 1 时,所有纠删都是一样的,这相当于复制。
    • 1MB 数据, 如果采用( 10,16 )纠删码,并且纠删片段数量是 0.1M ,则总存储数据就是 1.6MB 。

    上传和下载

    Storj 并不是只要发现冗余少了,马上就增加冗余,而是分了情况以确定是否增加冗余。

    • K:重建数据所需的最低要求
    • M:最低安全值,相当于重建数据的安全缓冲
    • O:最佳值,能够应付节点波动的缓冲区
    • N:长尾冗余

    K 的含义是:如果可用冗余的数量低于 K,数据将丢失。简单说,k 就是生死线。

    M 的含义是:当卫星节点发现到可用冗余的数量已经降至 M 以下,则它立即触发修复机制,以确保我们总是保持 K 个或更多。简单说,m 就是安全线。

    O 是存储的目标冗余度。 这个值用于上传和修复过程中,一旦 O 个分片完成了上传,那么多余的 k-n 之间的分片将被取消。

    因此,值 N 是超出目标冗余度。

    在 Storj 的设计中,未被确认信誉值的矿工,或者信誉值不高的矿工,就用于保存 O 到 N 之间的冗余度,这部分是没有收益的,直到任务足够产生信誉值之后,才能获得收益。简单地说,不稳定或者性能不达标的存储矿工是用于是存储多余的冗余的,他们不能获得收益。国内不少矿工抱怨 Storj 挖不到币,说 Storj 不靠谱;其实不是 Storj 不靠谱,而是他自己不满足 Storj 要求,不符合 Storj 的激励机制。

    耐用性

    Storj 白皮书 v3 仔细测算了耐用率。这个 QoS 指标非常重要。

    Storj 是在数学上是用泊松分布对依赖时间的过程进行建模的。其中假设在给定的单位时间中观察到事件。 因此,我们将耐用性建模为 Poisson 分布的累积分布函数( CDF ),其中平均数 lamda = pn,其中我们假设文件的片段每月会丢失。 为了估计耐用性,我们假定 CDF 为 n-k,考虑一个月内文件中最多 n-k 个部分丢失的概率,并且文件仍然可以重建。CDF 公式如下:

    $$P(D)=e^{-\lambda}\sum_{i=0}^{n-k}\frac{\lambda^i}{i!}$$

    Storj 做了如下假设:

    p 是纠删副本的每月丢失率,Storj 假设它是 10% n 和 k 分别是纠删算法参数 lamda 就是泊松分布的平均数,是 p*n Exp.factor 就是冗余的倍数

    可以看到,Storj 是能够做到很好的月耐用性的。

    但是,这个测算过程是有些问题的。

    1. 整个测算过程中,Stroj 没有考虑纠删分片恢复的时间。如前面所说,Storj 设计了 K,M,O 几个参数,纠删分片丢失后,是可以恢复的。/li>
    2. 计算的结果,得到的 P 只是月耐用性数据,而存储业内一般用年耐用性作为平台的参数。AWS S3 公布的耐用性是年耐用性。
    3. CDF 公式是泊松分布的拟合公式,CDF 公式得到的是近似值,只有当 p 很小,n 很大的的时候,才适用于 CDF 公式。而 Storj 的假设,p=0.1 已经不小了,CDF 公式得到的数字并不完全准确。Storj 白皮书 V3 还计算 k=1 的情况(就是模拟简单副本),这个 k=1 的计算出的数字偏差就比较大了。

    数据

    这里定义了 Storj 的每个数据单位:

    • 桶:存储桶是由路径标识的文件集合。每个文件在存储桶中都有唯一的路径。这和 AWS S3 中桶的定义一样。
    • 路径:路径是存储桶中文件的唯一标识符。这和 AWS S3 中桶的定义一样。除非另有要求,否则我们会在文件离开客户计算机之前对其进行加密。
    • 文件或对象:文件或对象是存储的文件实体。这和 AWS S3 中对象的定义一样。
    • 扩展属性:扩展属性是与文件关联的用户定义的键 /值字段。与其他文件元数据一样,扩展属性以加密方式存储。
    • 分段:分段表示单个字节数组,介于 0 和用户可配置的最大段大小之间。
    • 远程分段:远程分段是将分散在网络上纠删编码。远程段大于其所需的元数据,其中包括存储数据的节点 ID 等信息。
    • 内联分段:内联分段是一个足够小的段,它所表示的数据大小少于远程分段,需要跟踪哪些节点具有相应的数据。在这些情况下,数据存储为“内联”而不是存储在节点上。
    • 条带:条带是分段的进一步细分。条带是固定数量的字节,用作加密和纠删编码边界大小。纠删编码单独发生在条带,条带也是执行审计的单位。
    • 纠删片段:当条带被纠删编码时,它会生成多个分片,这就是纠删片段。只需要一部分纠删片段来恢复原始条带。每个纠删片段都有一个索引标识它是哪个纠删片段。
    • 分片:当远程段的条带被纠删编码为纠删片段时,具有相同索引的该远程分段的纠删片段被连接在一起,并且该连接的纠删片段组被称为分片。第 i 个部分是来自该部分条带的所有第三个纠删片段的串联。
    • 指针 :指针是一种数据结构,它包含内联数据分段,或跟踪远程分段的各个存储节点以及其他每个文件元数据。

    这就是 Storj 中的数据单元的示意图:

    元数据

    之前,Storj 白皮书 V2 中就简单提到了元数据,白皮书 v3 说明了元数据的细节。

    • 添加,编辑或删除对象时,需要调整此元数据存储系统中的一个或多个条目。
    • 在这个元数据系统中可能会有大量的流失,并且在整个用户群中,元数据本身变化得相当大。
    • Storj 希望该平台包含多个元数据存储实现,用户可以在其中进行选择。
    • Amazon S3 兼容性,Put (在给定路径上存储元数据),Get (在给定路径上检索元数据),List (现有路径的分页,确定性列表)和 Delete (删除路径)。

    加密

    所有数据或元数据都将被加密。在数据离开源计算机之前,必须对数据进行加密。与 AWS S3 接口兼容的客户端库应该和 用户的应用程序在同一台计算机上运行。我们的加密选择是经过验证的加密。这是为了便于用户知道是否有数据被篡改。加密应使用可插拔机制,可以选择不同的加密算法。Storj 采用 BIP32 的分层加密技术,这技术允许共享子树而不共享其父级,也就是允许共享某些文件而不共享其他文件。

    应对每个文件使用不同的加密密钥,因为访问一个文件将导致访问所有文件的解密密钥。因此,Storj 每个文件采用不同的密钥加密。数据以小批量条带为单位来加密,建议为 4KB 或更少。路径也是加密的。与 BIP32 一样,加密是分层的和确定的,并且每个路径组件都是单独加密的。

    审计

    审计只是用于确定节点稳定程度的机制。

    • 审计员(如卫星节点)将向存储节点发送挑战并期望得到有效响应。
    • 作为 HAIL 系统,Storj 使用纠删编码,一次读取单个条带作为挑战,然后验证纠删片段的响应。这使得 Storj 可以进行任意审计,在没有预先生成挑战的情况下。
    • Storj 要求所有存储节点的纠删片段是负责任的。然后,Storj 在所有纠删片段中运行 Berlekamp-Welch 算法[39,73]。当足够的存储节点返回正确的信息时,可以轻松识别任何错误,响应丢失。

    存储节点信誉

    要确定哪些文件需要修复,存储节点运行时间和总体健康状况是主要指标。根据每个节点的审计历史,建立一个信誉系统给定节点确定身份。存储节点信誉可以分为四个子系统。

    1. 工作识别系统证明:要求对存储节点运营商被投资的简要证据, 通过时间,份额或资源。
    2. 初始审查过程:慢慢允许节点加入网络。
    3. 过滤系统:它阻止不良存储节点参与。
    4. 优先系统:审计时收集的统计信息,将用于为上传好的存储节点建立优先权。

    数据修复

    为了修复数据,Storj 将通过从剩余部分的纠删码来恢复原始数据,然后重新生成丢失的部分,并将它们存储在新存储节点上。

    支付

    • 性能充足的存储系统是无法等待区块链缓慢操作的。
    • Storj 的框架反而更像游戏理论模型,确保网络中的参与者得到适当的激励,以保持长期在线,从而理性地行动以获得报酬。
    • Storj 框架中的存储节点应限制他们与不信任的付款人接触。
    • 基于以太坊的 STORJ ERC20 通证作为支付的默认机制,将来可以实施其他替代支付类型。

    卫星节点

    卫星节点:保存元数据的服务集合。网络用户将拥有特定卫星节点上的帐户,该实例将存储文件元数据,管理数据授权,跟踪存储节点的可靠性,在减少冗余时修复和维护数据,代表用户向存储节点付款。

    注意,Storj 中, 用户不是直接向存储节点付款的,而是用户先付款给卫星节点,然后卫星节点再付款给存储节点的。

    1. 卫星节点正在开发中,将作为开源软件发布。任何个人或组织都可以运行自己的卫星节点以方便网络访问。
    2. 从未向卫星节点提供未加密的数据,并且不保存加密密钥。
    3. 卫星节点实例由以下组件组成:
    • 完整节点发现缓存
    • 由加密路径索引的每对象元数据数据库
    • 帐户管理和授权系统
    • 存储节点信誉,统计信息和审核系统
    • 数据修复服务
    • 存储节点支付服务

    这是 put 操作的图:

    这是 get 操作的图:

    授权

    • 元数据操作将被授权。用户将使用他们的卫星节点进行身份验证,这将允许他们根据其授权配置访问各种操作。
    • 一旦通过卫星节点授权 Uplink,卫星节点将批准对存储节点的操作,包括带宽分配。Uplink 在使用存储节点进行操作之前,必须从卫星节点检索有效签名。

    宽带分配

    • 如果 Uplink 被授权用于请求,则卫星节点将只创建带宽分配。在存储操作开始时,Uplink 可以将带宽分配传输到存储节点。存储节点可以验证卫星节点的签名并执行所请求的操作,直到允许的带宽用满,存储并稍后将带宽分配发送到卫星节点以进行支付。
    • 在 Get 操作的情况下,假设卫星节点签名的带宽分配允许最多 x 个字节。Uplink 将通过发送一些少量( y 字节)的受限分配开始,然后逐步再发送另一个分配,其中 y 越来越大,继续发送,直到 y 增长到 x。

    垃圾回收

    • 每次删除数据时,联网和可访问的存储节点都会立即收到通知。
    • 存储节点有时会暂时不可用,并且会丢失删除消息。在这些情况下,不需要的数据被视为垃圾。

    Uplink

    Uplink 就是 Storj 的软件中间层。

    • 任何调用 libuplink 的软件或服务,以为了与卫星节点和存储节点交互。
    • Libuplink - libuplink 是一个库,提供对 Storj 网络中存储和检索数据的访问。
    • 网关 - libuplink 上的一个简单服务层。我们的第一个网关是 Amazon S3 网关。
    • Uplink CLI - 一个调用 libuplink 的命令行应用程序

    未来工作

    Storj 的白皮书 V3 中提到了他们未来要做什么事情。

    • 热门文件和内容分发。
    • 如有必要,卫星节点可以临时暂停访问,增加文件在更多存储节点上的冗余,然后继续允许访问。
    • 改善元数据的用户体验。
    • 从长远来看,我们计划将卫星节点构建出平台。我们希望通过可行的拜占庭容错一致性算法完全取消对元数据的卫星控制。

    总结

    优点

    1. 以产品和市场为目标,Storj 真正重视了服务质量 QoS,真心希望将去中心化存储落实到使用场景。
    2. 非常注重安全和隐私,这是第一设计准则。
    3. AWS S3 兼容性,支持了 AWS S3 的几个核心 API。对开始者来说,这是一件好事。
    4. 避免拜占庭分布式共识,这样就能大大提升效率。
    5. 设计了冗余细节,认真测算了耐用性,这是一个成熟的存储系统中最重要 Qos。
    6. 设计元数据,并单独对元数据做了处理。元数据不用于普通数据,是变化很频繁的。
    7. 审计和信誉,特别引入了信誉值,对整体经济系统有积极的良性影响。

    缺点

    1. 非常依赖于纠删技术,数据修复开销非常大。
    2. 依然很少提及区块链技术,Storj 对区块链技术的考虑非常少,作为一个做了 4 年多的项目,却还是中心化的结算方式,有那么点让人失望。
    3. 卫星节点是个非常集中的设计。除了存储数据外,其他所有的事情都由它做完。
    4. 每月支付,支付周期太长,对存储节点来说不够友好,特别是新存储节点,得到的反馈很慢。
    5. 带宽分配,以字节为单位,力度太低。
    6. 很少考虑热门文件和内容分发的情况。

    我为什么写这篇文章

    我的其他文章提到过,我设计和发起了 PPIO 存储公链项目,旨在给开发者提供去中心化的存储和分发网络,使得更便宜,更快,更隐私。虽然我设计的 PPIO 项目和 Storj 有些相似,但我写这篇文章是完全站在中立的角度写得。我认为去中心化存储相对于中心化存储(如 AWS S3,GoogleCloud,Microsoft Axure )来说是个全新的赛道。而这个新赛道的发展,以及最终产生价值,都是需要大家共同探索的。我希望能够共同进步。

    我在设计 PP.IO 的时候,我之前设计的很多想法和 Storj 刚发布的白皮书 V3 中提到的非常类似,包括兼容 AWS S3,重视 Qos,将去中心化存储和区块链系统视为 2 个独立的子模块,使用纠删副本,测算耐用率,设计了监督节点(类似 Storj 卫星节点的审计)。当然,PP.IO 也有很多和 Storj 不一样地方,PP.IO 有很多地方的设计比 Storj 要优秀得多,我后面会写文章来逐步说明。

    2 条回复    2018-12-23 06:27:33 +08:00
    Comdex
        1
    Comdex  
       2018-12-18 18:34:54 +08:00
    那么问题来了,发币么?
    crisfun
        2
    crisfun  
       2018-12-23 06:27:33 +08:00 via iPhone
    @Comdex +1 上交易所了吗
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2928 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 25ms UTC 00:26 PVG 08:26 LAX 17:26 JFK 20:26
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86