The Message is the Medium

in message •  7 years ago  (edited)

原文链接

最初的message设计

这篇文章讲一讲在区块链基础设施设计中,我认为存在的一些基本错误。简单的说,我们错误的把设计重心放到了状态修改的原子性上,而这里更好的替代方案是使用消息(而非状态)。错误的设计影响深远,并且对于非计算机行业的人群更加难以理解。

下面我们用一种通俗易懂的方式,针对非技术领域的朋友,解释消息和状态方案之间的区别。我会尽力简单地描述什么是消息, 在深入之前,你可以先把消息理解为我们发布出去的一篇博客文章,虽然这个比喻比较简陋。

什么是状态机?

状态机是一个软件装置,通过它,我们能在某一时刻得到一个确定的状态。换句话说,如果状态机初始状态一致,当我们输入同样的数据,那么状态机的输出结果肯定也是一样的。

我们可以把状态机比做一个自动贩卖机的系统软件,贩卖机的软件部分决定了硬件可以执行的行为。如下图,当贩卖机处在状态1下,它在等待用户投币。如果被投币,贩卖机进入状态2。在状态2下,贩卖机会等待用户点单。如果点单按钮被触发,则投递对应的饮料,最后回到初始状态1。本质上所有贩卖机都运行着同一套代码和内存数据, 这保证了我们可以通过算法准确获取到某一刻机器的实时状态。同时,它在感知到外部传入的消息后(如投币,按点单按钮),能够根据算法和当前状态产生确定的行为(如投递饮料)。

我们可以通过组合小的状态机,形成一个大的——数据库本质上就是一个大型状态机,数据库的表、表内的每一行、每行的每个属性,都可以看做为状态机。协议则是一对状态机,两头一边一个。区块链,则是另一个庞大的状态机,它由成千上万个“全节点”状态机组成,每个全节点还挂靠着成大量轻量客户端(SPV client)。本质上,状态机的设计很简单,但是如何将小的状态机组成一个大的,这是一门科学艺术(没有固定方法)。对这里的复杂性,我们不多作展开。

选型

创建一个状态机,一般有两种方式。

请注意,后面我以一种要求不太严格的、比较个人化的方法来描述。首先为了简洁,我们刻意省略了代码部分(IF语句)和输出部分(DRINK)。毕竟这篇文章的主要目的,是帮助并非geek的你,理解消息是什么。

我们设计的状态机通常如上图所示——从状态1开始,然后接收到消息1。对消息1的处理,使状态从1变成2。当它的状态由2变成初始状态1的过程中,会视情况发送消息出去。

实现一个状态机,主要是通过代码去控制保存交易状态,有消息过来,代码能控制已知状态间的转换。 实现它的过程中,最终我们发现本质上有两种构建方法。这两种选型的碰撞,极大丰富了我们的思考和设计,最终增强我们的技术能力。

方法一:创建一个状态机,先保存初始状态1。当消息到来,状态由变成2,然后保存状态2。一直不断重复!我们所有要考虑的,就是保存好上图两个蓝色圆圈所表示的状态,其他的任何信息都可以被忽略掉。

方法二:创建一个消息机,消息机启动时都在状态1。当输入数据(如上图的红色药丸,即消息)被灌入机器,我们将消息记录下来,然后输出新消息。这种场景下,我们保存了消息丢弃了状态,因为状态可以随时被计算出来。

实际上,因为机器的运行结果是可预测的,所以两种选型理论上很接近。这样的消息机一旦被创建,那么它的执行结果都可以可预期的,例如上图我们输入M1,一定会使消息机状态从State1转换为State2,最终输出M2。

接着,如果我们再拿一个一样的状态机,输入与刚才一样的消息,就可以得到一样的最终状态。再或者,如果记录所有状态,我们也能根据状态的前后变化,反推出它导致的执行动作,而导致状态变化的消息也不再重要。 大家都学习过几何,这其实就是一个“存储点”还是“存储边”的问题。

上面提供了区块链基础设计的两种思路。通过对我们的需求进行分析,可以决定选择其中的一个:
数据库是一个状态机,它就像一个开关——知道自己是开着还是关,但并不知道在这之前变化的过程。在与数据库通信时,协议就充当了消息机的角色。例如我们用email通信,拿到最后一个邮件并不能得知整个对话的经过,但是通过扫描两个人的来往消息,就能得知具体过程。

