频繁的交易使的以太坊虚拟机变得越来越慢,交易费也越来越高。当下,大多数建立在以太坊上的应用都是通过更新链上合约的存储变量来实现,用户需要支付交易费并花一定时间等待区块确认。
当然,这也是低效的。为了使用应用,我们要求用户手动将数据库更新提交至世界上最安全的、分布式的、无需信任的。。。1999 年老式手机(译者注:意为当前的以太坊就像 1999 年的老式手机)。
我们可以通过将一些工作转移到客户端而不是完全依赖以太坊编写足够安全的程序。我们将这类方法统称为“第二层”区块链技术。在 L4, 我们已经写了 很多帮助解决这个问题的不同方法。
大多数“以太坊是不可拓展”的观点不是因为底层区块链不合适。更准确的说,是因为开发人员难以使用像状态通道这样的“第二层”区块链技术。我们需要以太坊上有更好的开发者工具,从而使得用有效的方式编写应用程序变得更加简单。
Counterfatual 是一个正致力于解决该问题的开源项目。我们的目标是让开发者在以太坊上轻松地使用状态通道构建应用。你可以在我们的 主页 上了解更多项目相关信息,同时可以在 github 上查看我们的代码。
当下,如果开发者想要使用以太坊编写他自己的分布式应用,他们可能需要实现以下内容:
在大多数情况下,在开发者设计分布式应用时,这是一种较好的抽象方式。我们已经看到 成千上万的开发人员在过去一年中使用这种模式在以太坊上构建分布式应用 了,因此最好不要彻底改变它。
从这个角度思考状态通道可以让你与应用开发者更加感同身受。大多数情况下,当你尝试设计状态通道应用程序时,你会遇到各种各样的障碍,例如:
最糟糕的是,状态通道协议完全 没有既定标准 ,这使得框架以及公共库难以产生。
使状态通道应用程序更易于实现的最重要的第一步是要 清晰地将状态通道解析逻辑与应用逻辑分离开来,以此标准化通用状态通道功能 。应该尽可能简单地用状态通道兼容的格式编写应用程序,理想情况下,应该感觉你在编写常规智能合约代码。
其中一种实现方式就是将应用程序建模成状态机。 force-move game framework 就是一个例子,通常来说,EVM 就是建立在状态机的基本思想上——根据交易执行更新区块状态。
那么常规智能合约和状态通道兼容智能合约之间的区别是什么呢?从本质上来说,可以归纳为一句话: 我们需要一种与应用程序状态转换交互的标准方法 ,而不管公共 API 如何实现。更简单的说,我们需要一个入口函数实现状态转换。
假设我们想要写一个井字游戏程序。我们会写这样一个智能合约:它有 X 和 O 函数的公共 API ,可以检查 msg.sender 以验证玩家是否正确的进行游戏。
contract TicTacToe { address player1; address player2; uint8[3][3] board; uint8 nextTurn; function placeX(uint8 x, uint8 y) public { if (msg.sender == player1) { ... } } function placeO(uint8 x, uint8 y) public { if (msg.sender == player2) { ... } } }
将该游戏建模成一个状态机,我们可以看到共有 5 种状态以及 2 种有效的状态转换类型。
-
-
回到更新应用状态的标准接口的想法,我们想要创建一个函数以接受状态及一些先前状态(如, X_TURN)以及会导致状态迁移的操作(如, PLACE_X)。有趣的是,这与现有的一些常见 Web 框架的模式完全相同,比如 Redux 。这种功能常常被称作“reducer”。让我们试一下用这种方法编写井字游戏吧:
contract TicTacToe { enum ActionTypes { PLACE_X, PLACE_O } enum StateTypes { X_TURN, O_TURN, X_WIN, O_WIN, DRAW } struct Action { ActionTypes actionType; uint8 x; uint8 y; } struct AppState { StateTypes stateType; address player1; address player2; uint8[3][3] board; uint8 nextTurn; } function reduce(AppState state, Action action) public view returns (AppState) { if (action.actionType == ActionTypes.PLACE_X) { require(state.stateType == StateTypes.X_TURN); return onPlaceX(state, action); } else if (action.actionType == ActionTypes.PLACE_O) { require(state.stateType == StateTypes.O_TURN); return onPlaceO(state, action); } else { revert("Invalid action type"); } } function onPlaceX(AppState state, Action action) internal returns (AppState) { ... } function onPlaceO(AppState state, Action action) internal returns (AppState) { ... } }
有了这些,我们现在有了一种计算状态更新的方法了:可以通过一个公共接口——reduceinterface 对应用程序进行状态更新。这一点在保护状态通道免受各种攻击时非常有用。
但是状态通道合约到底需要做什么呢?
本质上说,状态通道对象需要 使用 应用逻辑来判断状态转移是否有效。核心状态功能可以在一个用于处理各种可能攻击的通用合约中实现,状态机的具体状态转换规则则需要视具体应用而定。
有两个需要处理的主要场景。如果我们使用 Alice 与 Bob 互相交换信息这一常见例子,这两个场景可以被描述为:
如果 Bob 提交过时的状态该怎么办?
合约必须能够实现 超时阶段 (timeout period),这样 Alice 就可以提交比 Bob 提交更新的状态。如果 Bob 提交的状态被证明是旧的,那么 Bob 就要受到惩罚。
如果 Bob 停止响应、该怎么办?
合约必须让 Alice 可以提交她从 Bob 那里收到的最新签署状态,以便将她的钱取出来(超时阶段后)。在某些情况下,Alice 可能可以推动应用状态机状态迁移,因此她必须要能够在这种情况下使用应用程序的 reducer。
为此,合约需要公开一个基础 API。请注意,这个基础 API 的主要作用是处理有争议的事件。状态通道用户可以通过调用一组函数来保证他们签名的离线状态更新有意义。
这个基础API包括:
这就是 我们的论文 中描述的许多特性非常有用的地方。我们将资产放在一个通用的多签名钱包中,并将其作为依据状态通道结果分配资产的主要合约。
这给我们带来了很多好处。最大的好处之一就是可以利用 counterfatual 实例技术,这一点也在 论文 中详细描述了。当我们将其添加到组合当中时,可以在链下维护状态通道合约以及应用逻辑合约。
在我们完成这些设置之后,我们又获得了另一个强大的特性: 安装和卸载应用都可以在链下进行。
当我们使用 counterfatual 时,安装和卸载应用都是免费和即时的。由于我们可以从多重签名钱包中无限调用有条件转移,因此,可以保证任意数量的应用免费且即时的安装与卸载。
在以后的帖子、演讲以及讨论中,我们将概述我们对于合约层之上的软件的愿景。要想在生产生活中应用状态通道,还需要整个生态系统进行大量的协调。我们当前正在开展并期待与其他人进一步合作的具体领域包括:
作为一个好的起点,我们建议你查看 我们共享在 GitHub 上的合约代码 ,代码包含该技术的参考实现。
我们将继续与对未来分布式应用开发感兴趣的优秀团队和个人合作,也期望邀请其他人和我们合作。
这只是旅程的开始。为了看到所有用户均可访问的通用状态网络网络,我们需要做的还有很多。
状态通道将成为用于点对点价值转移的协议。它们将需要进行标准化从而可以在各种客户端、钱包以及区块链中使用。
如果你有兴趣和我们一起实现这样的未来,请通过 hello@counterfactual.com 联系我们,或者在 Github 上加入我们。
原文链接: https://medium.com/statechannels/state-channel-applications-1f170e7d542e
作者:Liam Horne
翻译&校对:Aisling & Elisa