无状态以太坊的根基:零门槛了解Witness规范

洒脱喜 发布在 技术指南 35542

写在前面:无论是对于以太坊1.0,还是未来的以太坊2.0,无状态以太坊的概念都具有着颇为重要的意义,而要理解它,我们就需要了解Witness以及Witness的规范,那它们到底是什么呢?在这篇文章中,来自以太坊基金会的开发者Griffin Ichiba Hotchkiss将用生动的比喻来对这两个复杂的概念进行解释。

无状态以太坊的根基:零门槛了解Witness规范

有些东西看似可能会显得枯燥,但是它对于无状态以太坊而言却是非常基础和重要的:理解正式的Witness规范。

就像星际争霸中的战舰船长一样,我们会慢慢来讲这个话题。Witness规范不是一个特别复杂的概念,但它是非常深的,以至于这种深度有点让人望而生畏,但它是非常值得探索的,也许它会唤起书呆子的兴趣,它远远超出了区块链,甚至超出了软件的世界!

在这篇入门文章的结尾,您至少应该对理解正式的无状态以太坊Witness规范,有了最低程度的信心。我也会尽量让这篇文章显得更有趣一些。

 

概述:关于状态你需要知道的知识点

 

实际上,无状态以太坊这个词有点用词不当,因为状态才是整个工作的真正目的。具体来说,我们要找到一种方法,使得保留整个以太坊状态的副本,成为一种可选的事情。如果你没有关注过无状态以太坊的文章,那么你可能有必要看看我之前写的一些关于无状态以太坊状态的入门文章。在这篇文章当中,我先简单地总结一下,如果你已经很好地掌握了这个话题,那你就可以随便扫上一眼。

“ 以太坊的完整“状态”描述了所有账户和余额的当前状态,以及在EVM虚拟机中部署和运行的所有智能合约的集体记忆。链中每个最终确定的区块,都有且只有一个状态,这是由网络中的所有参与者商定的。该状态将随添加到链中的每个新区块而发生更改和更新。

以太坊状态以一种称为Merkle-Patricia Trie(默克尔-帕特里夏树,简称为MPT)的哈希数据结构呈现的,它将每一条信息(如帐户余额)组织成一个庞大的连接单元,然后可以验证其唯一性。

完整的状态树太大了,大到无法可视化,但是这里有一棵“玩具版”状态树,当我们接触到Witness的概念时,这会很有帮助:

无状态以太坊的根基:零门槛了解Witness规范

就像神奇的密码学毛虫一样,智能合约的账户和代码也存在于这棵树的叶子和树枝上,通过连续的哈希运算,最终得到一个根哈希。如果你想知道一棵状态trie树的两个副本是相同的,你可以简单地比较根哈希。在一个“规范”状态上保持相对安全,且无可争议的共识,是区块链设计的本质。

为了提交要包含在下一个区块中的交易,或验证特定更改是否与上一个包含的区块一致,以太坊节点必须保留状态的完整副本,并重新计算根哈希(一次又一次)。而无状态以太坊(Stateless Ethereum)是一组通过添加所谓的“witness”来消除此需求的更改。

 

witness究竟是什么?

 

在我们深入讨论witness规范之前,直观地认识下witness是什么是有帮助的。同样,上面链接的以太坊状态文章当中有一个更彻底的解释。

witness有点像一个健忘型(无状态)学生(客户端)的小抄,而这个小抄是通过其考试所需的最少信息量(提交有效的状态更改以包含在下一个区块中)。这类学生(无状态客户端)并没有阅读整本教科书(仅保留当前状态的副本),而是要求朋友(全节点)提供一张小抄来提交他们的答案。

在非常抽象的术语中,witness提供了一棵状态trie树中所有需要的哈希,并结合了一些关于这些哈希在trie树中属于何处的“结构”信息。这允许这类节点在其状态中包含新交易,并在本地计算新的根哈希,而不需要它们下载状态trie树的整个副本。

让我们脱离这种比喻式的想法,然后转向更具体的实现方式。以下是witness的“真实”形象:

无状态以太坊的根基:零门槛了解Witness规范