区块链的底层模型究竟选哪一种?

我们要说的是理论上的,而实际很可能不一样。比如,你的银行账号看起来就像一个状态机,里面存储着可以随时查看的余额。但是在银行内部,因为他们统计时采用复试记账,这看起来更像一个消息机。

区块链现在应该怎么做?

有可能是历史的原因,或者是因为惯性思维,区块链更多的被当做是一个状态机,而非一个消息机:

......区块链的主要功能,是维护一个可以被并行修改的状态。为了解决并发读写冲突,区块链把状态记做账本(LEDGER),账本中包含了一系列对初始状态的更改。区块链把这些更改记录到一个区块(BLOCK)当中。在比特币的例子中,区块链保存的状态通常指未被花费的余额(UTXO)。
——LM Goodman, "Tezos: 一个自动修复的加密账本立场文件",2013

再或者,我们来看最近的一个以太坊替代项目:

如何让交易语义和合约更好的融合在一起?
在消息处理的角度上看,交易是指在某条链上,它已经被见证过并且通告(给所有节点)。
消息只是一个被传输的虚拟的数据结构,但当它被发起方传递给合约后,将导致合约前后状态发生实际变化。而这个过程被另外的节点见证,最终将被打上时间戳,记录到存储器(区块链)中。
消息的传递是一个原子操作。不管一个消息是否被见证,只有被成功见证过的消息才会被记录到一个区块当中。
——anon?,“RChain架构-合约的设计”,2017 RChain Cooperative

我们留意到,上述作者创造了一个完整的、以存储交易消息为基础的区块链,却最终落地变回了典型的状态型区块链。

另外一个例子,如下图,我们看一看比特币的UTXO状态机模型(UTXO是用户未花费余额的状态集合)。在UTXO模型下,交易是一条对状态的记录,里面包含了一组输入和一组输出。对比上面的图3,我们只关注两个蓝色圈中表示的状态(忽略红色的消息)。通常每一笔交易就像下面的蓝色方框,从左边有一组状态输入,右边有一组新状态输出。

方框左侧输入的,是其他交易的输出。输入后,就代表他们被花掉了,并且从右侧输出一组相应的可用余额,输出的余额可以在未来被交易。上图中,TRANSACTION 1输出了0.5个比特币,TRANSACTION 2消费了刚才输出的0.5个比特币。

比特币的一个交易记录,记录了若干输入和输出,就好比一个小型的资产平衡表,输入的余额必须等于输出的余额。 交易记录就好比乐高积木,新的交易记录必须对接到旧的交易记录中,并且开放给更新的交易记录对接。

UTXO的脆弱性

我们很早就知道,但是这里我还是要重提一下:比特币的设计精妙非凡,但是从另一面看,它的很多组件相互的关联性太强了。如下所说:

“一个纯粹的P2P版本的电子现金,能够允许点到点的在线支付,这个过程绕过了传统的金融机构。”
中本聪,“比特币白皮书:一个点对点的电子现金系统”,2008

(变成流通)货币是比特币的目标,同时,货币也是维护它安全性的驱动力(通过奖励竞争挖矿的获胜者)。货币和安全性之间的强依赖,导致了比特币在架构上存在脆弱性。这里并不是说比特币会因此而崩溃,我们想说明的是,如果我们更改比特币系统中的某个设计,这可能导致(比特币) 的架构不再像之前那样经得起推敲。

同样的问题存在于UTXO。我们刚提到,比特币的目的是想成为流通货币。对于全节点来讲,它需要记录下当前时刻的每一笔可用余额,这样才能保证它独立验证所有交易,并且打包出块以获得奖励。相反的,对于SPV轻量节点或者其他远程轻量客户端,则只需要提供一个简单的方法证明有他能花这笔钱,完全无需将整个链(中交易输出的UTXO状态集合)记录到本地。

上述两个需求通常是矛盾的(在一个节点上,同时满足货币的流通性和安全性)。对于比特币这样拥有海量交易记录的链来说,UTXO的设计非常精巧,在一定取舍下满足了两个需求,同时保证了性能。当客户需要证明自己有一笔未花费余额(UTXO)的时候,它的优点就体现出来了。

An Order Book

