这55行状态通道代码,带你快速扩展以太坊生态

  • 辉哥
  • 更新于 2018-08-12 20:56
  • 阅读 4144

这55行状态通道代码,带你快速扩展以太坊生态

2017年底的以太猫游戏堪称是以太坊的一个经典去中心化应用,同时也导致了以太坊网络濒临瘫痪,从那以后,区块链扩展性问题逐渐被人们重视起来。

区块链可扩展性问题非常棘手,极大地限制了区块链技术的应用和普及。如何提高区块链吞吐量是急需解决的问题,状态通道技术在此背景下应运而生并快速发展,可以在一定程度上使区块链技术满足日常业务的需求。

本文从技术角度剖析状态通道存在的问题以及解决方法,并以井字游戏为实例帮助读者更好地理解状态通道技术。哪些操作可以放在链下?怎样保证链下操作的合法性?如何实现状态通道技术?希望本文能对你有所启发。

频繁的交易会导致以太坊虚拟机变得越来越慢,交易费用也越来越高。

目前,大多数建立在以太坊上的应用程序,都是通过更新链上智能合约的存储变量来进行存储工作的,用户需要支付交易费用并花费时间等待区块确认。

利用与链上合约交互来存储数据的过程是非常缓慢的。

幸好,我们找到了一个解决方案——状态通道。

我们可以利用一些客户端代码,而不仅仅是依靠以太坊来支持完全安全的应用程序,我们将之称为“第2层(L2)”技术。

“大部分以太坊是没有扩展性的!”,这并不是因为区块链技术不合适,准确地说,因为开发人员很难使用第2层技术,比如状态通道。我们需要在以太坊之上开发更好的工具,让开发人员可以高效地编写应用程序。

为什么现在很难使用状态通道?

目前,如果一个开发人员想要利用以太坊平台实现一个去中心化应用,需要实现以下所有的模块:

一个通用的API——智能合约上的公共或外部函数

授权逻辑——通常检查msg.sender

解析逻辑——决定如何分配资金

在大多数情况下,以上是开发人员在设计去中心化应用程序时需要考虑的因素。在过去的一年中,已经有数以千计的开发人员使用以太坊的模式来构建应用程序,所以不要从根本上改变以太坊的架构。

当你想尝试设计一个状态通道应用程序时会遇到各种各样的障碍,比如说:

不清楚应该如何编写公共API,因为你不再对以太坊的各种交易进行签名,而是对通用状态对象进行签名;

授权逻辑要求状态通道的每个用户为每个更新都签署一个对象,并使用ecrecover 来验证这些签名;

解析逻辑更加复杂,因为每次提交新状态时都有一个内置的“挑战”或“争议”期。

最糟糕的是,没有一个标准可以用于整个状态通道协议的建立,因此目前很难出现状态通道的框架或公共库。

怎样让状态通道技术变得更容易?

标准化通用态通道功能是使状态通道应用程序容易实现的关键,通过标准化功能可以将状态通道解析逻辑从应用程序逻辑中分离出来。

应用程序以一种与状态通道兼容的格式编写,而且编写应用程序需要尽可能简单,理想情况下,开发人员要感觉到自己正在编写常规的智能合约代码。

实现这一点的方法是将应用程序建模为状态机。 force-move game framework 就是这样的一个例子。

以太坊虚拟机(EVM)就是建立在状态机的基本思想之上,根据交易执行的结果更新每个块的状态。

常规的智能合约和与状态通道兼容的智能合约有什么区别呢?

从本质上说,可以归结为这样一个事实:我们需要一种标准的方式来与应用程序的状态转换进行交互,而不管公共 API 是如何实现的。简单来说,我们需要一个入口点函数来计算状态转换的结果。

一个例子——井字游戏

假设我们要编写一个井字游戏的程序。我们可能会编写一个智能合约,这个智能合约有 placeX 和placeO 两个公共API。检查 msg.sender 来验证玩家是否正确地进行游戏。

1contract TicTacToe {
 2
 3  address player1;
 4  address player2;
 5  uint8[3][3] board;
 6  uint8 nextTurn;
 7
 8  function placeX(uint8 x, uint8 y) public {
 9    if (msg.sender == player1) { ... }
10  }
11
12  function placeO(uint8 x, uint8 y) public {
13    if (msg.sender == player2) { ... }
14  }
15
16}

一个用solidity语言写的井字游戏的智能合约

将这个游戏建模为一个状态机,我们可以看到在它们之间有5种状态和2种有效的转换类型。

一个井字游戏的状态机,如果轮到X进行游戏, X可以赢得比赛、以平局结束比赛或者是让O进行游戏

创建一个函数,该函数接受状态机的一些先前状态(例如,X_TURN)和一个可以用于到达新状态(例如,PLACE_X)的操作。这与目前存在的一些常见Web框架的模式完全相同,比如Redux。我们以这种思想改写井字游戏应用:

1contract TicTacToe {
 2
 3  enum ActionTypes { PLACE_X, PLACE_O }
 4  enum StateTypes { X_TURN, O_TURN, X_WIN, O_WIN, DRAW }
 5
 6  struct Action {
 7    ActionTypes actionType;
 8    uint8 x;
 9    uint8 y;
10  }
11
12  struct AppState {
13    StateTypes stateType;
14    address player1;
15    address player2;
16    uint8[3][3] board;
17    uint8 nextTurn;
18  }
19
20  function reduce(AppState state, Action action)
21    public
22    view
23    returns (AppState)
24  {
25    if (action.actionType == ActionTypes.PLACE_X) {
26      require(state.stateType == StateTypes.X_TURN);
27      return onPlaceX(state, action);
28    } else if (action.actionType == ActionTypes.PLACE_O) {
29      require(state.stateType == StateTypes.O_TURN);
30      return onPlaceO(state, action);
31    } else {
32      revert("Invalid action type");
33    }
34  }
35
36  function onPlaceX(AppState state, Action action) internal returns (AppState) { ... }
37  function onPlaceO(AppState state, Action action) internal returns (AppState) { ... }
38
39}

一个井字游戏,只有一个还原剂函数来处理PLACE_X和PLACE_O操作,而不是多个函数placeX和placeO,还原剂函数将操作“分派”给辅助函数

遵循上面的思想,我们有了一种计算状态更新的方法,可以用一个通用接口(reduce interface)对应用程序进行更新。当考虑到在各种攻击下保护状态通道时,这一点是非常有用的。

但是状态通道合约的功能是什么呢?

本质上说,状态通道对象应该使用应用程序逻辑来确定状态转换是否有效。在通用的合约中设计状态通道的核心功能,这个合约用于处理各种可能的攻击场景,但是对状态机的特定转换规则需要委托给具体的应用程序。

讨论两个主要的场景,我们使用一个常见的例子:Alice和Bob交换消息,将这个例子定义为:

如果Bob提交过时的状态怎么办?

合约必须要实现一个超时时间等待的功能,这样Alice就有时间提交比Bob更加新的状态。如果Bob提交的状态被证明是旧状态,那么Bob应该受到惩罚。

如果Bob停止回复呢?

合约必须实现如下的功能:Alice可以提交她从Bob处收到的最新签署状态,以便将她的钱取出(超时后)。在某些情况下,Alice可能会“回退”应用程序的状态机,因此在这种情况下,她必须能够使用应用程序的 reducer。

为此,合约需要公开一个基本的API,它的作用是处理争端事件。状态通道的用户可以使用一组函数调用来确保他们正在签名的离线状态更新具有意义。

大体上说,这个API具有以下功能:

创建一个纠纷:一方提交最新签署的状态副本,并对该应用进行状态转换,从逻辑上将当前状态推进到下一个状态。

处理一个纠纷:一方对另一方的纠纷作出反应,对已提交的状态采取行动。

取消一个纠纷:双方同意解除纠纷,并恢复正常链下运行。

资金存放在哪里?

我们将这些资金放在一个通用的多签名钱包中,并把它作为一个智能合约,根据状态通道的结果对这些资金进行分配。

一个简单的状态通道应用所需要的一组合约,它不使用counterfactual实例,仅仅只使用常规的合约引用

这对我们而言有很多好处,其中一点是可以利用 counterfactual 实例化技术。当我们将其添加到组合中时,在链下维护状态通道合约和应用程序逻辑合约。

与上面的设置相同,但这一次状态通道合约和应用程序逻辑合约是counterfactual的——它们只需要在发生纠纷时部署上链

与上面的设置相同,但这一次状态通道合约和应用程序逻辑合约是counterfactual的——它们只需要在发生纠纷时部署上链

达成以上的功能后,我们得到了另一个非常强大的特性:安装和卸载应用程序都可以链下进行。

当我们使用counterfactual时,添加和删除应用程序是免费并且实时的。

实际上,由于我们可以从多签名钱包中为有条件的传送进行无限次的调用,因此这些承诺可以用于多个应用程序。

在未来,为了在真实的生产环境中使用状态通道,需要协调整个生态系统。

标准化研究术语,同时学习状态通道技术和第2层扩展中其他的研究问题。

基于链下的范式,将广义的状态通道模式集成到现有的状态通道系统和应用程序中。

与Web3框架合作,使开发人员更关注链下API的开发。

与钱包提供商合作,针对状态通道如何集成到其领域的问题,帮助提供清晰的协议规范和标准。

原文链接,作者:Liam Horne 编译:kou https://medium.com/statechannels/state-channel-applications-1f170e7d542e

本文转载自 《V神正在密切关注!这55行状态通道代码,带你快速扩展以太坊生态》 , 版权属于原作者

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
辉哥
辉哥
0x5bAe...0BE7
HiBlock技术社区上海合伙人,区块链落地产业应用布道者