我建议您在新的标签页中打开此图像,这样就可以放大它并真正欣赏它。之所以选择此witness,是因为它相对较小,且易于识别特征。这张图片中的每个小正方形,代表了一个"nibble",即半字节,你可以通过计数你必须“通过”的正方形数量来验证你自己,从根开始到一个以太币余额(你应该能数到64)。当我们在看这张图片时,请注意其中一笔交易中必须包含的大量代码(代码在witness中占到了相当大的一部分,并且可以通过代码默克尔(改天再聊这个话题)来进行减少。

 

一些繁琐的事

 

以太坊作为协议的一个基本特征,是它独立于特定的实现。这就是为什么以太坊不像比特币那样只有一个官方客户端,而是有几个完全不同的客户端版本。而这些用各种编程语言编写的客户端,必须遵守《以太坊黄皮书》,该《黄皮书》用更正式的术语解释了加入以太坊协议的任何客户端该如何运行。这样,为以太坊编写客户端的开发人员,就不必处理系统中的任何模糊问题。

而witness规范有一个确切的目标:为所有客户端提供“witness是什么”的明确描述,这将使它在任何语言中的实现变得简单。而当无状态以太坊成“型”时,可以将witness规范作为附录插入到《黄皮书》中。

这里我们所说的“明确”,它的意思是要比你在谈话中所说的要强烈。这并不是说正式规范只是对“witness是什么”,以及“它的行为是什么”的真正详细的描述。这是意味着,理想情况下,描述一个特定witness的方式只有一种。也就是说,如果你遵循了正式的规范,那么你为无状态以太坊编写的实现,它所生成的witness就不可能和遵循规则的任何其他实现不同。这是关键,因为witness将(有望)成为以太坊协议的新基石,它需要通过构造来纠正。

 

语义和语法问题

 

尽管“区块链开发”通常意味着一些新的、令人兴奋的东西,但必须要说的是,其中很多都是基于一些旧的、明智的计算机编程、密码学和形式逻辑。为了理解Witness的规范是如何工作的,我们需要了解一些技术术语,而为了做到这一点,我们将不得不跨界进入语言学和形式语言理论。

大声朗读下列两个句子,并特别注意你的语调和节奏:

  1. furiously sleep ideas green colorless
  2. colorless green ideas sleep furiously
我敢打赌,第一句有点机械化,每个单词后面都有扁平的强调和停顿。相比之下,第二句可能感觉上自然一些,尽管它有点愚蠢。尽管这句话实际上没有任何意义,但它是说的通的,但第一句话却不行。这有点吸引人们注意语法和语义之间的区别。如果你是说英语的人,就可以理解这些单词所代表的含义(它们的语义内容),但这与此处基本上无关。你注意到的是有效语法和无效语法之间的区别。

这个例句来自诺姆·乔姆斯基(Noam Chomsky)在1956年撰写的论文,你可能会认出这个名字。尽管乔姆斯基现在被认为是一位有影响力的政治和社会思想家,但他作为一名学者的最初贡献,是在逻辑学和语言学领域,在他的这篇论文中,他创造了一个最有用的正式语言分类系统。

乔姆斯基关注的是语法的数学描述,如何根据语法规则对语言进行分类,以及这些类别具有哪些属性。与我们相关的一个性质是句法歧义。

 

模棱两可的Buffalo

 

考虑语法正确的句子“Buffalo buffalo Buffalo buffalo buffalo buffalo Buffalo buffalo。” —— 这是一个典型的例子,说明了英语语法规则是多么的模糊。如果你知道的话,根据上下文,“buffalo”这个词可以用作动词(恐吓)、形容词(来自纽约州布法罗市)或名词(野牛),你可以根据每个词所属的位置来分析句子。

我们也可以使用完全不同的词和多个句子:

“You know those NY bison that other NY bison intimidate? Well, they intimidate, too. They intimidate NY bison, to be exact.”

“你知道被其他纽约野牛威吓的那些纽约野牛吗?好吧,它们也很吓人。确切地说,它们会威胁纽约野牛。”

但是,如果我们想消除歧义,但仍然限制我们的词只使用“ buffalo”,并将其全部保留为一个句子,该怎么办?是有可能的,但我们需要修改一下英语规则。我们的新“语言”会更精确一点。一种方法是标记每个单词以表示其词性,如下所示: Buffalo{pn} buffalo{n} Buffalo{pn} buffalo{n} buffalo{v} buffalo{v} Buffalo{pn} buffalo{n}

也许这对读者来说还不是很清楚。为了使它更精确,让我们试着用一些替代品来帮助我们把这些“buffalo”分成组。纽约州布法罗(Buffalo)市的任何野牛(bison)实际上只是我们称之为“名词短语”(或)<NP>的一个特殊版本。当我们遇到字符串Buffalo{pn} buffalo{n}时,可以用<NP>代替句子。由于我们的格式越来越正式了,因此我们可决定通过以下方式为该规则和其他将来的替换规则使用简写形式: <NP> ::= Buffalo{pn} buffalo{n}

其中:: = 表示“左侧的内容可以替换为右侧的内容”。重要的是,我们不希望这种关系发生变化。想象一下一头博尔德的buffalo会变得多么疯狂!

将我们的替代规则应用于整句话,它将改为: <NP> <NP> buffalo{v} buffalo{v} <NP>

现在,这仍然有点令人困惑,因为在这个句子中有一个偷偷摸摸的关系从句,通过在我们的句子的第一部分插入单词that,可以更清楚地看到它,即 <NP> *that* <NP> buffalo{v}...

因此,让我们制定一个替换规则,将关系从句分组为<RC>,并说: <RC> ::= <NP> buffalo{v}

另外,由于关系从句实际上只是对一个名词短语作出澄清,所以这两个从句合在一起就相当于另一个名词短语: <NP> ::= <NP><RC>

 

定义并应用这些规则,我们可以将句子写成: <NP> buffalo{v} <NP>

 

这似乎很好,而且真的得到了这个愚蠢的句子表达的核心关系:一组特定的野牛在恐吓另一组野牛。

我们已经走了这么远,为什么不一直走下去呢?每当“ buffalo”作为动词出现在名词之前时,我们都可以称其为动词短语或<VP>;并定义一个规则: <VP> ::= buffalo{v}<NP>

 

这样,我们就有了一个完整的有效句子,我们可以称之为S S ::= <NP><VP>

 

我们在此处所做的操作,通过视觉方式呈现便是:

无状态以太坊的根基:零门槛了解Witness规范

这种结构看起来很熟悉,不是吗?

buffalo的例子有点傻,也不够严谨,但它足以证明“Witness规范”中的怪异数学语言是怎么回事,我在关于buffalo的咆哮中偷偷地介绍了这种语言。它被称为巴科斯范式(Backus-Naur form ),在各种实际场景中,它经常用于类似这样的形式化规范中。

我们为受限制的英语所定义的“替换规则”,有助于确保,给定一堆“buffalo”,我们可以构造出一个“有效”的句子,而无需知道“buffalo”这个词在现实世界中的含义。在乔姆斯基首先阐明的分类中,一种有足够精确的语法规则允许你这样做的语言,被称为上下文无关语言。

更重要的是,规则确保对于由单词buffalo{np|n|v}组成的每一个可能的句子,都有一种且只有一种方法来构造上面树图中所示的数据结构。一点都不含糊不清!

 

继续阅读Witness规范

 

Witness的核心只是一个大对象,其被编码为一个字节数组。从无状态客户端的角度来看,该字节数组可能看起来有点像长句子,它由看起来很相似的单词组成。只要所有客户端都遵循相同的规则集,则字节数组应该转换为一个(且只有一个)哈希数据结构,无论实现如何选择在内存或磁盘中表示它。

与我们在玩具示例中使用的规则相比,规范第3.2节中写出的实际规则要复杂一些,并且直观性要差得多,但是其实质是相同的:为无状态客户端(或编写客户端的开发人员)提供明确的指导,并确保他们正确执行。

我在这篇论述文章中已略过了很多细节,可以肯定的是,正式语言的兔子洞要深得多。我的目的是提供足够的介绍和基础来克服理解的第一道障碍。既然你已经跨过了这个障碍,现在是时候打开维基百科,自己解决剩下的问题了!

与往常一样,如果你有反馈、问题或对主题的要求,请在twitter上@gichiba或@JHancock。

本文链接:https://www.8btc.com/article/595702
转载请注明文章出处

评论
登录 账号发表你的看法,还没有账号?立即免费 注册