PPIO 的状态通道设计
PPIO 是为开发者打造的去中心化存储与分发平台,让数据更便宜、更高速、更隐私。
PPIO 的定位不仅仅是做存储,还有数据分发和数据传输。在数据传输的时候,如何保证数据传输的流量也采用一种公正的,不可抵赖的方式来实现的。这就是我这篇文章要讲解的状态通道。PPIO 就是通过状态通道的机制来实现数据传输的公正计量。
传统意义的状态通道机制
状态通道在区块链领域是个已经存在的名字,主要应用于高频交易和微支付。因为在这两个场景下,交易吞吐量会非常大, 如果所有的操作都是在需要共识的去中心化的链上操作,性能低会成为重要问题。状态通道的解决思路,本质是在交易高吞吐量和验证者的去中心化之间做一个平衡。具体来说,就是把两两交易的细节,放在链下去协商完成,当多步交易完成后,或者交易发生争议,再通过区块链来进行“仲裁”。为了说明状态通过,我们先做个假设,两个人 Alice 和 Bob,后面也可能简称 A 和 B。假设 Alice 在一开始的资产是10,Bob在一开始的资产也是10,他们之间即将发生一系列高频的微支付。我们开始模拟这个状态通道。
图: Alice 和 Bob 使用状态通道交易的示意图
整个过程大概分为以下几步:
- Alice 或者 Bob 创建于一个状态通道智能合约 Contract,后面会简称 C,此时状态通道处于 opening。这个过程是要上链的。
- Alice 将10个资产打入到合约中,接着 Bob 也将10个资产打入到合约之中,此时状态通道就算是开启,进入 open 状态。这个过程中也是要上链的。这时候的分配方案是【A:10, B:10】。(分配方式是指交易双方都能够在链下都认可的资产分配方式,总量是一样的的,要么 A 多,要么 B 多,如果这个时候合约终止,就会按照分配方案的资产打回到各自的账户上)
- 此后,由于 A 和 B 之间的状态通道处于 Open 的状态,A和B之间可以开始交易。如果 A 向 B 转了1个资产,则分配方案为【A:9; B:11;N:1】,这时 B 拿到了 A 对分配状态的签名;而接着 B 又向 A 转了3个资产,这时的分配方案变为【A:12; B:8; N:2】,这时 A 拿到了 B 对分配状态。这里 N 表示 Nonce。每次链下双方按照约定改变资产分配,则双方都要自增一次 Nonce 值。诚实的交易者都会以 Nonce 最大的分配方案作为当前的分配方案,而 Nonce 值较小的分配方案都是失效的方案,可以随时抛弃。
- 状态提交,在交易的过程中,交易双方,A 或者 B都可以随时向智能合约 C 发起状态提交,如果 A 发起了状态提交,C 会验证 B 的签名;反之如果 B 发起了状态的提交,C 会验证 A 的签名,同时也会验证 Nonce 值。智能合约 C 只接收比上次链上分配的 nonce 值更大的方案,如果新提交的分配方案的 Nonce 和签名都合法,则 C 接收新的分配方案,并更新合约中的 Nonce 值为新分配方案的 Nonce 值。双方持续交易,... … 直到最后的分配方案,假设是【A:1; B: 19; N:50】,下面称为最终状态。假设该方案已被提交到智能合约 C,且被智能合约所接受。
- 关闭状态通道请求,这时候可由任一方发起关闭状态通道,即按照合约中的链上分配方案进行分配。一旦合约 C 接收到关闭通道的请求,合约会进入 Closing 状态并维持一定的有效期,在该状态下且在有效期内,另一方依然可以提交新的有效的分配方案来将状态通道置回 Open 状态。如果在有效期内另一方未能将状态通道置回 Open 状态,则状态通道会在有效期过后,进入 Closed 状态。比如,在这个案例中,B 是受益方,一般来说,是由 B 在这时候发起关闭状态通道请求,然后状态通道进入 Closing 状态,并在一定有效期后按照链上最后的有效分配方案【A:1; B: 19; N:50】进行分配。此时,若B是一个作恶者,虽然现在链上的分配方案为【A:1; B: 19; N:50】,但其实链下最新的分配方案已是【A:4; B: 16; N:55】,但 B 尝试用老的分配方案来分配资产,使自己获益增大。此时由于合约在 Closing 状态,只要A及时发现 B 的链上关闭通道请求的交易,则 A 可以立刻将更新的分配方案【A:4; B: 16; N:55】提交到合约,从而使得合约被置回到 Open 状态,防止 B 的恶意提款。之后 A 如果想关闭合约,则可重新向合约发起关闭状态通道的请求。之后只要 B 无法再给出比 N:55 更新的分配方案,那么状态通道最终将在有效期过后,进入 Close 状态。(注:具体实现时也可以将”状态提交”和“关闭状态通道请求”合并成一步)
- 最终资产分配:当合约 C 进入 Closed 状态后,任何一方都可以触发最终的资产分配,即按照链上已确定的最后有效的分配方案进行实际的资产分配。
回顾整个过程,需要写入区块链的步骤,只是和链上智能合约 C 相关的部分,分别是开始创建的时候和分配方案的提交以及最终状态的提交。其余都是在链下操作,所以在状态通道的设计中,项目一般设计为 只向区块链智能合约 C 提交一次,从而做到最高的性能。
PPIO 的状态通道机制的设计
PPIO 支持三个核心模块
- POSS 是 P2P Object Storage Service,对标 AWS 的 S3 存储。
- PCDN 是 P2P Content Delivery Network,对标传统的 CDN,就像 AWS 的CloudFront。
- PRoute,是基于 P2P 的自适应网络智能路由,做到两个节点之间,以最合理路径到达,从而速度最快,延迟最低 。这是协议层的实现,在 AWS 中没有对标的产品。
其中除去 POSS 模块外,PCDN 和 PRoute 都是更多激励带宽的贡献,其网络数据的传递非常频繁且实时。如果每个 Piece 的传输,都要写入区块链,这将是非常大的浪费 。其实,网络数据高速传输激励,本质上是高频交易和微支付,所以在设计 PPIO 的时候,我们借鉴了传统的传统的状态通道机制,来实现带宽的激励。
- U 创建了区块链上的智能合约 Contract(后面简称C)。然后 U 往 C 中转入资产,假设转入了10个资产。由于 PPIO 设计的是单向通道,只有 U 转入资产后,即可进入Open 状态,其分配方案是【U:10; M:0】
- 开始进行数据传输,U 向 M 请求数据,M 向 U 返回正确的数据后,U 会给予 M 一个 Voucher,即带有 U 签名的新的状态分配方案。由于网络传输的实时性要求非常高,M 需要先给数据,再拿 Voucher。此时分配方案逐步变成 了【U:9; M:1】。
- 继续传输数据,状态通道的分配方案,U 的资产越来越少,M 的资产越来越多。直到U 把之前存入状态通道的资产用完,即【U:0; M:10】;
- 最终状态提交:此时 M 用最新的 Voucher 去区块链上的智能合约用 Voucher 去提款。C 在验证 Voucher 中有 U 的正确签名后,接受了 M 的提款。之后状态通道关闭,标记为 Close 状态,之后该状态通道不能再进行交易。
- 之后 U 在 M 请求数据,由于资产已经用完,M 将不再提供服务。除非 U 创建新的状态通道合约 C1,再转一定的资产进去,才能再次向 M 请求数据。
图:PPIO 的数据传输状态通道设计
这就是 PPIO 整个状态通道的过程。下面我们做一下简单的攻防分析。
- 假设 User 作恶,作恶方式为 U 向 M 请求到了数据之后,不给 Voucher。处于网络性能的考虑,PPIO 的设计是 M 先给一定的数据,再要 Voucher。如果 U 不给 Voucher,M 给予一定量的数据发现收不到 Voucher,于是将不再对该 User 给予更多的数据了,并且标记为 U 为恶意用户,已经给予的部分数据作为自己有限的损失。
- 假设 Miner 作恶,作恶方式是给予 User 错误的数据。User 收到一定量的数据后,就会发现数据异常,于是不给予 Voucher,并向区块链智能合约 C 发起关闭状态通道,并标记该 Miner 为恶意矿工。如果网络中存在 Verifier,U 还可以向 Verifier 举报 M,之后 Verfier 会对 M 重点验证,分析 M 是否还存在其他作恶。
图:如果 User 发现 Miner 作恶的状态通道示意图
采用状态通道的方式,在交易双方存在作恶的情况下,可能存在一方有些轻微损失。但不影响整体的设计,因此,PPIO 中的带宽激励是不需要 Miner 做任何抵押的,这点和存储场景不太一样。
- 存储场景具有长时性,使得 Miner 抵押成为必要。一次存储少则几天,多则数月,甚至几年,如果在存储期间 Miner 作恶,User 可能面临文件的风险,后果很严重,因此在存储场景下,通过要求 Miner 抵押这一经济手段还迫使 Miner 诚实可靠的为 User 提供存储服务是必要的;
- 存储数据具有确定性,使得验证存储的持久性变的可行。确定性的数据可用 Merkle树来组织,然后利用叶子节点到 Merkle 根的路径作为数据持有证明,而这种证明的验证,利用智能合约或者可信的第三方就可以完成。
而带宽则不同,带宽具有瞬时性和不确定性。带宽传输相对于存储来说,交易时间很短,且传输什么数据在传输前一般都不可知。这两点导致了 User 很难在数学层面上限制 Miner 只传输正确的数据,也就很难通过证明来约束 Miner 使得 Miner 不作恶。一旦 Miner 作恶,可信的第三方或者智能合约也无法准确的判断出到底是 Miner 真的作恶,还是 User 在陷害 Miner,因此即使 Miner 做了抵押,可信的第三方或者智能合约也不知在纠纷出现时如何处置该抵押。所以解决带宽场景的思路和存储场景不一样,带宽场景的思路是利用状态通道实现“小步快跑”:每次都只做很小的交易,如果发现对方作恶,则立刻停止交易,转而寻找新的交易者。这样即使对方作恶,己方损失也不是很大。讲到这里,只是讲解了 PPIO 里面应用状态通道的基本原理,在 PPIO 的一些场景设计中,状态通道还有更复杂的用法,但基本原理是不变的。
Owner 角色的引入
PPIO 在设计的时候,我们还设计了一个 Owner 的角色,Owner 不是一个 P2P 传输角色,而是一个支付和结算角色。在 PCDN 架构中,每个 Peer 都需要指定一个 Owner。这个 Peer 产生的花费由它的 Owner 来承担,而同样该 Peer 赚取的收入也由它的 Owner 来接收。如下图,同一个 Owner 可以对接多个 Peer。
图:Owner 和 Peer 的关系图
这个角色可以简单理解为,在需求端就是开发者,在供给端就是矿池;它本质就是 CoinPool,(代理支付网关,详情可以参考文章《为什么 PPIO 要设计代理支付网关》)。由状态通道升级后的数据分发合约如下图所示
图:PCDN 下最简单的下载流程图
关于引入 Owner 角色的分发智能合约的描述,可以见文章《让智能合约在数据分发中更智能?PPIO 的设计小巧思》。但其中 Peer 和 Peer,Peer 和 Miner 之间的通信本质上还是走得状态通道的机制。
这是最基本的 PPIO 状态通道逻辑,另外在具体应用场景中,如 PCDN 和 PRoute,还有更多的考虑。关于状态通道在 PCDN 场景下应用,具体可见文章《让智能合约在数据分发中更智能?PPIO 的设计小巧思》。另外,我后面还会介绍,PPIO 在具体场景中更深入的实现,请大家敬请期待。效率提升与价值落地一直以来都是 PPIO 实现技术不断创新进步的标尺。
这一期文章,我们分享了如何基于传统的状态通道机制,完成了 PPIO 的状态通道机制的设计 ,从而实现数据传输的公正计量。我们又通过一个实际案例,分析了基于这样的设计, User 和 Miner 的两个角色如何进行有效的数据传输,避免双方作恶带来的不必要的损失。同时也解释了,PPIO 中的带宽激励是不需要 Miner 做任何抵押的,这一点和存储场景有本质区别。不知看到这里,是否让您对的 PPIO 的技术工程实现有了更深入的了解呢?如果您想更进一步的和我们一起学习探索,就快来关注 PPIO 公众号,加入 PPIO 开发者社区或 Discord 群组,和我们一起创造精彩。