美文网首页
技术深解 | Skycoin项目Obelisk(天空币的方尖碑)

技术深解 | Skycoin项目Obelisk(天空币的方尖碑)

作者: 钢铁肥蛋嘭嘭嘭 | 来源:发表于2020-06-09 19:30 被阅读0次

    原文作者:   Geoffrey Kublin——BTC、ETH、Skycoin开发者。

    原文链接:   https://medium.com/@bksquared1024/a-comprehensive-guide-to-consensus-and-skycoins-obelisk-ed8b768749ff

    工作证明只存在了十年,且变化很多。而“方尖碑”已经有几千年的历史了

    欢迎各位读者朋友们、区块链技术爱好者们。今天,我将带你进入一个共识模型之旅,它解决了现代 "共识三难 "解决方案的许多问题,同时也探索了奥贝斯克提供的解决方案的普适性。本文将详述驱动共识算法本身的数学之美,并为其非琐碎性提供一个有力的解决案例。

    【本文字数:3.3w字。预计阅读时间:90min。】

    本文会尽量提供尽可能多的上下文、图片和视觉、解释和相关信息,并尽可能提供与题目相关的信息。由于此次主题的宽泛性,不要指望它是一个简单、轻松的读物。

    本文的目的是:全方位剖析方尖碑的组成和运行机制,对它进行全面的描述,包括它的概念、背后的历史、现在的发展阶段、以及它所基于的技术。

    首先,本文会将从两个(大约三个)共识算法的细分开始介绍共识协议的历史。详细介绍至今使用最多的——Proof-of-of-Work (PoW) 和 Proof-of-of-Stake (PoS),这两个算法是什么。

    然后,从拜占庭容错(BFT)的背景下,将开始简单介绍一下现代共识的表达方式,直接引出Skycoin Obelisk(方尖碑)的共识算法。本文将会简单地谈一下BFT启发的共识模型,更加方便大家理解。

    在这篇文章的后半部分,将介绍更多的共识模型的原理,比如IOTA的Tangle,或者Radix Tempo等等,来显示出更多的共识模型的前景。

    如果你坚持完整的看完本篇文章,你基本上可以称自己为共识模型的概念专家。

    本篇文章的组织方式如下:

    首先,以一个章节的标题开始所有主要的主题;

    其次,关键的定义和对机制或过程的解释。之后,将把主要的章节分成若干小节,用段落来描述需要的内容。

    最后,每个章节会有一个结论分节,重申和概括在这一节中阐述的主要观点。

    第一章:共识机制的历史

    一张基本的图片,详述了我们现代互联网 "森林般的 "层次结构。不过,这有点儿骗人。我们现代的互联网,不管是硬件还是软件,在大的区域(比如大陆)之间都存在着瓶颈,这就造成了 "网状分叉",无论是攻击者还是政府实体,都是一个很容易被利用的对象

    我觉得有必要在下面的文字中,以及本文的所有其他章节中,加入一个共识的歧义。当我说共识时,我指的不是所使用的共识模型,不是指网络架构,也不是指验证系统,更不是指代表网络数据经济中不可改变的数据流的底层数据结构。我仅仅指的是在网络中实现诚实状态所使用的数学算法。这个共识的定义是由于最初对共识算法的数学兴趣,以及是什么让它们比任意解更重要,所以才有了这个共识的定义。

    因此,从现在开始,当我们说 "共识 "时,我们真正的意思是 "在共识模型/网络中用于实现诚实状态的算法"。相应地,这意味着我们将把参与共识模型的个体网络称为共识网络,而把达成共识的整体系统称为共识模型。我知道,这两个定义都是自作主张,但考虑到我下面提供的语境,它们的含义很快就会很清楚。

    人们对寻找共识解决方案的兴趣可以追溯到70年代,当时美国国防部正在研究ARPAnet的架构和传输协议。在这个时候,他们的兴趣只是纯粹的猜测,因为人们甚至可以追溯到早期的网状网架构也是在这个时期。然而,我们的互联网运行的并不是网状网架构,而是分层的 "森林式 "架构(如果要更详细地解释互联网的实际架构,需要的时间会多得多,所以上面的图片应该足够了),尽管网状网提供了更好的吞吐量和效率,以及其他方面的改进。同样的,共识在小测试之外也没有得到很大的应用。

    九十年代的时候,社会正处于网站数量、连接到互联网的电脑数量和家庭电脑整体数量的急剧膨胀期,通常被称为 "网状网泡沫"。当时,我们也正经历着网络战争的第一个十年的结束,最早的网络数字货币(Beanz、e-gold等)的出现,网络商业的开始,等等。在这段时间里,人们对共识再次产生了一些兴趣,但再一次,这多半是炒作,而且解决方案都集中在集中式的解决方案上(也就是共识网络有一个决策者团队在上面的解决方案)。

    所以,我们不妨跳到比特币的开端,来了解一下现代人对共识的兴趣。

    第二章:比特币、工作证明和 "区块链"

    比特币logo

    比特币通常被认为是第一个使用共识机制作为其功能的基本功的系统,这是一个愚蠢的考虑。当时,像HashCash这样的共识算法已经被整合到论坛网站和电子邮件系统中,而工作证明背后的想法并不是比特币白皮书的原创。然而,比特币使用的不仅仅是共识,所以要真正理解比特币为什么会成功,我们需要谈谈它所解决的问题。

    比特币背后的动机是找到一个可以处理不可逆交易的系统,而不需要信任第三方或托管系统。所谓不可逆转的交易,是指在交易完成后,是最终的交易。但是,在现实世界中,有些银行处理的交易,由于各种问题,需要反转。正因为如此,现实世界中的交易都不可能真正做到 "不可逆转",支付服务机构和银行要花费大量的资源来调解交易或纠纷。

    如果网络经济中的个人决定在货币体系的基础上做一个自己的去中心化的商业体系,那么,有一些根本性的问题需要解决。

    首先是铸币的问题。新的货币在铸币的时候,新的货币就会加入到经济中来,但我们如何验证铸出的货币不是假币?如果没有可信的第三方调解,我们如何安全地铸造新的货币?

    其次,就是消费本身的问题。我们如何验证有人 "消费 "了一部分货币,而且只花了一次,如何验证?如何验证交易是否是由他人冒充币主进行的诈骗?

    最后,就是维护经济的 "余额宝 "的问题。因为没有可信赖的第三方来维护交易历史,所以每个人都需要掌握整个经济体的交易历史。

    为了解决这些问题,我们将引入两个生活在共识之外的概念,这两个概念确实很好地解决了大部分提出的问题(也是没有提出的)。

    其中第一个是数据真实性的概念。数据真实性是一种验证谁创建、拥有或拥有数据对象的权利的手段。如果Alice有一个数据对象A,而Bob有一个数据对象B,并且有一定的机制来验证真实性,那么Bob可以验证Alice拥有对象A而不是对象B,反之亦然。验证数据真实性最常用的方法是使用数字签名。数字签名是一些唯一的数据对象,这样,给定一个数据对象A和一些ID B,一些唯一的函数f(A,B,签名)就可以通过签名来判断ID B的人是否拥有数据对象A。我们可以通过应用公钥密码学的思想更清楚地看到它。有了这个,每个用户都有一个私钥S,这个私钥S永远不会泄露给网络上的任何人,而公钥P则可以在不影响用户安全的情况下,向任何人发出去。在数字签名方案中,Alice可以使用散列函数计算出一个唯一的ID,然后用这个散列函数与自己的私钥进行签名,产生一个数字签名。因为这个签名函数不能被反转而暴露出Alice的私钥,所以这个签名是非常好的。那么Bob就可以看到Alice的签名对象,她的公钥,还有她的数据的唯一ID都是由散列函数产生的,然后把这些都放到签名验证函数中。如果签名是Alice的签名,而签名的对象也有给函数的ID,那么签名验证函数就会判断出这个签名对Alice和她的对象有效。所以,我们可以通过这个设置来验证是否有人拥有某个特定对象,而不会影响到过程中任何人的安全。

    解释数据自动性的图片。鲍勃在信息上签名,通过互联网发送,爱丽丝用鲍勃的公钥验证签名  

    接下来的概念就简单多了,就是数据完整性的概念。对于网络上的一个数据对象,我们可以通过给每个对象关联一个唯一的ID来检查它是否被修改。这只是上一段中介绍的对象的哈希值。但是,这就对网络中的数据对象提出了一个直接的限制:任何时候向网络中引入一个新的数据对象,都必须发送给网络中的每个人。这就引入了非重启的概念,即网络上说过的或发过的所有事情都不能取消,因为每个人都在网络上保存着事件的日志。不撤销在共识模型中起着关键的作用,也是数据的完整性和真实性。

    一个图像可视化的散列函数H,M是任意长度的数字数据,散列值h是一些固定的长度。对于大多数散列算法来说,两个不同的数据值散列到相同的散列值的概率非常非常低,低到根本不值得思考

    现在很明显,之前的去中心化的货币经济所带来的一些问题如何解决就很明显了。首先,网络上的每个人都可以拥有任意数量的地址,这些地址是去中心化经济中货币的来源和目的地。这些地址每个人都有一个唯一的私钥和公钥,每个地址的所有者尽可能地保持私钥的秘密性,永不泄露,而公钥则可以通过网络自由传播。我们可以将每个钱包的资产,或者说是拥有所有权的对象定义为某种面额的数字币。可以通过查看该资产的交易历史记录来确定所有权,并验证审计线索,确认每一笔交易都是合法的,每个所有者在交易时确实拥有该对象。当用户要进行资产交易时,他们将自己的资产作为交易的输入物进行分配,并且都同意这些资产应该如何在他们之间进行分割。对于数字货币而言,输入的总币值必须等于输出的总币值。之后,他们都在交易上签字,交易就会发布到网络上。每个人都保留一份交易的副本,以确保不被撤销,为了保证交易的合法性,我们需要进行共识。

    有人可能会问:在这种情况下,为什么要达成共识?那么,让我们举个例子。假设Alice有一个钱包,里面有一个资产A,她把这个资产花掉,然后把交易发布给Bob。然后,同时,她又做了第二笔交易,并将其发布给卡洛尔,这样就把同样的资产花了两次。这个概念被称为双重消费,仅靠完整性和真实性是无法解决的。同样,另一个可能出现的问题是改变之前的交易。因为每个人都有一份交易历史记录,所以要想找出哪一个是最诚信最真实的,就变得非常非常困难。

    人们可以通过提出投票方案来继续辩论。不幸的是,多数人投票无法用共识来解决这个问题。攻击者可以很容易地建立整个用户网络,将投票转向恶意交易记录。这种攻击被称为 "Sybil攻击",参考了同名的多重人格障碍的书。不;为了解决这些问题,我们需要创建一个能够抵御Sybil攻击、去中心化(即每个人都是 "平等的玩家")、解决双重消费问题的系统。这就是工作证明(Proof-of-Work)的作用所在。但在谈这个问题之前,我们首先需要再介绍几个概念。

    一个解释Sybil攻击的图片

    为了保证我们的网络不受不良行为者的攻击,我们或许应该把我们的交易收集(或者说 "历史")变成一个不可更改的数据结构。首先,不可变的意思是,在创建了一个东西之后,它或它的值是没有办法改变的。例如,一个不可变的值可以是一个常数,如π,也可以是服务器上的数据缓存(如网页),或者是被锁定或存档的用户帖子。

    数据结构本质上就是某种数字示意图,用于程序化存储数据。例如,假设你想存储一个杂货清单,这个清单由一系列代表你需要购买的物品的文本字符串组成:有 "葡萄",还有 "香蕉",可能还有 "面包"...........。

    存储这些值的一种方法就是把它们放在一行中。在计算机的内存中,这将是一个固定大小的 "大块",第一个 "元素 "是 "葡萄",下一个是 "香蕉",第三个是 "面包"。然而,如果我们想把 "蓝莓 "加入到我们的杂货清单中呢?这种固定的大小分配并不能让我们在清单中增加更多的东西。所以,相反,我们可以考虑如何实际制作一个可增长的清单。我们可以使用一个链接式的列表,列表的开头包含我们的第一个条目("葡萄"),然后 "指向 "列表中的下一个条目("香蕉"),以此类推,直到列表的结尾,其中的条目 "面包 "指向什么都没有。然后,我们需要做的就是到列表中的最后一个条目,分配更多的计算机内存来存储我们的新条目,并使 "面包 "指向这个新条目。

    数据结构类型的图片。"Primitive "在这里是指数据结构存储单一的数据,比如一个数字、一个文本字符串或其他一些固定大小的数据。因此,非原始数据结构更受人关注。在这种情况下,静态(像数组)意味着它们的大小不会改变,而动态(Dynamic)则意味着它们可以随着时间的推移而增长。链接列表通过在末端附加一个值来增长,而堆栈通过将值推到顶部来增长,而队列有多种形式的插入或检索值。树在叶子上附加值,而图是最一般的数据结构类型,可以表示这些数据结构中的任何一种。这使得图是抽象地谈论数据结构的理想人选

    这在某种程度上接近于我们存储历史事务的需求。然而,有一个问题。

    如果我是一个攻击者,我可以同时删除和添加新数据到这个历史记录中。要添加新数据,我需要做的就是找到我想在新数据前面的条目,并将其改为指向我的新数据,然后让我的新数据指向前面的条目,无论前面的条目是指向什么。我已经成功地插入了新数据,这肯定是一件坏事。但是,我也可以删除数据! 如果我去到我想删除的条目之前的条目,我只需改变前面的条目,让它指向我想删除的条目之后的条目。由于我的列表中已经没有任何东西指向我想删除的条目,所以它实际上已经不在列表中了!(这显然让人看不懂,所以我附上了一些图片。)

    在我们的列表中插入一个新条目的图像  

    所以很显然,我们需要改变一些东西。我们需要使之成为这样的一种情况,即在列表中添加了一些东西之后,它就不能再被删除了。我们需要使我们的数据结构在被改变时,能够保留以前的版本本身。这样的数据结构,在最近的版本中,所有以前的版本本身都是存在的,并且在最近的版本中保持不变,这种想法被称为持久化数据结构。对于我们来说,这和不可变的数据结构很像。

    为了创建我们的不可变数据结构,我们应该使我们的列表中的每一个条目反而指向前一个条目,并且让第一个条目指向无。我们首先要做的是取我们的数据对象的哈希,也就是我们在列表中的条目,以保持数据的完整性。这个散列可以作为我们的指针。散列的好处是它们看起来像随机数,所以即使你取了像数字0这样的散列,它的散列也可能是一个固定大小的1s和0的随机分布。这个属性在后面的时候很重要,所以要记住这一点。

    现在,我们要做的第二件事是确保我们的数据对象在列表中的大小是固定的。为什么要这样做呢?如果不是的话,那么攻击者就可以继续在条目的末尾添加比特,以匹配他们想要改变的对象的哈希值。既然我们想尽可能的保证安全,那么我们就需要固定条目的大小。然而,很明显的是,事务的大小是不同的。两个人之间的事务显然会比一百个人之间的事务要小,这一点我们可以直接看出来,因为后者只是简单的包含了更多的数据。所以,我们需要介绍一下区块的概念。

    一个区块,在网络安全领域,就是一个固定大小的数据块。实际上就这么简单,但不要被骗了,它是一个简单的拼法,但相当的不可破解。我们可以做的是让我们的列表包含交易,而不是让我们的列表包含块,让块以某种确定性的方式存储交易。幸运的是,有这样一种方法可以做到这一点,但我们需要引入一个最后的数据结构。我知道有很多事情要做,但这绝对是我们需要引入的最后一个数据结构。

    这个新的数据结构是一个简单而又强大的不可更改的数据结构,叫做Merkle树。merkle树是一种简单的数据结构,用于安全地存储元素,可以在未来以一种非常特殊的方式进行修改。其结构很简单。在树的头部(称为 "根"),有一个哈希。然后,根有两个分支,这两个分支是根的 "子项",这些子项以根为 "父项"。这两个孩子都是哈希。然后,这些孩子们都有两个分支到他们的孩子,这两个分支都是哈希,以此类推,直到我们到了树的 "叶子"。这些叶子没有分支(因此也没有子代),它们包含了我们Merkle树中的实际数据。而哈希值的构造如下,对于两个同父异母的叶子,父散列是这样计算的:首先,我们对这两个叶子进行散列;接下来,我们将这两个叶子的散列相加;最后,我们对这个值进行散列,这个值就是父散列。我们可以用这个来得到merkle树中所有的哈希值。那么,这个有什么特别之处呢?

    请注意,要改变树中的任何数据,就意味着需要改变它的父的散列,以及父的父的散列,以此类推,直到你需要改变根散列本身。所以要改变Merkle树中的任何数据,就意味着需要改变根哈希。这意味着整个树可以由根哈希安全地表示。这使得它成为存储在块中的交易的理想选择。但是,为什么呢?

    最终,经过一段时间后,我们可能需要修剪或删除旧事务,以减少数据结构的大小。如果网络中所有用户的审计线索中的某些交易集发生的时间太长了,以至于即使是为了安全起见,也没有必要再跟踪这些交易,我们只需将这些交易从网络中删除,就可以安全地从他们的merkle树中删除。我们需要做的就是保存它们树中最上面的哈希值。如果我们最终删除了一个区块中的所有事务,那么 merkle 树上就只有根哈希,这本身就很好,因为修剪下面的条目不会改变它们的哈希。根散列的值被保留了,因此保留了不变性(因此也保留了安全性,特别是完整性)。

    上面是一个Merkle树的图片。如你所见,事务A到H都是树的叶子,而树本身就是每个事务的哈希值,以此类推,一直到根哈希。

    而且,对于那些想知道的人来说,我们可以通过先把所有的事务打包到Merkle树中,而不超过块的大小,让块保持在一个固定的大小,如果我们的块小于块的大小,我们可以直接增加0字节,直到块达到块的大小。但是我们会留出空间给叫做block header的东西,它包含了事务的merkle树的根哈希,那个前一个指向块的指针(这只是前一个块的哈希),块的nonce,我们很快就会解释,还有额外的元数据,比如块创建时的Unix时间戳。所以现在我们终于可以谈工作证明了。

    工作证明(Proof-of-of-Work),也就是我们现在开始称它为PoW,是一种证明网络上的用户已经付出了努力,使系统保持诚实和没有不良行为者的算法。该算法一开始是由一个节点把所有已经创建的、还不在一个区块或历史数据结构中的交易,在不超过区块大小的情况下,把一个区块中可以容纳的交易量最大化。当达到这个值时,节点会取上一个区块的哈希值,并生成一个nonce,或者说是一个随机数,然后开始取这个新区块的哈希值。然后该节点检查这个哈希开始时有多少个0位。记得前面我说过,哈希中的0和1的分布是随机的,而且是均匀的。这意味着有50%的概率是以1个0开始,25%的概率是以2个0开始,12.5%的概率是以3个0开始,以此类推。如果一个散列位中至少有一定数量的前导0,那么这个块就可以发布到网络上。如果不是,通常情况下是这样,那么nonce就会被递增,然后再次对区块进行散列。这个过程会持续下去,直到节点为该块找到一个nonce,这样当散列时,哈希值有一定数量的前导0位。很明显,节点需要做一个指数级的工作来找到这个散列,从而通过它所做的工作量来证明它的诚实性。这就是工作证明。

    一旦广播后,网络上的所有节点都会接收到这个区块。他们通过开始为下一个区块进行工作证明(Proof-of-of-Work)来表达他们对这个区块的接受,他们的下一个区块使用广播过的区块的哈希值作为前一个区块的哈希值(从而将其添加到他们的列表中)。但是这决定了什么?

    还记得之前的Sybil攻击让一个用户,一票就能轻松破解的地方吗?那么从本质上来说,在这种新模式下,攻击者需要投入大量的CPU功率来超越网络。如果网络上的CPU功率大部分被诚实的节点所掌握,那么攻击者将永远无法追赶。另外,值得注意的是,我们如何判断哪个列表是正确的列表。无论哪一个列表更长,都意味着为制作这个列表做了更多的工作,假设网络中大部分的CPU功率被诚实节点所掌握,那么更长的列表就是正确的列表。这听起来很简单,但在工作证明共识的情况下,它的作用就很明显。

    一张图解释工作证明Proof-of-of-Work  

    现在有两个问题需要解决。第一,如果两个节点同时向网络发布不同的新块和有效的Proof-of-of-works,怎么办?那么,网络中的所有节点都会接受他们接收到的第一个块,但存储另一个块以备不时之需,并开始对他们接收到的第一个块进行Proof-of-of-Work工作。如果节点收到一个新的区块和有效的工作证明(Proof-of-of-Work),使用另一个区块作为前一个哈希,那么节点就直接切换到使用该版本。其次,如果一个节点没有收到最新的区块(或事务)怎么办?那么,它就会意识到自己落后了,并根据需要请求错过的事务和/或块。

    所以,这里介绍的实际共识算法就是工作证明的计算和测量最长的列表。当老实的CPU力量大部分被节点控制在同一列表的节点上时,就实现了共识。

    与共识分开的是验证交易。这很简单:只需检查签名,证明交易输入中的资产花费者是前一个所有者,检查输入来自于前一个交易的输出,以此类推。但是,这样的验证对于一个非常庞大而复杂的交易列表来说,需要花费大量的时间。因此,我们只需要假设前面和区块中的所有交易都是有效的,那么我们只需要检查输入资产和输出资产是否是相同的价值,以及该交易是由输入资产的所有者签署的。我们甚至也不需要保留完整的历史列表,我们只需要区块头和该交易的Merkle树的必要部分。

    头条列表和包含正在验证的交易的Merkle树分支的图片  

    现在,这就是你需要知道的关于比特币如何工作的一切。比特币的整个共识机制还包括另外三点:难度,激励,以及代币在网络上的实际表现方式。

    难度是Bitcoin调整网络上的工作证明所需的工作量的方式。这与区块散列中的前导0位的数量完全对应,这样才能被接受和工作证明有效。这是以移动平均数计算的,它试图固定每小时添加到诚实链上的区块数量。比特币试图将每小时添加到列表中的区块数量保持在6个,或大约每十分钟添加一个。用于计算新增难度的算法是确定性的;也就是说,它在每台机器上的工作原理都是一样的,在固定的输入下,每一次的输出都是一样的。

    激励只是比特币通过做工作证明来鼓励用户在诚实列表上工作的方式。比特币使用的激励方式是:每接受一个新的区块,区块的创建者就会投入一笔交易,这就给了创建者一个固定数量的代币。这有两个目的:它通过奖励那些在网络上工作的人来鼓励诚信,同时,它还可以作为一种方式来铸造新的代币并将其添加到网络中,因为没有中央机构来做这件事。比特币还有一种叫做减半的东西,它的作用是限制网络上的代币总数,使代币的价值不会过快膨胀。每当网络上的区块总数是某个大数的整数倍,那么给予新区块创造者的奖励就会减半。比特币的这个数字是21万(选择这个数字是因为它意味着大约每四年减半一次)。最初的奖励是五十个代币,但自从比特币开始后,这个数字已经降到了十二个半代币。最终,半代币会使奖励总额小于网络上最小的单价代币(也就是1亿分之一的代币)。还有另外一种奖励方式:交易的创造者也会给交易的处理者一笔费用。这个费用通常是交易中的代币总数的很小一部分,如果交易的规模很大,或者交易的创造者希望自己的交易得到更快的处理,那么这个费用会更高。

    未消费的交易输出,即UTXO,在其自然环境中的粗略图。由于它没有任何交易,所以它是未消费的,因此,它包含了网络上的实际代币  

    最后,还有一个问题,就是网络上的代币实际是如何表示的。显然,如果每个代币都是一个单一的交易输出,那是很愚蠢的。所以,比特币的解决方案是让每个交易都有一定数量的输入和输出。一个输入中的token的数量是尽可能少的一些数量,简称为滴滴数量。在比特币的情况下,水滴的大小是一个中子,也就是1亿分之一的代币。输入中的代币总量必须等于输出中的总数量,用户通过跟踪所有的交易输出,在目的地是到用户钱包的交易输出,而输出没有花掉的情况下,用户就会追踪到钱包中的代币数量。这种模型被称为UTXO,即未消费的交易输出,模型。你可以把这些对象看成是货币的面额。它们有一个固定的值,在交易中消费时,它们不能再次使用,而交易输出会产生新的货币面额。而且,永远不需要跟踪整个UTXO的交易历史,所以 "扇出",即UTXO的交易历史依赖于不断增加的交易量,这不是问题。

    现在你已经知道了关于比特币的一切,除了一件事之外。还记得那个区块链的列表吗?这就是区块链。区块链从字面上看只是一个数据结构,所以别忘了这一点。所有这些公司在谈论区块链的背后的魔力不是区块链的数据结构,而是这个去中心化的网络、验证系统、数据包逻辑、架构以及正在使用的共识机制,区块链只是将这一堆错命名了,所以现在精彩的技术在发展的时候,被一个流行语所掩盖了。

    第三章:以太坊(Ethereum)权益证明(POS)

    Ethereum是一个有趣的系统。它的出现是因为一个叫Vitalik的的人和他的超级梦想,让区块链成为大众可以使用的工具,几乎可以用于任何安全操作。Ethereum经常被引用为 "区块链作为计算机 "的概念,这可能是准确的,也可能不准确。我不打算玩 "谁是第一个 "的游戏,因为我已经浪费了你们太多时间。但我要做的是解释一下Ethereum带来的新奇且非常有趣的概念。

    首先,我想先解释一下 "区块链作为计算机 "的概念。区块链作为一台计算机,或者从现在开始我就把它称为 "区块链计算机",是指区块链存储某些系统的 "状态 "的概念。例如,让我们想象一下所有UTXO的集合,本质上只是所有者的钱包地址和一定数量的代币。这个集合代表了比特币的整个状态,因为它描述了在比特币历史上的某一点上,所有的代币都被分配到了哪里。如果我们这样看比特币,在某个时间点上的所有UTXO的集合就是比特币网络的状态,那么我们可以把交易看成是改变这个状态的一些操作。它是一些函数,接收比特币的状态,并输出一个新的状态;也就是说,它是将系统从一个状态过渡到另一个状态。这样一来,我们可以把交易看成是某种代码的构件。

    解释区块链上的状态转换的图片。交易修改了区块链的状态  

    这是任意的,没错,但交易是代码的这个概念很重要。事务本质上是一个可以被视为无状态的函数,也就是说,对于相同的给定输入,事务的操作是相同的,不需要任何外部或隐藏的信息。事务函数将接受系统的状态(即UTXO的空间)和一些指令,如 "Bob支付Alice 50令牌"。该函数将首先检查Bob所拥有的所有UTXO中的代币总数是否大于或等于50。如果不是,那么事务将返回系统的原始状态,不做任何修改。否则,该函数就会消耗掉必要的UTXO(即,将其标记为 "已用完",从而将其从空间中删除),然后创建一个新的,Bob拥有它,并且它包含50个代币。因此,人们之间的一系列交易可以定义一个非常非常简单的程序。虽然这可能看起来非常愚蠢,但它引入了这样一个想法,即以安全和去中心化的方式运行程序是可能的,这为区块链的新工作方式打开了大门。

    Ethereum就是考虑到了这一点而设计的。他们的目标是让你可以在区块链上运行程序。他们的目标是用这种奇怪的 "比特币脚本语言 "来解决很多问题。

    1.他们想让UTXO可以有多种状态,而不是 "已用完 "或 "未用完"。这将允许更多的控制数据在网络中如何转换数据,而不仅仅是消耗和创建地址中的值。

    2.他们想让交易知道UTXO中的值。如果有人想让它变得有一些取款限制,或者其他的东西,他们需要强迫用户使用预构建的UTXO,并在其中包含一些固定的值。交易并不关心里面的值,它们只是检查输入的金额是否等于输出的金额。

    3.他们希望将区块链上的元素,如nonce、之前的哈希等元素暴露在交易中,以便代码可以利用它。为什么会有用呢?想象一下,一个赌博应用,它需要一些生成随机值的方法,如果你只能用当前的交易和UTXO模型来工作的话,那是非常困难的。这些潜在的数据来源将给这些应用提供一种非常简单的方式来整合随机性。

    4.他们想要的是循环。因为比特币希望避免循环交易(输入历史记录在某一时刻依赖于自己),所以没有办法让一个交易在完成之前执行多次(就像编程中的 "for "循环)。循环让编写脚本变得更简单。它们不是必须的,但它们大大减少了冗余。

    考虑到这一切,Ethereum的开发者们一路前行,追求着区块链就是计算机的疯狂仙境梦境。而在彩虹的尽头,就是Ethereum的白皮书。

    我只想简单介绍一下这篇白皮书中介绍的概念,因为它的概念有点复杂,到了没有必要的地步。他们介绍的主要内容是智能合约的概念,我稍后会解释一下。

    他们对比特币模型的第一个改变是UTXO;UTXO本质上是所有者的钱包和里面的代币数量,而不是一个UTXO,现在Ethereum中的UTXO被称为账户,包含四个项目。一个nonce,是一个计数器,每次交易中使用这个账户时,这个计数器只增量一次;一个余额,只是账户中的代币数量;一个合约代码,是每当账户在交易中被使用时,就会运行的代码;一个存储,只是合约代码可以使用的内部数据空间。此外,现在有两种类型的账户:一是外部拥有的账户,也就是传统的用户拥有的账户,通过私钥进行备份;二是合约账户,也就是唯一利用Ethereum账户的合约代码和存储部分的账户。

    Ethereum账户

    他们的下一个改变是对交易本身的改变。回想一下,在比特币中,我们在交易中需要三个主要的东西:正在消费的UTXO的所有者(可以看做是UTXO哈希的所有者签名),所有者希望从这个UTXO中发送的代币数量,以及收件人(这只是一个地址)。Ethereum交易也包含这三个字段,但有三个额外的字段。第一个额外的字段是数据字段,其中包含了发送者希望在交易中包含的一些任意数据。Ethereum白皮书作者所说的拥有这样一个字段的理由是。"为了允许像域名注册这样的服务发生,在数据字段中可能有两块数据:一个是要注册的名字,一个是要注册的IP地址"(我转述了很多)。另外两个字段是STARTGAS和GASPRICE字段。从本质上说,Ethereum的开发者们希望防止拒绝服务攻击或滥用网络,所以他们使其代码语言中的每个操作都要花费一定数量的代币。此外,他们还让整个交易大小中的每一个字节,交易创建者也需要支付一定数量的代币。STARTGAS字段指定了交易创建者所允许的单个计算单位的最大数量,而GASPRICE则表示了交易创建者在每个计算单位上要花费的金额。有了上下文,这将变得更加清晰。

    但是,这类交易只能由外部账户进行。对于合约账户来说,不是交易,而是消息。消息是由合约账户产生的交易,只包含发送者、接收者、要转移的代币数量、数据字段和STARTGAS字段。这里的STARTGAS字段,如果收件人是一个合约账户,那么STARTGAS字段将包含最大的计算单位量,以允许收件人链上所有的合约。因此,如果Alice将她的事务STARTGAS设为100,而收件人合约Bob做了50个计算单位,那么合约消息给Carol,Carol做了30个计算单位,那么下一个Carol消息给谁,谁就最多可以做20个计算单位。

    形象地解释了Ethereum智能合约

    现在,为什么他们把代币费用称为燃料?好吧,他们的动机是,交易中的代币不只是用来转移价值,还可以作为燃料,为网络为将要运行的合约所做的计算提供资金。你投入的燃料越多,可以允许的计算量就越多。

    考虑到这一点,我们现在可以谈谈Ethereum是如何处理交易的。首先,一些外部拥有的账户会创建一个交易。通过检查该交易是否有效,检查该交易的nonce是否等于发送方账户中的nonce,签名是否有效(也就是说,如果制作该交易的用户拥有该输入账户),以及该交易是否形成良好(也就是说,它是否拥有所有正确的字段)。如果是有效的,那么从发送者的账户中减去STARTGAS乘以GASPRICE金额作为交易费用。如果发件人账户余额中的代币足够多,那么就递增nonce,然后继续。接下来,如果有足够的STARTGAS,则减去交易大小费,它只是每字节交易的价格(以代币为单位)乘以交易中的字节数。然后,如果发件人账户的余额里有足够的代币,就把这些代币发给收件人(如果收件人还不存在,就为收件人创建一个新账户)。如果收件人是合约,就运行合约代码,直到完成(或者直到用完为止),然后从发送方的余额中减去计算成本。如果在任何时候发件人账户的余额中没有足够的钱,或者出现了错误,则恢复网络上的任何修改,但要把经过的任何费用加到处理交易的节点的账户余额中。否则,完成后将任何剩余的气体送回发件人地址的余额。

    这听起来很复杂,但本质上是这样的:发送者为他们的交易创建一个车辆,用代币给它加油,车辆行驶到合约代码的终点,将里面的气体送回。或者,它坏了,因为燃料用完了,燃料已经用完了(你不能 "解燃 "燃料)。

    至于合约的工作原理,它有三个部分:堆栈、内存和存储。堆栈和存储器是在合约执行东西时使用,当执行结束后,这些东西就会被清空。存储器是持久性的(也就是说,它在执行完之后会一直存在),并保持着契约所需要的数据。该代码还可以访问事务或消息中的数据字段、发件人(地址和余额)、块头数据(前一个哈希、非etc等)。合约代码可以返回一个字节数组,这个字节数组只是添加到合约发送的消息字段中。

    Ethereum虚拟环境(Ethereum Virtual Environment,简称EVM)。你可以看到代码、存储、堆栈、参数(消息中的数据字段)和内存。标记为 "易失性 "的矩形是计算完成时才会暂时使用的内存,而标记为 "非易失性 "的内存是持久性的,在合约执行结束后会停留在那里

    所以,这就很直接了当了。但还有一些变化需要说明。首先,Ethereum区块链中的一个区块包含了一个比特币区块所拥有的所有东西,同时还存储了难度和一个叫做 "叔叔根 "的东西,这个东西很快就会被描述出来。它还存储了整个状态,也就是所有的账户(包括外链和合约),以及它们的存储,还有它们的代码,还有它们里面的其他一切。这在想象中是很荒谬的。但是,开发者们认为,做这样的事情确实是有道理的。

    现在,我之前说没有更多的数据结构可以描述,但Ethereum推出的数据结构确实有两个,但与之前不同的是,我只会简单描述一下,第二个我几乎不会涉及到。

    这第一个新的数据结构是merkle树的变体,叫做patricia树。与merkle树不同,patricia树可以插入和删除值,而不是像原始模型中的那样只是修剪。我不会细说为什么可以这样做,因为我很可能会让你感到无聊。但这种新的数据结构允许我们只需要存储区块链历史记录中的最新状态即可,因为它不会以破坏区块链安全的方式破坏之前的根哈希值。开发者最初声称,这将使区块链的存储空间效率提高10倍左右,尽管这一说法经常受到争议。

    区块链中的陈旧区块的图像。有效区块链由白色区块组成,陈旧区块为灰色。

    第二种数据结构的动机是比特币中的 "陈旧 "区块的想法。陈旧的区块是指它不属于区块链的一部分,但由于它是有效的,所以被保留了下来。还记得比特币的共识机制会要求节点保留同时广播的区块吗?在实践中,这种事件发生的频率非常高,以至于对系统的效率和安全性造成了损害,因为大量的CPU力量被用于区块上的Proof-of-works,而这些区块永远不会成为比特币区块链的一部分。Ethereum用来对抗这种情况的创新是由Yonatan Sompolinsky和Aviv Zohar在2013年首次提出的,被称为 "Greedy Heaviest Observed Subtree",即GHOST。当时的想法是,最长的链不再只从最近的区块计算,而是将所有前几代的陈旧区块,每一个区块都纳入到正在做的新的工作证明中。因此,从本质上来说,节点不再是在一条链上工作,而是一个不同的架构,称为有向无环图(DAG)。最后,新的区块集成了一个被称为区块的叔叔的区块散列树。

    这些叔叔区块不需要事先验证,也不需要是有效的区块,但它们确实需要有一个有效的区块头。此外,叔叔区块必须不是包括它在内的区块的祖先;也就是说,如果你要向后追溯以前的哈希指针,叔叔区块不能出现在那个列表中。另外,叔叔必须是发生在区块链的最后7个 "世代 "内的区块;也就是说,如果你要追溯叔叔之前的哈希指针,至少在两次追溯之后,你应该找到叔叔和包括它在内的区块的直接区块祖先,但不超过7个。最后,这个叔叔不能在包括它的区块的叔叔树中出现两次,甚至在之前的直接区块的叔叔中也不能出现一次。这听起来很复杂,但本质上意味着陈旧的区块可以非常容易地被重新纳入到网络中,这意味着浪费的Proof-of-Work计算量下降,网络可以处理更多的区块而不影响系统的安全性。

    DAG:有向无环图

    至于奖励方面,Ethereum使用的是区块奖励,其中87.5%的奖励归于最近添加到链上的区块创建者,12.5%归于区块的侄子(即未来的叔叔)。另外,作为修改后的GHOST奖励的一部分,每个包含的叔叔额外获得3.125%的奖励给区块创造者,而对于当前区块的每个叔叔,则给予93.75%的标准区块奖励给叔叔区块的创造者。在考虑基于Proof-of-of-work系统的范式中,增加对死板区块的再激励,无疑是一个不错的想法。

    而对于交易费,叔叔区块没有收到任何交易费。而且引入的交易费还有很多很多额外的限制,但我就不一一赘述了。解释GHOST已经足够惩罚了,但对理解DAG的含义有帮助。而且,简单说一下,一个区块的交易是这样处理的:处理这个区块的节点从第一个交易开始,执行第一个交易,然后执行下一个交易,以此类推;如果在任何时候出现错误,或者气量用完了,或者最终状态的根与原始根不匹配,以此类推,那么这个区块是无效的;在最后一个验证步骤之前,费用会被加到区块创建者的账户上。

    ....等一下。我的Proof-of-Stake(POS)证明在哪里。

    3.1  是什么的共识机制?

    这张图在解释Proof-of-of-Stake方面做得和Proof-of-of-Work一样好  

    我忘了说了。在Ethereum诞生的时候,Proof-of-Stake并不存在。事实上,Proof-of-Stake是在Ethereum存在了一段时间之后才出现的,而且由于某些原因,它还坚持了下来。

    现在,我认为,Proof-of-Stake是很重要的,因为它是现代共识思想最简单的引子之一,也是未来共识算法的目标,所以我认为理解Proof-of-Stake是很重要的。首先,Proof-of-Stake希望解决比特币的能量低效问题,我想我不需要推理是Proof-of-of-work模型的根本问题。第二,它想解决Proof-of-of-of-Work网络所面临的中心化问题;随着时间的推移,区块奖励变得被集中化,因为特殊的设备被做得更快,回报涌向更多的设备,导致大部分的CPU力量只被少数人掌握。第三,它的目的是防止51%的攻击,即攻击者会使用超过网络大部分的计算能力来恶意破坏区块链。最后,它希望阻止形成中心化的算力相互勾结,恶意改变区块链。

    Proof-of-Stake背后的想法很简单:你入股的代币越多,共识期间的投票权重就越大。用户可以通过进行一项特殊的交易,将用户账户中的一定数量的代币锁定在押金中,从而加入到Proof-of-Stake共识中;这就是所谓的押注,因为用户将自己的代币押注在共识中。区块链会记录所有押注到此轮共识的用户。现在,可以使用的共识证明模型有两种。

    我在网上搜索了一下 "Ethereum Staking",就出现了这个  

    这些模型中的第一个叫链式PoS。使用这种模型,在某个时间段(10秒,或者一分钟等)之后,共识算法会随机选择一些已经注资到共识网络的用户创建一个新的区块,最好是指向前一个区块,然后...........就这样。这样下去,随着时间的推移,区块图就会收敛成一个区块链。

    这些模型中的另一种是BFT-style PoS。要理解这一点,我可能应该描述一下拜占庭式容错,不过这个很快就会得到关注。在这个模型中,一堆被押注到共识网络中的随机用户可以提出新的区块,通过多轮的过程,他们都要对下一个区块在链上应该去哪一个区块进行投票(根据他们的押注大小进行加权),在这个过程结束时,他们都必须就某个区块是否在链上达成共识。这里的好处是,可以在一个区块内达成共识,不再存在最长的区块链有效的想法。但是,由于不能保证在一个区块内达成共识,这通常会使用DAG结构。

    可以看出,Proof-of-Stake没有什么好说的,只是因为它的范围很广。它本质上就是 "一枚硬币,一次投票",没有其他的东西。诸如如何奖励共识节点,如何惩罚串通者,如何确保正确的链是诚实的,等等,有几十种,甚至上百种争论。不幸的是,我可能需要解释一些。但首先,是时候说说拜占庭容错原则了。

    拜占庭将军问题,可视化。一个网络面对大量不协调的攻击者,只要有正确的结构,就可以非常成功地抵御这些攻击  

    拜占庭容错,或称BFT,是一个即将到来的华而不实的流行语,它掩盖了没有人正确使用它的事实。如果你在下一篇白皮书中加入这一点,你将成为百万富翁。没有任何附加条件。但说真的,BFT是指一个系统(通常是分布式计算机网络)在对抗拜占庭故障方面的可靠性如何。在这个领域,有两种故障。一种是指系统中的某些组件出现故障,而这种故障在所有用户看来都是一样的。更简明的说,如果某个组件出现了故障,系统就有完美的故障信息。而另一种故障是拜占庭故障,即系统没有完美的信息来判断某个组件是否出现故障。也就是说,一个系统的故障组件对不同的用户可能表现出不同的症状,而且是不一致的。为了阐述这个问题,我们来谈谈故障停止故障。这类故障是指当一个节点遇到故障时,节点简单的崩溃。这类故障是最简单的一种故障。但对于拜占庭故障来说,节点可能出现故障,也可能遇到故障而继续运行,而且故障的种类不受约束。节点可能会产生任意的数据,甚至看起来行为正常,但仍然会出现故障。由于拜占庭故障在系统中的任意性很强,很难发现,所以在共识过程中会导致混乱。此外,出现故障的节点甚至可能不是攻击者或恶意的节点。它们可能是一个延迟很高的节点,也可能是一个对哪个区块的正确性感到困惑的节点,甚至可能只是一个被下线的节点。虽然这看起来很随意,但是这类故障可以归纳出共识模型可能遇到的问题,让评估起来更容易。

    所以,共识模型的目标是尽可能地容忍拜占庭故障。而且,幸运的是,一个系统的容错率能有多大的容忍度是有实际界限的。

    让我们简单谈谈共识模型可能面临的几类问题。第一种类型是CAP定理。这是由计算机科学家Eric Brewer描述的一个简单但强大的定理,它适用于区块链这样的分布式数据存储。它说,一个系统只能保证这三样东西中的两样:一致性、可用性和分区容忍度。如果一个系统能够在任何时候都为所有用户提供数据库的一致性和可用性,这意味着它根本无法容忍分区事件的发生;也就是说,分布式系统的一个部分接收到的数据与分布式系统的另一个部分接收到的数据不同。在发生分区事件时,假设分布式系统想要分区容错(显然,它必须这样做),它可以选择以下两种方式,即 (1)丢弃一个或两个数据块,从而使分布式系统保持一致,但不使其可用;或者(2)接受无论哪一个数据块是先收到的,从而使系统始终可用,但不一致。这就意味着,共识网络在试图解决 "双重支出 "问题时,即给分布式系统的不同版本的数据给不同的一方时,必须做出取舍。

    CAP定理,可视化的CAP定理。包含了常见的数据库API,以显示它们在选择中的一致性。CP并不是指你这个不诚实的人,你可能认为它指的是这个图中的东西

    第二种是处理我们经常试图找到的共识版本,也就是强共识。在强共识中,分布式系统中:每一个非故障节点在有限的时间内决定某事是否有效;网络中的每一个节点总是达成相同的决策;而且这个决策一定是通过某种提议机制在分布式系统中产生的。也就是说,决策总是终止的;决策是一致的;而且决策值必须是提议的东西,就像区块链中的区块。弱共识放松了每个非故障节点都要做决定的限制,只要求somenon-on-faulty节点做决定。这种形式的共识被用来证明,在某些共识网络中,通信是异步的(即不能保证消息在一定的时间内得到发送,比如互联网上的延迟或滞后),如果至少有一个故障节点,那么在有限的时间内,共识永远无法实现。这还不包括在每一轮中一个节点有一个概率随机决定的算法(通常被称为 "拉斯维加斯 "算法),这种算法在实践中可以相当好地解决这个问题。然而,一些聪明人也能够将这个证明概括为强共识,这个概念被称为FLP不可能。

    "FLP不可能"

    第三个问题,与其说是个问题,不如说是某些共识网络对其能容忍的故障节点数量的约束。现在,当我说到拜占庭故障的时候,其实还有一种稍有约束的拜占庭故障类型被称为Authenticated Byzantine故障,在这种情况下,节点的识别是可能的,而且是一致的,就像在共识网络中使用公钥或钱包来识别节点一样。这个约束使我们能够提供两个上界。对于一个部分同步的系统,其中系统有一定的延迟,但有一定的上界(但这个上界是系统不知道的),我们可以期望它最多容忍(大约)三分之一的故障节点。这包括了所有类型的任意故障(但仅限于认证的拜占庭故障)。对于一个同步系统,系统有一个已知的延迟上限,这样的系统理论上可以容忍几乎所有的故障节点,但如果故障节点的数量大于或等于网络规模的一半,这样的系统就会受到极大的约束。

    如果我们再回到Proof-of-Stake,很明显,链式PoS模型是一种同步共识模型,甚至Proof-of-of-Work也是一种同步共识模型。但在Proof-of-work中,当网络中的大部分有错误时,看到的行为是对于错误或不诚实的区块达成共识,而当错误节点的数量等于诚实/正确节点的数量时,网络分裂。对于链式PoS来说,网络的容错率可以超过这个51%的攻击范围。此外,Proof-of-of-Work网络偏向于可用性而不是一致性(因为它们保留了陈旧的区块,这可能会分裂共识网络),而Proof-of-Stake则可以偏向于二者中的任何一个,这取决于实现方式。

    现在,Proof-of-Stake有一些问题是Proof-of-Stake所特有的,因此不值得描述。但如果你想无聊的话,你可以随意查一下“nothing at stake” 、"weak subjectivity-弱主观性"和 "social authentication-社会认证",可能前缀是 "PoS"。我会非常坦率的说Proof-of-Stake解决方案非常草率和可笑,尤其是他们对弱主观性的辩护。

    但要真正描绘出为什么Proof-of-Stake从根本上来说并不比Proof-of-Work好,只要记住:更多的钱意味着更多的权力。无论你为Proof-of-Stake网络建立了什么样的系统,共识模式总是依赖于那些最有钱的人。还记得Ethereum是如何批评比特币的工作证明导致中心化的吗,因为大公司可以控制大型挖矿设施。现在他们甚至不需要物理硬件,只需要有足够多的币的账户就可以了。关于Proof-of-Stake的问题,还有很多东西要讲,但我几乎已经到了我的能力极限,无法再打出更多关于这个话题的字了。我现在需要涉及 Obelisk(方尖碑),因为你现在已经具备了理解它的条件。

    第四章:方尖碑——《攻坚者》

    神奇的方尖碑现实应用展示图像

    好吧...........不止是方尖碑。我不会像我为Proof-of-Stake和Proof-of-Work所做的那样,但我会提到一些关于方尖碑的灵感。其中之一就是一个著名的共识算法,叫做Ben-Or的随机化共识。前面我提到了随机化共识算法可以避免FLP不可能,但我忽略了的是,随机化共识算法还可以避免同步系统可能发生的网络分裂。另一个被归结为启发Obelisk的算法是Paxos/Multi-Paxos泛化共识算法,它是基于意见动态的共识算法思想的前身,并引入了Web-of-Trust的思想。

    首先,我们来讨论一下之前我们讨论共识的方式的变化。首先,我们不再是直接处理数据,并对数据或块是否在某个序列中进行投票,而是改成使用二进制问题。在这个问题中,我们要么让一个节点投票认为某件事情是正确的(通常是1,但也可以是0,只要系统是一致的),要么就认为某件事情是不正确的。这样一来,就简化了描述这些系统的数学知识,更容易直观地看到这些系统的工作和变化。其次,还有一个共识问题。所谓共识问题,简单来说就是共识算法需要解决的任务。对于区块链共识来说,共识问题的形式是:(1)从某个候选区块链的某个集合中挑选出下一个区块,或者(2)决定某个特定的区块是否出现在区块链中。

    这个抽象的共识说的实际协议是值得讨论的。在这种共识模型的表述中,我们需要把共识说成通常情况下是一个多轮的过程。一个共识轮是一个共识建议的会话,也就是说,它由一些时间框架组成,在这个时间框架中,所有正确操作的节点都会提出一些共识值(记住它是二进制的,所以是1或0),并通过网络传播这个值。经过足够多的回合后,可能会有一个节点开始决定,或者选择一个值作为最终的选择。决策可能是在某个固定的回合数下进行的(比如40个回合后,我们都需要做出一个决定),也可以是近似地进行的(有一定的概率,一个节点在这一回合会做出决定)等。当所有诚实正确的节点都做出决定后,或者共识算法判断出一定大小的多数人做出决定后,共识值变成固定值,算法就可以开始新的多轮共识问题;这就类似于在验证了一个Proof-of-of-Work后,或者在Proof-of-Stake期间做出决定后,在链上增加一个区块,这时,就可以开始新的PoW或PoS盯住一个新的区块。

    另外就是讨论提案的概念。在这个共识的数学表述中,提议是指在共识中的某个回合中,某个节点在共识中 "提出 "一些值作为他们解决当前共识问题的参考答案。提议通常发生在共识算法对一个共识问题的每一轮迭代过程中。

    现在我们已经把术语弄清楚了,是时候解决共识算法可能面临的实际问题了。第一个问题是终止问题。在共识中,对于任何一个特定的共识问题,共识算法必须确保每个节点最终都要终止;也就是说,每个节点最终都必须对什么是正确的值或不正确的值做出决定。这听起来相当琐碎("只要有一个截止点就好了!"),但现代共识的很多问题可能都可以追溯到终止问题。你们中的一些人可能会沿着停顿问题的思路来考虑终止问题,这是计算机科学中的一个无法确定的问题;但大多数情况下,对于共识来说,你实际上可以证明一个算法最终是否终止。共识中的另一个问题是,在最坏的情况下,找出一个东西可能需要多长时间才能终止。为了我们的利益,我们不会太在意这个问题。

    解释终止的图,格式稍有不妥。看看所有的值最终是如何收敛的?这就是我们在共识网络中想要的,在有限的迭代次数中终止  

    还有一个问题,就是潜在的攻击者对系统的了解程度。例如,在比特币中,攻击者可以知道网络上的交易历史、区块历史,以及当前提出的区块的任何信息,但攻击者无法知道当前某些节点可能正在进行的Proof-of-of-Work。相比之下,对于Proof-of-Stake,攻击者甚至可以访问到潜在的投票和当前迭代共识区块的节点的内部状态。通常情况下,对于大多数共识算法,攻击者将可以访问以下内容 :

    (1)一个节点之前为某一轮共识提出的所有建议,

    (2)网络中每个节点之前的共识决定,

    (3)提出共识值的节点的内部状态。这是很多信息,远比攻击者可能接触到的PoW多得多,但与攻击者在PoS中的一致性非常接近。

    还有很多其他的问题需要讨论,但为了更好的理解,我需要提供上下文。所以,是时候进入Obelisk本身了。

    1.  Obelisk,不可变数据结构2.0

    一个比较过时的图像可视化的发布-订阅网络图像  

    为了开始我们的讨论,让我们介绍一下事件的概念。Obelisk是一种数据结构,它存储了共识网络上发送的任何消息的所有相关信息。在Obelisk中,共识网络上可以发生的事件有很多类型,我将在不久后介绍。但是事件都有一些形式,这些形式在创建后是不可更改的,也有一种有效的方式来表示事件内部的数据。而消息只是共识网络上的节点发出的一些数据包。我引入这个术语只是为了区分与共识网络上发送的消息相关的事件和俗称的 "事件 "一词。

    Obelisk通过引入公共广播信道的概念,立即使用了非撤销性。公共广播信道是一种不可更改的数据结构类型,它存储了来自一个节点的所有消息。实际使用的底层数据结构是CXO 2.0的feed,我将在未来的某个时候在另一篇关于CXO 2.0的文章中详细讨论。最基本的一点是,CXO 2.0 feed和公共广播频道在这种情况下是一样的(虽然不是一般意义上的),它们是不可更改的,允许插入和删除以及更改,但所有对feed的更改都会被广播给网络上的每个人。在实际操作中,Obelisk不会允许对公共广播频道中的消息进行删除或修改,但如果攻击者对自己的feed进行修改,网络上的每个人都会立即看到。

    关于公共广播频道还有一点需要注意的是:所有的消息都是内容加地址的,这意味着消息的哈希值是用来识别网络上的那条消息。此外,所有的消息都会包含其散列的签名,由其来源的公共广播频道的所有者对其散列进行签名。这意味着,在密码学上,攻击者无法对发布到网络上的任何消息进行修改。这提供了即时的认证、完整性和检查网络上的东西的有效性的方法。此外,所有的消息都会有时间戳,因此,如何提供因果关系(这意味着确定事件在某些连续体中的顺序)将是显而易见的。

    详解CXO的feeds

    最后说一下共识网络内的网络连接:网络由pub-sub渠道组成。这意味着每一种网络连接都是信息的发布者和发布者的订阅者之间的关系。所以,共识网络上的节点有一组订阅者,即订阅了这个节点的人,也就是订阅了这个节点的人,还有一组这个节点被订阅的节点,可以统称为 "订阅者 "和 "订阅 "集。每个节点还有第三和第四个节点集,称为 "黑名单集 "和 "嫌疑人集"。黑名单集是指被黑名单的节点完全忽略其消息的节点集。怀疑集是指当前节点怀疑其为不良行为者或行为有问题的节点的集合。

    另外,还有两个重要的数据结构值得一提。其中第一个是块建议集,这是一个不可更改的数据结构,包含了共识网络上所有的建议块。每个节点都有一些确定性算法,从未处理的事务集中生成一个新的区块。当它生成一个新的区块时,它在其公共广播频道上发布一条消息,该消息包含区块序列号、区块散列、该节点的公钥以及该节点对区块散列的签名。事实上,所有的消息都包含了相关数据的公钥和签名的哈希,这一点是很重要的。由于每个节点都使用相同的确定性算法来构建新的区块,所以区块建议集中的区块的复数将具有相同的哈希。但是,肯定会有一些节点发布了不同的区块;这是因为网络延迟和丢包的原因。如果一个节点遇到连接问题,它可能没有收到网络上所有最新的交易,会提出一个没有这些交易的区块。但是,应该是网络上的复数节点会发布正确的块。值得注意的是,即使在候选区块有很多不同的可能选择的情况下,由于共识的计算是非常的轻量级,网络也一样可以同时对多个区块进行共识。第二个数据结构是事务集,它只是一个节点收到的事务数组。

    所以,我们已经介绍了Obelisk使用的数据结构...... 算是吧。它是否使用区块链?答案是..... ... 是的,也不是。Obelisk可以使用区块链 但它可以在任何一种不可更改的数据结构上运行 这种灵活性正是Obelisk的强大之处。而Obelisk的灵活性还有很多东西要讲,这一点很快就会显现出来。

    2.  Obelisk,枯燥的技术部分

    这是一个无聊的形象

    现在该说说说《Obelisk》的无聊力学了,这些都是不言而喻的,但为了便于理解,还是需要解释一下。

    其中我要讲的第一个是Obelisk如何处理无限制参与的问题。在一个点对点、去中心化的网络中,节点在任何时候都可以自由加入和离开,这意味着在任何时候,整个网络都不可能有一个静态的地图。这使得我们很难判断节点的故障行为,因为它们可能只是脱机,也可能出现延迟问题等等。但Obelisk非常聪明:如果过了一段时间后,某个节点没有收到来自其订阅节点中的某个节点的消息,它只是将该节点移到可疑列表中,直到收到该节点的下一个有效共识消息。无界参与还有一些额外的问题,比如说稀疏的连接性。这指的是在网络中,每个节点只与极少量的其他节点进行物理连接,比如几个节点。但是,由于CXO 2.0馈送的底层机制(这一点我将在以后的文章中再次介绍),因此Obelisk在对抗稀疏连接方面非常强大。另外,在稀疏连接的情况下,每个节点只订阅和拥有少数节点的订阅,Obelisk仍然可以很好地发挥作用,因为这意味着许多节点之间的影响是非常分散和均匀的,理想化的去中心化。人们可能会担心一个攻击者会人为地让很多节点之间的订阅,但请记住,这一切都记录在他的公共广播频道中。所以一个节点可以判断一个节点在任何时候有多少订阅者或者订阅的数量,来判断是否有中心化。

    一张图片解释了可能的攻击方式

    接下来是解释一个订阅事件是如何运作的。首先,我们来谈谈indegree和outegree。indegreeof节点的indegree是指一个节点拥有的订阅数量,而outegree是指一个节点拥有的订阅者数量。对于一个订阅事件,接收节点可以检查请求的订阅者是否在黑名单中,或者怀疑是恶意订阅。由于网络上的每个节点都是怀疑的,所以接收节点会独立验证请求订阅者的有效性。如果被列入黑名单,则拒绝订阅并丢弃消息。如果怀疑,那么节点可以进行一些审计检查,在这里,节点会对请求订阅者进行统计,如节点的indegree和outegree等指标的统计。硬算法的选择由共识机制的实现者决定,但通常情况下,共识系统的架构师可能会对一个节点所能容忍的outegree设置一个硬限制。如果请求者的outegree过高,节点可以拒绝订阅并放弃消息。否则,如果请求订阅者是有效的,有一个合理的分散订阅者数量,并且统计数字匹配良好,接收节点可以将请求订阅者添加到它的订阅列表中,并在它的公共广播频道上发布订阅消息。这个消息很可能包含接收节点和请求节点的公钥、接收节点的outegree,以及其他一些关键的统计信息,这些信息会促进信息的冗余,从而使某些东西更容易被获取。另外,要求发布indegree和outegree会对节点进行问责,因为这些也可以在节点审核时通过检查节点的公共广播频道,计算出订阅事件的数量,再从已统计的未订阅事件数量中减去。如果一个节点曾经发布过错误的indegree或outegree,这是明显的欺诈行为的迹象,也是被列入黑名单的适当理由。退订事件的处理方式也是类似的。

    对于区块的生成,一个确定性算法会吸收交易集中的所有交易,并生成一个建议的区块。我们已经讨论了很久,所以我只谈一下这样的算法可能是什么样子。构建这样的区块的一个好方法就是简单地按照交易的接收顺序组织交易。然而,它们的顺序不一致是不可避免的,因为一个事务可能比某个节点附近的本地生成的事务需要更长的时间来传播到网络的另一端。所以在实践中,可能会采用某种确定性的横向方式,即在事务集内对数据进行排序,并以确定性、算法的方式遍历数据。由于事务有输入和输出,并且不能在本身上有循环,所以从技术上讲,它们创造了一种称为有方向的双元图(DPG)的图结构类型。如果做了一些确定性的横向算法来遍历由事务集形成的因果DPG,那么你就可以有一个非常强的确定性算法来打包一个块中的事务。这在理论上应该是可能的,但需要考虑到在DPG中甚至可以形成循环的事实,而且对于因果性来说,完全排序可能是不可能的。

    这就是一个有方向的二元图,所有的A是交易前的UTXO空间,B是交易后的UTXO空间。注意,你可以有不使用整个UTXO空间的事务。

    对于创建事务,协议非常直接。事务中的参与者集体分享他们的UTXO的散列,分享输出的散列,然后取输入和输出的散列(以及一些其他的指标)并创建内部散列。这个内部散列是用来代替单独的输入散列的,因为比特币交易中可能存在一个漏洞,允许交易是可突变的,也就是说,与不可变的相反。所以,计算出内部散列,每个人在内部散列上签名,然后他们形成一个交易,并在其中添加一个时间戳。然后,他们就可以在自己的公共广播频道上发布这个事务,这个消息就会通过网络上的blip-blop进行传播。Blip-blop是一种复制协议的原型,理论上可以实现在网络中最大限度的传播。如果你熟悉八卦协议的话,blip-blop本质上就是一个八卦步的最大扇形传播。这方面需要知道的是,一条消息可以在网络中以指数级的速度复制,所以一条消息可以在几秒钟,甚至几分之一秒内到达地球的另一端。

    接下来是有趣的部分:实际的共识部分。

    第五章:方尖碑共识的技术

    在开始之前,我们先来谈谈几乎无处不在的共识。在一个共识网络中,有一种被称为Eclipse攻击的攻击类型,在这种攻击中,一些对手或恶意代理会识别出一定数量的正确运行节点,并试图对其进行攻击,通常是通过某种拒绝服务攻击。因为攻击者总能识别出至少一部分正确运行的节点,所以完全的共识是不可能的。相反,共识算法的目标应该是几乎所有的共识,即几乎所有的节点在任何给定的节点都是诚实和正确的。所以,既然如此,方尖碑不是一个完全共识模型,而是一个几乎无处不在的共识模型。在实践中,这也是一样的好,在我们的案例中,甚至更强大,因为它避免了完全共识模型的许多限制。

    Obelisk的共识算法是一种多轮、部分随机化的共识算法,具有一定的逻辑性,可以处理我在Proof-of-of-Stake一节中提到的BFT启发的共识算法的问题。它直接解决了其中的一些问题,而其他的问题通过多年来的模拟实验证明它可以很好地解决。

    作为一个简短的旁观者,我想讨论一下一些不可能的英雄人物,这些英雄人物导致了Obelisk的卓越共识算法的现代灵感,很不幸的是,这可能会导致我们的 "简短的旁观者 "少了一些,而更多的是一种 "全面的百科全书 "的形式。

    早在上世纪90年代末,很多关于自旋的宏观统计力学特性或者说是自旋的涌现量子力学特性的工作,再加上一些基于量子力学中的自旋物理学的理论模型,都被输出到了生物学甚至是统计建模的领域。这种将物理学中的结果和模型用于该领域以外的领域,并在其他研究领域建立模拟模型的想法,导致了统计物理学的诞生。如今,统计物理学被广泛地应用于各种问题,而且非常奇特地适合于描述宏观的社会现象。由于某种原因,统计物理学领域的一些模型(也包含了简约优化(以及其他结构优化子领域的东西)、元启发式等),能够描述生物运输网络的构建、一种感染或一种观点在人群中的传播模式等等。这些模型中,有一个是基于统计力学模型的,叫做Ising自旋。我不想把它变成一个关于统计力学的10个部分的系列讲座,所以我只说一句话。Ising自旋本质上是一个更复杂的模型的简化版,它的重点是研究晶格中的自旋动力学(即所谓的 "自旋玻璃")。如果你想了解更多,外面有很多文献。

    Sznajd模型的图像,对于一维的情况下,Sznajd模型  

    最著名的模型之一是Sznajd模型,它是Ising自旋的延伸(本质上)。Sznajd,用最简单的话来说,就是一个理论,它的运作有两个思路。(1)社会验证,如果两个人认同相同的理论,他们的邻居就会开始认同他们的理论;(2)不和谐破坏,如果两个相邻的人互相不认同,他们的邻居也会被争论。这个简单的规则集实际上导致了非常复杂的宏观现象,它很好地描述了意见在人群中的传播方式。描述意见在人群中如何变化、传播或形成的理论,属于舆论动态研究领域的一部分。这个领域对于共识的研究非常重要,因为它可以对应于信任关系是如何形成、维持和改变的。事实上,这种采用某种形式的信任关系作为共识机制或网络拓扑结构的一部分的共识网络被称为Web-of-Trust。Obelisk通常被称为Web-of-Trust共识算法,因为它通过用户/订阅、嫌疑人、黑名单连接等方式采用了这样的东西。然而,值得注意的是,虽然信任通常被认为是只能在集中式或部分集中式网络中才能存在的东西,但只要网络上的实体(即节点)是去中心化网络,信任的概念就可以存在于去中心化网络中。

    1.智能性----节点通过对系统状态的一些稳健的、全面的分析,可以形成自己的意见,做出自己的决策和建议等。

    2.怀疑型----没有内在的信任关系,节点都会对网络上的其他节点及其信息进行自己的欺诈检测或验证。

    3.主权型--节点都是独立于某个大组织之外的行为,当涉及到决策时,节点共享相同的内在权力。

    4.参与性--节点在共识回合中主动产生内容并发表意见。

    Obelisk的底层共识算法的原始方案叫做Sznajd2,由Ethereum的原始开发者之一、Skycoin的创始人陈厚武(Houwu Chen)构建。这篇论文可以在Skycoin的白皮书网站上找到,但我就不说那篇了,因为实际的算法在那之后经历了很多变化。还有另一篇论文是关于被称为SkyHash的东西,这是对SKY模型的扩展,用于计算哈希值,实际上可能就是Obelisk使用的实现。我们后面会更多的触及到这个问题。

    实际上,现代的共识算法简单来说就是SKY。这就是基于意见动态的实际框架,也就是Obelisk中的共识算法将如何工作的数学表述。后来我和Synth,也就是Skycoin的创始人和现任BDFL聊过,他说这个模型有一些改进,确实提炼出了一些高度的容错性和安全性。我也探索了SKY舆图动态模型的变体,不用说,它为一个完全现代化的、加速的、先进的共识算法领域打开了一扇大门,它将为未来的去中心化系统提供动力。

    那么,你准备好了吗?

    未完待续........

    相关文章

      网友评论

          本文标题:技术深解 | Skycoin项目Obelisk(天空币的方尖碑)

          本文链接:https://www.haomeiwen.com/subject/kneetktx.html