如果上述两种需求发生变化,UTXO还好用么?例如我们想做一个交易所。综合很多因素后,我们发现最好的实现方式是把所有信息聚集起来,将买卖双方的报价组成一张清单,然后通过一个竞拍程序, 根据大家的报价找到一个最优方案进行撮单。当然也有其他方案可选,不过这已经是被众多交易所实践过,并且经受了时间考验的最优方法。

试想当在UTXO状态机下,有一批未知数量的买家和卖家。这里有两个需求因素制约着UTXO,让其难以发挥优势:1.不同交易员需要根据买入量、卖出量、价格随时动态撮合多方需求,达成多方满意的订单结果;2.撮合交易对消息非常敏感,当交易员得知新底价后,如果有办法他一定会撤销和撕毁之前的报价。这两个需求基本上是矛盾的。

基于消息流的设计可以轻易解决这个难题。如果链上的撮合者(在POW场景中指矿工,DPOS场景中指出块者)有稳定的买入和卖出订单消息流,它只需要简单地将接收到的订单全部放入一个“撮合合约”中,然后撮合价格匹配的订单达成交易,然后以消息的形式输出合约的执行结果。

这个过程中,消息都被日志记录下来,但是状态(例如UTXO)则是隐式的,这意味着状态只存在于机器内部的,无需(永久)保存下来。只要链上确定了消息的约束集(如消息如何输入、如何排序执行),那么同样的合约,部署在任意节点上,当我们输入同样的消息,合约执行结果一定也是一样的。

(消息机)还有两个优势:第一,当前块未确认的交易会自动延迟到下一个区块中进行确认。因为每一个传入的交易消息都是与时间无关的独立的一笔交易。而对于UTXO,每一次交易的输入和输出都会影响UTXO集合的状态,所以每笔交易都强依赖于当前时间点的UTXO状态集(每次均需重新判断)。

第二个优势,这种设计能反馈更多的(撮合交易订单的)问题。例如,当你和我想达成一笔交易,我们只需要把买入和卖出消息发送到交易合约中。这里,最复杂的一部分(撮合交易)被合约解决了,而合约的作者在设计的时候已经解决了这个问题。相反的,我们来看UTXO合约,如果你和我想按照figure5中蓝色方框内的内容达成交易,UTXO将最复杂的一部分(撮合交易)交给了交易的用户,而最简单的一部分(把记录消息到日志里)则放到了区块链上去解决。

更多的,你还可以对比在两种设计下,交易费处理上的不同。

(消息机模型的)一些疑虑

并不是说消息机就很完美,状态机的优势是跟踪定位bug更快。状态机下每一笔交易都必须对当前状态达成共识,而消息机只确认消息达成共识。对于撮合交易来讲,能够快速捕获到(状态不一致的)问题是一个很大的优势。这对于致力于削减成本和运营风险的金融部门来说,非常重要。

但是即使有这个优点,当区块链发生bug时,往往还是会产生硬分叉。

节点间的不一致,整条链都会陷入瘫痪。

当消息机模型的区块链发生bug时,由于bug都是隐式的,最多导致不同的节点对于相同消息的产生不一样的处理。受到bug影响的人可以把这条消息隔离开,然后将消息放到线下进行跟踪和重放,进一步观察bug是如何发生的。

结论

要组建一个广为人用、且可靠的区块链,消息机模型在很多方面都优异于状态机模型。但并不绝对,因为状态机在跟踪异常上更快。

虽然我们可以写一篇更全面的分析贴,列举两种模型间更多的优缺点,但本文只重点讲比较重要的几条。基于消息链模型除了有以上灵活的特性外,还能获得更高的运行效率。例如@danthemann设计的bitshare和steemit都建立在消息机模型上,两个系统均能达到1000以上的TPS。我自己研发的Ricardo系统也类似,即使它不是区块链项目,但却解释了为何我如此偏爱消息机。

理论上,消息机模型确实能提供一个更高性能的解决方案。同时,可能大家已经隐约知道,EOS项目就是基于消息模型构建!实际上,正是因为对(区块链链上数据处理)速度的需求,驱动着设计师@danthemann和我发现并且认识到(鉴谅我引用Marshall McLuhan的至理名言):

the message is the medium.

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

hello,请问你微信多少?加我们eos 开发者群不?

可以啊,不过这里不太方便公布微信号,要不先加个电报可以吗