UCD-ECS189f-区块链架构笔记-全-

UCD ECS189f 区块链架构笔记(全)

018:R3 Corda的核心原理 🧱

在本节课中,我们将学习R3 Corda区块链平台的核心原理。Corda是一个专为企业设计的分布式账本技术平台,它强调隐私性、互操作性和强身份验证。我们将从公司背景、平台愿景开始,逐步深入到其架构、共识机制、节点设计以及智能合约的工作原理。

R3公司介绍与愿景 🏢

R3公司最初由8家纽约银行于2014年底组成的联盟发展而来。这些银行希望探索区块链技术如何能为其业务带来益处。到2015年底,该联盟已扩展至42家银行成员,并发布报告,将区块链定义为一种分布式账本技术,旨在建立互信和无摩擦的业务信息共享系统。

然而,银行等企业无法使用比特币或以太坊等公有网络,因为它们需要将信息广播给网络上的所有节点,这不符合其隐私和监管要求。因此,R3的使命转向研发,并于2016年第四季度开源了Corda平台。随后,为满足银行的高监管要求,R3在2018年7月推出了Corda企业版。如今,R3已与近400家金融机构合作。

R3发现了区块链的力量在于通过智能合约使机构能够直接交易,从而消除业务交易中成本高昂的摩擦。这正是Corda平台的使命和愿景。

Corda平台概览 🚀

Corda提供两个主要产品:开源的Corda和企业版的Corda Enterprise。R3是一家平台公司,不开发具体应用,而是提供软件开发工具包。学生、公司或独立软件供应商等合作伙伴基于SDK开发应用,并部署在Corda网络上,从而构建生态系统。

Corda自称为第三代区块链平台。第一代是以比特币和以太坊为代表的公有链,缺乏强隐私性且网络效率较低。第二代是专注于隐私的联盟链,如Hyperledger Fabric,但它们容易在行业内形成数据孤岛,互操作性较差。

Corda作为第三代平台,旨在构建私密但可互操作的业务网络,支持可转移资产和实时交付与支付。其核心优势包括适用于所有行业、旨在构建跨行业生态系统,并专注于隐私和互操作性。

Corda的核心优势与架构 🔑

Corda的核心优势体现在以下几个方面:

  1. 强身份:Corda是一个私有许可网络,设有“守门人”(网络身份管理器)。所有客户在加入网络时都经过身份验证,确保网络参与者彼此知晓对方身份。
  2. 隐私性:交易采用点对点通信,信息仅在相关方之间共享,不会全网广播。
  3. 双层共识机制
    • 账本外共识:基于强身份,参与者知道交易对手是谁,建立了直观的信任层。
    • 账本上共识:通过公证人服务实现。公证人可以部署不同的共识算法(如BFT、Raft)。
  4. 性能与可扩展性:根据第三方报告,Corda是唯一能通过纳斯达克级别压力测试的平台。企业版网络每秒可处理数万笔交易。
  5. 全局互操作性
    • 与遗留系统互操作:Corda应用使用Kotlin/Java编写,运行在JVM上,可无缝与大量使用Java的后端系统集成。
    • 跨应用互操作:单个节点可部署多个Corda应用(称为CorDapp),这些应用可以相互通信,形成真正的生态系统。
  6. 开源与网络:Corda平台是开源的。其全球网络(Corda Network)由Corda基金会运营,R3作为技术公司参与其中。

网络、节点与数据模型 🌐

在Corda网络中,每个节点看到的账本视图是不同的。交易信息仅在与该交易相关的节点之间共享和存储,这提供了隐私性。例如,Alice和Bob之间的交易,只有他们俩的节点会存储该交易数据,其他节点如Carl则看不到。

Corda节点抽象了更新账本的复杂性,负责消息传递、并发、存储、灾难恢复、节点发现和密钥管理等。用户编写智能合约(指令),节点负责收集签名、与公证人交互并最终更新账本。

Corda采用UTXO(未花费交易输出)模型。数据以“状态”的形式存储,并通过“交易”进行更新。数据永远不会从数据库中删除,只是被标记为“已消耗”,并由新的状态取代,从而保持了分布式账本技术的不可变性。

智能合约:状态、合约与流 📝

Corda智能合约包含三个核心组件:

  1. 状态:数据的表现形式,可以被消耗、更新并最终存储到账本上。
  2. 合约:定义了业务逻辑规则。它验证交易的有效性。例如,在借书场景中,合约会强制规定还书期限。如果规则未满足,合约将拒绝该交易更新账本。
  3. :执行业务逻辑的工作流程。通常包含发起方和响应方。

交易是状态更新的载体,包含输入状态、输出状态和命令。合约会验证交易是否符合所有规则。

交易流程与公证人作用 🔄

一个典型的交易流程如下:

  1. 发起提案:发起方检查并签署交易提案。
  2. 交换签名:发起方将部分签名的交易发送给响应方。响应方检查并签署后返回。
  3. 公证验证:发起方收集所有签名后,将交易发送给公证人进行双重花费检查。公证人维护所有已消耗交易输入的哈希列表,确保新交易的输入未被使用过。
  4. 账本更新:公证人验证通过后,交易最终被记录到相关各方的账本上。

公证人主要提供三项功能:防止双重花费、时间戳和验证。在高度信任的环境中,可能使用简单的共识机制甚至无需共识;在需要更高信任度的场景下,可以组成公证人池并部署BFT等复杂共识算法。

总结 📚

本节课我们一起学习了R3 Corda平台的核心原理。我们了解到Corda是一个为企业设计的第三代区块链平台,它通过强身份验证、点对点隐私通信和可插拔的共识机制,解决了公有链的隐私和效率问题。其UTXO数据模型、由状态、合约和流构成的智能合约体系,以及独特的公证人机制,共同支撑起一个安全、高效且可互操作的分布式业务网络。Corda的设计旨在连接不同行业,构建一个无摩擦的全球商业生态系统。

019:ConsenSys的发展历程与核心理念

在本节课中,我们将跟随John Wolpert的分享,回顾他从IBM区块链到ConsenSys的旅程,并深入探讨他对企业级区块链应用的批判性思考以及ConsenSys提出的“基线协议”这一新范式。我们将学习到区块链技术在企业环境中的实际挑战与可能的解决方案。

今天我们的第二位演讲嘉宾是John Wolpert。他拥有辉煌的职业生涯,在过去30年里深耕于企业界和创业领域。目前,他是ConsenSys的高级管理人员。此前,他实际上是IBM区块链的联合创始成员,特别是负责了Hyperledger Fabric本身的开源工作。今天能邀请到John与我们交流,我们深感荣幸。那么,闲话少说,有请John开始。

谢谢。很高兴能(虽然是虚拟地)来到戴维斯。我过去在那里待过很长时间。我的大部分职业生涯是在伯克利、旧金山或南湾的库珀蒂诺度过的。后来我搬离过好几次,在澳大利亚悉尼、德国、纽约和其他地方住过一段时间。但现在我们住在北卡罗来纳州的罗利。当我在加州旧金山的IBM工作时,我住在伯克利,那时我接到了我最喜欢的老上司Jerry Cuomo的电话,他是IBM区块链的创始人之一。他说:“嘿,现在外面有个叫区块链的东西。” 实际上他说:“嘿,刘易斯,我是克拉克,你想做什么?” 他说:“嗯,现在有这个区块链的东西,我们去搞清楚它吧。” 我说:“好吧,给我一支船队,我去调查一下。” 他说:“嗯,我有两支步枪,一条狗和一艘独木舟。” 于是我们开始研究区块链。我们很幸运,我的意思是,它就从那里爆炸式地发展起来了。CEO开始打电话询问,很快我们就发现,我们不再是走在通往未知的小径上,而是在建立先驱城市之类的东西。这最终促成了IBM区块链和Hyperledger Fabric。从那里开始,故事变得有趣起来。

接下来,我将谈谈从2015年我们在商业领域对区块链的认知到现在的历程。当然,你们知道,区块链的历史比那更久远。事实上,区块链技术的基础相当古老,我相信你们都知道。David Chaum会告诉你他在80年代和90年代就发明了它,他某种程度上是对的,比如数字现金。你们还记得数字现金吗?实际上我听说过。你指出的另一件有趣的事是,我从2012年到2016年在IBM TJ Watson研究中心工作。一开始有很多关于人工智能的炒作,但在我离开IBM之前,也就是2015年,区块链和Hyperledger确实成为了头号话题。你的老上司也是我的老上司,他现在是CEO,是的,Arvind Krishna。最初是John Kelly,我开始时是跟着John Kelly,然后Arvind来了。嗯,我离开时Arvind还是副总裁和研究主管。你还记得John Kelly之前是谁吗?不,我不记得了。哦,是的,是的,天哪,保罗姓什么来着,这有点尴尬。他很酷,留着马尾辫。是的,我很喜欢他。抱歉扯远了,但没错,TJ Watson是周围最酷的地方之一,仅次于Almaden研究中心,而Almaden又仅次于Hursley,对吧?Hursley研究实验室对IBM来说有点像霍格沃茨。在英国南部。嗯,我真的很喜欢在IBM工作,我三次加入IBM,创办了三家公司和一个非营利组织。离开IBM又回来,离开又回来。最后一次,我们正在构建IBM区块链和Hyperledger Fabric。其背后的理念是,加密货币和作为应用的区块链并不是企业领域的游戏,我们不认为任何公司的财务部门或治理部门会愿意涉足加密货币,至少在2015年是这样。但作为分布式系统领域的人,我们看到了比特币背后基础设施中区块链基础原语的优势和方法。于是我们四处奔走,说“区块链不是比特币”,然后人们、高管和大公司开始重复这句话,突然间至少谈论区块链变得安全了。然后我们说,哦,那我们为什么不创建一个不需要挖矿或加密货币的区块链呢?它其实不关乎加密货币,更关乎数据。接着我们投入了大量资金,构建了一个我会称之为过于复杂、在数据隔离方面存在实际问题的数据库。

我自己的“孩子”,我想我是在说它丑,Hyperledger Fabric和其他企业区块链本质上是共享数据库。这没什么错,我喜欢共享数据库,我也喜欢Git。这是一种拥有共享数据的好方法。但事实证明,这些也存在着有趣的问题。在我继续之前,让我问一下,了解一下在座各位的情况。我没有被详细告知谁在线上,背景是什么。你能给我介绍一下吗?我们有两门课,一门是面向高年级本科生的分布式账本导论课。所以在过去的一个半月里,你们被介绍了无需许可的比特币、以太坊。实际上,前几天Mohan做了一个讲座,上周四的上一节课,来自Zurich的Marco,也是Hyperledger的主要成员之一,他也深入概述了Hyperledger。所以我想从Hyperledger的角度,大家都有很好的背景。另一半学生来自研究生区块链课程,他们也一直在阅读从PBFT到比特币的核心论文。他们对共识协议有更广泛的理解,可能上节课我们看了HotStuff,所以他们对核心理论也相当了解。这是一个很好的群体,我想现在这个时候大家都真正理解了这些材料。太好了,因为我要在房间里扔一颗炸弹,摧毁你们一直在学的一切。这至少应该会很有趣,对吧?绝对是的。好的。那么这里的每个人都是技术背景?是的。是的,每个人都是技术背景,好的,很酷。每个人都对分布式系统感兴趣吗?至少就他们正在修的课程而言,他们都在学习分布式系统,但在这门课之后是否还会继续就不得而知了,但现在是的,每个人都在学分布式系统。我告诉你们,你们来对地方了,因为分布式系统,我的意思是,有很多计算机领域的人并不理解分布式系统。如果你不理解分布式系统,你就不理解事物的发展方向。这很难,真的很难。而且,一旦你以为自己搞懂了,它又会变得很难。分布式系统,我想一位著名的分布式系统专家说过,分布式系统的第一法则是,如果你能避免使用分布式系统,那就避免。但没错,所以我们要讨论这个。Hyperledger Fabric,我是最初提出并塑造它的六个人之一。还有其他很棒的人,比如Gary Singh和Ben N.(他现在在State Street),Gary在加密学方面也做了很棒的工作,还有Yellen和其他一些人,当然还有Jerry Cuomo和其他人。听起来你和苏黎世的加密团队交流过,那是一个很棒的密码学团队。那里有很棒的工作。但我们在构建Fabric的整个过程中,著名的Mark Andreessen(构建了Mosaic的著名人物,现在是风投)一直在嘲笑我们构建私有区块链。我过去对此有点紧张。我想,嗯,他比我聪明,那我错过了什么?我过去常把这称为Andreessen的报复。我的意思是,他的观点是,如果你不做公共的、无需许可的区块链,那么你实际上只是在构建数据库,你应该直接使用数据库。事实证明他是对的。你可以使用分布式数据库,比如Cloudant(一个类似Cassandra的变体)。如果你想防止人们篡改它,或者想确保没有人更改了那个账本或数据库中被接受的历史记录,定期对状态进行哈希处理。将哈希值发布到《纽约时报》的分类广告版,你就有了防篡改的证明。或者,如果你想更进一步,想构建像IBM著名地构建的那些东西(在我任内构建了两件重要的事情),其中一个以前为我工作的人现在负责这个项目,就是与马士基合作的TradeLens项目。不,是提单和类似的东西。我不熟悉。然后是Food Trust,沃尔玛的那个项目,我敢打赌他们提到过。是的,Food Trust,我甚至要求覆盖Food Trust的内容。是的,有一个和我同姓的人,Bob Wolpert。哦,TradeLens是Everledger的吗?不,那是Everledger,那是Le... 是的,是的。那是完全不同的一套把戏。但在Hyperledger和Fabric以及私有区块链的早期,真正的动机是,比如沃尔玛打电话给你说:“你想加入我们的区块链吗?” 你说:“什么是区块链?” 他们说:“嗯,别担心那个,但我们要让你在拉斯维加斯3万人面前,和IBM的CEO一起上台,而且,如果你想继续和我们做生意,就加入我们的区块链。” 所以,当然,很多公司不得不加入那个沃尔玛区块链。但如果你仔细想想,如果事情这样发展,你其实并不需要区块链。我们真正做的(我写过一篇文章,你可能还会读到,叫做《在区块链上保持愚蠢的价值》)是,区块链这个词解锁了很多高管的钱包,让他们去探索那些我们30年前就可以做的项目,但如果你称之为数据库,他们就不会资助。事实上,我与银行和其他公司有过不止几次坦诚的对话,他们说:“你知道,我就像在问,你们为什么用区块链做这个?” 他们回答:“因为我们一直想做这个项目,但老板除非它叫区块链,否则不会资助。” 所以有很多这样的把戏。归根结底,在一个超互联的世界里更紧密地合作,让你的系统和我的系统之间的差距更小,这是个好主意。如果我们在同一条供应链上,能够做某些事情是好的。但我认为大多数人没有抓住要点。我们需要的是良好的数据卫生,我们需要良好的机器人流程自动化之类的东西,以减少数据输入等方面的错误。每当我们出去问“你们为什么用区块链”时,他们总是说“我们需要更好的数据,我们需要这个那个”,我就想,所有这些都只是把数据库工作做得更好,对吧?这其实不关区块链的事,你们在分散自己的注意力。但人类就是这样。

所以我们赚了很多钱来构建这些花哨、极其复杂的共享数据库。有一天我醒来,心想,等等。假设你是一家公司,有一堆内部私有信息,比如你的供应信息,假设你是一个种植者。你拥有所有这些你真正不想让竞争对手知道的数据。你不想这些数据被泄露,不想它们公开。这是大多数CEO在数据安全方面担心的问题,不是篡改,而是泄露,是数据被公开。现在你要把这些数据放到一个共享的新威胁面上。假设有100家公司都有一个节点。那就是100家公司,其中那个最愚蠢的管理员可能会被黑客攻击,给所有人带来糟糕的一天。这听起来是个很糟糕的主意,不是吗?我会回答,因为我们在Zoom上,实际上没人会回答。是的,这是个糟糕的主意。所以,你知道,一旦皇帝的新装被揭穿,我开始想,等等,这不是个好主意,区块链是糟糕的数据库。主要是因为它们在隔离方面天生就很差。对于任何普通数据库,你都有良好的访问控制,对吧?你可以说这条记录在这个条件下可被这个人访问,而不可被那个人访问。你可以在公司之间做到这一点。你可以说,嗯,这家公司可以访问这个表,但不能访问那个表。借助云的SaaS技术,你可以建立一个这样的系统,你可以组建一个联盟,你可以雇佣一个管理员(所有这些联盟无论如何都会这样做,即使是区块链)。你可以说,好吧。嗯,这样吧,我们100家都在这里,我们担心我们设立的管理员,所以我们用秘密共享,我们把根密钥分片共享,这样我们中60%的人必须同时使用密钥才能更改系统。现在你几乎拥有了区块链的所有好处,而没有任何区块链,你可以使用任何你喜欢的数据库,比如MongoDB。而且你有了一个更稳定、安全、简单、不那么复杂的系统,而复杂性是安全性的敌人。Hyperledger Fabric极其复杂,这让我担心。它之所以复杂,是因为我们试图使用一种结构。我们试图使用一种倾向于破坏隔离性的结构,这就是它的作用,它不喜欢隔离,这不是它使用的工具,它不是为这个设计的工具。然后我们试图让这个工具去做隔离。于是你有了所有这些Fabric通道和一堆麻烦事。结果变成了一个阶乘级的噩梦,任何实际的实现都因为必须管理所有这些彼此不通信的通道而变得复杂。所以,这就是我对我构建的东西的抨击,然后我转投了ConsenSys。

这真的很棒,也让你对周四Mohan的讲座有了一点不同的视角。他也有完全相反的观点,这很好,我喜欢这种有争议的课堂。唯一真实的东西是许可设置。把我们都放在一个房间里,我可以和他辩论。我肯定,我肯定。但我也认为,我们能有这么好的见解,分道扬镳也是好的。但让我们也许把这个问题拆开来看。也许再进一步说,什么是许可区块链?许可区块链的核心原语是什么?我的意思是,如果以太坊要尝试回答这个问题,那就是,在传统设置中,你有一个账本。我的意思是,这个账本可以追溯到银行出现之前。在某个时候,你信任某人记下谁付钱给谁,或者谁欠谁,你必须保证那个账本的安全。所以你信任你镇上、你社区里一个值得信赖的人,你去找那个会计,让他记录所有的交易。这就是账本。在数字时代,嗯,那个账本由摩根大通持有,花旗银行持有,所有大银行都持有。但还有另一件事,所有这些银行都做,而且一千年前那个人可能也做了,那就是他可能还有一个保险箱。他也把实际的钱(你给他的,或者他需要保管的,或者黄金)放在保险箱里。再看银行,他们也有保险箱,至少到20世纪70年代。我的意思是,只要货币有黄金支持,保险箱里就有东西。今天我不确定保险箱里是否还有东西,我想可能什么都没有了。不,不,93%已经是数字化的了,对吧?是的,所以背后没什么东西了。但再次,我认为比特币所做的是,这仍然是一个迷人的想法,它说,好吧,我要以一种民主的方式来维护这个账本。每个人都拿出自己的账本,写下我们认为的事实交易。如果每个人都同意那个写在足够多副本上的事实交易,那么我们就说,好吧,那是确定的。如果我们想讨论基础知识,我们得在这里待一整晚。我相信你们正在学习基础知识。我的意思是,Paxos、拜占庭容错、PBFT、轮询制,我帮忙补充了一点。当然,还有工作量证明、权益证明等等,对吧?这些都是很好的论点。但比特币并不是这个主题历史的终结,而是历史的开始。所以以太坊出现了,现在还有更多,以太坊2.0即将在12月推出第一阶段。如果我再多说两句,我们有了这个账本,现在每个人都民主地持有这个账本。但同样,这个账本里发生了一些令人兴奋的事情。那个账本不仅成为了我们存放钱的保险库,而且账本本身嵌入了货币,所以不需要单独有一个保险库。但另一件事是,我们也将要彼此交易的合同条款,那些协议的条件,不仅数据在那里,资产在那里,而且合同的条款也嵌入其中。所以对我来说,作为一个抽象模型,我认为这相当令人兴奋。现在,如果你要过渡到许可设置,你肯定没有资产的概念,至少资产被创造的方式没有。你可以,对吧?没有理由你不能。我的意思是,我们今天就在做,对吧?你银行里的一个数据库条目就被认为是一种资产。而且,你知道,所以它是一段数据,它是一种资产,因为我们同意它是。所以它不一定非要在区块链上才能成为资产。或者不一定,但没错,所以不仅仅是资产,而是一种资产生成方式。所以你需要一种控制货币如何生成和印刷的方式,本质上你需要建立一个经济体系。如果你能做到这一点,你可以在Hyperledger上做到,你只需要让每个人都同意它是合法的。你必须让每个人都同意,当然可以。我的意思是,我们现在就有,DB2和MQ以及其他东西运行着银行系统,我们已经同意那些东西是合法的,或者传统数据库当然也可以。所以让我们也承认这一点。那么,在那个模型下,为什么任何区块链不只是另一个分布式系统呢?分布式系统,分布式系统。你说了一些我认为非常有趣的话,关于民主持有。我会更进一步说,比特币不仅仅是实现了民主容错或拜占庭容错。它所做的,而且正如我所说,在90年代甚至80年代,就有一些方案被政府迅速关闭,比如数字现金,它们试图创建数字货币。这有很长的历史。问题是你可以关闭它们,有点像Napster,对吧?你可以找到运行服务器的人并逮捕他。这确实发生过。比特币做了什么?它说它不仅让民主持有成为可能,还让它变得不可阻挡。你再也找不到所有的服务器了。它们无处不在,你无法阻止它们。你必须关闭整个互联网。是的,绝对意味着激进的去中心化。但有一个问题,所以我们总是说,或者总是说这是一种新的计算范式,是去中心化和民主的,但有一个小小的警告,至少当我们观察比特币中发生的事情时,权力真正掌握在四到五个人手中。是的,这里没有什么新东西。新的是,一群人意图以某种方式使用我们已经拥有的东西。这才是激进的,你知道,我有一支铅笔,我可以为它申请专利,我可以用它写一些无聊的东西,我可以用它写一些有趣的东西,或者我可以把它戳进你的眼睛,现在它就成了颠覆性技术。比特币所做的就是,他们只是把传统的分布式系统概念和一些新颖的东西结合起来,在2008年(做这件事的一个有趣年份)以这样的方式组合起来。他们说,我们要把这个戳进你的眼睛,他们变得具有颠覆性。但有趣的是它的应用、它的使用方式、它的部署方式。然后像我这样的人出现了,说,嘿,让我们用它做个数据库。我认为那有点愚蠢的错误,我认为很多那样的东西会消失。就像90年代末外部网作为一种东西逐渐消失一样。

我真的很喜欢你的见解,但我仍然试图理解。你指出的所有那些有趣、令人兴奋但不一定是新发现的东西,也许是将现有的旧技术打包成一种更可用的形式。但所有这些似乎也适用于Hyperledger。但你似乎站在一边,认为Hyperledger的发展方向不是正确的方向。嗯,DB2,你知道,我是说,你仍然可以卖DB2,你仍然可以卖Oracle,共享数据库是一回事,它有一些价值,但不要混淆它们是什么,它们是共享数据库。你需要理解,在共享数据库中,其他不为你工作的人拥有一个完整的节点。即使你在那个数据库上加密数据,你也有其他不为你工作的人,现在有能力没有信息隔离,知道那上面的所有东西。我认为,当我们意识到这一点并清醒过来时,你会看到公司说,等等,我真的想把所有数据都放在这个东西上吗?不,我真的不想。看看Food Trust会发生什么。Bob Wolpert(和我同姓,没有亲戚关系)不久前对我说,嗯,我们喜欢Hyperledger,因为它透明。我说,真的吗?你真的想要透明?你在处理国家的食品信息,你和国土安全部合作。你真的认为如果每个人都知道所有流通的信息,他们会高兴吗?不,他们不会。他们不想要透明。他们希望合适的人在合适的时间、合适的条件下知道他们需要知道的东西。那是隔离。你需要良好的访问控制列表。我们几十年前就有了这些,贯穿我的大部分职业生涯。是的,政策、法规。我的意思是,它是封闭数据,只有选定的个人需要访问。是的,但区块链不喜欢那样,区块链希望每个人都拥有它。每个人。如果你说,嗯,我们要把它限制在只有一些有节点的朋友。嗯,那些朋友不会永远是朋友,朋友往往会变成竞争对手。那么,当你的供应链中的交易对手突然变成了亚马逊,并且他们开始与你竞争时,你仍然希望他们拥有所有那些数据吗?可能到那时就太晚了,对吧?所以,你知道,在某种程度上,我们用“区块链”这个词在企业中欺骗了自己去做更开放的事情,这是件好事。但我认为,我们也必须欺骗自己,但这样做的时候,很多“尖头发”经理戴上了眼罩,没有意识到他们正在陷入什么境地。没有首席安全官,没有安全官员会允许敏感的内部信息(任何公司80-90%的数据要么是个人身份信息,要么是在某些条件下敏感的,你不想让竞争对手知道你的发票信息)被放上去。

说到这一点,我的意思是,可能即使在今天,人们甚至不喜欢将数据部署到云上他们自己的实例中,那些在开放空间中、没有隔离的实例。我们花了好几年才克服这一点,即使现在。但我认为,在这一点上,云之所以扭转局面,是因为意识到当中央情报局选择亚马逊,因为它比他们自己能运行的更安全时,你开始想,好吧,也许他们擅长那个,也许他们正在做那个,而且他们可能有更多资源来做好安全,比我强。所以,我认为这就是云扭转局面的原因。但我有个问题。你说你预计对它的兴趣会下降,你指的是区块链吗?你在暗示什么?很多对私有许可联盟链的兴趣,比如Food Trust和TradeLens之类的东西。它们会有它们的辉煌时期,但归根结底,几十年来一直有各种联盟。它们很难维持,很脆弱,而且往往充满问题,因为公司里充满了人类,他们往往会改变观点,突然变得不像以前那么友好了。你可以在区块链上运行一个联盟。这没问题,但它并不具有变革性。你只是部署了一个非常复杂的数据库来做同样的事情,而你本可以部署一个简单的数据库来做。

所以你认为对它的兴趣不可持续,是因为缺乏隔离性,而且正如你所说,人们通常不想把信息放在那里,即使……等等,等等,等到第一次有联盟区块链被黑客攻击,某个人的节点被黑。顺便说一下,对此的答案一直是,哦,让我们把它们都放在IBM云上的大型机上,让IBM运行所有节点。我就想,嗯,如果你能BaaS(区块链即服务),你可以SaaS(软件即服务)。如果IBM运行所有节点,那么你真正实现的是,IBM向你收取的费用是他们为同一个SaaS系统收取费用的好几倍。但现在他们可以向每个对等节点、每个节点收费,而他们本可以将其作为云实现来正确运行。如果他们运行所有节点,谁在乎呢?我实际上和一家公司合作过,这是在以太坊上,他们说,哦,是的,这是一家贸易金融公司,他们有一堆银行,他们说,是的,我们有一个区块链解决方案。我说,真的吗?嗯,你们所有的节点都在哪里?哦,它们在我们的服务器上。我说,嗯,那太好了,你们的任何银行想要自己的节点吗?他们说,嗯,是的,他们都想。我说,嗯,那进展如何?他们说,嗯,问题是没有一家银行希望其他任何银行拥有节点。你看到问题了吧。是的。哎呀,问题,检查一下。所以。

我大致理解你提出的大部分观点,我认为它们非常有趣。但也许只是一个简单的澄清问题。你提出的这些问题,它们是否同样适用于无需许可的以太坊或比特币?好的,这让我们进入了我称之为皇帝新装问题的另一面。很高兴你问了这个问题,这让我们进入了我称之为皇帝新装问题的另一面。公共区块链有一个不同的问题。公共区块链是,我的意思是,所有区块链都是数字裸体殖民地。它们不喜欢,它们喜欢透明。你放在上面的任何东西,根据定义,所有节点都必须以某种方式运行,即使你有零知识证明。我的意思是,Zcash可能是最接近真正不透明的,因为基本上那个账本只是说某人给了某人东西,某人给了某人东西,永远都是一样的,对吧?零知识集有效地使每笔交易看起来都像其他交易,所以你不会丢失信息,你无法应用人工智能或机器学习算法来挖掘分类器并查看模式,没有模式可看。所以这相当安全。但在以太坊,你知道,你可以对各种智能合约和各种活动进行形态分析,甚至代币分布,你可以挖掘元数据或追踪数据或你可能不想泄露给其他人的信息。比如,如果我有一个非常好的人工智能,我可以挖掘模式,然后说,我现在不打算买入那个市场,因为上面有太多活动,虽然我不知道具体是什么活动,但我知道比昨天多。所以你可以设置这类游戏,你可能在泄露你不想泄露的信息。当我们与DTCC(美国股票系统中非常重要的机构)在Fabric上合作时,他们实际上让我们把它扭成一团,试图让除了他们之外没有人拥有实际数据,因为股票交易所就是这样运作的。你不应该让每个人都获得所有数据,你可以做所有这些抢先交易。所以,嗯,这也是Fabric如此复杂的部分原因,因为,你知道,他们让我们使用区块链模式来做一些用数据库就能更好服务的事情。

公共区块链是公共海滩上的数字裸体殖民地。我的意思是,至少私有区块链是私人海滩上的裸体殖民地,对吧?至少你知道。但在公共区块链上,你知道,每个人总是看到一切,任何人都可以访问账本和所有事件。你可以开始挖掘所有这些以寻找各种模式。那么,作为一家企业,我真的想在上面运行任何交易吗?不。所以这听起来很黯淡,对吧?区块链在两个方向上都显得愚蠢,我设置了一个可怕的场景。每个人都很沮丧。好吧,这是我今晚最好的教训。几年前,我曾在一家公司工作,我们有一句改变了我一生的话,那就是“但是……但是……”。这是一个“但是”,它行不通。“但是”如果……。如果你在开会,尤其是在优秀的科学家和工程师之间,你知道,你在进行头脑风暴,不是说没有坏主意,坏主意多的是。但如果你要指出别人的主意是坏主意,要有尊重的态度说:“但是,如果……,它就能行。”即使你能做的最好的事是某种疯狂的事。我确实有过一次改变经历。我们在一个房间里,有人说,嗯,但是我说,嗯,“但是……但是……”,你刚刚说那是另一个人的坏主意。说什么“但是”?他说,嗯,但是如果重力不同,它就是个好主意。这引发了一系列很棒的想法,最终导致了一项新专利。我们没有改变重力,但它引发了新的思考。所以,“但是……但是……”。但是区块链是企业无法使用的数字裸体殖民地,但是,它们看起来像一条消息总线。它们看起来像是一个很好的中间件。我不能把数据放在上面,不能放任何我不想让别人知道的任何数据。但是,如果我有一个SAP系统,我有一个像采购订单这样的记录。而你公司里有一个Oracle系统。我发送给你那个采购订单。我需要一个系统集成总线作为共同的参考框架,来告诉我们,你数据库中的记录确实可验证地与我数据库中的记录相同。而且我们不能否认,你不能说你没收到备忘录,我也不能说那个采购订单多了一个零,是你欠我的。我们知道我们可验证地拥有完全相同的信息。我们真正想要的是一台机器,它尽可能地抵抗篡改、锁定和被一群人控制。那就是公共区块链,实际上只有两个,比特币和以太坊。你想要极度分布式的大型网络,它们被篡改的可能性趋近于零。如果你拥有那个,并且它始终在线,不会关闭,也不能把你锁在外面。那对我来说看起来像一个很好的、通用的、始终在线的消息集成总线。它是中间件。当我们在ConsenSys意识到这一点时,我们开始与安永、微软等公司合作。我们提出了基线协议。我不知道你们能不能看到,但我有我的“魔法巴士”。所以我们一直从这个角度称公共区块链为“魔法巴士”。这就是我认为对企业可行的区块链方法。那就是,你在传统记录系统中有记录,我在传统记录系统中有记录。我们不会把那些数据放在任何其他威胁面上。我们会把那些数据留在我们各自的数据库中。但然后我们会使用有效的巧妙证明和零知识电路、消息传递、屏蔽合约和默克尔树,以这样一种方式,我们可以逐条记录地存放一致性证明,所以那是原子性的、隔离的,只是一条记录。如果我不必……嗯,主要你的系统挖掘我的,或者我的挖掘你的,或者建立MQ或一些新的共同参考框架,那将花费我们一百万美金来为每个新的合作伙伴关系建立,然后还得运行它,然后谁来运行它?不,我们可以直接使用这个始终在线的东西,叫做主网或公共区块链。我认为有趣的是,它成为了价值互联网,成为了始终在线的互联网,只为了两件非常无聊的事情:哈希管理和排序。所以,我的意思是,我不知道有多少区块链爱好者会高兴地认为他们美妙、令人兴奋的区块链技术是,是的,世界的哈希管理器和排序服务。但这正是我要告诉你们的。这听起来很无聊,但它是变革性的,因为数十亿、数十亿、数十亿美元损失在我的价值十亿的记录系统和你的价值十亿的记录系统之间的争议和错误中,而今天这些系统或多或少只能告诉你或我认为我们知道什么,而不是我们的交易对手知道什么。因此,以巧妙的方式使用零知识,基线协议(现在是OASIS标准,并且正在由成千上万的人、数百家公司——现在很难统计,有这么多——在OASIS开放标准机构中构建为标准协议),使用公共区块链的标准技术,以一种安全官员和其他CSO、CTO们可以说,哦,是的,不,这说得通。这不是安全风险。我没有把任何信息放在区块链上。我只是以没人能知道我们在做什么的方式使用区块链,以确保我可以确信,如果这条记录被基线化了,那么我知道所有需要拥有相同信息的交易对手都拥有它,并且他们处理了它,注意到了它,并正确存储了它。而且我们都有相同的信息。如果任何一方不同步,我们知道谁错了。有点像我们今年在经历了五年关于区块链的夸张宣传后常说的:无聊是新的兴奋。所以基线化是一种相当无聊的思考区块链的方式。但它有效。它有用。而且我们可以构建它,它已经可以部署了。

我有一个关于公共区块链和基线协议的问题。我意识到它们模型中的一个关键点是需要激励,因为它们允许任何人参与。如果缺乏激励,无论是工作量证明、权益证明还是任何协议,整个想法是参与者会得到某种激励,这促使他们正确行事,因为矿工或权益持有者是理性的,他们会试图创造自己的利润。那么,在共识中,你是如何避免或是否需要激励?在基线协议中,好的,所以你说的完全正确,所有形式的共识都有权衡,因为我相信你们都是优秀的计算机科学专业学生,你们知道计算机科学中的一切都是权衡。你知道,这就像打地鼠,你解决一个问题,就会失去另一个。总是这样,而且永远不会停止,因为物理定律就是那样。所以这就是艺术,艺术形式就是做出有趣的权衡。我认为在某种程度上,有时即使是真正聪明的计算机科学人员,区块链狂热也让我们忘记了这一点。我们就像,哦,它给了我们一切。我们得到了黄金三角。不,不,不,不是那样的。你越接近……嗯,你的延迟,你知道,活性、安全性等等,你知道,就是这样。所以我对权益证明还是工作量证明哪个是正确的方式不那么感兴趣。我感兴趣的是,如果我在做交易,如果我在公共区块链上进行金融交易,那么所有这些问题都会重新出现。我不是那样使用它。基线不在乎。它只是把它用作一个公告板,我只是在那里放键值对。没错,我不做任何其他事情,只是用它来排序和哈希管理。我可以在那个区块链上放一个哈希或一个默克尔树中的证明,证明这些数据与你的数据相同。然后我可以用它来说,好吧,我要强制执行一些新的工作步骤,知道一些转换或一些新增记录遵循先前记录的规则。否则,它的证明就不能被放入那个默克尔树。这就是它变得有趣的地方,因为你可以用它来进行流程控制。你可以说,嗯,我希望所有这些采购订单按顺序到达,不重叠,因为如果重叠,我会重复计算折扣或类似的东西,所以我需要强制执行针对服务协议的所有采购订单按顺序到达,并从同一基数计算。我可以编写那个规则,并可以使用公共区块链作为排序器来强制执行。作为那个的仲裁者。所有这些都没有任何金融交易。而且实际上没有任何信息被放上去。在零知识下,我不知道你们对零知识证明了解多少,但零知识Zk-SNARK通常被描述为,我要向你证明我有一个秘密的某个特征,而不告诉你秘密。我们以稍微不同的方式使用零知识,我们说我们要证明我们有一个共享的秘密。我们要用这台机器来告诉我们我们有相同的秘密,而不告诉那台机器任何关于我们秘密的事情。而那台机器就是公共区块链。现在,那台机器是使用权益证明还是工作量证明,对于那个用例来说是次要的,只要它有效,它不会消耗地球的能源成本,并且能防止篡改。所以以太坊2.0将转向权益证明。我是以太坊的支持者,我会说我是Vitalik和他的团队的忠实粉丝。他们异常成熟,他们处理这些事情的方式,他们没有仓促行事。他们犯了一些错误,你知道,我的意思是,我不认为以太坊是世界计算机。地球上没有一台重写机器可以同时作为每个应用的后端,这根本行不通。永远不会。你可以有一个极度分片的Cassandra数据库,没有共识算法,它仍然无法处理每个人的读写。仅仅是物理定律就打破了这个想法。这对你们来说有道理吗?我看到一些人在点头,对吧?所以那从来不是,也许它不是世界计算机,也许是世界的排序和哈希管理的状态机。我可以将其扩展到这样的水平:我们估计全球公司之间每天大约有100亿个企业对企业工作流事件。所以如果你假设每一个都需要一个基线证明,那就是每天100亿个证明。那是每秒1700个证明。这比我们今天用以太坊能做的多了四个零。我可以通过批处理获得其中两个零。而以太坊2.0将在以太坊的下一次迭代效率中给我另外两个零。现在我可以处理世界上所有的交易了。但我不把它用作后端,我不把它用作我的Twitch游戏背后的数据库。它永远不会擅长那个。而且还有嘈杂邻居问题,对吧?这在加密猫上得到了很好的证明。没有人希望加密猫因为堵塞网络而拖垮他们的企业系统。但如果你只是把它用作实际后端的二级后端。你有你的传统数据库。你只是试图确保该数据库中的一些记录可验证地与另一个家伙数据库中的一些记录一致。我可以做到。所以,我的意思是,这是一个非常有趣的观点,本质上是构建一个全球时钟和签名,所以那个机器之前的每一个全局滴答都有一个相关的签名,那个签名是为他们将要进行的交易交换的签名。所以我认为,我的意思是,BFT协议或一致性协议,正如你所说,它们只不过是排序服务,它们以去中心化的方式带来顺序,这就是目的。所以如果你能……顺便说一下,嗯,如果你能像EOS和其他一些项目那样,它们修改了BFT算法,我们有PBFT,围绕它也有一些相当不错的工作。同样,Gary Singh,如果你能邀请他上节目或来你们这里,他真的很棒,他在非确定性方面做了一些非常有趣的工作,我认为他应该获得图灵奖,他真的很聪明。是的。所以我的意思是,我们在PBFT周围做了很多工作,所以我的意思是基于BFT类型的协议,我们有并发的、分片的,你现在大概能达到每秒140万笔交易,然后通过伪随机分配谁在Paxos游戏的任何给定轮次中来扩展,大致是那样。但它能防范所有潜在的拜占庭故障加上恢复。但并发的总体想法正是那个想法,但复杂的恢复是为了在出错时能够恢复。但另一种观点是,本质上你保留旧的传统数据库,我们可以把它们看作是链下的,每个人在那里持有他们的数据,只是一个未链接的数据库,或者有一个未链接的区块链,它只提供顺序,并且是签名的存储库,这些交易或任何正在这些方之间交换的东西的签名。所以现在只看那个维护这些签名并提供时钟和排序服务的实体,我的意思是,它可以是任何东西。我的意思是,它可以是有许可的,可以是无需许可的,可以是联盟的,可以是去中心化的以太坊、去中心化的比特币,或者是Hyperledger的联盟,或者是Libra的联盟,或者是ResilientDB,无论什么,只要你有一定的信任,或者那个系统有足够的冗余,你说,好吧,我可以信任,只要有足够的冗余。那个系统的冗余性,抱歉,最后一件事,那个系统的冗余性可能在于激励系统。所以Sw刚才问的是,那个系统的冗余性可能是一种行为,有激励,你得到奖励,你从中得到一些东西,或者激励是,作为一个社会,我们想要建立这个共识,因为我们需要这个排序服务,我们都需要这个哈希服务,这是一个基本服务,我们所有人需要哈希服务,所以我们为什么不都投入一点钱来为所有人的利益创建这个哈希服务呢?绝对可以,如果我们能做到,那就太好了。我的意思是,我喜欢公共区块链的地方在于,它们某种程度上为了自己的原因运行,你知道,代币和所有那些东西。所以你不必激励它们存在。所以我写了一篇文章,在我Twitter feed的顶部,我不记得了,一个关于商业主网的常识性声明。所以我倾向于谈论主网,是的,我们试图劫持那个词,事实上,我们正在为O'Reilly写一本名为《主网》的书。你知道,这里的想法是,嗯,无论是以太坊还是未来的其他东西,你知道,需要有一个互联网状态服务。我称之为主网,大写M的主网,大写I的互联网。它只是一个状态服务,是的,排序和管理哈希、状态签名令牌,那就是我们过去称之为带有哈希的令牌。而且,你知道,非常低级,像互联网一样,对吧?互联网不做太多事。来回传递数据包。一遍又一遍。它不是,它是无状态的。而且它能扩展。它很棒。我们都喜欢它,但它不做太多事。这就是为什么它能服务这么多人,因为它不做太多事。你做得越多,你能服务的上下文就越有限。所以我喜欢你说的是,是的,它不做任何事,但它只是排序,只是管理签名。通过这样做,你说,我认为我们过去五年做错的是对区块链期望过高。我们希望它是全部,因为它是一个闪亮的新玩具,我们就像,哦,让我们用它来做所有事情。不。用它来排序和哈希管理,然后用数据库做其他一切。不要试图让它成为它不是的东西。所以当你让它变得非常小时。你只把它用于那个。那么你几乎可以把它用于任何事情。通过将它与其他更传统的系统结合。所以我认为,那个主网可以是,是的。如果我们要有一个主网,它需要具备所需的属性,即它必须非常擅长不被任何人接管。并且不能阻止访问或篡改给定的历史。你想想像EOS或其他区块链,甚至是轮询制的,你知道,权益证明。它们相对容易被篡改,当然,如果一群银行想建立一个Hyperledger网络。是的,就像银行从不合谋一样,对吧?所以你知道,它们只有在没有理由让它们所有人不一起工作来篡改的情况下,才能防止篡改。所以我喜欢公共区块链的地方在于,它真的把它从人类手中拿走了,但你不想把所有东西都放进去,因为你可能会犯像DAO黑客那样的错误。不要夸大其词。只做简单的事情,比如把哈希放入默克尔树。就这样,只是那样,实际上没那么简单,但至少是直接的。而且你可能能够把它交给这台无人机器。没错,但不要给那台机器你所有的数据。这有道理吗?不,有道理,我的意思是,它只是创建一个排序服务,一个安全的排序服务,你把你的哈希放在那里,一个公证存储库,本质上验证签名,给你一个时间戳,仅此而已。然后你继续做你的事,这就像每次你与某人交易时在《纽约时报》分类广告版上登广告一样。我猜你可以把它登在《纽约时报》分类广告版上,而且我想那份报纸有足够的印刷量,你可以以某种方式追踪它。但这是做完全相同事情的一种更易管理、更有条理的方式。是的,而且它不必特别快,对吧?我的意思是,你可以等待这些东西,所以一个大的、慢的公共主网永远不会比一个真正强大的私有数据库快。但如果你不那样用它,它就不必快。而且它很笨,所以它不必做任何复杂的计算,

020:LedgerDB的核心原理

概述

在本节课中,我们将学习阿里巴巴LedgerDB的核心原理。LedgerDB是一种集中式账本数据库,它结合了传统数据库的高性能和区块链技术的防篡改与可审计特性。我们将探讨其设计理念、关键特性、架构以及与传统区块链系统的对比。


历史背景与技术概念

上一节我们概述了课程内容,本节中我们来看看数据库与区块链技术的发展脉络,并明确几个核心概念。

我们都很熟悉分布式账本技术。集中式账本技术是账本技术中的一个新兴分支,我们为此提出了一个新术语:集中式账本数据库。LedgerDB、Amazon QLDB、Oracle区块链表以及ProvenDB都属于这类数据库。

接下来,我们需要区分不可变性防篡改性

  • 不可变性是一种特性或规则。
  • 防篡改性是一种系统能力。

可审计性是基于预设规则的一系列验证。

  • 内部审计确保账本的内部用户可以观察和验证所有其他(非受信)用户执行的所有操作的真实性。例如,传统DBMS中的审计表可以满足内部审计,因为DBA可以审计所有用户的历史操作日志。
  • 外部审计是指外部第三方观察和验证所有操作的真实性。传统审计表无法满足此要求,因为第三方无法信任审计日志,DBA可能篡改数据。

传统数据库与区块链的局限性

上一节我们定义了核心概念,本节中我们来看看现有技术面临的挑战。

在Codd发表关系数据模型的论文后,DBMS进入了一个新时代。传统的OLTP DBMS(如Oracle和DB2)具备一些安全和审计功能,但它们都有一个前提:DBA是完全可信的。但在现实中,DBA可以通过修改事务日志来篡改历史记录,也可以伪造数据库内部时间戳。这些缺陷使得传统DBMS缺乏司法级别的可信度。同样的情况也发生在云DBMS和传统NoSQL系统中。

区块链技术的出现引起了广泛关注。比特币是第一个区块链系统,它在一个允许任何人加入的公共网络上实现了哈希链接交易和工作量证明共识范式。它是一个高度去中心化且广泛分布的系统,但其吞吐量非常低,并且存在过多副本。

对于声称用于企业协作应用的许可区块链,我们观察到许多实际应用并未从去中心化架构中受益。相反,区块链架构(如多节点共识)限制了其吞吐量,并增加了存储开销。更糟糕的是,尽管其机制看似可信,但缺乏严格的可信度和可审计性。


集中式账本数据库的兴起与价值

鉴于传统系统和区块链的局限性,集中式账本技术变得重要且有价值。

许多应用将其区块链节点部署在由单一服务提供商(如阿里云或亚马逊AWS)维护的“区块链即服务”环境中。这形成了一种集中式部署,而非去中心化模式。此外,许可区块链和当前的DLT系统在性能、存储开销、监管问题和有限的外部可审计性方面也存在不足。

以下是Gartner的预测趋势数据。据他们估计,CLD系统在账本系统市场中的份额将从去年的20%增长到50%以上。如果这成为现实,将是区块链应用领域的一场革命。在我们的实践中,越来越多的区块链客户(如知识产权保护、数据溯源应用和供应链金融)转向了我们的项目。


LedgerDB 简介

上一节我们看到了CLD的兴起,本节中我们来详细介绍LedgerDB。

LedgerDB 是一种以集中式方式提供防篡改证据和不可否认性功能的账本数据库,它实现了强可审计性、高性能和数据移除功能。

以下是LedgerDB与其他账本系统的关键比较:

  • 在外部可审计性方面,LedgerDB能实现类似公链(如比特币)的可信度。我们通过与时间戳机构锚定来实现可信时间戳。
  • 我们指出QLDB和Fabric缺乏外部可审计性,因为其威胁模型使得联盟或账本服务提供商可以伪造时间戳,从而欺骗外部审计员。
  • 我们还支持清除隐匿操作,这打破了传统区块链的不可变性。在调查了真实世界的客户需求后,我们发现他们常常希望在不影响数据完整性校验的前提下删除历史数据,这是清除操作的动机。显然,非法信息应该被隐藏,这是隐匿操作的动机。
  • 我们还支持客户端和服务器端的不可否认性,以及高效的原生数据溯源插入、检索和验证。

LedgerDB 工作流程与架构

了解了LedgerDB是什么之后,现在我们来看看它是如何工作的。

下图展示了LedgerDB的签名框架工作流程。

  1. 用户发出请求。
  2. 账本代理将请求分派到账本服务器。
  3. 账本服务器记录数据。
  4. 服务器在签名后响应。
  5. 描述如何与作为公共服务的时间戳机构交互。这是实现外部可审计性的关键协议。

这是我们的数据和控制流架构。账本客户端将请求发送到账本代理,代理接收请求并将其分派到相关的服务器。账本服务器完成请求的最终处理,并与底层存储层(包含AStream、KV存储、MPT和HCFS)交互。AStream是我们设计的线性结构平面文件系统。


核心操作与API

上一节我们了解了整体架构,本节中我们来看看用户如何与LedgerDB交互。

以下是LedgerDB中的主要操作符和API:

  • Append API: 用于将用户事务或系统生成的事务追加到账本中。
  • Fetch API: 根据账本序列号或线索获取符合条件的日志。
  • Verify API: 用于基于日志证明验证返回日志的完整性和真实性。
  • Create: 用于创建具有初始规则和成员的新账本。
  • Purge: 从账本中移除旧的日志。
  • Obliviate: 从账本中隐匿日志。
  • Rollback API: 用于在链接的时间窗口内回滚一次清除操作。
  • Delete: 用于删除系统中的实体,如账本、行、成员或线索。

我们可以在数据结构图中看到签名工作流程。该流程使得客户端和L-OP可以在客户端重新计算。日志最初被封装为称为“日志数据”的有效载荷。服务器端,日志结构称为服务器日志。服务器在日志提交后计算日志哈希,并向客户端返回包含最终广播的日志回执。


事务管理与索引

为了实现高效处理,LedgerDB实现了三阶段事务管理。

  1. 执行阶段:在账本代理上运行,以实现更好的可扩展性。
  2. 提交阶段:在账本服务器上运行,它收集多个执行事务,并按唯一的全局顺序(我们之前提到的全局序列号)对它们进行排序,并将其提交到存储系统。
  3. 索引阶段:为数据检索和验证构建索引。

具体来说,我们这里有三种类型的索引:

  • 线索索引
  • BMT累加器
  • 区块信息

外部可审计性与数据移除

LedgerDB的强外部可审计性利用了涉及TSA日志的双向锚定协议。TSA代表时间戳机构,它提供可信时间戳。TSA日志包含提交的摘要和TSA发送的可信时间戳。这些日志相互纠缠,形成时间链。账本摘要首先被提交并发送给TSA,然后TSA日志作为TSA日志记录回账本。

我们提供时间账本服务,该服务在阿里云上可以维持更高的吞吐量。时间账本可以由可信方维护,作为公共账本的共享时间公证服务。它接受来自不同账本的摘要提交,并与TSA交互,充当公共账本和TSA之间的代理。

下图总结了确保账本不可否认性的多方签名。我们可以看到用户在提交到账本服务之前进行签名,LedgerDB在响应用户时发送回执,TSA在TSA日志上签名。


可变数据移除与原生数据溯源

现在,我们来谈谈可变数据移除。LedgerDB支持现实世界客户需求的几种数据移除操作符。它打破了传统区块链的不可变性,但仍保留了防篡改性。

在传统区块链中,数据一旦写入账本就无法删除或修改,但这导致了巨大的存储开销和现实应用中的监管问题。许多区块链用户希望清理历史记录以节省存储空间,清除操作满足了这一需求。清除操作会移除从创世区块(或最新的伪创世区块)到指定GSN之间的一组连续日志。

传统区块链不可变性的另一个缺陷是监管问题。想象一下,有人未经批准上传了他人的隐私数据(如个人身份证信息)。这在现实应用中应该被删除。隐匿操作旨在支持此类敏感信息隐藏。隐匿操作将原始日志转换为仅保留其元数据和新摘要的新日志。

我们通过提出的线索概念支持原生数据溯源。线索是用户指定的标签,承载着数据沿袭的业务逻辑。客户可以在插入数据时通过Append指定特定线索,通过Fetch检索特定线索记录,并通过Verify验证特定线索。

以下是一个商品订单的线索使用示例。订单ID 1,2,3,4,5,6 是指定的线索ID。当客户下单时,一个代表“未支付”的日志被插入账本;客户支付后,记录另一个代表此信息的日志。同样的情况发生在商品发货和收货时。我们可以看到,与此订单相关的所有日志都可以使用线索进行追踪。

我们设计了一个写优化的线索索引结构和专用的验证协议,结合线索计数器和MPT,以实现快速的线索获取和验证。


性能优化与实验结果

在性能方面,我们进行了多项优化。

传统的累加器为每个交易计算根哈希,当数据量很大时,这使得我们的CPU成本相当高。我们设计了批量累加算法,为一批日志计算单个根哈希以提高系统吞吐量。我们可以看到,批量大小越大,吞吐量越高,但证明粒度会降低。

LedgerDB的线索索引专为写优化而设计。实验数据显示,写操作每秒可超过一百万次,并且与RocksDB相比,线索索引对点读也很友好。

从这张幻灯片中,我们可以看到LedgerDB端到端性能的实验数据。LedgerDB的写入和顺序读取吞吐量可以达到每秒30万次以上。对于现实世界的应用,我们在LedgerDB和Hyperledger Fabric 1.4上部署了相同的存证应用。实验结果表明,LedgerDB比Fabric快80倍。


应用场景与案例

在实际应用中,存在三种用户场景模式:

  1. 单账本:最简单的模式,只存在一个参与方。
  2. 联邦账本:有多个参与者,他们有相互审计的需求。
  3. 委托账本:只与一个中心化代理交互,该代理进一步管理其他有相互审计需求的参与者。

这里我们将联邦账本与许可区块链进行比较。在供应链金融等应用中,LedgerDB可以获得更高的性能、更低的成本、更易用的特性以及更好的外部可审计性。

饼图显示了截至今年八月我们的客户应用分布百分比,包括物联网数据追踪、保险、供应链金融、知识产权、监管科技、零售、医疗保健、制造业和能源。一个真实世界的趋势是,越来越多的许可区块链客户正在转向CLD系统。


总结

本节课中,我们一起学习了阿里巴巴LedgerDB的核心原理。我们探讨了集中式账本数据库出现的背景,了解了LedgerDB如何通过结合数据库的高性能和区块链的防篡改、可审计特性来解决传统系统的局限性。我们详细介绍了其架构、工作流程、核心API、以及支持数据移除和原生溯源的创新功能。最后,我们通过性能对比和应用案例看到了LedgerDB在实际场景中的价值。欢迎在阿里云上尝试LedgerDB。

021:Fabric的核心原理 🔗

概述

在本节课中,我们将学习Hyperledger Fabric的核心原理。Fabric是一个为许可制区块链设计的分布式操作系统,其独特的“执行-排序-验证”架构解决了传统区块链在性能、隐私和灵活性方面的诸多挑战。我们将深入探讨其设计理念、关键组件和工作流程。


引言与背景

大家好,今天非常荣幸能与Marco Vcolic一起,继续我们在戴维斯分校的区块链系列讲座。Marco是IBM苏黎世研究院的研究员,也是Hyperledger Fabric背后的核心研究人员之一。他与团队发表的关于Fabric的原创论文曾获得IBM的Pat Goldberg纪念最佳论文奖,这是一项极高的荣誉。

Hyperledger Fabric是Linux基金会旗下Hyperledger项目的首个孵化项目,自2016年底以来一直非常活跃。它旨在成为一个用于开发通用区块链应用的框架,特别强调共识模块化、智能合约执行的机密性、弹性、可扩展性和可编程性。


Hyperledger Fabric简介

市场地位与历史

根据剑桥大学替代金融中心的研究,在许可制区块链项目中,Hyperledger Fabric几乎占据了近一半的市场份额,是开发此类应用的首选平台。它于2017年6月发布了全新的V1架构,这与早期的设计有根本性不同,也是本次讲座的技术重点。

Fabric的所有代码均在Apache 2.0许可证下开源。虽然IBM是主要贡献者,但已有来自27个不同组织的超过150名开发者参与其中,形成了一个活跃的开源社区。

应用案例

Fabric支撑着IBM区块链平台,并被许多其他公司采用。其应用案例广泛,以下是一些代表性例子:

  • IBM Food Trust:一个连接食品生产者、供应商到大型零售商(如沃尔玛)的区块链网络,用于追踪食品来源。
  • TradeLens:由马士基和IBM开发的全球贸易数字化平台。
  • IBM Digital Health Pass:一个近期发布的、用于安全验证用户COVID-19健康状态的系统,注重隐私保护,不将个人身份信息存储在链上。

这些案例表明,Fabric能够支持跨多个管理域、无需信任单一实体的复杂商业应用。


技术挑战与设计目标

在深入Fabric架构之前,我们需要理解它旨在解决的核心技术挑战。传统的“排序-执行”架构(如以太坊)存在以下问题:

  1. 顺序执行阻塞:智能合约按顺序执行,一个耗时长的合约会阻塞整个网络。
  2. 非确定性执行:在通用编程语言(如Go、Java)中,很容易编写出非确定性的智能合约(如调用随机数),这会导致节点状态不一致。
  3. 执行缺乏机密性:所有节点都需要执行所有交易,无法满足商业应用中对隐私的需求。
  4. 共识机制硬编码:难以根据需求更换共识算法。
  5. 信任模型耦合:应用层的信任假设与底层的共识信任模型绑定在一起。

Fabric的设计目标正是为了解决这些问题:

  • 支持用通用编程语言编写智能合约。
  • 消除原生加密货币。
  • 实现模块化、可插拔的共识机制。
  • 保证良好的性能。

Fabric的核心架构:执行-排序-验证

为了达成上述目标,Fabric摒弃了传统的“排序-执行”架构,创新性地提出了“执行-排序-验证”架构。

架构概述

在这个架构中,交易流程被分为三个截然不同的阶段:

  1. 执行:交易首先由指定的节点(背书节点)模拟执行,产生读写集(对状态的更改提议),但不实际提交。
  2. 排序:客户端收集足够的背书后,将交易提交给排序服务。排序服务仅对交易进行全局排序并打包成块,不关心其内容。
  3. 验证:所有节点(提交节点)收到排序后的区块后,并行验证其中的交易:检查背书策略是否满足,并验证读写集是否与当前状态冲突。只有通过验证的交易才会被提交到账本。

节点角色

Fabric网络中的节点有明确的角色分工:

  • Peer节点:维护账本状态,负责执行和验证交易。其中,背书节点是特定链码指定的执行节点。
  • 排序服务节点:组成排序服务,负责对交易进行全排序并生成区块。它们不维护应用状态。
  • 客户端:提交交易提案的实体。

交易流程详解

以下是“执行-排序-验证”流程的详细步骤:

  1. 客户端构造交易提案(包含链码ID、参数和签名),并将其发送给指定的背书节点。
  2. 每个背书节点模拟执行提案:基于本地状态快照运行链码,生成一个读写集(包含读取的键值版本和提议的写入内容)和背书签名,然后返回给客户端。
  3. 客户端等待收集到足够多的背书,以满足该链码定义的背书策略(例如,“需要3个背书节点中的2个同意”)。
  4. 客户端将背书后的交易提交给排序服务
  5. 排序服务对接收到的众多交易进行共识排序,打包成区块,并广播给所有Peer节点。
  6. 所有Peer节点(包括背书节点和其他节点)对区块中的交易进行验证
    • 验证交易背书是否满足背书策略。
    • 验证交易读写集中读取的键值版本是否与当前账本状态一致(防止双花或状态冲突)。
  7. 通过验证的交易被提交到账本,更新世界状态;未通过验证的交易则被标记为无效,但区块结构依然保留(确保全序一致性)。

关键特性与问题解决

现在,让我们看看“执行-排序-验证”架构如何逐一应对之前提出的挑战。

应对非确定性与资源耗尽

  • 非确定性:在“执行-排序-验证”架构下,非确定性执行的问题被转化为了活性问题而非安全性问题。如果一个链码是非确定性的,客户端可能无法收集到满足背书策略的、一致的执行结果,从而导致该交易无法提交。但这不会破坏整个网络或其他链码的安全性。
  • 资源耗尽/拒绝服务:由于执行是模拟的、在背书节点本地进行的,每个背书节点可以独立决定是否执行某个客户端的请求,或者设置本地超时策略。这种本地策略的差异是另一种形式的非确定性,同样被架构所容忍。

实现并行执行与机密性

  • 并行执行:在“执行”阶段,不同链码的交易可以由不同的背书节点集并行模拟执行。在“验证”阶段,签名验证等操作也可以并行化。这大大提升了系统的整体吞吐量。
  • 执行机密性:通过背书策略,可以指定只有特定的、被授权的节点子集(背书节点)才能执行某个链码。这样,交易的业务逻辑和初始数据就只在有限的节点间共享,实现了基础的执行机密性。Fabric还通过诸如Intel SGX可信执行环境和零知识证明等技术来进一步增强隐私保护。

模块化共识与解耦信任模型

  • 模块化共识:排序服务被设计为一个抽象的、可插拔的组件。Fabric历史上支持过基于Kafka(崩溃容错)和Raft(崩溃容错)的排序服务。目前,社区正在积极开发集成高效的拜占庭容错共识协议(如Mir-BFT),以提供更强的安全保证。
  • 解耦信任模型:应用的信任模型由背书策略定义(例如,需要哪些组织同意),而底层排序服务的信任模型由其所用的共识算法定义(例如,需要2/3多数诚实)。这两者可以独立配置,实现了信任模型的解耦。

性能与总结

在论文评估中,Fabric展示了可观的性能。例如,在一个仿比特币的“Fabcoin”应用测试中,在60个节点的配置下,吞吐量可以达到每秒数千笔交易(交易大小为~3.5KB),延迟在秒级。性能受众多因素影响,如网络拓扑、背书策略复杂度、交易大小等。

总结

本节课我们一起学习了Hyperledger Fabric的核心原理。我们了解到:

  1. Fabric是一个为许可制、多管理域场景设计的分布式操作系统。
  2. 其创新的执行-排序-验证架构解决了传统区块链在顺序执行、非确定性、隐私和灵活性方面的关键挑战。
  3. 该架构通过角色分离(Peer、排序服务)、模拟执行、背书策略和读写集验证等机制,实现了并行处理、机密性保障和信任模型解耦。
  4. Fabric的设计使其成为构建企业级区块链应用的强大、灵活的基础平台。

Fabric的持续演进,如在共识协议(Mir-BFT)、分片、隐私增强等方面的研究,预示着它将继续在区块链技术领域扮演重要角色。

022:许可链的现实意义 🧠

在本节课中,我们将学习许可链(Permissioned Blockchain)的核心概念、架构设计、它与无许可链(如比特币、以太坊)的关键区别,以及其在现实世界商业应用中的实际意义和挑战。课程内容基于加州大学戴维斯分校的讲座,由数据库领域的资深专家Mohan主讲。


概述

区块链技术自比特币诞生以来,引发了广泛关注。然而,无许可的公有链存在性能低下、能源浪费、匿名性导致的非法活动等问题。相比之下,许可链为已知身份的参与者组成的网络提供了更高效、可控且符合商业法规的解决方案。本节将深入探讨许可链的设计哲学、技术架构及其在现实商业流程中的应用价值。

上一节我们介绍了区块链的基本概念,本节中我们来看看许可链如何解决公有链的诸多痛点,并构建更实用的商业网络。


许可链 vs. 无许可链:核心理念对比 🔄

许可链与无许可链的根本区别在于参与者的身份和网络的准入机制。

  • 无许可链(公有链):任何人均可匿名加入网络,参与交易验证(如挖矿)。其核心是试图在“无需信任”的环境中通过工作量证明(PoW)等机制建立信任。这导致了交易吞吐量低(如比特币的7 TPS)、确认时间长(约10分钟)以及巨大的能源消耗。
  • 许可链(私有链/联盟链):只有经过身份验证和授权的实体才能加入网络。参与者因明确的商业目的(如供应链协作、跨境支付)而聚集。这借鉴了传统数据库系统中的认证与授权机制。

许可链的优势在于:

  1. 身份与责任:参与者身份已知,行为可追溯,符合商业和法律要求(如GDPR)。
  2. 性能与效率:无需耗能的竞争性共识机制(如PoW),可采用更高效的共识算法(如PBFT、Raft),从而大幅提升交易吞吐量和降低延迟。
  3. 隐私与控制:信息在授权范围内共享,保护了商业机密和敏感数据。
  4. 规则明确:通过智能合约明确定义多方之间的业务规则(规则集),比传统的、各自为政的工作流系统更严谨。

核心公式:许可链的共识效率通常远高于无许可链。
交易吞吐量(许可链) >> 交易吞吐量(无许可链)
交易确认延迟(许可链) << 交易确认延迟(无许可链)


许可链的典型架构与工作流程 ⚙️

我们以Hyperledger Fabric(一个流行的许可链框架)为例,说明其核心架构。Fabric采用了一种独特的“执行-排序-验证”(Execute-Order-Validate)架构,与以太坊等系统的“排序-执行”(Order-Execute)模式不同。

以下是Fabric v1.x版本中一个交易的生命周期:

  1. 提案与模拟执行(Proposal & Simulation)

    • 客户端应用程序向指定的背书节点(Endorsing Peer) 提交交易提案,调用智能合约。
    • 背书节点在隔离环境(沙盒)中模拟执行智能合约。此阶段会读取当前世界状态(World State),并计算出该交易将导致的读写集(Read-Write Set),但不会实际更新账本
    • 读写集和背书节点的签名被返回给客户端。
  2. 排序(Ordering)

    • 客户端收集到满足背书策略的足够响应后,将交易(包含读写集)提交给排序服务(Ordering Service)
    • 排序服务(可能由单个节点或基于共识的集群组成)对所有收到的交易进行全局排序,并打包成区块(Block)排序服务不检查交易内容,只负责确定顺序。
  3. 验证与提交(Validation & Commit)

    • 排序服务将新区块广播给所有提交节点(Committing Peer,通常也是背书节点)
    • 每个提交节点独立地验证区块中的每个交易:检查背书签名是否满足策略,并验证该交易读写集中的“读集”是否与当前世界状态一致(即自模拟执行后,相关数据未被修改)。这类似于乐观并发控制(OCC)的验证阶段。
    • 验证成功的交易将被提交:其“写集”被应用到世界状态数据库,交易本身被追加到不可变的区块链上。验证失败的交易则被标记为无效,但其记录仍保留在链上(用于审计)。

代码概念描述:智能合约模拟执行过程(简化伪代码)

# 在背书节点上模拟执行
def simulate_transaction(contract, args):
    # 1. 启动模拟环境
    sandbox = new Sandbox(world_state_snapshot)
    # 2. 执行合约逻辑,所有“读”操作访问sandbox中的快照
    #    所有“写”操作被记录但不生效
    read_set, write_set = sandbox.execute(contract, args)
    # 3. 返回读写集和数字签名
    return sign({‘read_set’: read_set, ‘write_set’: write_set})

上一节我们了解了许可链的基本工作流程,本节中我们来看看这种设计带来的优势与挑战。


许可链的优势与设计考量 ✅

许可链的设计选择使其特别适合企业环境:

  • 灵活的信任模型:通过背书策略,可以精细控制交易生效所需的条件。例如,一项交易可能需要5个特定组织中的3个背书,且其中必须包含组织A。
  • 模块化与可插拔:Fabric的组件(共识算法、成员服务、账本数据库)是可插拔的,允许根据用例需求进行定制。
  • 隐私与机密性:通过通道(Channel) 机制,可以在同一个网络中创建子网络,只有通道成员才能访问该通道内的交易和数据,实现了数据隔离。

然而,这种架构也存在一些挑战和曾被诟病的低效之处:

  • 性能瓶颈:早期的Fabric实现中,对区块交易的验证是串行进行的,且排序服务不感知交易内容,可能导致大量冲突交易(如同时递增同一个计数器)被排序后又在验证阶段失败,造成资源浪费。
  • 状态数据库的局限性:早期版本仅支持简单的键值对数据库,限制了复杂数据模型的表达。将SQL等丰富查询下推到智能合约层需要中间层解析SQL语义,增加了复杂性。
  • 节点初始化效率低:新节点加入网络时,需要从头回放所有交易来重建状态,而非从现有节点同步快照。

现实世界的应用场景与挑战 🌍

许可链并非万能,其适用场景需要仔细评估。

以下是判断是否应采用区块链(尤其是许可链)的决策考量因素:

  1. 多方参与:业务涉及多个独立组织或实体。
  2. 需要共享账本:各方需要基于一致的数据视图进行操作,且存在对账需求。
  3. 信任问题:参与者之间不完全信任,需要防篡改的记录来建立信任。
  4. 交易可审计性:需要不可篡改的历史记录用于审计和争议解决。
  5. 规则自动化:业务逻辑可以通过智能合约自动执行。

典型应用场景

  • 供应链溯源:追踪商品从生产到消费的全过程,确保真实性。例如,利用“加密锚点”(Crypto Anchor)技术将物理物品(如钻石、药品)的唯一特征记录上链。
  • 贸易金融:简化信用证、提单等流程,减少纸质文件和人工审核。
  • 身份管理:提供可验证的数字身份,用于跨境服务。
  • 资本市场:简化证券发行、交易和清算结算流程。

需要与传统系统集成:区块链网络通常不会完全取代企业现有的后端系统(如ERP)。相反,它作为跨组织的协作层,通过API与传统系统交互,触发内部业务流程。


总结与展望 🚀

本节课中我们一起学习了许可链的现实意义。核心要点如下:

  1. 定位清晰:许可链是针对特定商业联盟的解决方案,它放弃了无许可链的“完全去中心化”和“匿名性”,换取了性能、隐私、合规性和可控性
  2. 架构创新:以Hyperledger Fabric为代表的“执行-排序-验证”架构,通过将交易执行与共识排序解耦,提供了灵活性和隐私保护,但也引入了新的性能优化课题。
  3. 实用主义:许可链的成功在于解决真实的商业痛点(如对账成本高、流程不透明),而非追求技术乌托邦。它需要与物理世界(通过物联网、加密锚点)、法律框架和现有IT系统深度融合。
  4. 持续演进:当前的许可链系统仍处于类似关系数据库早期的“战国时代”,在标准化、开发工具、性能优化、可维护性等方面有巨大的改进和创业空间。未来的方向包括更高效的共识算法、跨链互操作性、智能合约形式化验证以及分析型查询(区块链数据分析)等。

许可链技术正在从概念验证走向规模化生产部署,它代表了区块链技术务实化、商业化的重要方向。理解其设计权衡和适用边界,对于构建真正有价值的分布式商业应用至关重要。

023:以太坊 2.0 🚀

在本节课中,我们将要学习以太坊 2.0(Serenity)的核心概念、设计目标、分阶段路线图以及它如何通过权益证明(PoS)和分片技术来解决以太坊当前面临的扩展性挑战。

概述

以太坊是一个去中心化的世界计算机,自2015年左右开始运行。它是一个由全球数千个节点共同维护的开源区块链,旨在支持去中心化应用(DApps)、智能合约和自主组织(DAO)。然而,当前以太坊主网(Eth1)在交易吞吐量、确认时间和扩展性方面存在限制。以太坊 2.0 是一次从底层开始的大规模升级,旨在通过引入权益证明和分片技术,在不牺牲安全性和去中心化的前提下,显著提升网络性能。

什么是扩展性?

扩展性是指提升区块链处理交易的能力。衡量指标主要包括交易吞吐量(每秒交易数,TPS)和出块时间(交易被确认所需的时间)。

以下是几个系统的对比:

  • 比特币:理论最大约7 TPS,实际约3 TPS。出块时间约10分钟。
  • 以太坊(当前):理论最大约27 TPS(简单转账),实际约12 TPS。出块时间约14秒。
  • Visa:平均约1600 TPS,交易确认仅需数秒。

如果区块链技术旨在取代Visa等中心化支付处理器,现有性能仍有巨大差距。

区块链不可能三角

设计一个优秀的区块链需要平衡三个核心属性:安全性去中心化可扩展性(速度)。试图提升其中一项而不损害其他两项是困难的。

上一节我们介绍了扩展性的挑战,本节中我们来看看两种提升扩展性的思路及其在三角模型中的权衡。

思路一:大幅提高区块Gas上限

如果我们将每个区块的Gas上限从800万提高到8000万,理论上吞吐量能提升10倍。

问题:更大的区块需要更多的计算资源来处理和验证。这会提高运行全节点的硬件门槛,导致网络趋向中心化(牺牲了去中心化)。

思路二:大幅缩短出块时间

如果将出块时间从14秒缩短到1秒,理论上吞吐量能提升14倍。

问题:区块在网络中传播需要时间。如果1秒内区块无法传遍全网,可能导致同时产生多个竞争区块,增加分叉概率。频繁分叉会降低网络安全性,使确认过程不稳定(牺牲了安全性)。

扩展方案的类型

鉴于直接修改协议层(链上扩展)的挑战,扩展方案主要分为两类:

链上扩展(第一层)

指直接改进区块链底层协议本身。这是首选方案,因为所有应用都构建于此层之上。如果设计得当,可以在不牺牲安全性和去中心化的前提下提升性能。然而,对于已运行的以太坊主网,这如同在F1赛车上高速行驶时更换引擎,实施难度极大。

链下扩展(第二层)

指在区块链主协议之上构建抽象层。交易在链下处理,最终将结果批量提交到主链。这能显著减少链上操作。

以下是链下扩展的特点:

  • 易于实施:可以独立于核心协议开发。
  • 定制化:可为特定应用(如去中心化交易所)量身定制。
  • 权衡:通常安全性或去中心化程度不如主链,可能需要信任某个运营者,存在服务中断或审查风险。

以太坊 2.0 总览

以太坊创始人Vitalik Buterin指出,以太坊 2.0 是一个长期的、多阶段的升级,旨在:

  1. 通过分片大规模提升可扩展性。
  2. 通过权益证明提升安全性。
  3. 改进最初设计中的一些程序化技术细节。

这是一次彻底的重构,因此采用分阶段推出的策略。

阶段 0:信标链 🏁

阶段0是Ethereum 2.0的基石,引入了权益证明共识机制。信标链本身是一个全新的区块链,与当前的Eth1并行运行。

信标链的核心职责包括:

验证者注册与管理

  • 想要成为验证者,需要向Eth1上的存款合约质押 32 ETH
  • 信标链负责维护验证者注册表,跟踪余额、奖励和退出状态。

奖励与惩罚

  • 奖励按时段(Epoch,约6.5分钟)发放。
  • 验证者如果积极参与(提议区块或进行 attestation),会获得小额ETH奖励。
  • 如果因离线等原因未能参与,则会受到小额惩罚,罚金通常等于该时段应得的奖励。

罚没机制

  • 这是权益证明中保证安全的关键。验证者质押的ETH作为“保证金”。
  • 如果验证者被证明有恶意行为(如试图混淆区块链),其部分质押金将被销毁,并被踢出系统。
  • 举报恶意行为的“吹哨人”可以获得奖励。

随机洗牌与最终性

  • 每个时段,验证者会被随机分配到不同的“委员会”和出块 slot。这防止了验证者合谋攻击,因为无法提前预知自己未来的任务。
  • 权益证明引入了最终性。在Eth1中,交易只是概率性最终确认,理论上存在通过51%算力攻击进行长程重组(reorg)的可能。
  • 在Eth2中,一旦某个区块获得足够多(约三分之二)验证者的连续投票,它就被最终确定。根据协议规则,任何人都不能再在更早的、已最终确定的区块上构建,彻底消除了长程重组风险。

验证者的角色

验证者主要承担两种职责:

1. 区块提议者

  • 被选中打包和创建一个新区块。由于验证者数量众多,单个验证者被选中的频率很低。
  • 成功提议区块会获得较高的奖励。

2. 证明者

  • 每个时段,验证者都会被分配到一个 slot 进行 attestation(投票)。
  • Attestation 的内容是表明自己认为哪个区块应该是链的头部。
  • 所有 attestation 被收集和聚合。如果某个链分支获得了足够多的权重(三分之二以上验证者同意),它就可以被最终确定。

区块处理流程

当一个节点收到新区块时,会按以下步骤验证:

  1. 从父区块获取前置状态。
  2. 验证区块头中的元数据。
  3. 验证随机数(RANDAO)的生成。
  4. 处理区块内的所有“交易”对象(在阶段0主要是 attestations、罚没证据、存款等)。
  5. 计算得到后置状态,其哈希树根必须与区块头中声明的根匹配。
  6. 如果全部验证通过,则接受该区块,并可能在其上继续构建。

阶段 1:分片数据层 🧩

在阶段0搭建好权益证明框架后,阶段1将引入分片的数据层。

  • 计划创建 64 条分片链
  • 初始阶段,分片链仅用于存储数据(约每秒共识10MB数据),不执行智能合约。
  • 数据分片本身已有用途,例如:
    • 作为零知识证明Rollup的数据可用性层。
    • 存储“一次写入,多次读取”的数据,如社交媒体帖子、GPG密钥服务器或网站托管。
    • 作为企业区块链的备份数据层。

阶段 1.5:合并 ⚡

这是介于阶段1和阶段2之间的一个重要步骤,目标是将当前的Eth1(工作量证明链)合并到以太坊 2.0 的权益证明体系中。

  • 合并后,Eth1将成为以太坊 2.0 的一个分片。
  • 现有的以太坊交易将由信标链的验证者(而非矿工)处理。
  • 对用户和开发者而言,这个过程应该是无缝的。现有的合约、地址和工具无需迁移即可继续工作,只是底层安全模型从PoW切换为PoS。

阶段 2:状态执行与eWASM 💻

阶段2将为分片链引入完整的智能合约执行功能,真正实现“世界计算机”。

  • 新的虚拟机:计划用基于WebAssembly的以太坊虚拟机(eWASM)取代现有的EVM。
  • 多语言支持:eWASM允许开发者使用任何能编译到WASM的语言(如C++、Rust等)编写智能合约,而不仅限于Solidity,这将极大改善开发体验。
  • 跨分片交易:允许不同分片上的智能合约相互调用。
  • 可移植性:如果某个分片的Gas费用过高,开发者可以将合约迁移到其他分片,并在原地址设置重定向。

阶段2的完整实现预计在2021年底或2022年。

如何参与验证?🛠️

运行一个验证者节点既有趣也有风险(非投资建议)。以下是关键考虑因素:

客户端架构

通常采用客户端-服务器架构:

  • 信标节点:负责与网络通信、同步链数据、处理区块等繁重工作。
  • 验证者客户端:连接到信标节点,使用私钥对区块进行签名和投票。一个验证者客户端可以管理多个验证者密钥。

收益与成本

  • 收益:年化收益率取决于网络中的验证者总数。早期参与者收益率较高(预计在10%-18%之间),随着更多验证者加入,个体收益率会逐渐下降。
  • 成本
    • 质押金:每个验证者需要32 ETH。这是一笔可退还的押金,但存在机会成本。
    • 硬件成本:很低。你可以在树莓派、旧笔记本或廉价服务器上运行。运行10个验证者和运行1000个验证者的硬件成本几乎相同。
    • 运营成本:主要是电力和网络费用。

风险与注意事项

  • 长期承诺:在阶段1.5或阶段2之前,质押的ETH无法提取或转移。
  • 离线惩罚:如果验证者离线,会持续受到小额惩罚。但需要连续离线数年才会损失一半的质押金。短期离线(如几天)影响很小。
  • 罚没风险:如果因配置错误或恶意行为导致被罚没,可能损失大量质押金。必须谨慎操作。
  • 网络风险:如果大量验证者同时离线,惩罚会加剧。

开始测试

有兴趣的用户可以立即加入Medalla测试网进行零风险体验。访问 medalla.launchpad.ethereum.org 即可参与,测试网会提供测试用的ETH。

开发与实施流程

以太坊 2.0 的开发是一个全球协作、开源透明的过程:

  1. 研究:以太坊基金会研究团队提出核心思想和规范。
  2. 讨论:在论坛、Discord、Telegram等渠道进行社区讨论。
  3. 规范制定:在GitHub上以开源形式编写和迭代技术规范。
  4. 实现与测试:多个独立的客户端团队(如Prysmatic Labs的Prysm)根据规范进行实现,并进行严格的单元测试、集成测试和跨客户端测试。
  5. 发布:定期发布新版本,并最终部署到测试网和主网。

总结

本节课我们一起学习了以太坊 2.0 的宏伟蓝图。它通过引入权益证明分片技术,旨在彻底解决以太坊的扩展性难题。这是一个全新的区块链,采用分阶段的谨慎策略进行部署:从阶段0的信标链奠定PoS基础,到阶段1引入数据分片,再到阶段1.5合并现有Eth1,最后在阶段2实现全功能分片执行。整个升级计划在2021-2022年完成。对于开发者与用户而言,以太坊 2.0 承诺了一个更快速、更安全、且容量大幅提升的去中心化计算平台,同时通过测试网和质押机制为社区提供了早期的参与和体验机会。

024:去中心化应用(DApp)开发 🚀

在本节课中,我们将从开发者的视角,学习如何构建去中心化应用。我们将探讨DApp的核心范式、开发工具链以及完整的开发生命周期,并通过一个简单的“Hello World”示例来实践。

概述:什么是去中心化应用?

去中心化应用运行在区块链网络之上,其核心逻辑和数据存储在被称为“智能合约”的代码中。与传统的中心化应用相比,DApp具有无需信任中介、抗审查、可存储价值等独特特性。

上一节我们介绍了区块链的基础架构,本节中我们来看看如何在其上构建应用。

开发范式与核心考量 🔍

构建DApp与构建传统Web或移动应用在范式上存在根本差异。以下是开发者需要理解的核心概念:

  • 信任与中介:DApp通过区块链的共识机制和密码学,在互不信任的各方之间建立信任,无需银行或平台等中心化中介。
  • 应用特性:部署在区块链上的应用具有不可阻挡不可审查的特性,因为其代码和数据在全球节点网络中复制。
  • 价值存储:智能合约可以原生地存储和管理价值(如加密货币、通证),这是平台的内置功能。
  • 去中心化治理:许多DApp会设计治理模型,让利益相关者(如通证持有者)共同参与项目的决策与演进。
  • 智能合约:这是DApp的“后端”逻辑,其代码(通常用Solidity等语言编写)同时包含了业务逻辑和应用程序状态(数据)

与传统架构的对比

在传统Web应用中,客户端通过API与中心化服务器交互,业务逻辑和数据存储(数据库)是分离的。而在DApp架构中:

  • 智能合约 集成了业务逻辑数据存储
  • 合约被部署后,其代码和状态会在区块链网络的所有节点上复制。
  • 用户通过钱包(如MetaMask)与合约交互,交易被签名并广播到网络,经矿工/验证者打包进区块后,状态得以更新。

公式/代码描述核心概念:智能合约结构

// 一个简单的智能合约示例
contract SimpleStorage {
    // 状态变量(数据)
    string public storedData;

    // 设置数据的函数(业务逻辑)
    function set(string memory x) public {
        storedData = x;
    }

    // 获取数据的函数(业务逻辑)
    function get() public view returns (string memory) {
        return storedData;
    }
}

开发DApp的关键考量 ⚙️

从传统开发转向DApp开发,需要关注以下新维度:

以下是开发者需要特别注意的几个方面:

  • 身份管理:用户使用其区块链地址(公钥)作为身份标识,而非由应用管理的用户名/密码。用户拥有并控制自己的身份。
  • 交互与用户体验:区块链交易需要时间进行网络传播和区块确认,存在延迟。用户通常需要为状态更新操作支付交易费用(Gas费)
  • 安全与审计:由于合约可能管理真实资产,安全性至关重要。在部署前,进行专业代码审计和设立漏洞赏金计划是常见做法。
  • 存储成本:在链上存储数据(“上链”)成本高昂,因为数据需要在全网复制。大量数据通常存储在IPFS等去中心化存储方案中。

主流应用场景与开发工具链 🛠️

并非所有应用都适合去中心化。目前,在以太坊等平台上,以下几个领域展现了巨大潜力:

  • 数字资产与通证:创建和交易代表各种价值的通证,如NFT(非同质化通证)或证券型通证。
  • 去中心化金融:构建无需许可的金融协议,如借贷、交易、衍生品等,常被称为“货币乐高”。
  • 治理与身份:实现去中心化自治组织(DAO)的投票治理,或创建用户自主掌控的数字身份系统。
  • 创新领域:探索供应链、医疗记录、游戏等领域的全新协作与价值交换模式。

为了高效地构建DApp,开发者需要一套完整的工具。Truffle Suite 是目前最流行的开发框架之一。

Truffle Suite 简介

Truffle Suite 是一套用于简化DApp开发流程的工具集,旨在让开发者能更轻松地将想法转化为可部署的智能合约和前端应用。

以下是Truffle Suite中的核心工具:

  • Truffle (CLI):核心命令行工具,管理项目生命周期,包括编译、测试、部署和调试智能合约。
  • Ganache:个人本地区块链环境,用于快速开发和测试。它提供GUI和CLI两种版本,预配置了测试账户和资金。
  • Drizzle:前端库集合(基于React),用于构建与智能合约交互的用户界面。
  • Truffle Teams:云端SaaS平台,提供项目的持续集成、监控、可视化调试和团队协作功能。

DApp开发生命周期与实践 🧑‍💻

DApp的开发遵循一个特定的生命周期,其中某些环节与传统软件开发显著不同。

上一节我们介绍了核心工具,本节中我们来看看如何使用它们完成一个完整的开发流程。

生命周期概览

  1. 规划与设计:首先确认项目是否真正需要区块链技术。
  2. 开发:使用Truffle等工具编写、编译和测试智能合约。
  3. 安全审计:聘请专业团队对合约代码进行审计,查找潜在漏洞。
  4. 测试网部署与漏洞赏金:将合约部署到公共测试网络(如Rinkeby),并启动漏洞赏金计划,鼓励社区白帽黑客测试。
  5. 主网部署:经过充分测试和审计后,将合约部署到以太坊主网。
  6. 监控与维护:使用Truffle Teams等工具监控合约状态、交易和性能。

动手实践:创建第一个DApp

让我们通过一个简单的“Hello World”合约,快速体验Truffle的开发流程。

步骤1:环境安装与项目初始化
首先,确保系统已安装Node.js,然后通过npm安装Truffle:

npm install -g truffle

创建一个新目录并初始化Truffle项目:

mkdir my-first-dapp && cd my-first-dapp
truffle init

这会生成一个包含contracts/migrations/test/目录和truffle-config.js配置文件的初始项目结构。

步骤2:编写智能合约
contracts/目录下创建HelloWorld.sol文件,并输入以下Solidity代码:

pragma solidity ^0.8.0;

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_31.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_33.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_35.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_37.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_39.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_41.png)

contract HelloWorld {
    string public message;

    constructor() {
        message = "Hello, World!";
    }

    function setMessage(string memory newMessage) public {
        message = newMessage;
    }

    function getMessage() public view returns (string memory) {
        return message;
    }
}

这个合约定义了一个可公开访问的状态变量message,以及设置和获取该消息的函数。

步骤3:编译与部署
编译合约:

truffle compile

migrations/目录下创建部署脚本(如2_deploy_contracts.js):

const HelloWorld = artifacts.require("HelloWorld");

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_49.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/f7f6f6ed9c1792d6afe4cd164e95f3b9_50.png)

module.exports = function (deployer) {
  deployer.deploy(HelloWorld);
};

启动Truffle开发控制台(它内置了Ganache)并执行迁移(部署):

truffle develop
# 在打开的控制台中运行:
migrate

步骤4:与合约交互
在Truffle开发控制台中,你可以直接与已部署的合约实例交互:

// 获取合约实例
let instance = await HelloWorld.deployed()
// 读取消息
let msg = await instance.getMessage()
console.log(msg) // 输出: Hello, World!
// 更新消息
await instance.setMessage("Hello, Blockchain!")
// 再次读取
msg = await instance.getMessage()
console.log(msg) // 输出: Hello, Blockchain!

进阶学习资源:Truffle Boxes

Truffle Boxes 是预置的样板项目,涵盖从基础到高级的各种应用场景(如React前端、DeFi协议等),是绝佳的学习起点。使用以下命令可以快速获取一个Box:

truffle unbox <box-name>

总结与后续步骤 🎯

本节课中我们一起学习了去中心化应用开发的核心知识。我们首先从开发者视角剖析了DApp的范式,理解了其与传统应用在架构、身份、成本和安全上的根本区别。接着,我们介绍了以太坊生态中流行的开发工具链——Truffle Suite,并概述了包含安全审计在内的完整DApp开发生命周期。最后,我们通过一个简单的“Hello World”合约实践了从初始化、编码、编译到部署和交互的全过程。

如何继续深入?

  • 查阅官方文档:访问 trufflesuite.com/docs 获取详细的教程和指南。
  • 探索Truffle Boxes:通过truffle unbox尝试不同的样板项目,快速上手特定类型的DApp。
  • 参与开源贡献:访问Truffle的GitHub仓库 (github.com/trufflesuite),从标记为“good first issue”的问题开始,参与开源开发。
  • 关注行业动态:参加线上会议(如TruffleCon)和关注社区,持续了解区块链和DApp开发的最新进展。

希望本教程为你打开了通往去中心化应用开发世界的大门。构建快乐!

025:去中心化应用(DApp)入门 🚀

在本节课中,我们将要学习去中心化应用(DApp)的基本概念、它们与区块链技术的关系,以及如何在以太坊平台上构建这些应用。我们将从宏观的“为什么”开始,逐步深入到技术细节,包括以太坊虚拟机(EVM)和Solidity编程语言。

为什么需要DApp? 💡

上一节我们介绍了区块链作为价值互联网的潜力。本节中我们来看看为什么需要在其上构建应用。

互联网实现了信息的自由流动,而区块链技术则有望为价值实现类似的功能。我们希望在数字世界中拥有一种可以安全转移和管理的价值表现形式,即数字货币或代币。然而,数字信息可以零成本复制,这给创建数字原生货币带来了挑战。区块链通过密码学证明和博弈论激励的结合,解决了数字资产的“双花”问题,使得创建可信的数字价值成为可能。

什么是DApp? 🧩

理解了区块链的价值基础后,我们来看看什么是去中心化应用。

DApp是构建在区块链之上的应用程序。与比特币等单一用途的区块链不同,以太坊等平台提供了一个可编程的通用基础层。这意味着开发者无需为每个应用创建独立的区块链,而是可以共享以太坊的网络、安全和数据层。这种共享基础设施极大地降低了开发门槛,并带来了一个关键优势:可组合性。不同DApp之间可以轻松、廉价地相互通信和集成,从而创造出更复杂、功能更强大的生态系统。

以下是DApp的一些常见类型示例:

  • 代币:遵循ERC-20等标准,代表可互换的数字资产。
  • 借贷协议:如MakerDAO,允许用户抵押资产并借出稳定币。
  • 稳定币:如DAI、USDC,其价值与法币(如美元)挂钩,以减少波动性。
  • 去中心化交易所:如Uniswap,允许用户直接在链上交易代币。
  • 预测市场:如Augur,允许用户对事件结果进行预测和投注。
  • 非同质化代币:代表独一无二的数字物品,如艺术品或收藏品。
  • 去中心化自治组织:一种通过智能合约和代币治理来协调人员和资本的新型组织形态。

区块链的可编程性:从比特币脚本到以太坊虚拟机 🔧

了解了DApp的种类,我们需要理解它们是如何在技术上实现的。这涉及到区块链的“可编程性”。

比特币区块链内置了一个简单的虚拟机(VM),称为Script。它主要用于验证交易签名和实现多签等基础功能。其设计 intentionally 保持简单,以增强安全性和稳定性,但这也限制了在其上构建复杂应用的能力。

以太坊的核心创新在于引入了以太坊虚拟机。EVM是一个图灵完备的、基于堆栈的虚拟机。与比特币Script相比,EVM功能强大得多:

  • 它拥有临时内存和持久化存储。
  • 支持完整的算术、逻辑和控制流操作。
  • 允许部署任意的、状态化的字节码程序(即智能合约)。

为了防止恶意代码(如无限循环)耗尽网络资源,以太坊引入了Gas机制。每一条EVM操作码都有其Gas成本,用户发送交易时需要支付Gas费用。这相当于为计算资源建立了市场,确保了网络的安全和可持续运行。

Solidity:编写智能合约的高级语言 📝

直接在EVM字节码层级编程非常困难。因此,就像我们用高级语言(如Python)代替汇编语言一样,我们使用Solidity来编写智能合约。

Solidity是一种语法类似JavaScript和C++的静态类型语言,专为面向智能合约而设计。它被编译成EVM字节码,然后部署到区块链上。

以下是一个简单的Solidity合约示例,它允许存储和读取一个整数值:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract SimpleStorage {
    uint256 storedData; // 状态变量,永久存储在链上

    function set(uint256 x) public {
        storedData = x;
    }

    function get() public view returns (uint256) {
        return storedData;
    }
}

我们可以使用Remix IDE等工具在浏览器中编写、编译、部署和测试这样的合约。部署后,合约会获得一个唯一的地址。任何用户都可以通过向该地址发送交易(附带编码好的函数调用数据)来与合约交互,例如调用set函数更新数据,或调用get函数读取数据。

安全至关重要:警示与最佳实践 ⚠️

在探索了如何构建DApp之后,我们必须正视一个核心挑战:安全。

区块链应用管理着真实的价值。智能合约中的漏洞可能导致用户资金的永久损失。由于区块链的不可篡改性和去中心化特性,通常没有“撤销”按钮或中心化机构来补救。

因此,对于开发者和用户而言,安全是重中之重:

  • 代码审计:在部署涉及大量资金的合约前,必须由专业的安全团队进行审计。
  • 形式化验证:使用数学方法证明代码符合其规范。
  • 全面测试:覆盖各种边缘情况和攻击向量。
  • 谨慎交互:作为用户,在将资产存入陌生合约前,应尽可能了解其代码和风险。
  • 理解风险:这是一个新兴领域,工具和保险机制尚不完善,风险自担。

总结与展望 🌟

本节课中我们一起学习了去中心化应用的世界。我们从区块链作为价值传输网络的基本原理出发,探讨了DApp的概念、优势(如可组合性)以及多种类型。我们深入了解了以太坊虚拟机如何通过图灵完备性和Gas机制实现智能合约的灵活与安全执行,并介绍了使用Solidity语言进行合约开发的基础。最后,我们强调了在这个管理着数十亿美金真实价值的生态系统中,安全是首要考虑因素。

区块链和DApp领域仍处于早期阶段,充满了实验和创新机会。无论是全新的经济协调机制(如二次方投票),还是开放的金融系统(DeFi),都在重新定义我们对于价值、所有权和协作的认知。希望本次课程能激发你的兴趣,并鼓励你继续探索这个令人兴奋的技术前沿。

026:基于比特币的创新 🚀

在本节课中,我们将跟随Joe Bender的分享,探讨如何在比特币这一成熟且安全的区块链基础上进行创新。我们将了解Web3的核心思想、比特币的现状与挑战,并深入解析Blockstack的Stacks 2.0如何通过创新的共识机制,为比特币生态带来智能合约和去中心化应用的可能性。


概述:从Web2到Web3的演变 🌐

Web3是一个常与区块链关联的流行术语,但其定义往往模糊不清。本质上,Web3是关于将网络从大型企业和国家的控制中解放出来,将权力交还给用户。

互联网最初是去中心化的,例如早期的ARPANET和点对点文件共享协议(如LimeWire、BitTorrent)。然而,如今谷歌、Facebook和苹果等巨头掌握了大部分权力。Web2.0时代的特点是“读写”交互,用户可以创造和分享内容。而Web3的核心突破在于,它为互联网引入了原生价值。在区块链出现之前,要在网上转移价值,必须依赖PayPal、信用卡等第三方中介。区块链技术,特别是像比特币这样的加密货币,创造了一个具有原生价值、去中心化的网络。


用户体验与主流采用:Coinbase与MetaMask的对比 🔑

为了让区块链技术被大众接受,用户体验至关重要。以下是两个关键平台的对比:

  • Coinbase:它通过简化流程(如使用邮箱/密码登录、托管用户私钥)极大地降低了加密货币的入门门槛,推动了主流采用。然而,它本质上是中心化的,用户并不真正掌控自己的资产。
  • MetaMask:这是一个浏览器插件钱包,用户需要自己保管12个单词的助记词(私钥)。它提供了真正的自我主权,是与以太坊去中心化应用交互的主要工具,但对新手来说更具挑战性。

这个对比揭示了区块链普及中的一个核心矛盾:我们应该在多大程度上教育用户理解底层技术,又应该在多大程度上将其隐藏起来,提供像使用互联网一样简单的体验?


比特币:数字黄金与不变性的基石 ₿

比特币由中本聪于2009年1月3日创世,其创世区块中编码了当天《泰晤士报》的头条:“财政大臣正处于实施第二轮银行紧急援助的边缘”。这巧妙地讽刺了传统金融体系的失败,并宣示了比特币的使命:创造一个不受中心化机构操控的货币系统。

比特币的核心优势在于其强大的网络效应不变性。它是市值最高、认知度最广的加密货币。其不变性意味着历史交易记录无法被篡改,这与政府可以随意增发法币形成了鲜明对比,也是其作为“数字黄金”价值存储主张的基石。


区块链的分叉与哲学:以The DAO事件为例 🍴

区块链的不变性并非没有争议。2016年,以太坊上一个名为“The DAO”的去中心化自治组织因漏洞被攻击,损失巨大。以太坊社区最终决定通过“硬分叉”回滚区块链,挽回损失。这导致了以太坊分裂为两条链:

  • 以太坊:接受了回滚的新链。
  • 以太坊经典:坚持“代码即法律”、反对回滚的原链。

这个事件引发了关于区块链治理和不变性的深刻哲学讨论。比特币也因扩容等理念分歧产生了比特币现金等分叉。这些分叉体现了加密世界中价值观的多样性。


比特币的扩展性方案:闪电网络 ⚡

比特币网络交易速度较慢、费用较高,不适合小额高频支付。闪电网络是一个第二层解决方案,旨在解决比特币的可扩展性问题。

它的工作原理是:交易双方在比特币主链上开设一个支付通道,并存入一定资金。随后,他们可以在该通道内进行无限次、即时、几乎零费用的交易。只有当通道关闭时,最终的余额状态才会被结算到比特币主链上。这就像在GitHub上创建一个功能分支进行开发,完成后再合并回主分支。


Blockstack与Stacks 2.0:赋能比特币生态 🛠️

上一节我们介绍了比特币的扩展性挑战,本节我们来看看Blockstack提出的创新解决方案。Blockstack的愿景是构建“用户拥有的互联网”,而其核心创新是Stacks 2.0协议,它旨在为比特币带来智能合约和去中心化应用功能。

Stacks 2.0的关键在于其新颖的共识机制——转移证明。以下是其核心组件:

  1. 转移证明:矿工通过发送比特币来竞争生成Stacks区块,而不是像工作量证明那样燃烧电力。这利用了比特币已有的价值和安全性。
  2. Stacking:STX代币持有者可以通过“锁定”他们的代币来参与网络共识,作为回报,他们会获得矿工发送的比特币作为奖励。这类似于权益证明中的质押。
  3. 与比特币锚定:Stacks区块链的每个区块都与一个比特币区块哈希绑定,确保其安全性与比特币网络同步,同时通过微区块实现更高的交易吞吐量。

简单来说,Stacks 2.0创建了一个独立的、功能更丰富的区块链(支持智能合约),但其安全性和经济激励深深植根于比特币网络。它试图将比特币的稳定安全性与以太坊的灵活可编程性结合起来。


总结与展望 🎯

本节课我们一起探索了基于比特币进行创新的多种路径。我们回顾了Web3的愿景,分析了比特币作为价值存储基石的地位和其面临的扩展性挑战。我们深入探讨了闪电网络作为支付层解决方案的潜力,并重点学习了Blockstack的Stacks 2.0如何通过“转移证明”这一创新机制,试图为比特币生态引入智能合约和去中心化金融功能。

区块链领域仍在快速演变,核心在于通过精巧的机制设计(游戏理论)来协调激励,在安全性、去中心化和可扩展性之间寻找平衡。无论是专注于支付效率的闪电网络,还是旨在扩大生态能力的Stacks,这些创新都共同推动着一个更开放、由用户主导的互联网未来。

027:ResilientDB实操教程 🚀

在本节课中,我们将跟随加州大学戴维斯分校的博士生Sajad Rana,学习ResilientDB区块链平台的核心概念、架构以及如何上手操作。ResilientDB是一个由UC Davis团队在过去三年中自主研发的区块链框架,已有超过100名学生通过课程使用过它。本教程将分为三个部分:平台介绍、使用Docker运行ResilientDB,以及在Google Cloud上运行并进行代码调整。


概述 📋

ResilientDB是一个用C++编写的分布式区块链框架。它依赖一些外部库(如CryptoPP、Boost、Nanomsg)来处理加密和网络通信,但所有依赖都已预先打包,方便用户快速上手。其核心是一个高度流水线化和多线程的架构,能够高效处理共识协议。

第一部分:平台介绍与配置

ResilientDB是一个分布式系统,需要在多台机器上运行。对于本地开发和测试,最简单的方法是使用Docker来模拟多节点环境。

核心配置文件

运行系统前,需要了解配置文件 config.h 中的几个关键参数:

  • NODE_CNT:系统中节点的总数。
  • CLIENT_NODE_CNT:系统中客户端的数量。
  • 流水线线程数:系统为输入、输出、共识处理等任务配置的线程数量,用户通常无需修改。
  • TOTAL_PROCESS_TIMEWARMUP_PROCESS_TIME:系统总运行时间和预热时间。
  • PROTOCOL_TYPE:当前开源的唯一协议是 PBFT(实用拜占庭容错)。

上一节我们介绍了平台的基本情况,本节中我们来看看如何快速运行它。

第二部分:使用Docker运行ResilientDB 🐳

为了简化在多机器环境下的部署,ResilientDB提供了Docker脚本。

运行步骤

以下是使用Docker脚本一键运行ResilientDB的步骤:

  1. 确保Docker引擎运行:在终端执行 docker ps 命令,确认Docker服务正常。
  2. 执行运行脚本:使用 ./resilientdb_docker.sh 脚本,并指定副本节点和客户端的数量。
    ./resilientdb_docker.sh -r 6 -c 4
    
  3. 脚本自动执行流程:该脚本会自动完成以下工作:
    • 根据参数生成配置文件。
    • 创建Docker Compose文件,并启动对应数量的容器(例如S1-S6, C1-C4)。
    • 从Docker引擎获取各容器的IP地址,并生成 ifconfig.txt 文件。
    • 解压所有依赖库。
    • 编译ResilientDB源代码,生成 runDB(副本节点程序)和 runCL(客户端程序)二进制文件。
    • 通过共享文件夹将二进制文件分发到各容器。
    • 启动系统运行。

系统将首先进行预热(Warmup),然后开始正式运行并测量吞吐量和延迟。运行结束后,脚本会收集所有容器的结果并汇总展示。

PBFT协议工作流简介

ResilientDB当前实现的PBFT协议工作流程如下:

  1. 客户端:将请求批量发送给主节点(Primary)。
  2. 主节点:创建 Pre-Prepare 消息,并广播给所有副本节点。
  3. 所有副本节点:收到Pre-Prepare消息后,创建 Prepare 消息并广播给所有节点。
  4. 所有副本节点:收到足够多的Prepare消息后,创建 Commit 消息并广播。
  5. 所有副本节点:收到足够多的Commit消息后,执行交易,将其加入区块链,并向客户端发送回复。

主节点 负责为交易分配序列号以确定顺序。如果主节点出现故障(拜占庭错误或崩溃),系统内置的视图更换(view change)协议会选举新的主节点。

拜占庭副本 是指可能表现出任意恶意行为的故障节点,例如不发送消息、向不同节点发送不同消息等。

第三部分:代码结构与开发入门 💻

如果想基于ResilientDB实现自己的协议或进行修改,需要了解其代码结构和工作流程。

代码目录结构

对于初学者,主要需要关注两个目录:

  • system/:包含共识协议的核心逻辑,如节点处理消息的流水线。
  • client/:包含客户端行为逻辑。

主要的入口二进制文件对应的主函数分别在 runDB.cpprunCL.cpp 中。

核心工作流程追踪

理解PBFT在代码中的实现,最佳方式是追踪一个客户端请求的完整生命周期。

  1. 客户端发起请求

    • 代码位于 client/client_thread.cpprun() 函数中。
    • 这是一个无限循环,客户端不断创建批量请求,发送给当前视图的主节点,然后等待回复。
    • 关键函数 create_and_send_batchreq() 会构建请求,签名后放入消息队列,由输出线程发送。
  2. 节点处理消息(事件驱动)

    • 所有副本节点的核心逻辑在 system/worker_thread.cpprun() 函数中。
    • 节点不断从工作队列中取出消息,并根据消息类型调用相应的处理函数。
    • 处理函数是一个大的 switch-case 结构,例如:
      switch (msg->rtype) {
          case CLIENT_BATCH:
              process_client_batch(msg);
              break;
          case BATCH_REQ:
              process_batch(msg);
              break;
          // ... 其他消息类型
      }
      
    • 如果你想添加新的消息类型或协议阶段,需要在此处添加新的 case 并编写处理函数。
  3. 处理客户端批量请求(主节点)

    • 当主节点收到 CLIENT_BATCH 消息时,会调用 process_client_batch()
    • 该函数验证请求后,会为每个请求创建交易管理器,计算整个批次的摘要(Digest),然后创建 BATCH_REQ(即Pre-Prepare)消息,广播给所有节点。
  4. 处理批量请求(所有副本节点)

    • 当任何节点收到 BATCH_REQ 消息时,会调用 process_batch()
    • 此函数会验证消息,然后创建 PREPARE 消息并广播,从而进入协议的下一阶段。

后续的 PREPARECOMMITEXECUTE 等阶段的处理方式类似,都是通过相应的 process_pbft_prepare_msg(), process_pbft_commit_msg() 等函数推进状态。

开发与调试技巧

  • 添加打印语句:在关键函数中添加 cout 打印(如我们演示的在 process_client_batch 中添加打印),是理解代码执行流的最直接方法。
  • 理解流水线:ResilientDB采用多线程流水线设计。例如,可能有独立线程处理客户端请求、处理共识消息、执行交易等。性能统计中显示的各个线程的“空闲时间”有助于分析系统瓶颈。
  • 修改与测试:修改代码后,只需重新编译 (make clean && make -j),因为Docker容器共享工作目录,二进制文件会自动更新。然后可以像之前一样,在独立的终端中分别启动每个容器节点来观察修改效果。

如何参与贡献

  1. Fork代码库:访问 ResilientDB GitHub 页面,点击Fork按钮,将代码库复制到你的账户下。
  2. 克隆与修改
    git clone git@github.com:<你的GitHub用户名>/resilientdb.git
    cd resilientdb
    # 创建新分支并进行修改
    
  3. 提交与推送
    git add .
    git commit -m “描述你的修改”
    git push origin <你的分支名>
    
  4. 发起拉取请求(PR):在你的GitHub仓库页面,点击 “Pull Request”,向官方ResilientDB仓库提交合并请求。经过审核后,你的代码可能被并入主分支。

总结 🎯

本节课我们一起学习了ResilientDB区块链平台。我们首先了解了它的背景和核心架构,特别是其多线程流水线设计。然后,我们学习了如何使用Docker脚本快速搭建一个多节点的PBFT共识网络进行演示。最后,我们深入代码层面,追踪了PBFT协议从客户端请求到交易执行的核心工作流,并介绍了如何通过添加打印语句、理解消息处理循环来开始自己的开发工作。ResilientDB作为一个研究原型,代码结构相对清晰,是学习分布式共识和区块链实现的优秀平台。

001:Web3 - 用区块链编写Instagram复刻版 🚀

概述

在本节课中,我们将学习如何构建一个基于区块链的去中心化图片分享网站,类似于Instagram。这个应用将允许用户发布图片并赚取加密货币。我们将使用以太坊区块链和星际文件系统(IPFS)来创建一个抗审查、不可阻挡的Web 3.0应用。即使你之前没有编程或区块链经验,本教程也将一步步引导你完成整个过程。

应用架构

上一节我们介绍了项目的目标,本节中我们来看看应用的整体架构。

传统中心化应用的问题

首先,让我们看看像Instagram这样的传统应用是如何工作的。当你使用Instagram时,你的移动设备会与一个后端Web服务器通信。这个服务器存储了应用的所有代码、数据和图片。当你请求时间线图片时,数据会从Web服务器传回你的设备。这种架构存在几个主要问题,最大的问题是应用创建者对向用户展示哪些内容拥有完全控制权。社交媒体算法臭名昭著,其最大的问题之一是它们可以通过隐藏某些内容、突出显示应用创建者认为最适合用户看到的内容,从而有效地审查平台上的用户。

我们不希望以这种中心化的、容易受到此类操纵的方式构建图片分享网站。我们希望以一种去中心化的方式构建它,采用一个非常不同、直接、透明且免于审查的算法。

去中心化应用架构

那么,去中心化版本是什么样的呢?我们将不再让移动设备与Web服务器通信,而是构建一个基于区块链的应用。你将通过带有区块链钱包的网页浏览器访问它。这个应用将直接与用HTML、CSS和JavaScript编写的网站交互,然后这个网站将直接与区块链通信。我们的代码将以以太坊智能合约的形式编写,并部署到以太坊区块链上。所有图片将存储在一个名为IPFS的去中心化文件存储系统中,这样图片就永远不会被审查或删除。这将是一个完全透明的算法,我们知道它每次都以相同的方式工作,因为智能合约代码是不可变的,无法更改,用户可以通过阅读代码来验证其工作原理。

以下是应用架构的图示:

[用户浏览器 + MetaMask钱包] <-> [React前端应用] <-> [以太坊智能合约] + [IPFS文件存储]

环境与依赖安装

在开始编码之前,我们需要设置开发环境并安装必要的依赖项。

以下是构建此项目所需的工具和库:

  1. Node.js:允许我们在计算机上安装所有软件包并运行客户端应用。

    • 你可以通过在终端输入 node -v 来检查是否已安装Node.js。本教程推荐使用版本 9.10.0 以获得最佳效果,但你也可以使用最新版本。
    • 你可以直接从官网下载Node.js,或使用像Homebrew这样的命令行工具来安装。
  2. Truffle框架:这是一个用于创建、测试和部署以太坊智能合约的开发框架。

    • 你可以通过命令行安装:npm install -g truffle@5.1.39
  3. Ganache:这是一个在本地计算机上运行的以太坊区块链模拟器。我们可以用它来部署智能合约和运行交易,而无需支付真实的加密货币。

    • 前往Ganache官网,下载适合你操作系统的版本并安装。运行后,你将看到一个全新的区块链在本地运行,其中包含多个预充值了100个假以太币的账户。
  4. MetaMask浏览器扩展:大多数现代网页浏览器默认无法连接到区块链,因此我们需要安装一个特殊的浏览器扩展,MetaMask就是一个以太坊钱包,可以将我们的浏览器变成区块链浏览器。

    • 前往Chrome网上应用店,搜索并安装MetaMask扩展。安装完成后,按照设置步骤完成初始化。

项目初始化与代码结构

现在,让我们开始初始化项目并查看代码结构。

我们将从一个包含启动代码的特定Git分支开始,而不是从头开始设置一切。

  1. 克隆启动代码仓库:
    git clone -b starter-code https://github.com/dappuniversity/decentagram.git decentagram
    
  2. 进入项目目录并安装依赖:
    cd decentagram
    npm install
    
  3. 确保Ganache正在运行。这是我们将用于本教程的测试区块链。
  4. 在另一个终端标签页中,启动Web服务器以确保一切设置正确:
    npm run start
    

现在,你应该能在浏览器中看到一个基础的应用界面,包含导航栏,但尚未连接任何功能。

让我们快速浏览一下项目结构:

  • src/contracts/Decentagram.sol:我们将在这里编写智能合约的Solidity代码。
  • src/contracts/Decentagram.json:这是由Truffle生成的智能合约ABI和地址信息文件。
  • test/decentagram.test.js:我们将在这里为智能合约编写JavaScript测试。
  • src/components/App.js:这是React应用的主组件文件。
  • src/components/Main.js:这是应用主要内容区域的组件。
  • src/components/Navbar.js:这是导航栏组件。

编写智能合约(第一部分)

上一节我们搭建好了环境,本节中我们来编写第一个智能合约。

我们将首先在 src/contracts/Decentagram.sol 文件中编写业务逻辑。Solidity是以太坊智能合约的主要编程语言。

基础合约结构

首先,我们定义合约的基本框架和一个状态变量。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Decentagram {
    string public name = "Decentagram";
}
  • pragma solidity ^0.8.0; 指定了Solidity编译器的版本。
  • contract Decentagram { ... } 定义了一个名为 Decentagram 的智能合约。
  • string public name = "Decentagram"; 定义了一个公开的字符串状态变量 name,其值存储在区块链上,并且可以从合约外部读取。

部署与测试

为了验证我们的设置,让我们部署这个基础合约并进行测试。

  1. 首先,我们需要创建一个迁移文件来告诉Truffle如何部署合约。在 migrations/ 目录下创建 2_deploy_contracts.js
    const Decentagram = artifacts.require("Decentagram");
    
    module.exports = function(deployer) {
      deployer.deploy(Decentagram);
    };
    
  2. 在终端中编译并部署合约到Ganache:
    truffle migrate --reset
    
    --reset 标志确保我们部署的是最新版本的合约。
  3. 打开Truffle控制台与合约交互:
    truffle console
    
  4. 在控制台中,获取合约实例并读取 name 变量:
    let decentagram = await Decentagram.deployed()
    decentagram.address // 查看合约地址
    let name = await decentagram.name()
    name // 应输出 "Decentagram"
    

自动化测试

为了更高效地开发,我们将为合约编写自动化测试。打开 test/decentagram.test.js 文件。

我们将编写一个测试来验证合约能成功部署并且 name 变量正确。

const Decentagram = artifacts.require("Decentagram");

require('chai')
  .use(require('chai-as-promised'))
  .should()

contract('Decentagram', (accounts) => {
  let decentagram

  before(async () => {
    decentagram = await Decentagram.deployed()
  })

  describe('deployment', async () => {
    it('deploys successfully', async () => {
      const address = await decentagram.address
      assert.notEqual(address, 0x0)
      assert.notEqual(address, '')
      assert.notEqual(address, null)
      assert.notEqual(address, undefined)
    })

    it('has a name', async () => {
      const name = await decentagram.name()
      assert.equal(name, 'Decentagram')
    })
  })
})

运行测试:

truffle test

如果一切正常,测试应该通过。

设计数据模型与存储

现在我们已经验证了基础设置,接下来设计应用的核心数据模型。

我们的应用需要存储图片帖子。每个帖子将包含以下信息:

  1. 唯一ID
  2. IPFS上的图片哈希值(即图片的地址)
  3. 图片描述
  4. 收到的打赏总额
  5. 作者的钱包地址

在Solidity中,我们使用 struct 来定义自定义数据类型,使用 mapping 来存储键值对数据,类似于数据库。

定义数据结构和存储

让我们更新 Decentagram.sol 合约。

contract Decentagram {
    string public name = "Decentagram";

    // 存储图片数量,也用作ID生成器
    uint public imageCount = 0;

    // 定义图片结构体
    struct Image {
        uint id;
        string hash;
        string description;
        uint tipAmount;
        address payable author;
    }

    // 使用映射来存储图片,键是ID,值是Image结构体
    mapping(uint => Image) public images;
}
  • uint public imageCount = 0;:一个公共的无符号整数,用于追踪图片总数,并作为生成新图片ID的计数器。
  • struct Image { ... }:定义了一个名为 Image 的结构体,包含我们需要的所有字段。注意 author 被声明为 address payable,这意味着我们可以向这个地址发送以太币。
  • mapping(uint => Image) public images;:定义了一个公共的映射。键是 uint 类型的ID,值是 Image 结构体。声明为 public 后,Solidity会自动生成一个 images(id) 函数,允许我们通过ID查询单个图片。

实现核心功能:上传图片

有了数据模型,我们现在可以实现第一个核心功能:上传图片。

上传图片函数

我们将创建一个函数,允许用户将图片的IPFS哈希和描述上传到区块链。

// 事件:用于在前端监听图片创建
event ImageCreated(
    uint id,
    string hash,
    string description,
    uint tipAmount,
    address payable author
);

function uploadImage(string memory _imgHash, string memory _description) public {
    // 验证输入
    require(bytes(_imgHash).length > 0, 'Image hash is required');
    require(bytes(_description).length > 0, 'Description is required');
    require(msg.sender != address(0), 'Author address is required');

    // 增加图片计数
    imageCount ++;

    // 将图片添加到映射中
    images[imageCount] = Image(
        imageCount,
        _imgHash,
        _description,
        0, // 初始打赏金额为0
        payable(msg.sender) // 调用者即为作者
    );

    // 触发事件
    emit ImageCreated(imageCount, _imgHash, _description, 0, payable(msg.sender));
}

代码解释:

  1. event ImageCreated(...):定义了一个事件。当图片创建时,会触发这个事件,前端应用可以监听它。
  2. function uploadImage(...) public:这是一个公开函数,任何人都可以调用。
  3. require(...):这些是条件检查。如果条件不满足,交易将回滚,状态不会改变。我们确保哈希、描述和发送者地址有效。
  4. imageCount ++;:每次上传,图片总数加1。新的 imageCount 值就是新图片的ID。
  5. images[imageCount] = Image(...);:在映射中创建一个新的 Image 条目。
  6. emit ImageCreated(...);:触发事件,通知所有监听者一个新的图片已被创建。

为上传功能编写测试

现在,让我们为上传功能编写更全面的测试。回到 test/decentagram.test.js 文件。

我们将添加测试来验证图片创建、输入验证以及事件触发。

describe('images', async () => {
  let result
  const imgHash = 'abc123'
  const description = 'Hello World'

  before(async () => {
    // 使用第一个测试账户作为作者上传一张图片
    result = await decentagram.uploadImage(imgHash, description, { from: accounts[0] })
  })

  it('creates images', async () => {
    // 检查图片总数增加
    const imageCount = await decentagram.imageCount()
    assert.equal(imageCount, 1)

    // 检查事件参数
    const event = result.logs[0].args
    assert.equal(event.id.toNumber(), imageCount.toNumber(), 'ID is correct')
    assert.equal(event.hash, imgHash, 'Hash is correct')
    assert.equal(event.description, description, 'Description is correct')
    assert.equal(event.tipAmount.toNumber(), 0, 'Tip amount is correct')
    assert.equal(event.author, accounts[0], 'Author is correct')
  })

  it('lists images', async () => {
    // 通过ID获取图片
    const image = await decentagram.images(1)
    assert.equal(image.id.toNumber(), 1, 'ID is correct')
    assert.equal(image.hash, imgHash, 'Hash is correct')
    assert.equal(image.description, description, 'Description is correct')
    assert.equal(image.tipAmount.toNumber(), 0, 'Tip amount is correct')
    assert.equal(image.author, accounts[0], 'Author is correct')
  })

  it('fails for empty image hash', async () => {
    // 尝试用空哈希上传,应该被拒绝
    await decentagram.uploadImage('', description, { from: accounts[0] }).should.be.rejected
  })

  it('fails for empty description', async () => {
    // 尝试用空描述上传,应该被拒绝
    await decentagram.uploadImage(imgHash, '', { from: accounts[0] }).should.be.rejected
  })
})

运行测试以确保所有功能正常工作:

truffle test

实现核心功能:打赏图片

图片分享的另一个关键功能是允许用户为他们喜欢的图片打赏。接下来我们实现这个功能。

打赏图片函数

我们将创建一个函数,允许用户向特定图片的作者发送以太币作为打赏。

// 事件:用于在前端监听打赏
event ImageTipped(
    uint id,
    string hash,
    string description,
    uint tipAmount,
    address payable author
);

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/3240d77ebb9dd9a14111406bce3a787e_73.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/3240d77ebb9dd9a14111406bce3a787e_74.png)

function tipImageOwner(uint _id) public payable {
    // 验证ID有效
    require(_id > 0 && _id <= imageCount, 'Invalid image ID');

    // 获取图片
    Image memory _image = images[_id];

    // 获取作者地址
    address payable _author = _image.author;

    // 确保作者地址有效
    require(_author != address(0), 'Author address is invalid');

    // 向作者转账(msg.value 是随交易发送的以太币数量)
    _author.transfer(msg.value);

    // 更新图片的打赏总额
    _image.tipAmount = _image.tipAmount + msg.value;

    // 将更新后的图片存回映射
    images[_id] = _image;

    // 触发打赏事件
    emit ImageTipped(_id, _image.hash, _image.description, _image.tipAmount, _author);
}

代码解释:

  1. function tipImageOwner(uint _id) public payable:这是一个 payable 函数,意味着调用它可以附带以太币。_id 是要打赏的图片ID。
  2. require(_id > 0 && _id <= imageCount, ...):验证提供的ID在有效范围内。
  3. Image memory _image = images[_id];:从存储中读取图片数据到内存中。memory 关键字表示这是一个临时变量。
  4. address payable _author = _image.author;:获取图片作者的支付地址。
  5. _author.transfer(msg.value);:这是最关键的一行。它将调用者随交易发送的以太币(msg.value)转账给作者。
  6. 更新图片的 tipAmount 并将其存回映射。
  7. 触发 ImageTipped 事件,通知前端打赏已完成。

为打赏功能编写测试

现在,为打赏功能添加测试。我们需要检查作者在打赏后是否收到了资金。

describe('tipping', async () => {
  let result
  const tipAmount = web3.utils.toWei('1', 'Ether') // 1个以太币,转换为Wei单位

  before(async () => {
    // 假设我们已经有一张ID为1的图片,由accounts[0]上传
    // 现在由另一个账户(accounts[1])来打赏
    result = await decentagram.tipImageOwner(1, { from: accounts[1], value: tipAmount })
  })

  it('allows users to tip images', async () => {
    // 获取打赏后作者的余额
    let oldAuthorBalance = await web3.eth.getBalance(accounts[0])
    oldAuthorBalance = new web3.utils.BN(oldAuthorBalance)

    // 执行打赏
    result = await decentagram.tipImageOwner(1, { from: accounts[1], value: tipAmount })

    // 检查事件
    const event = result.logs[0].args
    assert.equal(event.id.toNumber(), 1, 'ID is correct')
    assert.equal(event.tipAmount, tipAmount, 'Tip amount is correct')

    // 检查作者余额是否增加
    let newAuthorBalance = await web3.eth.getBalance(accounts[0])
    newAuthorBalance = new web3.utils.BN(newAuthorBalance)

    const tip = new web3.utils.BN(tipAmount)
    const expectedBalance = oldAuthorBalance.add(tip)

    assert.equal(newAuthorBalance.toString(), expectedBalance.toString(), 'Author received the tip')
  })

  it('fails for invalid image ID', async () => {
    // 尝试打赏一个不存在的ID(例如99),应该被拒绝
    await decentagram.tipImageOwner(99, { from: accounts[1], value: tipAmount }).should.be.rejected
  })
})

运行所有测试,确保打赏功能按预期工作。

部署完整智能合约

在开始构建前端之前,让我们确保完整的智能合约已部署到我们的本地区块链。

在终端中运行:

truffle migrate --reset

这将编译并部署我们刚刚编写的完整 Decentagram 合约到Ganache。

构建React前端应用(第一部分)

智能合约的后端逻辑已经完成,现在我们将构建用户与之交互的前端界面。我们将使用React框架。

项目结构与组件

我们的前端主要包含三个组件:

  1. App.js:主应用组件,负责初始化区块链连接和管理全局状态。
  2. Navbar.js:导航栏组件,显示应用名称和用户账户。
  3. Main.js:主内容组件,显示图片流和上传表单。

连接区块链与MetaMask

首先,我们需要将React应用连接到以太坊区块链。这需要两个步骤:使用Web3.js库,并通过MetaMask钱包提供连接。

App.js 中,我们添加初始化代码。

  1. 加载Web3:检查浏览器中是否注入了Web3实例(由MetaMask提供)。
    async loadWeb3() {
      if (window.ethereum) {
        window.web3 = new Web3(window.ethereum)
        await window.ethereum.enable()
      } else if (window.web3) {
        window.web3 = new Web3(window.web3.currentProvider)
      } else {
        window.alert('Non-Ethereum browser detected. You should consider trying MetaMask!')
      }
    }
    
  2. 加载区块链数据:获取用户账户、智能合约实例,并加载图片数据。
    async loadBlockchainData() {
      const web3 = window.web3
      // 加载账户
      const accounts = await web3.eth.getAccounts()
      this.setState({ account: accounts[0] })
    
      // 网络ID
      const networkId = await web3.eth.net.getId()
    
      // 加载智能合约
      const decentagramData = Decentagram.networks[networkId]
      if (decentagramData) {
        const decentagram = new web3.eth.Contract(Decentagram.abi, decentagramData.address)
        this.setState({ decentagram })
    
        // 获取图片总数
        const imageCount = await decentagram.methods.imageCount().call()
        this.setState({ imageCount })
    
        // 加载所有图片
        let images = []
        for (let i = 1; i <= imageCount; i++) {
          const image = await decentagram.methods.images(i).call()
          images.push(image)
        }
        // 按打赏金额排序,最高的排前面
        images.sort((a, b) => b.tipAmount - a.tipAmount)
        this.setState({ images })
      } else {
        window.alert('Decentagram contract not deployed to detected network.')
      }
      // 数据加载完成
      this.setState({ loading: false })
    }
    
  3. 在组件挂载时调用:使用React的生命周期方法 componentDidMount 来触发初始化。
    async componentDidMount() {
      await this.loadWeb3()
      await this.loadBlockchainData()
    }
    
  4. 管理应用状态:在构造函数中初始化状态。
    constructor(props) {
      super(props)
      this.state = {
        account: '',
        decentagram: null,
        images: [],
        loading: true
      }
      this.loadWeb3 = this.loadWeb3.bind(this)
      this.loadBlockchainData = this.loadBlockchainData.bind(this)
      this.captureFile = this.captureFile.bind(this)
      this.uploadImage = this.uploadImage.bind(this)
      this.tipImageOwner = this.tipImageOwner.bind(this)
    }
    

导入账户到MetaMask并显示

为了进行测试,我们需要将Ganache中的账户导入MetaMask。

  1. 在Ganache界面中,点击第一个账户旁边的钥匙图标,复制其私钥。
  2. 在MetaMask中,点击账户图标,选择“导入账户”。
  3. 粘贴私钥并导入。现在你的MetaMask中应该有了一个带有测试以太币的账户。
  4. 刷新前端页面,导航栏上应该会显示你的以太坊地址和一个Identicon(根据地址生成的头像)。

构建React前端应用(第二部分):上传图片到IPFS

现在,让我们实现上传图片的功能。这涉及两个步骤:先将图片上传到去中心化的IPFS网络,然后将返回的哈希值存储到区块链智能合约中。

集成IPFS客户端

首先,我们需要在应用中集成IPFS。我们已经通过 ipfs-http-client 包安装了IPFS客户端。

App.js 顶部导入并初始化IPFS客户端:

const ipfsClient = require('ipfs-http-client')
const ipfs = ipfsClient({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' })

处理文件上传

我们需要一个函数来处理用户选择的图片文件,并将其转换为IPFS可以接受的格式(Buffer)。

App.js 中添加:

captureFile = event => {
  event.preventDefault()
  const file = event.target.files[0]
  const reader = new window.FileReader()
  reader.readAsArrayBuffer(file)
  reader.onloadend = () => {
    // 将文件转换为Buffer,这是IPFS需要的格式
    this.setState({ buffer: Buffer(reader.result) })
    console.log('buffer', this.state.buffer)
  }
}

这个函数在用户选择文件后被调用,它将文件内容读入一个 Buffer 对象并存储在组件状态中。

上传到IPFS和区块链

接下来,创建 uploadImage 函数,它首先将Buffer上传到IPFS,获取哈希,然后调用智能合约的 uploadImage 函数。

uploadImage = description => {
  this.setState({ loading: true })
  console.log("Submitting file to IPFS...")

  // 将文件上传到IPFS
  ipfs.add(this.state.buffer, (error, result) => {
    console.log('IPFS result', result)
    if(error) {
      console.error(error)
      this.setState({ loading: false })
      return
    }
    // 调用智能合约的 uploadImage 方法
    this.state.decentagram.methods.uploadImage(result[0].hash, description)
      .send({ from: this.state.account })
      .on('transactionHash', (hash) => {
        this.setState({ loading: false })
        // 可以在这里添加成功提示或重载图片列表
        window.location.reload()
      })
      .on('error', (e) => {
        window.alert('Error uploading image')
        this.setState({ loading: false })
      })
  })
}

构建上传表单

现在,我们需要在 Main.js 组件中构建一个表单来触发这些函数。

Main.js 中的表单部分大致如下:

<form onSubmit={(event) => {
  event.preventDefault()
  const description = this.imageDescription.value
  this.props.uploadImage(description)
}}>
  <input type='file' accept=".jpg, .jpeg, .png, .bmp, .gif" onChange={this.props.captureFile} />
  <input type='text' ref={(input) => { this.imageDescription = input }} placeholder="Image description..." required />
  <button type='submit'>Upload Image</button>
</form>
  • 文件输入框的 onChange 事件调用 captureFile
  • 表单的 onSubmit 事件调用 uploadImage,并传递描述文本。

现在,你可以尝试选择一张图片,输入描述,然后点击上传。MetaMask会弹出交易确认窗口(需要支付Gas费)。确认后,你的图片将被上传到IPFS,其哈希值会被记录在区块链上。

构建React前端应用(第三部分):显示图片与打赏功能

最后一步是在前端显示图片流,并实现打赏功能。

显示图片流

App.jsloadBlockchainData 函数中,我们已经循环获取了所有图片并存储在 this.state.images 中。我们需要将这个状态传递给 Main 组件。

App.js 的render方法中:

<Main
  images={this.state.images}
  captureFile={this.captureFile}
  uploadImage={this.uploadImage}
  tipImageOwner={this.tipImageOwner}
/>

Main.js 中,我们可以遍历 this.props.images 数组来渲染每张图片。

{this.props.images.map((image, key) => {
  return(
    <div className="card" key={key}>
      <div className="card-header">
        <Identicon string={image.author} size={30} /> {image.author}
      </div>
      <img src={`https://ipfs.infura.io/ipfs/${image.hash}`} alt={image.description} />
      <div className="card-body">
        <p>{image.description}</p>
        <p>Tip Amount: {window.web3.utils.fromWei(image.tipAmount, 'Ether')} ETH</p>
        <button
          name={image.id}
          onClick={(event) => {
            let tipAmount = window.web3.utils.toWei('0.1', 'Ether')
            this.props.tipImageOwner(event.target.name, tipAmount)
          }}
        >
          TIP 0.1 ETH
        </button>
      </div>
    </div>
  )
})}
  • 使用 Identicon 组件根据作者地址生成头像。
  • 图片的 src 通过IPFS网关链接构建:https://ipfs.infura.io/ipfs/${image.hash}
  • 显示描述和当前打赏总额(从Wei单位转换回Ether)。
  • 点击按钮会调用打赏函数,固定打赏0.1 ETH。

实现打赏函数

App.js 中实现 tipImageOwner 函数:

tipImageOwner = (id, tipAmount) => {
  this.setState({ loading: true })
  this.state.decentagram.methods.tipImageOwner(id)
    .send({ from: this.state.account, value: tipAmount })
    .on('transactionHash', (hash) => {
      this.setState({ loading: false })
      window.location.reload() // 刷新以更新打赏金额和排序
    })
    .on('error', (e) => {
      window.alert('Error tipping image')
      this.setState({ loading: false })
    })
}

这个函数调用智能合约的 tipImageOwner 方法,并附带一定数量的以太币(value: tipAmount)。

测试完整流程

  1. 切换账户:在MetaMask中切换到另一个Ganache账户(例如第二个账户),以模拟另一个用户。
  2. 打赏图片:找到你想要打赏的图片,点击“TIP 0.1 ETH”按钮。MetaMask会弹出确认窗口。
  3. 确认交易:确认后,等待交易完成。页面刷新后,你会看到该图片的打赏金额增加了0.1 ETH。
  4. 排序生效:由于我们在 loadBlockchainData 中按打赏金额降序排序了图片,打赏金额最高的图片会自动跳到顶部。

总结

在本节课中,我们一起学习并完成了一个完整的去中心化图片分享应用——Decentagram。我们回顾一下所完成的工作:

  1. 智能合约开发:我们使用Solidity编写了 Decentagram 智能合约,实现了图片上传、存储和打赏的核心逻辑,并确保了代码的安全性和可验证性。
  2. 自动化测试:我们为智能合约编写了全面的JavaScript测试,确保其功能在各种情况下都能按预期工作,这对于不可变的区块链代码至关重要。
  3. 本地区块链环境:我们使用Ganache搭建了本地测试网络,并使用Truffle框架进行合约的编译、部署和迁移。
  4. 前端应用构建:我们使用React构建了用户界面,并通过Web3.js库将其与以太坊区块链连接起来。
  5. 集成IPFS:我们实现了将用户上传的图片文件存储到去中心化的IPFS网络,仅将内容哈希存储在高效的区块链上,解决了区块链存储成本高的问题。
  6. 钱包集成:我们通过MetaMask浏览器扩展管理用户身份、签名交易并支付Gas费。
  7. 核心功能实现:最终的应用允许用户连接钱包、上传图片到IPFS和区块链、浏览按打赏排序的图片流,并为喜欢的图片打赏加密货币。

你已成功构建了一个真正的Web 3.0应用:它去中心化(逻辑在链上,文件在IPFS)、抗审查(无人能删除你的帖子)、透明(算法由公开的智能合约定义)且由用户拥有(打赏直接给创作者)。

这只是区块链开发的起点。你可以在此基础上扩展更多功能,例如用户评论、关注系统、将前端也部署到IPFS以实现完全不可阻挡,或者将其部署到真实的以太坊测试网甚至主网。继续探索,构建更强大的去中心化未来吧!

002:逐步编写区块链游戏

概述

在本节课中,我们将学习如何创建一个基于区块链的记忆匹配游戏。我们将从零开始,逐步构建一个完整的Web3应用。课程将涵盖如何编写以太坊智能合约、使用Solidity编程语言、为合约编写测试、将其部署到区块链,以及如何创建一个客户端应用,让用户能够玩游戏并与智能合约交互。即使你没有编程或区块链经验,也能跟上本教程。

游戏演示

我们将构建一个基于区块链的记忆游戏,目标是找到匹配的卡片。

一旦找到匹配项,你就可以永久地将它们保存在区块链上。这是因为每个卡片都由一个基于区块链的代币表示。每当你找到并匹配代币时,你就可以将它们保存在你的钱包里。这些代币可以转移到游戏之外,因为它们永久存在于区块链上,你可以在市场上出售它们,或作为收藏品保存。

这个应用的灵感来源于另一位YouTube开发者Anyao的教程,我们已将其适配用于区块链和现代React JS Web开发。

应用架构

以下是应用程序的工作原理图:

我们将首先构建一个客户端网站,大部分游戏逻辑将在这里运行。我们将使用JavaScript和React JS编写这个游戏。当我们在记忆游戏中匹配代币时,我们实际上会在区块链上创建新的代币。这些代币由以太坊智能合约驱动,智能合约将充当转移代币和管理代币所有权的业务逻辑。拥有代币的用户账本也将存在于区块链上,它将充当我们的后端数据库。一旦代币存在于区块链的公共账本上,它们就可以被发送到任何其他区块链钱包,在市场上出售等。

代币类型:非同质化代币

在本教程中,我们将逐步构建的代币不是货币,它是一种不同的类型,称为非同质化代币。你可能听说过数字收藏品,比如CryptoKitties,这就是一个例子。

为了理解这个概念,我们需要区分同质化代币非同质化代币

  • 同质化代币:可以互换,每个代币价值相同。例如,加密货币如UNI代币,每个UNI代币的价值都与其他UNI代币相同,可以一对一交换。
  • 非同质化代币:每个代币都是独一无二的,价值不一定相同。一个代币可能因为稀有而比另一个代币价值更高,这使其非常适合作为收藏品。

在本教程中,我们将创建的就是这种非同质化代币。

使用ERC-721标准

我们将使用ERC-721标准。你可能听说过用于基于以太坊的代币的ERC-20标准,而ERC-721就是用于非同质化代币的标准。它基本上描述了代币必须实现的函数和事件类型。这只是一个用Solidity编程语言编写的以太坊智能合约,它描述了必须存在的Solidity函数类型,例如:

  • balanceOf:查看个人拥有多少代币。
  • ownerOf:查看每个代币的所有者。
  • transferFrom:转移代币的能力。
  • approve:批准他人发送代币的能力。

我们将在本视频中深入所有这些细节,但这就是对我们将要构建的ERC-721标准的快速概述。

环境与依赖安装

在开始构建之前,我们需要安装一些必要的工具。

以下是安装步骤:

  1. Node.js:允许我们在计算机上安装所有软件包并运行客户端应用程序。你可以在终端输入 node -v 来检查是否已安装。建议使用Node 9.10.0版本以获得最佳效果,但你也可以使用最新版本。可以从官网下载Node.js,或使用Homebrew等命令行工具安装。
  2. Truffle框架:用于创建以太坊智能合约的框架。我们可以用Solidity编程语言编写智能合约,为其编写测试,并使用Truffle将其部署到区块链。可以通过命令行安装:npm install -g truffle@5.1.39
  3. Ganache个人区块链:一个运行在我们计算机上的区块链。我们可以简单地下载它并在区块链上运行交易、部署智能合约,而无需支付任何真实货币。请根据你的操作系统下载相应版本。运行后,你会看到一个全新的区块链在计算机上运行,其中有许多账户,每个账户都有100个假的以太币。
  4. MetaMask浏览器扩展:大多数现代网络浏览器默认无法连接到区块链,因此我们需要安装一个特殊的浏览器扩展来实现这一点。MetaMask就是一个以太坊钱包,它将我们的浏览器变成了区块链浏览器。请前往Google Chrome网上应用店,找到MetaMask并点击安装。安装后,你会在右上角看到一个狐狸图标,按照设置步骤完成即可。

项目初始化与代码获取

现在让我们开始构建项目。为了快速启动,我将提供一个GitHub仓库链接,其中包含应用的初始代码。

在终端中执行以下命令来获取代码:

git clone -b starter-code https://github.com/dappuniversity/blockchain-game.git blockchain-game

进入新创建的目录:

cd blockchain-game

接下来,安装所有依赖项:

npm install

安装完成后,启动开发服务器:

npm run start

现在,你应该能在浏览器中看到应用的基本模板。它有一个导航栏,标题为“Memory Tokens”,一个图标,以及一个显示以太坊地址的位置。游戏区域和代币收集区域将在后续教程中构建。

启动本地区块链

在开始构建之前,我们需要启动Ganache本地区块链,以便我们可以向其部署智能合约。

打开Ganache应用程序,确保它正在运行。你会看到许多账户,每个账户都有100个假的以太币。

项目结构概览

让我们在文本编辑器中打开项目,查看其结构。

项目主要包含以下目录和文件:

  • truffle-config.js:配置我们的项目以连接到区块链。
  • contracts/:智能合约存放的目录。我们已经有一个设置好的MemoryToken.sol智能合约。
  • tests/:为智能合约编写测试的目录。我们已经有一个基本的测试框架。
  • src/:客户端代码目录,包含React JS组件。

编写智能合约:MemoryToken

现在,让我们开始编写代币的智能合约。我们将创建一个ERC-721代币,用于在游戏中收集记忆代币。

首先,我们打开contracts/MemoryToken.sol文件。我们将继承OpenZeppelin库中的ERC-721标准实现,这样可以免费获得许多标准功能。

以下是智能合约的基本结构:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./ERC721Full.sol";

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/84667de9984b90e1ba962183151f4b9e_39.png)

contract MemoryToken is ERRC721Full {
    constructor() ERRC721Full("Memory Token", "MEMORY") public {
    }

    function mint(address _to, string memory _tokenURI) public returns (bool) {
        uint256 _tokenId = totalSupply().add(1);
        _mint(_to, _tokenId);
        _setTokenURI(_tokenId, _tokenURI);
        return true;
    }
}

代码解释

  1. 导入与继承:我们导入ERC721Full.sol文件,并让MemoryToken合约继承它。这使我们能够使用所有标准的ERC-721函数。
  2. 构造函数:在合约部署时调用。我们传入代币的名称"Memory Token"和符号"MEMORY"
  3. mint函数:用于创建(铸造)新代币。
    • 它接受两个参数:接收代币的地址_to,以及代币元数据(如图片)的链接_tokenURI
    • 函数内部,我们首先获取当前总供应量并加1,作为新代币的ID。
    • 然后调用继承的_mint函数来铸造代币给指定地址。
    • 接着调用_setTokenURI函数来设置该代币的元数据链接。
    • 最后返回true表示成功。

这个简单的智能合约就是我们游戏所需的核心。

部署智能合约

在编写测试之前,让我们先尝试将智能合约部署到区块链,以确保一切设置正确。

首先,我们需要创建一个迁移文件来告诉Truffle如何部署合约。在migrations/目录下,创建一个名为2_deploy_contracts.js的文件,内容如下:

const MemoryToken = artifacts.require("MemoryToken");

module.exports = function(deployer) {
  deployer.deploy(MemoryToken);
};

然后,在终端中运行以下命令来部署合约:

truffle migrate --reset

--reset标志确保我们部署的是最新版本的合约。部署成功后,我们可以打开Truffle控制台与合约交互:

truffle console

在控制台中,我们可以获取合约实例并读取其名称:

let token = await MemoryToken.deployed()
token.address
let name = await token.name()
name

如果一切顺利,你应该能看到合约地址和名称"Memory Token"。恭喜你,你已经成功将智能合约部署到了区块链!

为智能合约编写测试

上一节我们成功部署了智能合约,本节我们将为其编写自动化测试。测试对于智能合约开发至关重要,因为一旦部署,合约代码就无法更改。

我们将使用Mocha测试框架和Chai断言库,它们已与Truffle捆绑。

打开test/MemoryToken.test.js文件。我们将编写测试来验证合约的部署、名称、符号以及代币铸造功能。

以下是测试的核心内容:

const MemoryToken = artifacts.require('MemoryToken')

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/84667de9984b90e1ba962183151f4b9e_99.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/84667de9984b90e1ba962183151f4b9e_101.png)

require('chai')
  .use(require('chai-as-promised'))
  .should()

contract('MemoryToken', (accounts) => {
  let token

  before(async () => {
    token = await MemoryToken.deployed()
  })

  describe('deployment', async () => {
    it('deploys successfully', async () => {
      const address = token.address
      assert.notEqual(address, 0x0)
      assert.notEqual(address, '')
      assert.notEqual(address, null)
      assert.notEqual(address, undefined)
    })

    it('has a name', async () => {
      const name = await token.name()
      assert.equal(name, 'Memory Token')
    })

    it('has a symbol', async () => {
      const symbol = await token.symbol()
      assert.equal(symbol, 'MEMORY')
    })
  })

  describe('token distribution', async () => {
    it('mints tokens', async () => {
      await token.mint(accounts[0], 'https://www.token-uri.com/nft')

      // 应增加总供应量
      let result = await token.totalSupply()
      assert.equal(result.toString(), '1', 'total supply is correct')

      // 应增加所有者余额
      result = await token.balanceOf(accounts[0])
      assert.equal(result.toString(), '1', 'balance is correct')

      // 代币应属于所有者
      let owner = await token.ownerOf('1')
      assert.equal(owner, accounts[0])

      // 所有者应拥有所有代币
      let balanceOf = await token.balanceOf(accounts[0])
      let tokenIds = []
      for (let i = 0; i < balanceOf; i++) {
        let id = await token.tokenOfOwnerByIndex(accounts[0], i)
        tokenIds.push(id.toString())
      }
      let expected = ['1']
      assert.equal(tokenIds.toString(), expected.toString(), 'tokenIds are correct')

      // 代币URI应正确设置
      let tokenURI = await token.tokenURI('1')
      assert.equal(tokenURI, 'https://www.token-uri.com/nft')
    })
  })
})

测试解释

  1. 部署测试:确保合约成功部署,并且具有正确的名称和符号。
  2. 代币铸造测试
    • 调用mint函数为第一个账户铸造一个代币。
    • 检查总供应量是否增加到1。
    • 检查所有者余额是否增加到1。
    • 检查代币ID 1的所有者是否正确。
    • 使用循环获取所有者拥有的所有代币ID,并验证其正确性。
    • 检查代币的URI是否设置正确。

运行测试:

truffle test

如果所有测试通过,说明我们的智能合约功能正常。

构建客户端应用

现在智能合约部分已经完成,让我们开始构建客户端应用。我们将使用React JS来创建用户界面,并使用Web3.js库与区块链交互。

首先,确保你的开发服务器仍在运行(npm run start),Ganache正在运行,并且MetaMask已配置连接到Ganache网络(RPC URL为http://127.0.0.1:7545)。

连接应用与区块链

我们需要将React应用连接到区块链。这主要通过Web3.js库实现。

src/components/App.js文件中,我们首先导入Web3,然后创建函数来加载Web3并获取区块链数据。

关键步骤包括:

  1. 加载Web3:检查浏览器是否注入了Web3实例(由MetaMask提供)。
  2. 加载区块链数据:获取当前账户、智能合约实例、总供应量以及用户拥有的代币。
  3. 更新状态:将获取到的数据(如账户地址、合约实例、代币列表)存入React组件的状态中,以便在UI中显示。

以下是loadBlockchainData函数的核心部分:

async loadBlockchainData() {
  const web3 = window.web3
  // 加载账户
  const accounts = await web3.eth.getAccounts()
  this.setState({ account: accounts[0] })
  // 网络ID
  const networkId = await web3.eth.net.getId()
  const networkData = MemoryToken.networks[networkId]
  if(networkData) {
    const abi = MemoryToken.abi
    const address = networkData.address
    const token = new web3.eth.Contract(abi, address)
    this.setState({ token })
    // 总供应量
    const totalSupply = await token.methods.totalSupply().call()
    this.setState({ totalSupply })
    // 加载用户代币
    const balanceOf = await token.methods.balanceOf(this.state.account).call()
    for (let i = 0; i < balanceOf; i++) {
      const tokenId = await token.methods.tokenOfOwnerByIndex(this.state.account, i).call()
      const tokenURI = await token.methods.tokenURI(tokenId).call()
      this.setState({
        tokenURIs: [...this.state.tokenURIs, tokenURI]
      })
    }
  } else {
    window.alert('Smart contract not deployed to detected network.')
  }
}

完成这些步骤后,你的应用应该能够显示连接的以太坊账户地址。

构建游戏逻辑

现在,让我们构建记忆游戏本身。游戏的核心是一个网格卡片,玩家点击翻转两张卡片,尝试找到匹配项。

我们需要在状态中管理以下数据:

  • cardArray:所有卡片的数组,包含卡片名称和图片路径。
  • cardsChosen:当前被选中的卡片ID数组。
  • cardsChosenIds:当前被选中的卡片在数组中的索引数组。
  • cardsWon:已匹配成功的卡片ID数组。
  • tokenURIs:用户收集到的代币URI数组。

游戏流程如下:

  1. 初始化:在组件加载时,创建并随机排序卡片数组。
  2. 渲染卡片:根据状态映射卡片数组,显示卡片图片(未翻转时是背面,翻转后是正面,匹配成功后是空白或标记)。
  3. 卡片点击:当玩家点击一张卡片时,触发处理函数。
    • 如果这是第一次选择(cardsChosen长度为0),则将卡片ID加入cardsChosen
    • 如果这是第二次选择(cardsChosen长度为1),则检查两张卡片是否匹配。
  4. 检查匹配
    • 如果两张卡片相同,则匹配成功。将卡片ID加入cardsWon,并调用智能合约的mint函数为用户铸造一个新的NFT代币。
    • 如果两张卡片不同,则匹配失败。重置cardsChosencardsChosenIds,让玩家继续尝试。
  5. 更新UI:根据游戏状态(选中、匹配成功等)动态更新每张卡片显示的图片。

关键函数flipCardcheckForMatch实现了上述逻辑。当匹配成功时,我们调用智能合约的mint方法,并传入当前账户地址和卡片图片的URL作为代币URI。

显示收集的代币

最后,我们需要在页面底部显示用户通过游戏收集到的NFT代币。

我们可以在render函数中映射tokenURIs状态数组,为每个代币URI创建一个图片元素来显示。

<div className="row">
  <h2>Tokens Collected: {this.state.tokenURIs.length}</h2>
  {this.state.tokenURIs.map((tokenURI, key) => {
    return (
      <div className="col-md-3 mb-3" key={key}>
        <img src={tokenURI} alt={`NFT Token ${key}`} width="100%" />
      </div>
    )
  })}
</div>

测试完整应用

现在,所有部分都已就绪。你可以玩这个记忆游戏了。

  1. 点击翻转两张卡片。
  2. 如果找到匹配项,MetaMask会弹出交易确认窗口,要求你支付Gas费来铸造代币(使用Ganache的假以太币)。
  3. 确认交易后,新的NFT代币就会被铸造并归属于你的账户。
  4. 匹配成功的卡片会从游戏板上消失,新收集的代币会显示在页面底部。

你可以刷新页面,之前收集的代币仍然会显示,因为它们被永久记录在区块链上。

总结

在本节课中,我们一起学习了如何从零开始构建一个完整的区块链游戏。我们涵盖了以下核心内容:

  1. 项目规划:了解了我们将要构建的记忆匹配游戏及其基于区块链的奖励机制。
  2. 环境搭建:安装了Node.js、Truffle、Ganache和MetaMask等必要工具。
  3. 智能合约开发:使用Solidity编写了符合ERC-721标准的非同质化代币合约,并利用OpenZeppelin库加速开发。
  4. 测试驱动:为智能合约编写了自动化测试,确保其功能正确性,这是区块链开发中至关重要的一步。
  5. 客户端开发:使用React JS构建了游戏前端界面。
  6. 区块链集成:通过Web3.js库将React应用连接到以太坊区块链(Ganache),实现了账户读取、合约交互和交易发送。
  7. 游戏逻辑实现:编写了记忆游戏的完整逻辑,包括卡片翻转、匹配检测和状态管理。
  8. 代币铸造与展示:在玩家匹配成功时,调用智能合约铸造NFT代币,并在UI中展示用户收集的所有代币。

通过这个项目,你不仅学会了如何创建智能合约和DApp前端,还亲身体验了如何将区块链技术融入传统应用,为用户创造拥有真正数字资产所有权的游戏体验。这为探索更复杂的Web3应用奠定了坚实的基础。

003:Web3 - 用区块链编写YouTube复刻版

概述

在本节课中,我们将学习如何构建一个基于区块链的视频分享网站,类似于YouTube。这是一个面向未来的、不可阻挡的Web 3.0应用,因为它运行在以太坊区块链之上。我们将从零开始,学习如何编写以太坊智能合约、将其部署到区块链,并创建前端网站,让用户可以上传和观看视频。

应用架构

上一节我们介绍了项目的目标,本节中我们来看看这个去中心化应用的整体架构。

传统的YouTube采用中心化模型:用户通过浏览器连接到YouTube服务器,所有代码和数据都存储在中心化的服务器和数据库中。这种模式下,应用创建者可以随时删除视频或更改算法。

我们想要构建的是一个去中心化的版本,其工作原理如下:

  • 用户通过浏览器和区块链钱包(如MetaMask)连接到网站。
  • 网站直接与区块链通信,应用的所有核心逻辑和数据都存储在以太坊智能合约中。
  • 智能合约存储平台上视频的引用,这些视频文件实际存储在IPFS(星际文件系统)上。IPFS是一个去中心化的文件存储系统。
  • IPFS将视频文件服务回用户的浏览器。

以下是构建应用的组件图:

  • DApp创建者:使用Truffle框架创建智能合约。
  • 开发区块链:将合约发布到Ganache(个人开发区块链)。
  • 前端连接:使用MetaMask连接我们创建的React JS网站。
  • 交互流程:当与区块链交互时,通过MetaMask直接与Ganache通信;客户端应用(React)同时与IPFS通信。

环境与依赖安装

在开始编码之前,我们需要安装所有必要的依赖项。

以下是需要安装的软件和工具:

  1. Node.js:允许我们在计算机上安装所有软件包并运行客户端应用。可以通过官网下载或使用Homebrew等包管理器安装。
  2. Truffle框架:用于创建以太坊智能合约的框架。我们可以使用Solidity编程语言编写合约,用Truffle进行测试和部署。通过命令行安装:npm install -g truffle@5.1.3
  3. Ganache个人区块链:一个可以在本地计算机上运行的区块链,用于测试和部署智能合约,无需支付真实货币。从官网下载对应操作系统的版本并运行。
  4. MetaMask浏览器扩展:一个以太坊钱包,可将浏览器变为区块链浏览器。从Chrome网上应用店安装MetaMask扩展,并完成设置步骤。

项目初始化与智能合约开发

环境配置完成后,让我们开始编码项目。我们将从智能合约开始。

首先,从GitHub仓库克隆项目启动代码。进入项目目录并打开代码编辑器。

快速浏览项目结构:

  • truffle-config.js:Truffle项目配置文件,用于连接区块链(例如Ganache)。
  • contracts/:存放智能合约的目录。其中DVideo.sol是管理应用的主要合约。
  • migrations/:存放部署脚本的目录。2_deploy_contracts.js用于将DVideo合约部署到区块链。

DVideo.sol是用Solidity语言编写的智能合约。Solidity是以太坊智能合约的主要编程语言,语法类似JavaScript。合约顶部声明了Solidity版本。合约内有一个公共状态变量name,其值会永久写入区块链。合约还包含一些函数。

在深入开发合约之前,我们先在控制台中测试基础设置,确保项目能连接到区块链。

  1. 首先安装Node模块:npm install
  2. 然后迁移合约到区块链:truffle migrate
  3. 启动Truffle控制台:truffle console。在控制台中,我们可以通过JavaScript与区块链和智能合约交互。

设计智能合约功能

现在,让我们重新审视应用的工作流程图,并设计智能合约需要实现的核心功能。

我们的智能合约需要完成以下几件事:

  1. 上传视频:用户上传视频到IPFS,然后将IPFS返回的哈希值存储到智能合约中。
  2. 存储视频:在区块链上保存视频的相关信息。
  3. 列出视频:能够检索并列出所有已上传的视频。

具体流程是:用户将视频上传到IPFS,IPFS返回一个唯一哈希(即文件在IPFS上的ID)。然后,我们将这个哈希连同视频标题等信息一起存储到智能合约中。之后,我们可以通过智能合约列出所有已保存的视频。

实现智能合约

明确了功能后,我们开始一步步实现智能合约代码。

1. 定义视频数据结构

首先,我们需要定义视频的数据模型。在Solidity中,可以使用struct(结构体)来定义自定义数据类型。

struct Video {
    uint id;
    string hash;
    string title;
    address author;
}

这个Video结构体包含四个字段:

  • id:视频在合约内的唯一标识符(无符号整数)。
  • hash:视频在IPFS上的哈希值(字符串)。
  • title:视频标题(字符串)。
  • author:视频上传者的以太坊地址。

2. 存储视频数据

接下来,我们需要一个地方来存储这些视频。在Solidity中,可以使用mapping(映射)数据结构,它类似于一个键值对数据库。

mapping(uint => Video) public videos;

这个映射的键是uint类型的ID,值是Video结构体。我们将它声明为public,这样我们就可以通过一个自动生成的函数videos(id)来根据ID查询单个视频。

我们还需要一个计数器来管理视频ID。

uint public videoCount;

3. 实现上传视频函数

现在,我们来实现核心的uploadVideo函数。这个函数接收两个参数:IPFS视频哈希和视频标题。

function uploadVideo(string memory _videoHash, string memory _title) public {
    // 输入验证
    require(bytes(_videoHash).length > 0);
    require(bytes(_title).length > 0);
    require(msg.sender != address(0));

    // 增加视频计数并作为新视频ID
    videoCount ++;

    // 将新视频添加到映射中
    videos[videoCount] = Video(videoCount, _videoHash, _title, msg.sender);

    // 触发上传事件
    emit VideoUploaded(videoCount, _videoHash, _title, msg.sender);
}

函数内部逻辑:

  1. 使用require语句进行输入验证,确保哈希、标题非空,且上传者地址有效。
  2. videoCount加1,作为新视频的ID。
  3. 创建一个新的Video结构体实例,并将其存入videos映射。
  4. 使用emit关键字触发一个VideoUploaded事件,便于前端应用监听。

我们还需要在合约顶部定义这个事件:

event VideoUploaded(uint indexed id, string hash, string title, address author);

测试智能合约

智能合约编写完成后,进行测试至关重要。虽然本教程因时间关系不逐步编写测试,但项目提供了完整的测试文件。

test/目录下的DVideo.test.js文件中,包含了用Mocha和Chai编写的测试用例。这些测试会验证合约部署是否成功、能否创建视频以及能否正确列出视频。

运行测试命令:truffle test。如果所有测试通过,说明我们的智能合约逻辑正确。

部署更新后的智能合约

测试通过后,我们需要将更新后的智能合约部署到区块链。由于区块链的不可变性,要更新合约代码必须部署一份新的副本。

使用命令truffle migrate --reset来重新部署合约。这会生成一份新的合约副本到区块链上。

开发客户端应用(前端)

智能合约部署完毕,现在开始构建客户端部分,即用户交互的网站。

1. 启动开发服务器

首先,在新的终端标签页中启动React开发服务器:npm run start。这将在浏览器中打开一个React应用,目前是一个空白模板,包含导航栏和空的内容区域。

2. 连接前端与区块链

默认情况下,浏览器无法直接连接区块链,我们需要通过MetaMask来实现。同时,前端应用需要使用Web3.js库与以太坊通信。

连接步骤:

  1. 在MetaMask中添加Ganache网络(使用Ganache提供的RPC URL)并导入一个测试账户(使用Ganache中某个账户的私钥)。
  2. 在前端代码中,我们已经在App.js组件里配置了Web3.js,它通过MetaMask注入的ethereum提供者来实例化与区块链的连接。

3. 获取并显示用户账户

接下来,我们要从MetaMask获取当前用户账户并显示在页面上。

App.jsloadBlockchainData函数中,我们添加以下代码:

const accounts = await web3.eth.getAccounts();
this.setState({ account: accounts[0] });

这会将第一个账户地址保存到React组件的状态(state)中。然后,我们将这个状态作为属性(props)传递给Navbar组件,最终在导航栏中显示用户地址和一个由Identicon库生成的头像。

4. 加载智能合约实例

为了在前端调用智能合约的函数,我们需要创建合约的JavaScript实例。这需要合约的ABI(应用二进制接口)和部署地址。

App.js中,我们根据当前连接的网络ID,从Truffle构建的DVideo.json文件中获取ABI和对应的部署地址,然后使用Web3.js创建合约实例:

const networkId = await web3.eth.net.getId();
const networkData = DVideo.networks[networkId];
if(networkData) {
    const dvideo = new web3.eth.Contract(DVideo.abi, networkData.address);
    this.setState({ dvideo });
    // ... 后续加载视频数据
} else {
    window.alert('智能合约未部署到当前网络。');
}

创建合约实例后,我们将其保存到组件状态中。

5. 从区块链加载视频数据

有了合约实例,我们就可以调用其函数来获取数据。在loadBlockchainData函数中,我们获取视频总数,然后通过循环获取每个视频的详细信息,并存入状态。

const videoCount = await dvideo.methods.videoCount().call();
this.setState({ videoCount });

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/7527852448b62b40f94952190cd9680e_139.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/7527852448b62b40f94952190cd9680e_141.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/7527852448b62b40f94952190cd9680e_143.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/7527852448b62b40f94952190cd9680e_145.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/7527852448b62b40f94952190cd9680e_147.png)

// 加载视频
for (var i = videoCount; i >= 1; i--) {
    const video = await dvideo.methods.videos(i).call();
    this.setState({
        videos: [...this.state.videos, video]
    });
}
// 设置最新视频为当前播放视频
this.setState({
    currentHash: this.state.videos[0].hash,
    currentTitle: this.state.videos[0].title
});

6. 实现视频上传功能

前端需要提供一个表单让用户上传视频。这是一个两步过程:

  1. 将视频文件上传到IPFS,获取文件哈希。
  2. 调用智能合约的uploadVideo函数,将IPFS哈希和标题保存到区块链。

步骤一:处理文件并上传至IPFS
Main.js组件中,我们创建一个表单,包含文件输入框和标题输入框。当用户选择文件时,captureFile函数会将文件转换为Buffer格式,为上传到IPFS做准备。表单提交时,uploadVideo函数被调用。

App.js中,我们定义了uploadVideo函数的核心逻辑:

// 1. 上传到IPFS
ipfs.add(this.state.buffer, (error, result) => {
    if(error) {
        console.error(error);
        return;
    }
    // 2. 保存到区块链
    this.state.dvideo.methods.uploadVideo(result[0].hash, _title)
    .send({ from: this.state.account })
    .on('transactionHash', (hash) => {
        this.setState({ loading: false });
    });
});

这里使用了之前配置的IPFS客户端。上传成功后,我们调用智能合约的uploadVideo方法,使用.send()发送一个交易,并指定发送者账户。交易被确认后,将加载状态设为false。

7. 显示视频列表与播放器

最后,我们需要在页面上显示视频播放器和侧边栏的视频列表。

  • 播放器:我们将状态中的currentHashcurrentTitle传递给Main组件。在Main.js中,使用HTML5的<video>标签,其src属性指向IPFS网关URL加上当前视频的哈希(例如:https://ipfs.io/ipfs/${currentHash})。
  • 视频列表:我们将状态中的videos数组传递给Main组件。在Main.js中,使用.map()方法遍历视频数组,为每个视频在侧边栏生成一个预览项。点击某个视频项时,会调用一个函数来更新状态中的currentHashcurrentTitle,从而切换播放器中的视频。

总结

本节课中,我们一起学习并完成了一个基于区块链的去中心化视频分享网站(YouTube复刻版)的构建。我们涵盖了以下核心内容:

  1. 项目架构:理解了中心化与去中心化应用的区别,以及如何利用以太坊智能合约和IPFS构建去中心化应用。
  2. 智能合约开发:使用Solidity语言编写了DVideo合约,实现了定义数据结构、存储映射、上传视频和事件触发等功能。
  3. 前端开发:使用React框架构建了用户界面,并通过Web3.js和MetaMask实现了前端与以太坊区块链的交互。
  4. 文件存储:集成IPFS,实现了视频文件去中心化存储与检索。
  5. 完整流程:实现了从用户上传视频(到IPFS并记录哈希至区块链)到在页面列表展示和播放视频的完整闭环。

通过这个项目,你创建了一个抗审查的视频平台,因为视频内容存储在IPFS,交易记录在不可篡改的区块链上。这为你进一步探索Web3和去中心化应用开发奠定了坚实的基础。

004:Web3 - 用区块链编写DROPBOX复刻版

在本节课中,我们将学习如何使用以太坊区块链和星际文件系统(IPFS)构建一个去中心化的文件存储网站,类似于Dropbox。我们将从零开始,逐步创建智能合约、部署到区块链,并构建一个完整的React前端应用。

概述

我们将构建一个名为“DStorage”的去中心化文件存储应用。用户可以通过网页界面上传文件,文件将被存储在IPFS上,而文件的元数据(如位置哈希)则通过以太坊智能合约记录在区块链上。这种方式确保了文件的抗审查性和长期存储。

项目架构与依赖安装

上一节我们介绍了项目的整体目标,本节中我们来看看实现这个目标所需的技术栈和开发环境。

以下是构建项目前需要安装的核心依赖:

  1. Node.js:用于运行JavaScript环境和安装项目包。
    • 检查安装:在终端输入 node -v
    • 建议版本:v10.16.0或更高。
  2. Truffle框架:用于开发、测试和部署以太坊智能合约。
    • 安装命令:npm install -g truffle@5.1.3
  3. Ganache:一个本地以太坊区块链,用于开发和测试,无需消耗真实加密货币。
    • 从官网下载并安装对应操作系统的版本。
  4. MetaMask:浏览器扩展钱包,将普通浏览器变为区块链浏览器。
    • 在Chrome网上应用店搜索并安装。

安装完成后,运行Ganache,你会看到10个预充值了100个测试以太币的账户。同时,在浏览器中设置MetaMask,连接到Ganache的RPC服务器(通常是 http://127.0.0.1:7545),并导入一个Ganache的账户私钥。

初始化项目与后端智能合约开发

环境配置好后,我们开始初始化项目并编写核心的智能合约。

首先,克隆项目启动代码并安装依赖:

git clone -b starter-code https://github.com/dappuniversity/dstorage
cd dstorage
npm install

项目结构中的 contracts/ 目录用于存放Solidity智能合约。我们将在此创建 DStorage.sol 文件。

智能合约的核心功能是充当一个去中心化的数据库,记录上传到IPFS的文件的哈希值。我们使用 mapping 数据结构来建立文件ID和文件详情之间的映射。

// 定义文件结构体
struct File {
    uint fileId;
    string fileHash;
    uint fileSize;
    string fileType;
    string fileName;
    string fileDescription;
    uint uploadTime;
    address payable uploader;
}

// 创建映射:文件ID => 文件详情
mapping(uint => File) public files;

接下来,我们编写 uploadFile 函数,用于处理文件上传逻辑。该函数接收文件哈希、大小、类型、名称和描述作为参数,并执行以下操作:

  1. 使用 require 语句进行输入验证。
  2. 递增文件计数器 fileCount 以生成新文件ID。
  3. 使用传入的参数和全局变量 msg.sender(上传者地址)、now(当前时间戳)创建一个新的 File 结构体实例。
  4. 将新文件存入 files 映射。
  5. 触发一个 FileUploaded 事件,以便前端应用监听。
event FileUploaded(
    uint fileId,
    string fileHash,
    uint fileSize,
    string fileType,
    string fileName,
    string fileDescription,
    uint uploadTime,
    address payable uploader
);

function uploadFile(string memory _fileHash, uint _fileSize, string memory _fileType, string memory _fileName, string memory _fileDescription) public {
    // 输入验证
    require(bytes(_fileHash).length > 0);
    require(bytes(_fileType).length > 0);
    require(bytes(_fileDescription).length > 0);
    require(bytes(_fileName).length > 0);
    require(msg.sender != address(0));
    require(_fileSize > 0);

    // 增加文件ID
    fileCount ++;

    // 添加文件到映射
    files[fileCount] = File(fileCount, _fileHash, _fileSize, _fileType, _fileName, _fileDescription, now, msg.sender);

    // 触发事件
    emit FileUploaded(fileCount, _fileHash, _fileSize, _fileType, _fileName, _fileDescription, now, msg.sender);
}

编写完成后,使用Truffle编译并部署合约到Ganache网络:

truffle migrate --reset

你可以使用 truffle console 进入控制台与合约进行交互测试。

前端应用开发与区块链连接

智能合约部署成功后,我们开始构建与之交互的React前端应用。

首先,确保开发服务器运行:npm run start。应用的核心是 src/components/App.js 文件。

前端需要完成两件事:1. 连接浏览器到区块链(通过MetaMask);2. 连接React应用到区块链(通过Web3.js库)。

我们在 loadWeb3 函数中初始化Web3连接,并在 loadBlockchainData 函数中加载区块链数据:

  1. 获取当前MetaMask账户。
  2. 获取已部署的 DStorage 合约实例(需要合约ABI和地址)。
  3. 从合约中读取文件总数和所有文件详情,并存入React的 state 中。

async loadBlockchainData() {
    const web3 = window.web3;
    const accounts = await web3.eth.getAccounts();
    this.setState({ account: accounts[0] });

    const networkId = await web3.eth.net.getId();
    const networkData = DStorage.networks[networkId];

    if(networkData) {
        const dstorage = new web3.eth.Contract(DStorage.abi, networkData.address);
        this.setState({ dstorage });
        const filesCount = await dstorage.methods.fileCount().call();
        this.setState({ filesCount });

        // 加载文件数据...
    } else {
        window.alert('智能合约未部署到当前网络。');
    }
}

账户信息通过 props 传递给 Navbar 组件显示在页面上。

集成IPFS与文件上传功能

现在,我们将IPFS集成到应用中,实现完整的文件上传流程。

首先,在应用中初始化IPFS客户端(这里使用Infura的公共网关):

const ipfs = new IPFS({ host: 'ipfs.infura.io', port: 5001, protocol: 'https' });

文件上传分为三个步骤,在 Main 组件中实现:

  1. 准备文件:通过 captureFile 函数,使用JavaScript的 FileReader API将用户选择的文件转换为Buffer格式,以便IPFS处理。
  2. 上传至IPFS:在表单提交时,调用IPFS客户端的 add 方法上传Buffer数据。成功后会返回一个唯一的文件内容哈希(CID)。
  3. 存储到区块链:获得IPFS哈希后,调用智能合约的 uploadFile 函数,将该哈希、文件大小、类型、名称和描述等信息发送到区块链上。这需要用户通过MetaMask确认并支付一笔极小的Gas费用。

// 步骤2和3的示例代码
const result = await this.state.ipfs.add(this.state.buffer);
const fileHash = result[0].hash;

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/42765643d30b926b61467dd8d1f5adec_102.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/42765643d30b926b61467dd8d1f5adec_104.png)

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/42765643d30b926b61467dd8d1f5adec_106.png)

this.setState({ loading: true });

![](https://github.com/OpenDocCN/sec-notes-zh/raw/master/docs/ucd-ecs189f-bc-arch/img/42765643d30b926b61467dd8d1f5adec_108.png)

// 调用智能合约
this.state.dstorage.methods.uploadFile(fileHash, fileSize, fileType, fileName, fileDescription).send({ from: this.state.account })
.on('transactionHash', (hash) => {
    this.setState({ loading: false });
});

文件列表展示与项目完成

最后一步是在前端页面上展示所有已上传的文件。

我们已经在 loadBlockchainData 中从合约获取了所有文件数据并存入 state。现在,在 Main 组件中,我们通过一个表格来遍历 this.props.files 并展示每个文件的详细信息,包括ID、名称、描述、类型、大小、上传时间、上传者以及一个可点击的IPFS哈希链接。

{this.props.files.map((file, key) => {
    return(
        <tr key={key}>
            <td>{file.fileId}</td>
            <td>{file.fileName}</td>
            <td>{file.fileDescription}</td>
            <td>{file.fileType}</td>
            <td>{file.fileSize}</td>
            <td>{file.uploadTime}</td>
            <td>{file.uploader}</td>
            <td><a href={`https://ipfs.infura.io/ipfs/${file.fileHash}`} target="_blank">{file.fileHash}</a></td>
        </tr>
    )
})}

至此,一个完整的去中心化文件存储应用就构建完成了。用户可以上传文件,文件被永久存储在IPFS网络上,而其存证则不可篡改地记录在以太坊区块链上。

总结

本节课中我们一起学习了如何构建一个基于Web3技术的去中心化Dropbox复刻版。我们涵盖了以下核心内容:

  • 使用 Solidity 编写智能合约,作为去中心化数据库。
  • 使用 Truffle 框架编译和部署合约到 Ganache 本地区块链。
  • 使用 React 构建前端用户界面。
  • 使用 Web3.js 库连接前端与以太坊区块链。
  • 使用 MetaMask 处理用户账户和交易签名。
  • 集成 IPFS 用于去中心化文件存储。
  • 实现了完整的文件上传、存储和列表展示流程。

通过这个项目,你掌握了构建一个完整DApp(去中心化应用)的核心技能组合。你可以在此基础上继续扩展功能,例如添加文件访问权限控制、付费下载或社交分享等特性。

005:比特币的核心原理 🧱

在本节课中,我们将要学习比特币的基本原理,包括其核心概念、交易结构、工作量证明机制以及如何验证交易。我们将从密码学基础开始,逐步深入到比特币如何解决双重支付问题。

概述

比特币是第一个成功实现去中心化、无需信任任何中央机构的加密货币。它的核心在于利用密码学和时间戳服务器(区块链)来创建一个公开、不可篡改的交易账本。本节课将解析比特币如何运作,以及其背后的关键设计思想。

密码学基础

在深入比特币之前,我们需要理解两个基础的密码学概念:哈希函数和公钥密码学。

哈希函数

哈希函数是一种单向函数,它将任意长度的输入数据映射为固定长度的输出(哈希值)。关键特性是:

  • 单向性:从哈希值几乎不可能反推出原始输入。
  • 抗碰撞性:很难找到两个不同的输入产生相同的哈希值。
  • 雪崩效应:输入的微小变化会导致输出哈希值的巨大差异。

比特币主要使用 SHA-256 哈希函数。以下是一个简单的Python示例,展示了输入微小变化如何导致完全不同的哈希输出:

import hashlib

# 原始字符串
original = "Hello Bitcoin"
print(hashlib.sha256(original.encode()).hexdigest())

# 添加一个空格
modified1 = "Hello  Bitcoin"
print(hashlib.sha256(modified1.encode()).hexdigest())

# 删除一个字母
modified2 = "Hell Bitcoin"
print(hashlib.sha256(modified2.encode()).hexdigest())

公钥密码学与数字签名

公钥密码学使用一对密钥:私钥公钥

  • 私钥:一个保密的巨大随机数,用于生成签名。
  • 公钥:由私钥通过特定算法(如椭圆曲线加密)派生而来,可以公开。
  • 核心特性:用私钥签名的信息,可以用对应的公钥验证,但无法从公钥推导出私钥。

在比特币中,数字签名主要用于签署交易,以证明你对某些比特币的所有权。签名本身通常由一对值(r, s)组成。

上一节我们介绍了支撑比特币的密码学基础,本节中我们来看看比特币本身是如何被定义和构成的。

比特币是什么?

根据其白皮书,比特币是一个点对点的电子现金系统。它并非第一个加密货币,但是第一个成功实现以下目标的:

  • 完全去中心化,不依赖任何中央权威机构(如中央银行)。
  • 使用密码学来控制和创建货币单位。
  • 解决了电子货币中的核心安全问题——双重支付

在比特币系统中,“硬币”并非物理实体,而是数字签名的信息链。每一枚“硬币”实际上代表一笔交易的输出,其价值可以是任意的(但有一个最小单位,即1聪,等于一亿分之一比特币)。

交易、区块与区块链

理解了比特币的基本定义后,我们来拆解其数据结构的三个核心组成部分。

交易

一笔交易(Transaction)就是一次所有权的转移。它包含:

  • 输入:引用你之前收到的、尚未花费的比特币(称为UTXO - 未花费交易输出)。
  • 输出:指定新的接收者地址和金额。
  • 签名:使用你的私钥对交易进行签名,以授权这笔支出。

关键规则:所有输出的总价值必须小于或等于所有输入的总价值。差额部分将作为交易费奖励给打包该交易的矿工。

区块

区块(Block)是一个交易容器。矿工大约每10分钟收集网络上的交易,将它们打包成一个区块。区块中还包含一些元数据,如时间戳、前一个区块的哈希等。

区块链

区块链(Blockchain)通过密码学哈希将区块按顺序链接起来。每个区块的头部都包含前一个区块的哈希值,形成一条链。这种结构使得篡改历史记录变得极其困难,因为要修改一个区块,就必须重新计算该区块之后所有区块的工作量证明。

工作量证明与挖矿

我们知道了交易被打包进区块,区块又链接成链。那么,谁有权创建新区块并将其添加到链上呢?这就是工作量证明机制要解决的问题。

工作量证明的原理

矿工通过解决一个计算密集型难题来竞争创建新区块的权利。这个难题是:找到一个随机数(Nonce),使得区块头数据的双重SHA-256哈希值满足特定条件(例如,哈希值的前若干位是0)。

这个过程可以表示为寻找一个 Nonce,使得:
SHA256(SHA256(BlockHeader)) < Target
其中 Target 是一个由网络难度决定的目标值。

挖矿过程

以下是计算区块哈希所需的主要字段:

  1. 版本号
  2. 前一个区块的哈希
  3. Merkle根(本区块所有交易的哈希树根)
  4. 时间戳
  5. 难度目标
  6. 随机数

矿工不断改变随机数(Nonce)并计算哈希,直到找到满足条件的解。第一个找到解的矿工将其区块广播到网络。其他节点验证该区块有效后,会将其接受为最长链(实为最重链,即累计工作量最大的链)的一部分,并开始基于这个新区块竞争下一个区块。

难度调整

网络大约每2016个区块(两周)调整一次难度目标,以确保平均出块时间保持在10分钟左右。如果全网算力增加,难度会相应提高,反之亦然。

上一节我们解释了矿工如何通过工作量证明获得记账权,本节中我们来看看网络如何利用这种机制达成共识并保证安全。

共识、安全与激励

比特币网络通过经济激励和密码学保证,使分散的节点能够就交易历史达成一致。

最长链共识

节点总是将累计工作量最大的区块链视为有效链。当出现临时分叉(两个矿工几乎同时找到有效区块)时,节点会在先收到的区块上继续工作。随着后续区块的添加,总有一条链会变得更长(更重),另一条就会被网络抛弃。这实质上是一种基于计算力的投票机制。

安全性分析

攻击者想要篡改交易(例如双重支付),需要“改写”历史。这意味着他需要从目标区块开始,重新计算所有后续区块的工作量证明,并且速度要快过诚实网络,才能使自己的链成为最长链。这需要掌握全网超过50% 的算力(51%攻击)。

重要限制:即使攻击者拥有超过50%的算力,他也只能:

  • 阻止新交易被确认。
  • 逆转他自己发出的交易(双重支付)。
  • 他无法盗取他人的比特币,因为他没有他人的私钥来签署交易。

经济激励

矿工维护网络的动力来自区块奖励交易费

  • 区块奖励:当前每个新区块奖励6.25个新比特币(约每4年减半一次,总量上限为2100万)。
  • 交易费:由交易发起者支付,鼓励矿工优先打包其交易。

这种设计将网络安全与矿工的经济利益绑定在一起。

交易验证与简化支付验证

对于不运行全节点的用户(如手机钱包),如何在不下载整个区块链的情况下验证一笔交易呢?这依赖于Merkle树简化支付验证

Merkle树

Merkle树是一种二叉树,其中:

  • 叶子节点:是区块中所有交易的哈希值。
  • 非叶子节点:是其两个子节点哈希值的哈希。
  • 根节点:称为Merkle根,被包含在区块头中。

任何对交易的修改都会导致其哈希值变化,并层层向上传递,最终改变Merkle根。因此,Merkle根可以唯一地代表该区块中的所有交易。

简化支付验证

SPV钱包只存储区块头(约80字节),而不存储完整的交易数据。要验证一笔交易是否被包含在某个区块中,它只需要:

  1. 获取该笔交易的哈希。
  2. 从全节点获取一个Merkle路径(即从该交易哈希到Merkle根路径上所需的所有兄弟节点哈希)。
  3. 利用这些哈希值重新计算Merkle根。
  4. 将计算结果与区块头中的Merkle根进行比较,如果匹配,则证明交易确实存在于该区块中。

这种方法使得轻量级客户端能够以极小的存储和带宽开销进行有效的交易验证。

总结

本节课中我们一起学习了比特币的核心原理。我们从密码学基础开始,了解了哈希函数和数字签名的作用。接着,我们探讨了比特币作为点对点电子现金系统的本质,以及其通过交易、区块和区块链组织数据的方式。

我们深入分析了工作量证明机制,这是比特币实现去中心化共识和安全性的基石,它通过计算竞赛来决定记账权并防止双重支付。我们还了解了网络的共识规则(遵循最长/最重链)和经济激励模型(区块奖励和交易费)。

最后,我们学习了如何使用Merkle树简化支付验证,使得用户无需运行全节点也能安全地验证交易。比特币的精妙设计在于它综合运用了密码学、博弈论和分布式系统理论,创造了一个无需信任第三方即可可靠运行的金融系统。

006:以太坊的工作原理

概述

在本节课中,我们将学习以太坊的工作原理。我们将从历史背景开始,了解以太坊在加密货币生态系统中的位置,然后深入探讨其核心概念,特别是智能合约。我们还将比较以太坊与比特币的异同,并分析以太坊的独特架构、优势以及当前面临的挑战。

历史背景与定位

上一节我们介绍了区块链的基本概念。本节中,我们来看看以太坊是如何诞生和发展的。

比特币在2008-2009年间由中本聪推出,证明了去中心化共识的可行性。随后几年,出现了大量“山寨币”,它们分叉比特币代码并尝试解决比特币的某些问题,如激励模型、中心化风险等。

2014年,以太坊由Vitalik Buterin等人创立。Buterin的想法是利用区块链技术构建去中心化应用。这些应用不依赖于单一服务提供商。他还认识到需要一个更强大的脚本语言。比特币的脚本语言Script功能有限,无法编写复杂应用。以太坊旨在提供一个功能更完备的平台。

以太坊的发展经历了一系列里程碑:

  • 前沿(Frontier)家园(Homestead):初始发布阶段,旨在确保网络稳定运行。
  • 拜占庭(Byzantium)君士坦丁堡(Constantinople):旨在解决可扩展性和安全性问题。
  • 宁静(Serenity / 以太坊 2.0):一次重大的协议升级,旨在提升网络的安全性和吞吐量。这些升级有时需要通过硬分叉来实现,即所有节点都必须更新协议。

与比特币的相似之处

如果你了解比特币的架构,会发现以太坊在某些方面与之相似。

  • 两者都使用由区块通过哈希值链接而成的链式结构。篡改一个区块会使之前的所有区块失效。
  • 两者都可能出现孤块,即同时提交两个有效区块,最终由更长的链胜出。
  • 两者都采用基于挖矿的激励模型,通过消耗计算能力来验证交易。
  • 两者都依赖节点来保存区块链副本,并负责验证和传播交易,以保持网络同步。

核心创新:智能合约

尽管有上述相似之处,但以太坊的“秘密武器”是智能合约

首先,我们理解传统合约。传统合约是至少两方之间的协议,通常需要一个可信的第三方(如银行)来认可和执行。如果合约被违反,会有相应的惩罚机制。但传统模型有一个明显缺陷:第三方可能被贿赂或本身不可信。

1990年代,学者尼克·萨博提出了智能合约的概念。它仍然是多方之间的协议,但执行者不再是可能被收买的人,而是由机器或计算机自动执行。他举的例子是自动售货机:投入硬币,自动获得商品,无需人工干预。

以太坊将这一概念与区块链技术结合,实现了由区块链技术执行的智能合约。关键在于图灵完备性的脚本语言,这使得在区块链上开发复杂应用成为可能。

以下是智能合约在以太坊中的工作原理:

  1. 编写与编译:开发者使用高级语言(如Solidity)编写合约代码,然后将其编译成以太坊虚拟机(EVM)可以理解的操作码
  2. 部署:编译后的代码会“搭载”在一笔交易中被发送到网络。节点能识别出这不是普通的转账交易,而是一个待执行的合约单元。
  3. 创建地址:该智能合约会被分配一个唯一的地址。通过这个地址,用户可以调用合约的功能或与其交互。
  4. 全网执行所有以太坊节点都会执行这份合约代码,而不是仅由部分节点执行。这确保了去中心化和一致性。

智能合约的用途广泛,例如:

  • 创建代表企业所有权的代币
  • 构建托管应用,在满足特定条件或多方签名后自动释放锁定的资金。

以太坊节点与EVM

上一节我们介绍了智能合约的概念。本节中,我们来看看运行这些合约的底层环境——以太坊节点和以太坊虚拟机。

以太坊节点不仅存储区块链副本,还能执行代码。每个节点都包含一个以太坊虚拟机

EVM是一个功能极简的虚拟机:

  • 它只有不到255个操作码(指令)。
  • 它是基于栈的计算机模型。
  • 它在沙盒环境中运行,与主机计算机隔离,以防止恶意合约攻击系统。
  • 它支持并发但不支持并行。所有节点同时执行相同的合约(并发),但无法将一个计算任务拆分给不同节点同时处理以加快速度(并行)。

关于程序长度限制和防止恶意攻击:以太坊通过 Gas 机制来解决。用户无法上传无限循环的程序来瘫痪网络,因为执行每一步操作都需要消耗Gas,而Gas需要购买。

Gas 与 Ether

这是一个关键概念。Ether 是以太坊的原生加密货币单位,就像比特币中的“BTC”。而 Gas计算工作的计量单位

  • 智能合约中的每一个操作(如加法、哈希计算)都有其对应的Gas成本。
  • 用户需要支付Ether来购买Gas,以支付合约执行所需的计算资源。
  • 网络内部处理Ether与Gas的兑换,用户不能在交易所直接交易Gas。

为什么要把计算单位(Gas)和货币单位(Ether)分开?主要是为了将效用与市场波动性分离。加密货币价格波动剧烈,如果应用性能直接受币价影响,会非常不稳定。Gas价格相对稳定,确保了网络计算能力不受币价短期波动的过大冲击。

一个常见的类比是:开车需要汽油(Gas),但你用钱(Ether)来购买汽油。

去中心化应用与DAO

智能合约可以相互调用和组合,从而构建出去中心化应用。DApp完全运行在以太坊区块链上,不依赖任何中心服务器。即使一半的网络节点失效,应用仍可继续运行。

DApp催生了一种新型组织:去中心化自治组织。DAO的组织规则被编码为智能合约。

  • 例如,管理者的薪酬支付可能取决于股东投票或特定业绩指标的达成。
  • 代币持有者可以通过投票决定公司的发展方向。
  • 资金被锁定在智能合约中,只有在完成预定工作后才会支付。

这减少了人为干预,降低了腐败的可能性。

以太坊的架构特点

了解了核心组件后,我们再来看看以太坊其他一些重要的架构特点。

  1. 动态区块大小:以太坊的区块大小不是固定的(比特币约为1MB)。它由区块内所有交易和数据的Gas总量上限决定(目前约为1000万Gas)。矿工可以集体投票调整每个区块的Gas上限,从而间接影响区块大小。这带来了更快的交易确认时间。
  2. 挖矿算法:目前采用工作量证明,但将很快转向权益证明。它使用的哈希算法是Ethash,这是一种内存密集型算法,旨在抵制专门为挖矿设计的ASIC芯片,促进去中心化。
  3. 难度炸弹:代码中内置了难度定期急剧上升的机制,以抑制挖矿权力的过度集中。
  4. 叔块奖励:在比特币中,同时产生的有效孤块被丢弃,矿工得不到奖励。在以太坊中,这些区块被称为叔块,开采它们的矿工可以获得部分奖励。这降低了矿工加入大型矿池的动机,有助于防止51%攻击。

挑战与局限性

尽管功能强大,以太坊也面临诸多挑战。

  1. 可扩展性三难困境:区块链难以同时完美实现去中心化安全性可扩展性。以太坊目前更侧重于前两者。
  2. 速度限制:以太坊并非为高性能计算设计。它支持高并发(容错性好),但不支持并行计算(拆分任务加速处理)。
  3. 不可升级性与状态爆炸:智能合约一旦部署就难以修改,发现漏洞后通常需要部署新合约并迁移用户。此外,随着DApp和交易的增长,区块链数据量已超过1TB,运行全节点的硬件要求越来越高,影响了去中心化程度。
  4. 预言机问题:这是智能合约的一个根本性限制。智能合约无法主动获取区块链外部的真实世界数据。例如,一个“如果明天下雨就付款”的合约,需要可靠的方式将天气数据输入链上,而这在去中心化、需验证的环境中非常困难。

DAO事件:一个关于不可变性的案例

2016年的“The DAO”事件是以太坊历史上的一次重大危机。一个众筹DAO的智能合约存在漏洞,被黑客盗取了大量ETH。社区面临两难选择:

  • 不进行分叉:遵守“代码即法律”和不可变性原则,但投资者蒙受损失。
  • 执行硬分叉:回滚交易,挽回损失,但这违背了区块链不可篡改的核心原则。

最终,以太坊社区执行了硬分叉,但一部分社区成员拒绝接受,继续维护原来的链,这就是以太坊经典。这一事件凸显了智能合约安全性的极端重要性,以及在实际操作中与“不可变性”原则妥协的复杂性。

未来展望:以太坊 2.0

最后,我们以积极的眼光看看以太坊的未来发展——以太坊 2.0。

  1. 权益证明:将从耗能的工作量证明完全转向权益证明。用户通过锁定一定数量的ETH成为验证者,负责验证交易。作恶将导致质押的ETH被罚没。这更加节能,但可能带来财富集中化的问题。
  2. 分片:这是解决可扩展性的关键方案。将主区块链拆分成多个分片链,交易被分配到不同的分片上并行处理,从而大幅提升网络吞吐量。
  3. 信标链:在分片架构中,需要一个协调层来管理验证者和确保各分片之间的通信与最终一致性,这就是信标链的角色。

总结

本节课中,我们一起学习了以太坊的工作原理。我们从其历史背景和与比特币的对比入手,深入探讨了其核心创新——智能合约,以及支撑它的EVM和Gas机制。我们了解了DApp和DAO如何构建在以太坊之上,并分析了其动态区块、叔块奖励等架构特点。同时,我们也正视了以太坊在可扩展性、速度、预言机问题等方面面临的挑战。最后,我们展望了以太坊 2.0 通过权益证明和分片等技术带来的未来可能性。以太坊作为一个活跃的开发平台,仍在不断演进,以平衡去中心化、安全与效率之间的关系。

007:Diem (原Libra) 核心原理 🧱

在本节课中,我们将学习由Dahlia Malki主讲的Diem(原Libra)支付网络的核心原理。我们将了解Diem如何作为一个受监管、分布式且基于区块链的平台,旨在创建一个简单、包容、高效的全球支付系统。

概述

Diem的使命是创建一个简单、包容、高效的支付平台,让全球任何拥有智能手机的人都能使用其支持的货币和金融服务。Diem支付网络本质上是一个基于区块链的系统,用于记录支付历史、追踪账户余额,并支持一系列单币种稳定币及其相关金融服务。

为了在全球范围内实现这一颠覆性目标,Diem需要获得用户、金融界和监管机构的信任。这主要通过三个支柱来实现:创建一个高效的日常交易媒介;建立坚实的技术和经济基础;以及构建一个能够持续发展、具有分布式和包容性治理能力的框架与组织。

区块链架构的演变与Diem的创新

上一节我们介绍了Diem的使命和信任支柱。本节中,我们来看看Diem在区块链演进历程中的独特定位。

传统的加密货币系统(如比特币、以太坊)通常从完全去中心化、无监管的基础设施起步,其价值创造机制依赖于网络参与者的挖矿或质押,主要作为价值存储而非交易媒介。这导致了流动性和波动性问题。随后,出现了在底层去中心化基础设施之上运作的Layer 2服务(如USDC、DAI),它们以中心化、受监管的方式发行稳定币,仅将底层链用于透明结算。

Diem则完全不同,其所有三个层面(基础设施、价值创造、金融服务)都设计为分布式且从一开始就寻求获得许可。整个系统由Diem协会及其成员分布式控制和运营,旨在成为一个获得许可的全球交易媒介和支付平台。

Diem平台技术概览

理解了Diem的定位后,我们深入其技术架构。以下是Diem平台及其组件的一个概览:

  • Diem区块链:位于最底层,是一个复制交易历史的机制。
  • Diem框架:位于区块链之上,是一组定义参与者如何与区块链交互、请求更改账本状态的规则。它由经过测试和审查的软件模块组成,使用专为金融资产安全处理而设计的Move语言编写。
  • 参与者与层级
    • Diem Networks:运营储备金,是链上唯一可以创建和销毁代币资源的实体,通过协会运营服务进行操作。
    • 指定交易商:通常是银行,负责与储备金进行法币与代币的兑换(铸造和销毁操作),为网络提供流动性。
    • 虚拟资产服务提供商:包括钱包和流动性提供商,它们从指定交易商处获取代币并为终端用户服务。
    • 终端消费者:位于支付网络边界之外,通过VASP间接访问网络。

Diem通过将法币资产“代币化”引入其框架,实现了即时终结、即时结算、透明和包容性,使得资金流动不再受传统银行系统边界的限制。

共识、治理与系统演进

Diem区块链采用基于许可的验证者集合,每个验证者都是经过严格筛选、能够提供高可靠服务的实体。这构成了一个拜占庭容错复制系统,具备零恢复时间的高可用性,并通过合同确保部署的地理和行政多样性,避免单点故障。

系统的治理和演进能力至关重要。Diem区块链是一个自我治理的系统,其创世区块包含了更改几乎所有方面的规则(如验证者集合、网络参数、软件模块)。系统演进通过“重新配置交易”实现,有两种路径:

  • 常规路径:像开源项目一样运作,通过Diem改进提案流程进行社区讨论和升级,需要三分之二验证者确认新软件版本后生效。
  • 紧急路径:针对安全或合规性紧急问题,由持牌的Diem Networks公司执行快速修复。

这种设计将决策权(协会和技术指导委员会)与安全执行权(验证者节点)分离,结合了联盟治理的效率和BFT共识的安全执行保障。

铸造与销毁机制

为了保证代币始终有足额法币支持,Diem设计了安全的铸造与销毁协议,遵循“付款交割”原则。

以下是铸造流程:

  1. 指定交易商向协会运营服务请求预铸造授权。
  2. 指定交易商进行法币转账。
  3. AOS监控并确认转账后,立即在链上执行铸造操作,并将代币发送给指定交易商。

以下是销毁(赎回)流程:

  1. 指定交易商向AOS发送赎回订单。
  2. AOS确认有足够法币可用于支付。
  3. 指定交易商将代币转移到链上仅由储备金控制的“预销毁”账户。
  4. 法币转账确认后,储备金权限将预销毁账户中的代币永久销毁。若法币转账失败,代币可被退回。

核心技术深度探讨:HotStuff共识与创新

Diem区块链的核心共识协议基于HotStuff。HotStuff的灵感来源于中本聪共识,它通过链式区块和需2f+1投票的法定人数证书来工作。等待连续三个这样的QC可以保证唯一性,避免分叉。该协议线性高效,且对异步网络安全。

在HotStuff基础上,Diem进一步引入了乐观高弹性BFT协议。通过让投票同时成为“强投票”(声明自某个区块后未对冲突区块投过票),系统可以合并多个QC中的投票,从而在实际攻击发生时,获得高于传统1/3故障容忍度的弹性(例如接近2/3)。这是一种根据实际攻击模式(主动腐败 vs. 良性崩溃)优化弹性边界的新思路。

系统性测试:Twins方法

测试拜占庭系统极具挑战。Diem团队提出了创新的“Twins”方法,用于系统化模拟拜占庭攻击。

其核心思想是:最有趣的攻击是内部攻击,即利用正确代码但通过微妙修改产生恶意行为。Twins方法通过为每个故障节点部署一对“双胞胎”实例来实现。它们共享相同的凭证和网络地址,但内部状态独立。这样,无需修改代码,仅通过配置就能系统化地产生诸如“双重提案”、“违背锁定规则”等复杂攻击行为。

Twins框架包含一个网络模拟器和场景生成器,可以自动生成并执行攻击场景。它已成功用于发现新协议漏洞、复现已知攻击,并对Diem自身系统进行加固验证。这为BFT协议测试开辟了新的系统化方向。

总结

本节课我们一起学习了Diem支付网络的核心原理。我们从其创建包容性全球支付平台的使命出发,探讨了它在区块链演进中的独特定位——一个从底层开始就寻求许可、分布式治理的体系。我们深入了解了其技术架构,包括基于HotStuff共识的许可区块链、安全的铸造销毁机制,以及支持系统演进的治理模型。最后,我们还探讨了Diem在共识协议优化(乐观高弹性BFT)和系统测试(Twins方法)方面的前沿技术贡献。Diem的设计展示了如何将区块链技术的优势与金融系统所需的合规、稳定和信任相结合。

008:去中心化金融入门 🚀

在本节课中,我们将学习去中心化金融的基本概念、核心应用及其与传统金融的区别。我们将通过具体的例子和工具,帮助初学者理解DeFi如何运作以及它为何重要。


大家好,欢迎来到今天的讲座。我们很荣幸邀请到Travis,也被称为DeFi Dad,他是Zapper的首席运营官。过去三年,他致力于揭开区块链领域的神秘面纱,特别是在金融应用方面。今天,他将带领我们深入了解去中心化金融的可能性与前景。

首先,Travis分享了他的背景。他最初学习化学,后来转向软件行业,并在2017年通过朋友了解到以太坊。他被以太坊结合公共政策、治理、经济学和货币理论的特点所吸引,并开始积极参与社区活动。现在,他在Zapper工作,这是一个用于可视化DeFi投资组合的工具。

什么是DeFi?🤔

DeFi,即去中心化金融,旨在将传统金融服务重建为点对点的自动化应用。它基于智能合约运行,无需中介机构,用户完全掌控自己的资产。

DeFi的核心特点

以下是DeFi的几个关键特征:

  • 无需许可:用户无需注册或提交身份信息即可使用。
  • 用户完全掌控资产:私钥由用户自己保管,资产完全由用户控制。
  • 基于智能合约:金融服务由代码自动执行,无需人工干预。
  • 透明可验证:所有交易和合约状态都记录在区块链上,公开可查。

DeFi与传统金融的区别 ⚖️

上一节我们介绍了DeFi的核心特点,本节中我们来看看它与传统金融(CeFi)的主要区别。

以下是两者之间的关键差异:

  • 所有权与控制权:CeFi服务由单一实体控制,可以决定用户准入;DeFi旨在实现社区所有,代码由社区维护。
  • 准入机制:CeFi通常需要注册和KYC;DeFi只需一个加密钱包即可连接,无需许可。
  • 资产托管:在CeFi中,用户需信任交易所托管资产;在DeFi中,用户自我托管资产,交易通过点对点互换完成。

DeFi的主要应用场景 💰

理解了DeFi是什么之后,我们来看看它的一些具体应用。这些应用重构了借贷、交易等传统金融服务。

1. 借贷平台

以Compound为例,用户可以在其中存入资产以赚取利息,或抵押资产借出其他资产。利率根据市场供需动态调整。

代码示例: 在Compound上存入DAI的基本交互是通过智能合约函数 supply(asset, amount) 完成的。

2. 去中心化交易所

Uniswap是一个典型的去中心化交易所,允许用户直接交易代币。它采用自动做市商模型,流动性由用户提供。

公式: 恒定乘积公式 x * y = k,其中x和y是流动性池中两种代币的数量,k是常数。

3. 稳定币与抵押借贷

MakerDAO允许用户抵押ETH等资产,生成去中心化稳定币DAI。这为用户提供了获取流动性的方式,同时保持对抵押资产的所有权。

面临的挑战与未来展望 🔮

尽管DeFi发展迅速,但它仍面临一些挑战,例如交易费用高昂、用户体验复杂以及与物理世界的连接问题。然而,其“数字优先”的理念和赋予用户金融自主权的潜力,预示着它可能在未来金融体系中扮演重要角色。

未来的研究方向可能包括:更高效的扩容方案、更安全的资产自托管方案以及去中心化的法币出入金渠道。


本节课中我们一起学习了去中心化金融的基本原理、核心应用及其与传统金融的对比。我们了解到,DeFi通过智能合约和区块链技术,正在构建一个更开放、透明和高效的金融生态系统。虽然仍处于早期阶段并面临挑战,但其发展潜力巨大。对于感兴趣的同学,可以从创建一个以太坊钱包(如MetaMask)和探索Zapper等仪表板工具开始实践。

009:融资、Gitcoin资助与区块链投资

概述

在本节课中,我们将学习区块链生态系统中的融资机制与投资视角。课程将涵盖开源软件的资助模式、Gitcoin平台及其二次方融资机制,以及风险投资机构如何评估和投资区块链项目。我们将探讨这些机制如何共同支持开发者生态,并推动去中心化应用的创新。


Gitcoin:为开源软件构建可持续商业模式

上一节我们介绍了区块链的基本架构,本节中我们来看看一个旨在支持开源软件和区块链开发者生态的具体平台——Gitcoin。

Gitcoin的使命是培育和维持开源软件的发展。开源软件是我们数字生态系统的基石,每年创造约5000亿美元的经济价值。Gitcoin致力于为开源软件开发者寻找可行的商业模式,目标是构建一个让每个人都有经济能力离开传统工作,全身心投入为开放互联网工作的世界。

自2017年成立以来,Gitcoin在过去24个月内已为开源软件提供了约800万美元的资助。其核心理念在于:信息互联网允许计算机在没有中介的情况下跨网络发送信息,从而颠覆了依赖信息的行业(如新闻、娱乐)。同理,金融互联网(区块链)允许在没有中介的情况下跨网络发送金融价值,这有望颠覆所有依赖金融价值的行业(如银行、投资、就业)。Gitcoin将自己视为“就业互联网”的先行者之一。


区块链的未来用例:超越DeFi

在了解了Gitcoin的使命后,我们自然会思考区块链技术除了当前的去中心化金融(DeFi)之外,还有哪些潜在的重大应用。

类比信息互联网的发展,雅虎采用图书馆卡片目录式的分类法,而谷歌则发明了搜索框,从根本上重新构想了信息的索引方式。区块链领域同样需要这种“第一性原理”思考:我们拥有区块链网络、智能合约、代币这些核心模块,如何以全新的方式组合它们,提供前所未有的价值?

一个令人兴奋的设计空间是“就业互联网”和社区工作。例如,Gitcoin运营的Kernel加速器正在探索一种模式:让同期学员的项目能够相互持有权益。这可以通过代币化实现,让每个人都能分享同期其他所有人项目的成功,从而从根本上改变团队间的激励与合作模式。这体现了区块链在协调和激励群体方面的新颖应用。


Gitcoin Grants与二次方融资机制

那么,Gitcoin具体通过什么机制来资助项目呢?以下将介绍其核心平台:Gitcoin Grants。

Gitcoin Grants是一个为区块链开源项目募资的平台,类似于加密世界的Patreon。项目可以在平台上发布并筹集资金。其独特之处在于每季度进行的“匹配资金”轮次,该机制运用了“二次方融资”公式。

二次方融资是一种数学上最优的民主化公共物品融资方式。其核心公式是:项目获得的匹配资金与贡献者数量的平方根之和的平方成正比,而不是与贡献总额成正比。

简单来说,一个拥有大量小额捐助者的项目,会比一个拥有少量大额捐助者的项目获得更多的匹配资金。这种机制将权力从大型资金方分散到边缘的广大社区,使资助决策更加民主化。对于基础设施类公共产品,贡献者的广泛性比捐款总额更能体现其价值。

在Gitcoin Grants上,一笔1 DAI的小额捐赠,通过匹配池的放大,可能产生高达90美元的影响。这种机制激励了更多人参与资助,是区块链技术催生的全新融资原语。


区块链投资视角:Polychain Capital的策略

看完了社区驱动的资助模式,我们再来看看传统风险投资在区块链领域的视角和策略。

Polychain Capital是一家多策略加密基金,投资范围覆盖整个生态系统:

  1. 对冲基金:交易比特币、以太坊等流动性加密货币。
  2. 风险投资:投资早期公司的股权和代币。
  3. 孵化器:从想法阶段帮助创始人孵化项目。
  4. 内部工程团队:参与网络质押(Staking)和治理,是许多权益证明(PoS)网络最大的质押运营方之一。

其投资理念的核心是:加密货币和智能合约能够实现传统技术无法做到的事情——在没有中心化中介的情况下转移价值并协调激励。他们更关注无需许可的区块链,因为代币经济模型能提供传统企业区块链所缺乏的参与和安全性激励。


重点投资领域与去中心化自治组织(DAO)

Polychain的投资主要集中于几个关键领域:

以下是其重点关注的赛道:

  • DeFi(去中心化金融):如借贷协议Compound、MakerDAO。
  • 交易基础设施与托管:如托管服务商Anchorage。
  • 前沿协议:如跨链网络Polkadot、存储网络Filecoin。
  • 隐私与密码学:如隐私网络Oasis。
  • 研究与开发工具:如DeFi风险建模平台Gauntlet。

其中,去中心化自治组织(DAO) 被认为是一个具有颠覆性的概念。DAO通过代币将网络的所有权赋予其用户和贡献者,而不是分离的公司股东。例如,在一个DAO化的“优步”中,司机会因为提供服务而实时获得网络代币奖励,其利益与网络的繁荣完全一致。这代表了“用户即所有者”的新型组织范式,与当前公司制截然不同。


无需许可区块链与代币激励的重要性

一个常被讨论的问题是:为何投资重心在无需许可的区块链,而非许可链(企业区块链)?

关键在于经济激励与网络安全的内在联系。在比特币或以太坊这样的网络中,矿工或质押者通过保护网络获得代币奖励。如果攻击网络,其持有的代币价值会受损,因此其经济利益与网络安全完全一致。这种经济约束使得篡改历史账本的成本极高。

相比之下,大多数许可链缺乏这种原生代币激励。参与节点没有足够的经济动力去投入资源保障网络安全,也难以形成去中心化的信任。因此,Polychain认为,将经济因素通过代币正确嵌入网络,是区块链技术发挥潜力的基础。企业区块链可能只是传统机构迈向这个新领域的过渡步骤。


总结

本节课我们一起学习了区块链生态中的关键融资与投资模式。

  1. 我们探讨了Gitcoin如何通过社区资助和二次方融资支持开源软件,这是一种基于区块链的新型民主化融资机制。
  2. 我们分析了风险投资机构如Polychain Capital的投资策略,他们专注于无需许可区块链,并看好DeFiDAO等能够利用代币经济创造新激励模式的领域。
  3. 我们理解了代币经济模型在协调激励、保障网络安全和推动创新方面的重要性,这是许多投资决策的核心依据。

这些机制共同构成了支撑区块链开发者生态和驱动技术前沿创新的金融基础设施。

010:稳定币与支付 💸

在本节课中,我们将要学习区块链领域中的两个核心主题:稳定币与支付。我们将探讨稳定币的不同类型、工作机制,并深入了解Celo网络如何利用其独特的架构和共识机制来构建一个面向移动端的、普惠的支付系统。

稳定币简介

上一节我们介绍了课程主题,本节中我们来看看什么是稳定币。从技术角度看,稳定币是一种加密货币,是一种设计在区块链上运行的数字货币。稳定币与其他加密货币的不同之处在于,其设计目的是为了最小化价格波动。对于比特币和以太坊等主流加密货币,价格波动是阻碍主流用户采用的最大摩擦之一。用户对价格的大幅波动感到不适。

稳定币为用户提供了一个在清算资产前暂时存放资金的场所,避免了直接兑换为法币可能产生的税务问题和高昂手续费。稳定币保持稳定的主要方式是将其价值与某种资产挂钩,目前最流行的挂钩资产是美元。

以下是几种稳定币的例子:

  • Tether (USDT):目前最流行的稳定币。
  • USD Coin (USDC):由Coinbase和Circle创建。
  • MakerDAO的DAI:最初最受欢迎的去中心化稳定币。
  • Celo Dollar (cUSD):我们将在后面详细讨论。

Tether与稳定币市场

在了解了稳定币的基本概念后,我们来看看一个具体的例子:Tether。Tether于2014年由Tether Limited公司创建。其核心理念是,每铸造1个USDT,Tether基金会(理论上)会在储备中持有1美元,以实现1:1的资产支持。

Tether在2014年发行时供应量很小,直到2017年随着比特币价格上涨,对稳定币的需求增加,它才真正流行起来。Tether的主要问题来自法律层面,例如关于其储备金是否充足的质疑,这暴露了由中心化实体持有法币储备的稳定币模型的潜在问题。

从交易量来看,稳定币市场自2017年起增长显著。根据Coin Metrics的报告,稳定币的总供应量已超过120亿美元,并且可能更高,这显示了稳定币市场的庞大规模。

稳定币的替代方案

上一节我们讨论了以法币为抵押的稳定币,本节中我们来看看其他替代方案。当我们谈论替代方案时,指的是那些试图使用法币支持其稳定币的1:1匹配模式,以及其他模型。

替代方案包括USDC、Gemini Dollar (GUSD) 和 MakerDAO。MakerDAO创造了第一个去中心化稳定币DAI,它最初不是由美元支持,而是由以太坊支持。用户可以将以太坊存入一个称为“抵押债仓”(CDP)的智能合约,并以此为基础借出DAI。它有一套复杂的机制来维持稳定,例如稳定费和清算机制。

Celo Dollar是去中心化稳定币的另一种变体,是Celo网络上的原生稳定币资产,同样与美元挂钩。我们将在后续讲座中详细讨论Celo。

市场压力下的稳定币表现

在介绍了不同类型的稳定币后,我们来看看它们在市场压力下的表现。2020年3月的事件非常有趣,当时新冠疫情、石油期货跌至负值等市场不确定性,导致一些稳定币出现了不稳定。

表现突出的例子包括Gemini USD,其价格一度跌至0.9美元左右,这是由于供应不足和流动性缺乏。DAI的价格则一度超过1.05美元,这是因为市场恐慌时,更多人想要清算他们的抵押头寸,加上网络拥堵和Gas费高昂,导致了DAI的短缺和价格上涨。MakerDAO事后对此现象进行了很多讨论,因为许多情况是之前未预料到的。

关于稳定币长期相关性的讨论

在深入Celo之前,有一个关于稳定币长期相关性的重要讨论。一个观点是,加密货币旨在取代我们现有的物理世界事物,例如不信任中心化机构。因此,投资于稳定币可能显得有些矛盾,因为稳定币似乎依赖于它试图取代的东西(如法币)。

然而,稳定币的目标可能并非取代美元。从理论上讲,稳定币允许人们接触到其本国可能面临高通胀风险的稳定货币之外的选择。例如,USDC正被发送给受通货膨胀严重影响的委内瑞拉人。稳定币的承诺在于为“无银行账户者”提供银行服务,在全球那些人们无法轻易开设银行账户或购买美元的地区,提供对稳定货币的访问权限。

此外,对于交易者而言,稳定币提供了一个在不清算为法币、不产生税费的情况下,在加密生态内持有稳定价值资产的场所。

Celo网络介绍

在讨论了稳定币的宏观背景后,我们现在将焦点转向Celo网络。Celo的使命是创建一个为繁荣创造条件货币体系。这里的“繁荣条件”是指让所有人,特别是那些受通货膨胀严重影响、无法开设美元账户或受到严格资金外流限制的人们,能够通过移动电话使用稳定币。

简而言之,Celo的产品Valora旨在创建一个“无需银行账户的Venmo”。Celo团队对这项使命的投入和 alignment 程度非常高。

Celo架构概述

上一节我们介绍了Celo的使命,本节中我们来看看其技术架构。Celo是第一个以移动端为先的区块链,采用权益证明(PoS)共识机制。

它是一个基于EVM(以太坊虚拟机)的网络,这意味着它可以运行Solidity或Vyper编写的智能合约。目前,EVM网络是智能合约的黄金标准。

从高层架构看:

  • 验证器:在PoS网络中,验证器负责打包交易、出块并获得奖励。
  • 全节点:保存网络副本,使客户端能够获取交易历史。
  • 客户端:在移动端,应用程序发起交易,交易被发送到网络,由验证器处理并最终上链。

基于地址的加密与身份证明

Celo架构的第一个创新是基于地址的加密。在讨论它之前,我们先了解基于身份的加密。在传统的非加密服务中,系统会利用你的电子邮件等身份标识进行加密,但这引入了执行加密的第三方。

Celo提出的基于地址的加密是对基于身份加密的修改。用户仍然生成公私钥对。但在创建公钥后,他们会将一个地址(如电话号码)与公钥的映射注册到一个智能合约中。这个智能合约运行在去中心化的区块链上。

然后进行身份证明:验证器会向请求证明的用户发送一条签名短信,用户再发送一条用自己的密钥签名的消息回智能合约。合约通过验证器和用户的签名来验证地址与公钥的映射关系。

这个过程可以防止攻击者通过伪造大量电话号码来映射公钥,因为需要验证器实际发送短信并由用户完成签名确认才能完成注册。

共识机制:IBFT

在了解了身份验证机制后,我们深入探讨Celo的共识机制。Celo使用一种名为IBFT(Istanbul Byzantine Fault Tolerance) 的拜占庭容错共识机制。

IBFT的基本流程如下:

  1. 新一轮开始:验证器以轮询方式随机被选为提议者
  2. 提议区块:提议者广播一个包含交易的区块提案,并发送 预准备 消息。
  3. 准备阶段:其他验证器检查提案有效性,然后广播 准备 消息。系统需要等待 2f + 1 条准备消息(f是可容忍的故障节点数,在Celo中约为33,因此需要至少67个验证器同意)。
  4. 提交阶段:收到足够的准备消息后,广播 提交 消息。同样需要等待 f + 1 条提交消息。
  5. 出块:收到足够的提交消息后,将区块插入区块链,然后进入新一轮。

验证器通过验证器组的形式组织,每个组最多可包含5个验证器,全网最多有100个验证器席位。这有助于防止巨鲸匿名控制大量验证器席位,因为需要以组为单位进行公开组织和竞选。

稳定协议概述

现在,我们专门探讨Celo的稳定协议。我们已经讨论了稳定币,稳定协议特指Celo的设计。在讨论Celo的做法之前,我们先回顾几种稳定币设计模型:

  1. 法币抵押型:如Tether、USDC。优点是最简单直接,相对稳定;缺点是依赖链下实体,可能牺牲速度和透明度。
  2. 加密货币抵押型:如MakerDAO的DAI。优点是更去中心化;缺点是抵押资产本身波动可能影响稳定性。
  3. 算法(Seigniorage)型:通过算法根据条件扩张或收缩稳定币供应量。它通常需要一种治理代币,该代币本身可能波动,其价值会随着稳定币系统的扩张而增长。

Celo Dollar机制从以上三种模型中汲取灵感。它依赖于 Celo储备金,该储备金持有一篮子加密货币,包括Celo治理代币、比特币、以太坊和DAI。储备金会定期重新平衡。

稳定比率定义为储备金价值与已发行稳定币价值的比率,目标为1。如果比率低于1,系统会通过提高转账手续费(部分归入储备金)、调整 epoch 奖励分配等机制来提高比率。

去中心化的1:1机制与套利

Celo采用一种去中心化的1:1机制,这是其法币抵押型的体现。用户可以通过链上去中心化交易所,将Celo治理代币发送到交易所,换取等值的Celo Dollar,反之亦然。

由于存在扩张和收缩周期,这为套利提供了明确的机会,从而帮助系统保持平衡。例如:

  • 假设cUSD价格跌至0.95美元。用户可以在市场上以0.95美元购买1个cUSD,然后通过储备金合约将其兑换成价值1美元的Celo治理代币(例如0.2个,假设每个价值5美元),最后在市场上卖出这些治理代币获得1美元,赚取0.05美元利润。
  • 反之,如果cUSD价格升至1.05美元,用户可以通过反向操作套利。

此外,Celo还采用了恒定乘积做市商模型来保护储备金,防止针对预言机的攻击。该模型只提供部分流动性,并通过动态调整价格来应对供需变化,避免因预言机被操纵而导致储备金被掏空。

移动端优先策略

Celo与其他区块链的关键区别在于其移动端优先的策略。我们已经讨论过的身份证明服务就是其他网络所没有的,它极大地改善了用户体验,用户无需再依赖复杂的公钥,可以像发短信一样发送资金。

选择移动端优先的原因包括:全球移动用户更多,智能手机在发展中地区更普及;从用户体验角度看,移动端比命令行更直观,降低了使用区块链的门槛;许多新兴市场已经习惯于通过移动设备进行支付。

Valora是Celo的移动钱包应用,旨在提供类似Venmo的体验,目前已在iOS和Google Play商店上线。

与其他网络的简单比较

我们简要地将Celo与其他网络进行比较:

  • Polkadot:采用分片(平行链)架构,有中继链协调不同链之间的通信。它使用GRANDPA共识,并且平行链插槽数量有限。Celo则是一个单一的EVM兼容链,不侧重于分片。
  • Cosmos:旨在通过统一的IBC协议连接独立的“枢纽”,实现不同区块链间的互操作。它是无许可的,没有验证器数量限制。Celo则是一个独立的、专注于移动支付和稳定币的网络。

案例研究:菲律宾与肯尼亚试点

Celo团队为了理解用户需求,特别是在新兴市场,进行了一些案例研究。

菲律宾试点:与23名低收入快餐店工人合作。主要洞察包括:慢速网络严重影响交易确认速度;过时的智能手机可能导致兼容性问题;用户为节省流量经常关闭移动数据;用户初期对移动支付信任度较低。这些洞察促使团队优化轻客户端,以实现快速同步。

肯尼亚试点:肯尼亚的M-Pesa移动支付服务普及率高达86%。洞察包括:产品必须切中用户实际需求(如汇款);用户倾向于用旧有概念理解新技术;口碑传播比机构推广更有效;用户更信任社区而非大型组织。这些信息为Valora的市场推广和用户获取策略提供了指导。

总结与问答

本节课中我们一起学习了稳定币的基本概念、不同类型及其工作机制,并深入探讨了Celo网络如何通过其独特的基于地址的加密、IBFT共识机制、复合型稳定协议以及移动端优先的策略,来构建一个普惠的全球支付系统。我们还通过案例研究看到了Celo在实际应用中的挑战和洞察。

(注:教程正文结束,后续为讲座结束语,已按指令省略。)

011:机制设计与去中心化治理

在本节课中,我们将要学习博弈论与机制设计,这是区块链技术中至关重要但常被忽视的核心组成部分。我们将探讨如何通过设计巧妙的规则来引导参与者行为,从而实现去中心化系统中的协作与治理。


什么是博弈论?🎲

上一节我们介绍了课程概述,本节中我们来看看什么是博弈论。博弈论是研究在策略性互动情境中,个体如何根据对其他参与者行为的预期来做出决策的学科。它关注的是人们的激励以及他们如何相互反应。

为了让大家直观理解,我们进行了一个名为“选美比赛”的小游戏。

以下是游戏规则:

  • 每个人选择一个0到20之间的整数。
  • 计算所有人所选数字的平均值。
  • 目标是猜测一个数字,使其最接近这个平均值的75%。

这个游戏的关键在于,你的猜测不仅基于数字本身,更基于你对其他参与者会如何猜测的预判。如果所有参与者都是完全理性的,他们会进行多轮推理:既然最高可能数字是15(20的75%),那么理性的人会猜测15的75%(约11),接着其他人会猜测11的75%……最终,完全理性的均衡点将是0或1

然而,在实际游戏中,答案往往不是0或1。这揭示了一个核心洞见:作为应用设计者,我们需要理解“聪明答案”(完全理性下的均衡解)与“正确答案”(实际发生的结果)之间的平衡。这就是博弈论与机制设计的起点。


从博弈论到机制设计 ⚙️

上一节我们通过游戏了解了博弈论,本节中我们来看看与之紧密相关的机制设计。如果说博弈论是分析给定规则下人们会如何行动,那么机制设计就是反向工程:为了达成某个期望的结果,我们应该设计怎样的规则或“机制”。

一个经典的例子是囚徒困境

以下是囚徒困境的收益矩阵:

囚徒A \ 囚徒B 保持沉默(合作) 背叛(揭发)
保持沉默(合作) 各判1年 A判3年,B获释
背叛(揭发) A获释,B判3年 各判2年

在这个情境中,警方的机制设计(隔离审讯并给出特定条件)导致了对每个囚徒个体而言的最优策略(背叛)却带来了对两人整体更差的结果(各判2年)。而外部力量(如黑帮)可以通过改变机制(例如,威胁背叛者的家人)来将博弈从“单次囚徒困境”转变为“重复囚徒困境”,从而促使合作(都保持沉默)成为稳定策略。

其背后的数学逻辑是:在重复博弈中,当前作弊的净现值收益,可能无法超过未来所有合作带来的净现值收益总和。机制设计的目标,就是如何将单次博弈转化为重复博弈,以鼓励协作。


区块链中的机制设计案例 🧩

理解了基本概念后,我们来看看在区块链世界中可以构建哪些具体的机制设计。

1. 子博弈精炼均衡:解决票务信任问题

第一个案例是关于建立信任,例如在线购买演唱会门票。买家担心先付钱却拿不到票或拿到假票,卖家担心先给票却收不到钱。

以下是解决此问题的智能合约机制步骤:

  1. 卖家将门票提交至智能合约,买家将付款提交至智能合约。
  2. 双方提交后,门票转移给买家。
  3. 买家可以选择接受门票(付款转给卖家,交易结束)或质疑门票真伪。
  4. 若买家选择质疑,则需额外支付门票价格的50%作为保证金。
  5. 随后卖家可以选择接受质疑(承认是假票,交易取消)或反驳质疑(声称是真票)。
  6. 若卖家反驳,则交由仲裁员判定。若仲裁判定为假票,卖家损失;若判定为真票,则质疑的买家不仅损失门票,还损失保证金。

通过设计这个包含额外成本和仲裁环节的机制,唯一让双方都满意的稳定结局就是:卖家提供真票,买家接受真票。这迫使理性参与者只会进行真实的交易。

2. 拍卖机制设计

拍卖是机制设计的经典领域。不同的拍卖机制会激励不同的行为。

以下是几种常见的拍卖类型:

  • 英式拍卖:价格公开上升,出价最高者以其最后出价获胜。
  • 荷式拍卖:价格公开下降,第一个接受当前价格的出价者获胜。
  • 密封第二价格拍卖:所有出价者秘密提交报价,出价最高者获胜,但只需支付第二高的报价。这有助于发现真实的支付意愿。
  • VCG拍卖:一种更复杂的机制,旨在最大化社会总效用,获胜者需支付其获胜对其他参与者造成的“边际损失”。

关键启示是:不存在放之四海而皆准的“最佳”机制。应用构建者的目标是理解特定场景中的利益相关者及其激励,然后设计最适合的机制来引导行为,实现从当前状态向更理想未来状态的过渡。


治理与投票机制设计 🗳️

机制设计在去中心化治理和投票领域有着激动人心的应用。

1. 二次方投票

传统“一人一票”无法体现偏好强度。二次方投票是一种允许个体表达偏好强度的集体决策机制。

其核心规则是:你可以投多票支持某个选项,但购买第 n 张选票的成本是 n^2(即1票成本1单位,2票成本4单位,3票成本9单位,以此类推)。

这种设计允许有强烈偏好的人表达意见,但通过成本的二次方增长,有效防止了财富最多的人完全主导投票结果,从而在考虑偏好强度的同时,平滑了贫富差距带来的影响。

2. GovernDAO:基于结果的捐赠

在政治捐款中存在囚徒困境:选民希望捐款给能解决问题的政客,政客希望专注于解决问题而非筹款,但双方因缺乏信任而陷入僵局。

GovernDAO 设计的机制叫做基于结果的捐赠

  1. 捐赠者的资金被锁定在智能合约托管账户中。
  2. 捐赠者设定明确的可衡量成果目标(例如“旧金山无家可归者减少2%”)。
  3. 只有当目标在约定时间内达成时,资金才会释放给政客,用于其下一次竞选。

这个机制改变了博弈的三要素:概率(通过托管和清晰条款明确资金释放条件)、收益(政客通过解决问题而非单纯筹款来获得资金)以及博弈次数(从单次交易变为基于持续成果的迭代互动)。它激励政客将更多时间用于解决问题,因为他们知道解决问题就能获得连任所需的资金。


去中心化自治组织:机制设计的集大成者 🏛️

DAO 是“去中心化自治组织”的缩写,它代表了组织形式的范式创新。DAO 利用区块链的可信中立性(规则不会单方面改变)和可组合性,旨在规模化人类协作。

DAO 的实践案例

  • MolochDAO:旨在资助以太坊公共基础设施开发。它引入了 Ragequit(愤怒退出) 机制:成员如果不同意某项资金提案,可以在执行前随时退出并取回自己的资金份额。这迫使提案必须符合集体利益,否则成员会离开,从而解决了公共物品融资中的“搭便车”问题。
  • MetaCartel DAO:专注于投资早期的以太坊应用项目,展示了DAO如何作为风险基金运作。
  • The LAO:一个合法成立的、基于区块链的营利性DAO,它拥有美国LLC结构,其法律文件指明“请参考区块链代码作为资产”,标志着DAO开始与实体法律框架融合。

DAO 的核心在于将股权代币化,并通过程序化激励吸引全球贡献者。它预示着未来可能出现由数百万人在线协作、没有传统公司结构的新型组织。


总结与核心启示 💡

本节课中我们一起学习了博弈论与机制设计在区块链中的核心作用。

我们首先通过“选美比赛”和“囚徒困境”理解了博弈论分析激励与行为的方式。接着,我们探讨了机制设计如何作为博弈论的反向工程,通过设计规则来引导系统达到期望的均衡,例如解决票务信任的智能合约和各类拍卖机制。

然后,我们深入研究了治理领域的机制设计,如二次方投票和基于结果的捐赠,它们展示了如何通过精巧的规则设计改善集体决策和政治激励。最后,我们以DAO作为机制设计的集大成者,看到了如何利用区块链的可信中性与可组合性,创建全新、规模化、全球协作的组织形态。

核心启示:区块链的革命性不仅在于分布式账本或不可篡改性,更在于它首次为大规模、无信任环境下的机制设计提供了可编程的土壤。作为开发者,我们的目标不应仅仅是“使用区块链”,而是深刻理解所要解决问题中的激励结构,然后利用区块链的特性设计机制,从而构建出促进协作、创造信任、指向更理想未来的下一代应用。这才是Web3.0+的真正内涵。

012:解决区块链三元悖论

概述

在本节课中,我们将学习区块链技术中的核心挑战——三元悖论,并深入探讨 Algorand 区块链如何通过其独特的“纯权益证明”共识机制,同时实现安全性、去中心化和可扩展性这三个目标。课程内容分为理论设计与技术实现两部分。


第一部分:区块链基础与三元悖论

区块链本质上是一个分布式、安全、高效的账本创建技术。可以将其想象成一个任何人都可以按顺序写入信息,但信息一旦写入就无法删除或篡改的公告板。这与传统中心化数据库形成对比,后者存在单点故障、访问受限和信任问题。

区块链提供了全局即时访问、低交易成本和极强的抗篡改性,这些特性在供应链管理等应用中至关重要。

然而,区块链设计面临一个核心挑战,即所谓的“三元悖论”。理想情况下,我们希望区块链同时具备:

  1. 安全性:交易一旦被确认,就无法被篡改或移除。
  2. 可扩展性:能够支持现实世界所需的高吞吐量交易。
  3. 去中心化:允许广泛的参与者参与共识过程。

传统观点认为,一个区块链系统最多只能同时实现这三个目标中的两个。


第二部分:共识机制的演进

上一节我们介绍了区块链的目标与挑战,本节中我们来看看为实现这些目标,共识机制是如何演进的。

以下是主要的共识机制类型及其特点:

  • 工作量证明:以比特币为代表。节点通过解决计算密集型难题来竞争记账权。其优点是安全性高,但缺点是能耗巨大、交易速度慢、成本高,并且可能存在分叉,缺乏最终性。
  • 权益证明:一种改进机制。节点记账的权利与其持有的代币数量(权益)相关。这降低了能耗,但通常涉及代币抵押和委托投票,可能影响去中心化程度。
  • 纯权益证明:这是 Algorand 采用的方法。它旨在结合前两者的优点,同时解决三元悖论。其目标是实现绿色节能、快速、低成本、具有最终性且真正去中心化。

第三部分:Algorand 的解决方案

了解了共识机制的背景后,本节我们将深入探讨 Algorand 如何具体实现其“纯权益证明”共识。

核心机制:可验证随机函数与秘密委员会

Algorand 共识的核心在于使用可验证随机函数 来秘密地选择区块提议者和共识委员会成员。

公式/概念

  • 可验证随机函数:一个密码学原语,允许持有私钥的节点独立生成一个随机数(作为“凭证”或“彩票”),并附带一个证明。其他任何人可以使用公钥验证该随机数确实是由该节点正确生成的,但无法预测其值。
  • 秘密选举:在每个区块轮次中,每个节点独立使用 VRF 判断自己是否“中签”成为区块提议者或委员会成员。由于选举是本地和秘密进行的,攻击者无法提前知道谁将被选中,从而无法进行针对性攻击。

共识流程:两阶段提交

Algorand 的区块生成并非提议后直接上链,而是包含一个确认阶段:

  1. 提议阶段:被秘密选中的提议者使用 VRF 生成凭证,并提议一个新区块。
  2. 拜占庭协议阶段:一个由 VRF 秘密选出的小型委员会运行一个快速的拜占庭共识协议,对该区块进行投票。委员会成员在每个步骤后“只发言一次”即被替换,这称为玩家可替换性,进一步增强了安全性。
  3. 最终确认:一旦委员会达成共识,该区块就被最终确认并添加到链上。这个过程几乎完全消除了分叉的可能性,实现了最终性

解决三元悖论

通过上述设计,Algorand 宣称同时实现了:

  • 安全性:基于密码学签名和秘密选举,攻击者难以篡改。
  • 可扩展性:VRF 计算极快,且共识仅在小型委员会内进行,支持高吞吐量(约每秒1000笔交易)和大量用户。
  • 去中心化:任何持有 ALGO 代币的人都可以参与,进入门槛低。

第四部分:Algorand 的技术特性与应用

在理解了核心共识机制后,我们来看看构建在其之上的技术特性和应用。Algorand 采用分层架构,每一层都增加功能而不损害底层的优势。

第一层特性

第一层功能直接内置于共识协议中,享有与基础交易相同的速度、安全性和低成本。

以下是第一层的主要功能:

  • Algorand 标准资产:允许任何人轻松创建自定义代币(类似 ERC-20/ERC-721),用于稳定币、奖励积分、证券化资产等。交易费用极低,且无需编写智能合约。
  • 原子传输:允许将最多16笔交易捆绑成一个组。要么组内所有交易都成功执行,要么全部失败。这解决了跨资产交易中的信任问题,例如无需中介的原子交换。
  • 无状态智能合约:一种简单的、基于堆栈的脚本语言(TEAL),用于批准或拒绝交易。它限制严格(无循环、计算量小),但因此非常安全、易于形式化验证,且执行成本与普通交易相同。结合 ASA 和原子传输,能实现复杂逻辑,如去中心化交易所限价单。

第二层智能合约

为了支持更复杂的应用,Algorand 引入了第二层智能合约。

核心思想:将复杂合约的执行移出主链共识流程。一个由 VRF 选出的专门委员会在链下执行合约。执行完成后,委员会对结果及其执行前提条件(如当时的区块链状态)进行签名,再将这个签名后的结果提交到主链。这样,复杂的合约计算不会阻塞主链的高速交易处理。

其他进展

  • 跨链互操作性:开发“紧凑证书”技术,以更简单、通用的密码学形式证明 Algorand 区块的有效性,便于其他区块链(如以太坊)验证,从而实现资产跨链转移。
  • 开发者生态:提供了全面的开发工具包、SDK、IDE插件、API服务和钱包等,以降低开发门槛。

总结

本节课我们一起学习了区块链的三元悖论挑战,并深入了解了 Algorand 区块链如何通过其创新的纯权益证明共识机制来应对这一挑战。我们探讨了其利用可验证随机函数进行秘密选举、通过小型委员会运行拜占庭协议以实现快速最终性的核心原理。此外,我们还了解了 Algorand 分层的技术架构,包括其低成本、高效的第一层功能(如标准资产、原子传输)以及为复杂应用设计的第二层智能合约。Algorand 的设计旨在不牺牲去中心化和安全性的前提下,提供可扩展、绿色且开发者友好的区块链平台。

013:波卡的权益证明经济学与分片技术

在本节课中,我们将要学习波卡(Polkadot)网络中权益证明(PoS)的经济学原理,特别是惩罚(Slashing)机制如何与分片技术结合,以构建一个安全且可扩展的区块链系统。我们将探讨为何在单链系统中惩罚机制可能并非必要,但在多链或分片环境中却至关重要。

引言:去中心化系统的假设

上一节我们介绍了区块链的基本目标。在构建去中心化系统时,我们通常需要做出一些假设。主要有两种类型:

  • 诚实性假设:我们假设系统中一定比例(例如超过三分之二)的参与者是诚实的,会遵循协议规则。
  • 理性假设:我们假设参与者是理性的,会追求自身利益最大化,并通过设计激励机制来引导他们的行为符合系统安全目标。

权益证明区块链的目标是论证:如果系统中大部分权益由理性且活跃的参与者持有,那么系统就是安全的。与工作量证明(PoW)只能奖励参与者不同,PoS系统还可以通过罚没参与者的质押权益来惩罚不当行为。

单链系统中的惩罚机制争议

本节中我们来看看在单一区块链中,惩罚机制面临的争议。一个基于拜占庭容错(BFT)的协议,只要诚实的参与者达到一定比例(如同步网络中超过一半,部分同步网络中超过三分之二),系统就能安全运行。

在这种情况下,惩罚机制可能面临一个困境:

  • 如果作恶者控制了足够多的节点(例如超过三分之一),他们可以合谋审查链上信息,即使诚实的参与者知道他们作恶,也无法成功提交惩罚报告,因为报告会被审查掉。
  • 如果作恶者没有控制足够多的节点,他们无法成功攻击系统,因此也不会被惩罚。

因此,有人认为在单链系统中,惩罚主要针对的是因技术故障导致的“无心之失”,而非恶意攻击者。这可能会打击参与者的积极性,因为他们需要承担因设备被黑等原因导致资金损失的风险。许多源自学术界的区块链协议(如Algorand、Avalanche、Cardano)在设计时只依赖诚实性假设,不采用惩罚机制。

分片与跨链带来的转变

然而,当我们从单链系统转向多链系统(无论是分片还是跨链互操作)时,情况发生了根本变化。关键在于:我们可以将一条链上的不当行为报告到另一条链上

这意味着,即使作恶者能审查某一条分片链,也无法阻止其他链(如中继链/主链)收到报告并执行惩罚。这正是Layer 2解决方案(如Plasma)和分片系统(如波卡、以太坊2.0)的核心思想:利用一个共同信任的主链来解决分片上的争议。

分片安全性的两种设计思路

以下是实现分片安全性的两种主要途径及其所需的验证者数量分析:

1. 仅依赖诚实性假设(每分片需多数诚实)

这种方法将全部验证者随机分配到各个分片,并假设每个分片内部都有足够多(如超过三分之二)的验证者是诚实的。根据概率计算,要保证在10年内,100个分片中任何一个被攻击的概率低于1%,整个系统需要的验证者总数约为 338 人。这是一个较大的数字,因为需要确保每个分片内部的诚实多数。

2. 结合诚实性与经济惩罚(仅需少数检查者)

这种方法利用主链进行争议解决。它不要求每个分片内部多数诚实,而是要求整个系统多数诚实,并引入一组随机选出的“批准检查者”来二次验证分片区块。如果检查者发现无效区块并报告,作恶的验证者将被罚没全部质押。

通过经济模型分析,如果我们希望攻击一个分片的期望成本高于系统中全部质押的总价值,那么每个分片所需的验证者(包括初始的“支持验证者”和随机的“批准检查者”)总数可以降低到约 14 人。这远低于第一种方法的要求,使得系统能够支持更多的分片。

波卡的分片协议设计

在波卡的具体协议中,结合了上述第二种思路,并解决了两个关键问题:数据可用性防止针对性攻击

  • 数据可用性:通过纠删码技术将分片区块数据编码并分发给众多验证者,确保即使原始提交者隐藏数据,网络也能恢复出完整区块。
  • 防止针对性攻击:使用可验证随机函数(VRF)随机、私密地选择批准检查者,使得攻击者无法提前知道将检查他们的是谁,从而无法进行针对性贿赂或腐蚀。

协议流程简述如下:

  1. 一组“支持验证者”对分片区块进行初始签名背书。
  2. 该区块的纠删码片段被分发,网络确认其数据可用性。
  3. 一组随机选出的“批准检查者”下载数据并验证区块有效性。
  4. 如果任何检查者报告无效,则争议升级,区块被回滚,作恶者被罚没。
  5. 只有当成批的分片区块都通过了检查,相应的中继链区块才会被最终确定(finalized)。

这种“乐观执行,延迟最终确定”的机制,使得在最终确定前发现并回滚无效交易成为可能,从而将成功攻击的期望成本提得很高。

对轻客户端与跨链桥的启示

本节我们来看看这种“质押+概率性检测”的思路对其他场景的启发。例如,构建连接波卡与以太坊等外部链的轻量级桥接时,在目标链(如以太坊)上完全验证源链的所有签名成本极高。

我们可以采用一种简化方案:

  1. 首先在源链上,足够多的验证者对一个已最终确定的区块头进行签名。
  2. 在目标链的智能合约中,我们并不提交所有签名,而是只提交一个声称“大多数验证者已签名”的声明,并附上少量随机挑选的签名作为样本证明。
  3. 目标链利用其自身的区块哈希作为随机源,随机抽查这些签名。如果作恶者试图伪造声明,随着抽查次数 M 的增加,其不被发现的概率按 2^{-M} 指数级下降。
  4. 通过结合对源链验证者诚实性的假设以及对目标链矿工/验证者操纵随机源的经济成本分析,可以论证这种桥接方案的安全性。

总结

本节课中我们一起学习了波卡权益证明经济学与分片技术的核心内容。主要结论是:对于单链系统,惩罚机制的作用可能有限;但在分片或多链互操作场景中,惩罚机制变得至关重要。通过结合整个系统的诚实性假设随机抽样检查以及严厉的经济惩罚(如罚没全部质押),可以构建出安全性更高、可扩展性更强的分片协议。波卡的方案正是通过这种方式,在理论上用更少的每分片验证者数量,实现了更高的安全保证,从而支持更多的并行链(分片)。这种“经济安全”与“密码学安全”相结合的设计思想,也为轻客户端和跨链通信提供了新的解决方案思路。

014:NEAR的核心原理-分片技术再探 🔗

在本节课中,我们将深入探讨区块链分片技术的核心原理与挑战,并以NEAR协议为例,分析其独特的分片架构设计。我们将从分片的基本概念入手,逐步解析其面临的安全问题、跨分片通信模型以及解决方案。

概述

区块链技术面临的核心挑战之一是可扩展性。传统的单链架构要求网络中的每个节点验证所有交易,这严重限制了系统的吞吐量。分片技术通过将网络状态和计算任务分割成多个并行的“分片”,旨在实现性能的线性扩展。然而,分片也引入了新的复杂性,例如跨分片通信、数据可用性和安全性问题。本节课程将系统性地剖析这些挑战,并介绍NEAR协议如何应对它们。

分片的基本架构

上一节我们介绍了分片旨在提升区块链吞吐量的目标,本节中我们来看看其典型的系统架构。

一个分片区块链通常由多个并行处理交易的分片链和一个负责协调的主链(或称信标链)组成。主链不处理常规交易,而是负责关键的系统级元数据管理,例如验证者选择、分片分配和区块头验证。

以下是分片架构的核心组成部分:

  • 分片链:每个分片链独立处理自己的交易和状态更新,类似于一个独立的区块链。
  • 主链(信标链):作为系统的“指挥中心”,负责验证分片区块头的有效性、管理验证者集合、并最终确定跨分片交易的状态。
  • 验证者:负责在分片上生产区块和验证交易。为了保障安全,验证者通常会被随机分配到不同的分片。

分片面临的核心挑战

了解了基本架构后,我们来看看分片技术必须解决的几个关键难题。

1. 安全性稀释与随机抽样

在非分片系统中,攻击者需要控制全网超过51%的算力或权益才能发动攻击。但在分片系统中,如果每个分片只有少量验证者,攻击单个分片所需的作恶验证者比例会大大降低,这被称为“安全性稀释”。

解决方案:通过在全网验证者池中为每个分片随机抽样选择验证者。假设全网有大量验证者,且恶意者只占少数,那么随机抽选出的小组中恶意者占多数的概率极低。这保证了每个分片区块都是由诚实多数签名的。这个过程依赖于安全的分布式随机数生成。

2. 无效状态转换

这是分片中最严重的攻击之一。攻击者控制一个分片后,可能在该分片上产生一个无效的状态转换(例如,凭空创造代币),然后将基于此无效状态的结果通过跨分片交易发送到其他分片。

公式描述

  • 有效交易:Alice.balance -= 10; Bob.balance += 10
  • 无效交易:Alice.balance -= 10; Bob.balance += 1000 (错误地增加了990)

在非分片链中,所有节点都会验证并拒绝无效交易。但在分片中,接收方分片可能无法直接验证发送方分片内部状态的正确性。

3. 跨分片异步通信

跨分片交易无法像单链交易那样原子性地执行。NEAR等协议采用异步通信模型

流程描述

  1. 交易在源分片(Shard 1)执行,更新发送方状态,并生成一个包含执行结果的“收据”。
  2. 该收据被发送到目标分片(Shard 2)。
  3. 目标分片在后续的区块中接收并执行该收据,更新接收方状态。

这种异步性带来了复杂性,例如,如果目标分片执行失败,需要设计回滚或补偿机制。

4. 数据可用性问题

恶意验证者可能产生一个有效的区块头并提交到主链,但扣留区块的实际数据(交易内容)。这样,其他诚实验证者无法获取数据来继续构建后续区块,导致网络停滞或用户被欺诈。

NEAR的解决方案与设计选择

面对上述挑战,不同的区块链项目提出了各自的解决方案。以下是NEAR采用的一些关键设计。

渔夫与挑战期

为了防范无效状态转换,NEAR引入了“渔夫”角色。渔夫是特殊的验证者,他们监控全部分片的状态。如果发现某个分片产生了无效的状态转换,他们可以在一个设定的挑战期内向主链提交包含密码学证明的挑战。

代码逻辑描述

if (渔夫检测到分片区块B存在无效状态转换) {
    向主链提交挑战证明;
}
if (挑战期内无有效挑战) {
    区块B被最终确认;
} else if (挑战被验证有效) {
    作恶验证者被罚没(Slash),区块B被回滚;
}

这创造了一种经济威慑:作恶的成本可能远高于收益。

纠删码确保数据可用性

为解决数据扣留攻击,NEAR使用纠删码技术。每个分片区块的数据被编码成许多片段,分发给该分片的各个验证者。只要收集到一定比例(例如1/3或1/2)的片段,就能重构出完整区块数据。

流程

  1. 区块生产者将区块数据通过纠删码编码成N个片段。
  2. 每个片段附带一个Merkle证明,证明它属于原始区块。
  3. 验证者存储并传播各自的片段。
  4. 如果某些验证者离线或作恶,其他节点仍然可以从足够的片段中恢复数据,确保网络持续运行。

NEAR的独特设计:分块而非分片链

与以太坊2.0等明确维护多条分片链的架构不同,NEAR采用了一种更集成的设计。NEAR没有独立的分片链,而是将每个分片的生产的“区块”称为。这些块直接嵌入到主链的区块中。

优势:这种设计简化了系统状态管理,减少了分片链自身可能产生的分叉、回滚等复杂问题,降低了工程实现的复杂度。

行业其他方案概览

除了NEAR,其他主流项目也提出了各自的分片或类分片方案:

  • Cosmos:采用“枢纽与分区”模型,各分区链高度自治,通过跨链通信协议(IBC)连接。安全性由各分区自行负责。
  • Polkadot:采用“中继链与平行链”模型,共享中继链提供的安全性。平行链通过插槽接入。
  • 以太坊2.0:采用信标链加分片链的架构,是目前最受关注的分片方案之一,正在逐步部署中。

从技术到生态:行为经济学与无限机器

最后,我们将视角从技术细节提升到生态系统层面。权益证明(PoS)区块链的安全基石不再是密码学算力,而是行为经济学模型。系统通过精心设计的经济激励和惩罚(如罚没)来预测并引导验证者的行为,使其诚实参与比作恶更有利可图。

这种经济模型催生了一种新的商业范式雏形——“无限机器”。基于PoS的DApp可以通过其收入自动重新质押网络原生代币,持续获取质押收益。这意味着即使一个应用的用户增长停滞,它也可能依靠质押收益长期维持运作,为开发者提供了前所未有的可持续性。

总结

本节课我们一起学习了区块链分片技术的核心原理。我们从分片的基本架构出发,深入分析了其面临的安全性稀释、无效状态转换、跨分片通信和数据可用性四大挑战。随后,我们以NEAR协议为例,探讨了通过随机抽样验证者、引入渔夫角色、采用纠删码以及独特的集成块设计等方案来应对这些挑战。最后,我们拓宽视野,认识到PoS分片区块链的安全本质是行为经济学,并展望了由此可能催生的新商业模式。分片是实现区块链大规模应用的关键路径之一,但其设计与实现充满了复杂性与权衡,仍需持续的研究与探索。


相关资源

  • NEAR 开发门户:near.dev
  • NEAR 代码仓库:github.com/nearprotocol
  • NEAR 社区聊天:near.chat

015:Hedera Hashgraph 核心原理 🧩

在本节课中,我们将学习Hedera Hashgraph平台的核心原理。Hedera Hashgraph是一个面向企业应用的第三代公共分布式账本,其独特之处在于采用了名为Hashgraph的共识算法,而非传统的区块链结构。我们将从平台概述、独特的治理模型,到深入探讨Hashgraph共识算法的工作原理,并了解其生态系统中的应用案例。

平台概述与企业定位 🏢

上一节我们介绍了课程主题,本节中我们来看看Hedera Hashgraph平台的总体定位和设计目标。

Hedera Hashgraph的目标是成为互联网的信任层。其核心使命是解决阻碍企业采用公共分布式账本的主要障碍。平台旨在系统性地解决性能、安全性、稳定性和治理四大问题,为企业提供一个稳定可靠、值得信赖的部署环境。

Hedera的技术栈建立在Hashgraph共识算法之上。与区块链不同,Hashgraph是一种有向无环图数据结构,它结合了八卦协议和虚拟投票机制。在此共识层之上,Hedera构建了多种网络服务。

以下是Hedera网络服务架构的核心组成部分:

  • 加密货币服务:原生加密货币HBAR,用于支付网络使用费用。
  • 共识服务:一种高效的数据记录服务,可作为其他分布式账本(如Hyperledger Fabric、R3 Corda)的排序或公证服务。
  • 代币服务:支持发行自定义代币(类似ERC-20标准),并与InterWork联盟的代币分类框架兼容。
  • 智能合约服务:支持EVM和Solidity,可运行智能合约。
  • 文件服务:提供分布式文件存储。

网络节点分为两种类型:负责运行共识算法和处理交易的主网节点,以及可存储全部或部分历史交易数据的镜像节点。这种设计实现了处理能力与存储需求的解耦,保障了高可扩展性。

Hedera自视为第三代公共分布式账本,致力于解决前两代(如比特币、以太坊)在可扩展性和企业适用性方面的挑战。其关键性能指标包括:单分片内每秒处理超过10,000笔交易、以美元计价的稳定手续费、以及2-4秒的交易最终确定性。

治理模型:Hedera治理委员会 👥

了解了平台的基本架构后,我们来看看Hedera如何通过其独特的治理模型确保网络的稳定与可信。

Hedera采用了一个由全球领先企业组成的治理委员会模型,这是其市场策略中最独特的部分之一。该委员会负责监督Hashgraph共识算法和所有网络服务。

以下是Hedera治理委员会的核心运作机制:

  • 成员构成:委员会由最多39家全球领先机构组成,这些机构需是其所在司法辖区的财富500强公司,覆盖至少11个不同行业,并包含至少一所大学和一个非营利组织。
  • 职责与运作:委员会成员必须运行一个共识节点,并通过参与不同的委员会(如产品路线图、财务经济、法规事务等)来共同决策。他们决定平台的功能添加、手续费定价、代币经济模型以及资金库的使用。
  • 任期限制:成员任期最长为三年,最多可连任两届。这确保了治理权的轮换,避免了权力长期集中。
  • 稳定性保障:Hedera拥有专利和知识产权保护来防止网络分叉,并通过技术控制确保所有节点同步升级,为企业用户提供了网络不会意外分裂的稳定性保证。

目前委员会成员包括谷歌、IBM、波音、德国电信、LG电子等知名机构。这种将平台控制权和所有权直接交给使用它的企业的模式,旨在建立企业级信任。

Hashgraph共识算法深度解析 ⚙️

现在,我们进入本节课的核心部分:Hashgraph共识算法。正是这一算法赋予了Hedera高性能和公平性。

Hashgraph共识算法包含两个核心概念:“八卦的八卦” 协议和虚拟投票。它并非区块链,而是一种基于DAG的共识机制,旨在实现高吞吐量、公平排序和快速最终性。

虚拟投票是一种算法,它能以拜占庭容错的方式,计算出网络中超大多数节点对交易时间戳的共识。传统的投票共识算法虽然稳健但速度慢,而Hashgraph的虚拟投票在保持拜占庭容错和DDoS抵抗力的同时,实现了高吞吐量和交易排序的公平性。

“八卦的八卦”协议是一种原子广播协议。节点不仅广播交易事件本身,还广播它们所知的、其他节点之间通信的历史(即元数据)。以下是其工作流程的简化说明:

  1. 事件传播:当一个节点(例如Alice)收到一笔交易,她会随机选择另一个节点(例如Dave),将她知道而对方不知道的所有事件(交易及元数据)发送过去。
  2. 指数级扩散:收到信息的节点(Dave)会继续随机选择其他节点(例如Bob)进行传播。同时,Alice也可能选择另一个节点(例如Gina)进行传播。这个过程以指数级速度在网络中扩散。
  3. 构建DAG:每次通信都会创建一个带有加密签名、时间戳和指向之前事件哈希的新事件。所有节点最终都会构建出一个结构相同、记录着“谁在何时收到了何种信息”的DAG。

由于网络延迟和随机选择,不同节点可能以不同顺序接收到多个并发交易。但这没有关系,因为DAG中包含了完整的传播历史信息。

当网络中超大多数(≥2/3 + 1)节点都知晓一个事件后,节点便可以基于本地存储的DAG运行虚拟投票协议。该协议通过分析DAG图,确定哪些事件是“著名的”,并计算出所有节点收到该事件的时间戳中位数。这个中位数时间戳即为该交易的共识时间戳

所有交易将按照共识时间戳的顺序被最终确定和排序。这种机制保证了,除非某个实体控制了超过三分之一的网络权重,否则很难操纵交易排序,从而实现了公平性。

最终,这个排好序的交易列表会被提交给上层的网络服务(如加密货币服务),来更新账本状态。Hashgraph算法本身只负责达成共识顺序,不处理具体的账本状态。

应用案例与生态系统 🌱

在深入理解了核心算法之后,本节我们来看看有哪些实际项目正在Hedera网络上构建。

Hedera生态系统虽然年轻,但发展迅速,已经在多个领域出现了引人注目的用例。目前主要聚焦于数据完整性、微支付和去中心化身份三大垂直领域。

以下是部分已上线或已宣布的典型应用案例:

  • AdsDax:一家广告技术公司,利用Hedera共识服务实时记录广告事件,用于第三方审计和打击广告欺诈,这是一个价值数十亿美元的市场问题。
  • The Coupon Bureau:一个由宝洁、沃尔玛等大型零售商支持的联盟,基于Hedera构建数字优惠券系统,解决优惠券欺诈问题。
  • Acoer:与Safe Health合作,在亚利桑那州立大学用于追踪COVID-19检测数据;同时与梅奥诊所、达美航空合作进行医疗报告追踪。
  • DLA Piper:全球领先的律师事务所,正在Hedera上构建证券型代币发行产品。
  • Hala Systems:利用Hedera技术构建警报系统,用于向叙利亚等地的人们预警空袭或冲突区。

这些案例展示了Hedera在高吞吐、低费用和快速最终性方面的优势如何满足企业级应用的需求。

开发者入门与资源 🛠️

最后,如果你对在Hedera上开发应用感兴趣,本节将为你提供起步指南。

Hedera为开发者提供了便捷的入门途径和丰富的资源。你可以轻松接入测试网,开始构建应用程序。

以下是开始构建所需的步骤和关键资源:

  1. 获取测试网账户:访问 portal.hedera.com,只需一分钟即可注册并获得测试网账户ID及公私钥对。
  2. 选择SDK:Hedera官方支持Java、JavaScript和Go的SDK,社区也提供了.NET、Rust等版本的支持。Python和Swift的官方支持正在开发中。
  3. 查阅文档与教程:访问 hedera.com/get-started,这里有详细的用例介绍、示例应用程序和教程。
  4. 加入社区:Hedera拥有一个活跃的Discord开发者社区,有数千名工程师在线,可以实时提问和获取帮助。
  5. 运行本地节点:所有Hashgraph共识算法代码和网络服务代码均已开源,你可以下载并在本地运行,观察共识过程。

总结 📝

本节课中我们一起学习了Hedera Hashgraph平台的核心原理。我们从其作为企业级信任层的定位开始,探讨了其独特的由全球企业理事会管理的治理模型,这是其稳定性和可信度的基石。随后,我们深入剖析了Hashgraph共识算法的核心——“八卦的八卦”协议和虚拟投票机制,理解了它如何实现高吞吐、公平排序和快速最终性,而不依赖于传统的区块链或工作量证明。我们还浏览了其生态系统中一些高调的应用案例,看到了该技术在广告、医疗、金融等领域的实际应用。最后,我们为有意向的开发者提供了入门路径和资源指引。Hedera Hashgraph以其独特的技术路径和治理结构,为分布式账本技术的企业级应用提供了一个值得关注的选择。

016:Radix的核心原理

概述

在本节课中,我们将学习Radix分布式账本技术的核心原理。我们将从创始人Dan Hughes的视角,了解Radix项目的发展历程、设计目标,并深入探讨构建一个无需许可、可扩展的区块链平台所需考虑的四个关键方面:数据模型、分片模型、共识机制和女巫攻击防护。课程将解释这些组件如何协同工作,最终实现一个安全、可扩展且支持复杂原子操作的平台。


项目背景与目标

大家好,欢迎来到区块链系列讲座。今天,我们很荣幸邀请到Radix的CTO兼创始人Dan Hughes。Dan在NFC移动支付领域有深厚的基础研究背景,近年来一直专注于区块链。他创立并开发了Radix项目,我们的实验室在过去一年左右也有幸与Radix团队合作。今天我们非常兴奋能请到Dan。

感谢教授的邀请。我原本希望这次演讲能更技术化一些,但Radix涉及众多领域和主题,将其纯粹技术化并归入单一主题并不合适,那样可能会让大家失去对Radix整体及其目标的背景理解。因此,我将从一个较高的层面,概述我们过去几年所做的工作、必须思考的问题,以及构建一个无需许可的区块链或分布式账本时需要考虑的关键事项。我们将探讨所有这些因素如何共同构成一个可扩展、安全、分片的共识平台。如果大家有任何问题,可以随时提问。

我的旅程和大多数人一样,始于比特币的发布。比特币最吸引我的一点是,有人成功地在无需许可的环境中解决了拜占庭将军问题,这在此前对我们计算机科学家和爱好者来说几乎是天方夜谭。之前从未有人真正接近解决这个问题,总是存在某种中心化元素或需要信任某个实体。

我是一名工程师,喜欢拆解事物、理解其工作原理、测试极限,并尝试改进或发现可以修复的低效之处。因此,在很久以前,我研究了比特币白皮书,获取源代码,进行拆解、测试,搭建网络,运行大量交易以观察会发生什么。

我发现或直觉上认为,随着时间的推移,比特币会在计算、存储、通信等方面遇到可扩展性问题;挖矿会逐渐中心化(当时还没有GPU加速卡用于工作量证明);并且由于网络中的经济、发行和激励机制,比特币将长期保持市场波动性。

在对比特币进行了几年的研究和多次“破坏性”测试后,我认为,如果比特币想成为一种全球货币,想要去中心化全球金融并成为一个价值网络,那么它首先需要能够扩展。其他问题或许可以容忍,但如果将70亿人接入当时的比特币(即使是现在的比特币),也会导致重大问题。这大致就是Radix在2013年的起点。

我首先思考的是如何扩展区块链,这自然引向了多链、区块树和有向无环图(DAG)的路径。这主要是改变数据层,允许多个计算共识实例运行,使得网络的不同部分可以在不同时间处理不同事务。此时它还不是传统意义上的分片,每个人仍然存储所有数据,但这种数据模型允许存在多个共识实例。不过,这种方法有很大的局限性,例如无法在你所在的分支之外进行交易等。尽管如此,它是通往下一个迭代——称为“Tempo”——的垫脚石。

Tempo是第一个真正的分片模型,有1024个分片。状态中的数据被明确地彼此分离,存在一种稀疏状态树,网络中的节点可以重建它,并从需要的地方获取状态树的片段,验证状态的有效性。该模型中的验证者很大程度上是无状态的,因此存在数据孤岛和验证者,数据孤岛向验证者提供所需的状态信息。

这个模型显示出了很大的潜力,但像零知识证明、用于从稀疏默克尔树证明状态的子弹证明、阈值签名等技术,在2015年时还远未成熟到可以实际应用的程度。

因此,我们进入了下一个迭代,称为Tempo。值得注意的是,每一次迭代虽然从某种意义上说是失败的,但都带来了很多学习经验,这些经验被传承下来。每次我们在规模化和效率方面都取得了显著进展。当我们到达Tempo时,我们有了更明确和改进的分片模型,更深入地理解了数据模型和分片模型需要如何交互。我们的共识机制是异步的,它使用逻辑时钟和状态承诺来确定事件发生的顺序以及网络中哪个事件获得了多数同意。

在2019年,通过这个迭代,我们实现了每秒超过100万笔交易,并在大约15分钟内重放了整个比特币历史(4.6亿笔交易)。我们以为Tempo已经成功了,但它存在一些边缘情况,涉及相当严重的安全性和活性问题。我们花了一些时间,可以解决这些问题。但真正缺失的是原子性

原子性在当前尤为重要,尤其是在各种DeFi产品中,它们都涉及跨合约交互,例如收益耕作,智能合约需要与其他地方的智能合约进行通信。

因此,我们带着从Tempo中学到的几乎所有经验,重新开始,最终得到了Cerberus。它为我们提供了可扩展性和所需的原子性,但其共识机制与Tempo有根本性的不同。

到目前为止有问题吗?大家都明白?很好。


Radix的设计目标与核心组件

Cerberus是我们过去七年左右所有先前迭代和研究的结晶。我们的目标是开发一个可扩展的网络,无论其形式是分片还是其他机制,是否无状态等。我们的延伸目标是让它比工作量证明更高效,同时提供类似的安全级别。

Cerberus比我们最初设定的目标走得更远一些。它允许我们拥有一些额外、理想且有趣的功能,例如复杂操作的可组合性和前面提到的原子性

这些功能很重要。以比特币为例,让它做其设计之外的事情非常困难。它的角色非常特定,本质上是转移价值。多年来提交了各种比特币改进提案,增加了新功能,但用它进行复杂操作仍然很困难。下一步是以太坊,它拥有图灵完备的虚拟机,开发者可以轻松组合复杂操作,但实际开发中仍然存在很多复杂性。

我们稍后也会讨论这些。在开发这项技术和Cerberus时,我们花了大量时间思考的主要有四到五个主题。

  1. 数据模型:如何组织账本上的数据?它是如何构建的?它是否需要是通用的,以便网络不关心正在处理的信息内容,只负责达成共识、确保安全,而数据内容由应用层处理?还是像比特币那样非常特定,只有交易,因此可以拥有更简单的数据模型?
  2. 分片模型:分片看起来如何?如何分片数据?如何分片状态?如何分配验证者来处理这些分片?是动态分片模型还是静态分片模型?这些都是需要考虑的不同问题和事项。
  3. 共识机制:显然,你需要某种共识机制,以便状态机副本能够就发生的事件达成一致,可以重放和验证,确保一切正常。
  4. 女巫攻击防护:或许中本聪用工作量证明和区块链解决的最困难的问题是女巫攻击防护。如何防止恶意行为者轻易控制网络?如何确保始终满足 2f+1 的保证?如何使其变得昂贵,无论是通过计算、经济还是其他声誉手段?比特币的天才之处在于,它能够使用工作量证明作为女巫攻击防护机制,同时也将其用作共识决策要素(例如,当存在多个链时,选择工作量最多的最长链),还将其用作货币分发的经济手段,一举三得,非常优雅。

由于本次演讲不会完全技术化,你可以在我们与Expo实验室合作的Cerberus共识论文中找到一些技术内容。他们帮助我们验证了我们的想法是否可行。教授和他的团队在这方面做了很多工作,我们非常感激。论文内容需要动点脑筋消化,但值得一读。此外,在 radixdlt.com 上,我们有很多内容,包括我将要讨论的一些内容的白皮书、关于Radix将采用的经济模型及其激励机制的经济学论文,以及关于Radix引擎(我们Radix技术栈的应用组件)的文档。


数据模型

首先从数据模型开始是合理的,因为一切都源于此。数据模型相当简单,这是件好事,但它非常适合分片。

如果我是客户端,想要向网络提交某个操作(例如交易)以供执行,我会创建一个称为 Atom 的原语。Atom是称为 Particle 的原语的集合。一个Particle携带状态信息以及对该状态执行操作的操作指令。

例如,假设你拥有10个比特币,并想花费给其他人。那么携带的状态就是你拥有10个比特币且尚未花费,操作指令是创建一个新的Particle,将这10个比特币转移给你要花费的对象。

Particle还可以携带消息并执行各种操作,包含状态、有效载荷和操作指令。Particle有一个 Spin,代表该Particle的生命周期。在上一个例子中,代表你持有的10个比特币的Particle将处于 Spin-up 状态。当你花费它并且Atom被执行时,该Particle将进入 Spin-down 状态。Spin-up 类似于构造函数,Spin-down 类似于析构函数。只有这两种明确的Spin状态。还有第三种隐式状态,基本上是中性状态,意味着Particle尚未被构造或销毁,它根本还不存在。

状态模型(或者说数据模型)深受比特币UTXO(未花费交易输出)模型的启发。它非常适合状态分片,因为你有这些输入和输出(或Spin-up和Spin-down),不需要跨分片跟踪余额,更容易让某个状态永久驻留在特定分片中,然后只在该分片内管理其生命周期。

这也意味着,如果你以确定性的方式映射你的Particle,它们将始终驻留在同一个分片。因此,给定关于Particle或某个状态的特定信息,网络中的任何人都将始终知道该特定状态片段的整个生命周期将驻留在哪个分片,从而在需要时很容易获取该状态。

为了更直观地展示,请看这个简单的示意图。绿色的Particle处于Spin-up状态,红色的处于Spin-down状态。你可以将这些想象成比特币,每个Particle代表一个比特币,这些比特币在网络中流转。从这个图中可以很容易地看到Particle如何从Spin-up状态转换到Spin-down状态,并且可能会创建新的Particle(因为接收资金的人获得了新状态)。在一系列Atom之后,所有状态的总和代表了这些Particle的总账本状态。

显然,有些操作中你不希望Particle进入Spin-down状态。例如,如果你有一条消息,你无法“花费”一条消息或将其置于任何Spin-down状态,它要么存在,要么不存在。同样,如果你在创建一种代币,那么定义该代币属性(流通量、发行曲线等)的Particle,你绝不希望它进入Spin-down状态,因为如果那样,可能会使所有已创建的这种代币失效。

关于智能合约如何融入这个模型?这正是我们整个Radix技术栈的众多组成部分之一,很难在一小时内涵盖所有内容。我们正在做的一件事是拥有一个称为 Radix引擎 的组件。Radix引擎是Particle的应用环境。我们当前的版本相当简单,包含一些预定义的组件,Particle可以调用它们来执行各种操作,例如消息、代币价值转移、代币定义、多重签名等。

我们正在开发Radix引擎的下一个迭代,使其更加灵活和通用,实际上允许你编写自己的状态机,Particle可以调用它来执行特定操作。例如,你可以部署一个特定的状态机,对具有特定参数或输入参数的Particle执行某些代码和功能。这样,你可以实现Particle和状态机的有趣组合,定义它们的执行顺序,完成所有这些可组合性操作。

这对开发者来说非常重要,因为目前很容易在Solidity等语言中犯错。我们更多地从另一个方向着手,提供类似乐高积木的预定义状态机,你可以将它们组合起来,满足开发者90%的需求。但如果你是硬核开发者,或者在构建去中心化应用方面进行真正的创新,你可以更深入,编写实际代码,定义状态机,然后将其作为Particle部署到网络上。

为了吸引开发者,我们还采用了这样一种模式:我可以为我提交到网络并被使用的任何Particle状态机定义收取版税。这有点像将你的依赖项货币化。我可以构建一个非常酷的东西,其他人可以利用其他可用的依赖项、Particle、内置组件以及所有这些不同的状态机定义,围绕它构建不同的应用程序,变得非常像拖放操作,在很大程度上几乎成为领域特定语言。如果你想深入底层,也可以做到。


分片模型

分片模型可能是迭代次数最多的部分。尝试创建一个能满足我们标准的模型,允许我们进行状态分片,以一种高效的方式进行,以补充数据模型和共识机制,同时还能处理所有女巫攻击防护问题,这确实花费了大量时间。

最终,我们确定了一个想法:我们应该有一个非常大的、稀疏的分片空间。如图所示,我们有一个 2^256 的分片空间,这是一个巨大的数字。选择固定分片空间的原因是,你可以在固定分片空间内执行这些有趣的确定性函数。如前所述,你有一个Particle,你知道它将始终驻留在哪个分片,你知道如何索引到该分片,你知道如何查找需要与谁交谈以获取该分片中的信息。

如果是动态分片空间,分片数量可能会增长或收缩,那么这些信息将不断变化,Particle和状态信息以及共识输出将随着分片空间的增长或收缩在不同分片之间转移,那么你就会遇到诸如如何针对不断变化的分片空间同步新副本、如果分片空间不断变化如何确定谁将服务哪些分片等问题。这些问题起初看似微不足道,但实际上变得非常复杂。

因此,仅仅拥有一个固定的、已知的、静态的分片空间(无论是 2^256 还是其他数字)是最好的,因为空的分片不占用任何空间、通信带宽或CPU。拥有一个非常大但稀疏的分片空间的一个优点是,当无状态验证技术进一步发展时,固定但稀疏的分片空间可以很好地映射到稀疏默克尔树等结构上,以及所有正在开发的利用数据集稀疏性来证明或证伪特定事物的各种零知识技术。

分片包含共识输出、任何状态信息、Particle生命周期内的任何参数和有效载荷。由于分片空间如此之大,两个Particle占据同一个分片的几率微乎其微。一个Particle及其分片(或者说一个分片负责一个Particle)使得你总能知道需要去哪个分片、需要与谁交谈以获取该分片的信息、确定该Particle的生命周期和状态等。映射函数相当简单,只是Atom和Particle哈希的函数,它们决定了该Particle及其生命周期内的后续信息驻留在哪里。

显然,在分片模型中,你需要验证者,需要一个机制来确定谁验证什么、他们在哪里、他们做多久、他们是否被轮换、如果验证者离开网络会发生什么、当他们加入时会发生什么。我们有一个全局的验证者集合,他们通过某种方式注册到网络。根据我们拥有的验证者数量、网络中看到的吞吐量、占用的分片数量等输入信息,我们将这些验证者放入集合中,并确定每个验证者集合负责哪些分片组。

例如,如果我们网络中有1000个可用验证者,并且我们想绝对最少维持每个集合10个验证者,那么我们最多可以有100个验证者集合。这100个验证者集合将大致负责整个分片空间。在这种情况下,分片空间将被分成100等份,一个验证者集合将负责百分之一的分片空间。

这里有一个 Epoch 的概念,目前是每天一次。在每个Epoch,我们会轮换验证者集合。原因有二:第一,我们不希望任何被攻破的验证者集合保持原状,因此在轮换时,我们会移出一部分验证者并用其他验证者替换,希望移除一些恶意验证者;第二,验证者可能会离开网络,如果你不轮换验证者集合并移除那些已知离开的验证者,那么之后可能会遇到活性问题。

为了能够管理验证者集合并将它们放在需要的位置,并在每个Epoch轮换它们,有一个 根分片 的概念,专门用于存储注册的验证者信息。稍后我们还会看到,该分片中还有一些与我们的女巫攻击防护模型相关的附加信息,这些信息决定了谁进入哪个验证者集合以及他们去哪里。但本质上,这个根分片每个人都有副本,它提供了所有验证者信息。从该根分片,对于任何给定的Epoch,你都可以确定性地计算谁在服务什么、验证者集合是什么样子、他们服务哪些分片组等。

因此,Particle和状态信息查找是高效的。当前Epoch的验证者集合充当了进入分片空间的映射。

我提到过未来某个时候转向无状态验证者。这样做的原因是,轮换验证者集合是有成本的。一些现有集合中的验证者将被移出到不同的集合,而该不同集合将服务不同的分片组,因此这些验证者将没有那些分片的信息。在每个Epoch,离开当前集合并移动到新集合的验证者需要与新集合中的验证者同步所有状态信息和Particle信息。这显然有成本,不仅对移动的验证者,也对特定集合中剩余的验证者,因为他们必须将信息传递给新加入者。因此,Epoch不能太短,否则网络将陷入无休止的验证者同步,消耗可用带宽、吞吐量和计算资源。

如果你有无状态验证,即有一种安全的方式向一组验证者提供状态,他们可以高效地验证并确信其正确性,那么他们就不需要同步状态,因为他们可以信任并验证提供给他们的任何状态。这样,你可以更自由地移动验证者,可以在不增加额外工作的情况下移除被攻破分片中的恶意部分,并且你的Epoch也可以更短。因此,如果有人想在受攻破的验证者集合内造成破坏或导致活性/安全性故障,其机会窗口也会更短。


共识机制

如果你读过Cerberus论文,你可能已经了解了大部分内容。对于那些还没读过或没时间读的人,简单来说,Cerberus有两个共识域:状态共识域账本共识域

状态共识是在验证者集合内运行的共识。这些验证者处理正在执行某个操作的特定Particle,他们查看该分片中存储该Particle所有信息的数据,并希望他们的共识机制就“该状态是否发生了此更改”达成一致或不同意。

如果你有一个包含多个Particle的Atom,那么你将涉及2、3、5、10个或任意数量的验证者集合,它们都将为各自负责的特定Particle进行状态共识。

账本共识发生在本地共识完成,并且他们就“是”或“否”达成了法定人数(例如准备提交、预提交等阶段)之后。此时,所有这些特定分片的验证者集合的领导者相互交叉通信他们的法定人数证书,以传递关于“应该发生什么”的“是”或“否”协议。

之后,所有验证者集合的领导者按顺序拥有当前阶段的所有法定人数证书。如果存在多数“是”,则他们进入下一阶段;如果没有,则不进入。这就是账本共识。具体来说,所有验证者集合必须在所有阶段获得 2f+1 个验证者的同意才能提交,但任何验证者集合在任何阶段获得 2f+1 个验证者的反对即可中止。

这意味着:如果我们有一个涉及三个分片的交易,那么为了将其提交到账本并让所有状态更改发生,你需要分片一、分片二、分片三都获得 2f+1 的“是”同意。但如果你有分片一和二分同意提交,而分片三说“不”,那么整个提交将在所有分片中止。无论你有多少个验证者集合,即使你有一个涉及100个分片的非常复杂的事件,只要这100个中有一个产生了 2f+1 的“否”法定人数证书,那么其他99个分片也不会提交。这对于原子性和DeFi及去中心化应用非常重要。

这些规则也帮助我们在女巫攻击防护方面做了很多工作。

Cerberus的另一个优点是,状态域共识实际上可以是任何东西。只要你在那里使用的任何东西都能产生符合Cerberus要求的法定人数证书,那么你可以让一些分片使用HotStuff,一些使用PBFT,一些使用Raft,甚至一些使用电话会议共识——只要你能产生法定人数证书。只要那些进行状态域共识的验证者集合能产生Cerberus可用的法定人数证书,你就可以让这些不同的共识机制在状态级别运行。如果你想放宽一些安全性和活性保证,采用概率性共识,通过一些工作,你甚至可以让一些验证者集合使用工作量证明类型的区块链混合体。

为了更直观地展示,请看这个示意图。它展示了偏向乐观的Cerberus协议的一个例子。这里有一些相当棘手的方面,比如内存池(待处理交易池)以及如何从中选择交易以获得响应性并维持低延迟网络。因为如果你有不同的验证者集合服务不同的分片组,那么处理Particle X的领导者从内存池中挑选特定内容并开始他的回合(例如预准备阶段)时,处理该Atom中Particle Y和Z的验证者可能正忙、可能有积压、可能负载很高,因此他们可能在一段时间内无法处理第一阶段,从而导致超时问题。如何处理超时?如何尽可能同步所有不同验证者集合的内存池,以确保如果出现负载或延迟问题,可以将其降至最低?这本身就是一个完整的主题领域。

这张幻灯片假设这些问题已解决。本质上,这里发生的是:分片X中Particle X的领导者启动了这个特定Atom的三阶段提交过程,该Atom涉及X、Y、Z分片中的Particle。他进行准备阶段,添加一些信息,包含一个先前的法定人数证书(这是必需的),增加视图编号,进行所有必要的内务处理,然后广播给集合中的验证者。

然后他等待这些验证者的响应一段时间。如果没收到,则超时;如果收到足够响应以形成法定人数,则一切顺利,可以继续;如果没有足够响应形成法定人数,则失败,客户端被告知此操作无效。在这个特定协议中,分片Y和Z中的验证者甚至不知道发生了什么,因为在这里就短路了。

如果确实有足够的验证者同意形成分片法定人数,那么该法定人数证书会广播给分片Y和Z的领导者。他们做同样的事情:进行准备,包含他们正在处理的上一轮的任何先前法定人数证书,包含Atom、Particle等信息,打包准备消息,发送给其验证者集合中的验证者,等待响应。

他们是否有法定人数?如果有,则将该法定人数证书通信给分片中的领导者。他们收到这些证书后,这就是Cerberus发挥作用的地方。Cerberus验证这些法定人数证书,检查我们是否在所有分片上有足够的法定人数以继续。如果不能,则失败;如果可以,则进入下一阶段。

所有这些特定分片中的领导者然后进行预提交,他们包含先前的法定人数证书(将是上一轮的准备),广播给验证者,等待响应,查看是否有状态法定人数,如果有,则将其传播给分片中的其他领导者。他们等待来自其他分片的法定人数证书,接收它们,检查是否所有验证者集合都有账本法定人数,是则继续,否则失败。

失败情况显然可能有多种:超时、分片被攻破(其中对手拥有三分之一的投票权,他告诉集合中的一组验证者“是”,另一组“否”),通信问题等。

我们使用HotStuff的另一个原因是,如果领导者失败或被怀疑是恶意的,进行视图变更非常容易简单,后续领导者可以很容易地接替该领导者离开的地方(如果他们确实提交了一些有效阶段并将其提交到账本)。例如,如果此处的领导者在预提交阶段失败且没有恢复,其他分片完成了这一轮并提交了。最终,Particle X的验证者集合中的其他验证者会得知:“我们已经做了这件事,正在等你。你还没有给我们你的提交决定。”这里可以快速进行领导者选举和视图变更,从离开的地方继续,进行一些状态级共识,然后可以向等待的分片报告结果。

所以,澄清一下,就像Cerberus一样,在分片内部,你仍然在使用PBFT(或类似机制),而Cerberus是为跨分片交换而实现的。是的,基本上是这样。Cerberus是你的跨分片协议。各个验证者集合进行实际分片级共识(可能是PBFT、HotStuff或其他)有一些要求。为了使两者协同工作,有一个规范,规定了特定分片使用特定本地共识机制的验证者必须产生什么、以什么格式、符合什么规范,然后才能通过Cerberus协议传递给其他分片的领导者,并共同决定:“我们是否就此达成账本级共识?”


女巫攻击防护

我假设这里的每个人都了解女巫攻击及其含义,以及缓解女巫身份和攻击的各种技术。但对于那些不了解的人,简单来说,女巫攻击是一种创建许多无法相互关联的身份的方法,目的是压倒或影响或控制某些资源、协议或过程。

在现实生活中,我们可能会遇到女巫攻击,例如,如果我能够为自己创建许多身份,我可以在选举中多次投票,或者我可以获得多个银行账户和多个贷款,享受仅限新客户的优惠利率,但我扮演了100个新客户。

对于工作量证明,产生那个前面有一定数量零的哈希值(你通过暴力计算找到的)是最流行的女巫攻击防护形式。因为我必须花费计算能力、电力来找到一个具有特定难度的哈希,我不能轻易创造更多的计算能力或电力,这需要我花钱(电力成本、设备成本、设备磨损成本)。而且,至少在比特币中,这是竞争性的,因此进入门槛永远越来越高。

权益证明则有所不同。权益证明使用网络的原生代币本身作为提供女巫攻击防护的手段。原因在于代币具有价值。例如,如果比特币是权益证明网络,那么每个比特币目前价值16,000美元。对于我来说,要获得我想用作网络中权益的比特币,每个将花费我16,000美元。

有趣的是,权益证明代币也用于购买东西、投机、在整个经济中作为购买力。它有多种用途。因此,它不仅用于安全,也有一定的效用。如果你分析权益证明网络,通常会发现有3%到5%的流通货币被用作权益证明。

因此,如果你想压倒一个权益证明网络(例如最终将转向权益证明的以太坊2.0),你需要购买或拥有大约1.5%的所有以太坊流通供应量。在经济方面,这开始变得有趣。在公开市场上,通常也有大约3%到5%的流通货币。因此,如果我需要购买1.5%的所有流通货币来压倒以太坊2.0,而公开市场上只有3%的流通货币可用,那么我购买这1.5%的行为将推高该代币的价值。

所以,当我试图购买更多权益来攻击网络时,我想购买的每个以太坊的成本会越来越高,因为我通过购买行为推高了以太坊的价值。因此,这开始变得相当昂贵和复杂,有很多变数,因为你不仅要对抗网络中的诚实参与者,还要对抗市场,因为我买得越多,价值就上涨得越快。这实际上激励了人们在价值快速上涨时不出售。我试图购买更多权益来压倒网络的次要后果是,市场上实际可用的权益反而更少,因为此时市场中的理性参与者会持有而不出售。

当然,我可以更隐蔽地进行,我可以慢慢积累。但那是非常长线的玩法,大多数51%攻击或双花攻击或对网络的尝试通常持续时间较短,因为展望那么远的未来(市场会如何、网络拓扑结构如何、验证者集合有哪些、有多少验证者、验证者集合在哪里、网络是否增长所以我被放入特定集合的机会更小)并不常见。长线攻击通常不是理性对手的行动方案。当然,如果我不关心双花,只想破坏网络,那么我可以慢慢积累,然后在后期释放,但这通常是你无法过多防御的,就像你无法真正防御自私挖矿和长线工作量证明攻击一样。

关于权益证明还有很多边缘情况需要考虑,尤其是在区块链中,例如 无利害关系问题。这是以太坊必须努力解决的问题之一,因为他们的分片实现方式以及他们的数据模型(基于余额而非UTXO)等工作方式。

无利害关系问题是指存在链的分叉。我可能会在两条链上都下注,创建区块。问题在于,在权益证明中,因为我的权益是有效的,并且在我质押权益的点之后存在分叉,那么我在所有这些分叉上都有多个我的权益副本,它们彼此同样有效,因此我可以在所有这些不同的分叉上挖矿、生产区块、验证。这没有成本,所以这就是权益证明网络中惩罚条件等发挥作用的地方。在工作量证明中,我不能那样做,如果我想在不同的链上挖矿,我必须将我的哈希算力分散到我可能感兴趣的所有链上。

无利害关系问题只是众多问题之一,还有惩罚条件可能是主观而非客观等问题。我强烈建议任何对区块链上的权益证明女巫攻击防护感兴趣的人去阅读以太坊关于Casper等的所有资料。

在我们的模型和Cerberus中,幸运的是,我们不必担心其中一些边缘情况,但我们仍然需要考虑一些。首先,我将深入探讨当你有验证者集合时权益是如何使用的,以及这意味着我们需要处理的一些边缘情况。

在此之前,网络中的验证者,其一票代表价值“1”。在基于权益证明的Cerberus网络中,验证者的投票权重由其控制的权益数量决定。因此,如果我有一个拥有100个Radix代币的验证者,另一个有10个,那么这些验证者拥有的投票权是不同的。一个是100,一个是10。

如果这两个验证者自己在一个分片组中,那么拥有100的验证者基本上控制每一票。而拥有10的验证者并不是真正需要的,因为他只能与拥有100的验证者一起投票,因为如果他自己投票,他没有该分片和验证者集合中总权益的 2f+1(因为在这个模型中,f 代表故障权益的数量)。如果总权益是110,那么他只有不到10%的权益。

因此,f 代表故障权益的数量。验证者及其投票由其控制的权益数量加权。如果你错误地生成了验证者集合,那么你可能自然就会得到一个拥有大量权益的特定验证者,他可以控制那个验证者集合,即使他不是恶意或敌对的,你也不希望这样。

因此,我们必须解决的更困难的事情之一是如何在每个Epoch生成验证者集合。它们需要负载均衡,以避免出现一个验证者有100权益而其他人都只有1权益的情况。显然,你希望这样做,因为你既不希望那个特定验证者控制验证者集合,也不希望如果他碰巧离线、崩溃或因任何原因出现故障而从该集合中消失时,导致该验证者集合想要验证的任何事物出现活性问题。

我们目前正在研究解决这个特定问题的方法,你们中的一些人也在与教授一起研究。我们目前正在研究的解决方案是组合优化。我相信你们许多人都听说过背包问题、旅行商问题等。这是我们用来负载均衡验证者集合的方法之一,以确保我们没有在验证者集合中拥有不成比例的投票权。

我们不能使用简单的规则,比如“将所有拥有10个Radix权益的验证者放入同一个集合”,因为那样的话,我作为对手,只需创建一堆拥有10个Radix权益的验证者,那么它们很可能最终都在同一个验证者集合中,我就可以控制那个集合。显然,我们也不希望对手能够控制他们的验证者去向。

因此,这些验证者集合的生成以及谁去哪里,最初是由任何权益活动、任何新验证者注册、我在几页前提到的根分片中验证者配置的任何更改来“播种”的。这样,如果我试图使用蛮力计算能力来计算“网络将选择哪种对我最有利的验证者集合配置,能将我的验证者放在这个特定位置”,那么如果我尝试去调整下一个Epoch将使用的输入以产生我期望的输出,我对该输入的调整(我的更改、我移动权益的位置、我移动我控制的验证者的位置)将产生不同的输出,因为我改变了输入。所以这也是一个棘手的领域,我们一直在研究如何让所有这些事情融合在一起,那里还有很多其他边缘情况。

例如,如果我有一个验证者集合,其中少数验证者拥有大量权益,并且我引入许多其他验证者来尝试负载均衡,那么我不希望该验证者集合变得太大,因为那样会有内部通信复杂性问题,并且我可能实际上没有足够的验证者来组成我需要的其他验证者集合。

关于女巫攻击防护就讲这么多,这更像是一次头脑倾倒,而不是一次有建设性的演讲,但希望它对某些人有一定意义。


原子性与用户体验

今天我想讨论的最后一件事是DeFi用户体验和原子性。原子性或许是我们从Tempo转向的主要原因,因为我们当时没有这个特性。它之所以重要,是因为分布式应用、DeFi产品正变得越来越复杂,开始对许多其他事物有很多依赖。

例如,如果我使用一个Uniswap资金池,我有一些以太坊,想兑换一些美元,可能某个地方有一个预言机提供价格信息到那个池子,然后一旦我完成,在另一个地方的另一个池子有一个套利机会,然后那又反馈到某个交易所。如今的产品和应用程序都在进行这些与所有不同移动部分之间的复杂交互。

因此,能够进行原子性的跨分片提交不仅仅是锦上添花,对于这些复杂的DeFi和分布式应用来说,它是必须具备的。因为它能带来更好的用户体验和开发者体验。如果开发者必须串行操作,先提交这个,再提交那个,然后在这里做这个,在那里做那个,那么每个提交、转换、检查是否成功、在哪个区块、是否发生等,都会带来很多复杂性。如果失败怎么办?如何回滚?如何进入下一阶段?然后我在这里做什么?这变得非常非常复杂。显然,如果复杂,就可能安全性较低,因为人类编写这些代码时难免出错。

从长远宏观来看,原子性的跨分片提交对网络也更高效,因为你不需要处理“出错时该怎么办”、“执行这组功能需要多少步骤”、“我将在网络上调用多少次写或读操作”等复杂性。

为了突出其中一些问题,我准备了一个简单的例子:一个非原子性的假期预订,然后在下一张幻灯片上有一个原子性的版本。

假设我有一个应用程序,可以一站式满足我所有的假期需求:预订航班、预订酒店、租车、预订一些短途旅行等。在应用程序中,我可以列出所有这些事项,然后点击“开始”。在幕后,应用程序根据我的要求选择航班、预订酒店、租车等。

非原子性的情况下,你依次在分片一预订航班(提交),在分片二预订酒店(提交),在分片三租车(提交)。但如果租车时没有你想要时间的车可用,提交失败,而你已经预订了酒店和航班,也许你不在乎车,但酒店和航班已经订好了。如果酒店和车都不可用,但你已经订了航班,也许你不想去那个假期了,因为去不了想去的酒店,没有车,也不能做想做的吉普车之旅。那么应用程序必须以某种方式撤销之前的操作,否则你会留下不想要的机票。它可能需要向网络发出另一个指令说“撤销上一个操作”,但撤销可能失败,或者可能无法在账本上取消航班,你必须打电话给航空公司。那么我应该先执行哪个操作?哪个最重要?酒店最重要?航班最重要?租车最重要?如果失败,我最愿意被哪个困住?

从开发者的角度来看,实现这个功能、处理失败情况非常复杂。从用户的角度来看,体验不好,因为这需要一段时间,如果任何环节失败,可能会给我带来麻烦。因为已经订了航班,去不了那个酒店,我得打电话尝试取消,这不是良好的用户体验。

而在原子性的情况下,你可以在同一个状态转换(同一个Atom)中发出预订航班、预订酒店、租车的指令。所有这些不同的操作将在各自的分片中进行状态级共识。如果任何一个失败,那么它们都会失败(因为顶层的Cerberus协议)。要么全部通过,要么一个都不通过。没有需要清理的东西,开发者不需要处理回滚逻辑,用户不需要因为其他环节出错而打电话给酒店取消,没有遗留的零碎事项。

因此,展望未来,随着DeFi和去中心化应用的发展,这只是一个非常简单的例子。有些应用变得非常复杂,如果出现问题,会有很多清理或回滚工作,在某些情况下你甚至无法回滚。想象一个套利机会:我购买一些以太坊,等待提交,然后在下一个操作中,我将以太坊转移到某个交易所,因为那里有很好的套利机会,然后等待提交,然后在交易所最终抓住套利机会,出售我的以太坊,换回一些Radix。但如果中间环节失败或耗时太长,或者当到达交易所时套利机会已经消失,那么我现在手头有一些我并不真正想要的以太坊,或者因为套利机会刚刚消失。而在原子性的情况下,购买以太坊、转移到交易所、然后抓住套利机会,所有这些在一个操作中完成。如果到这些步骤完成时机会已经消失,那么整个操作取消,我不会留下一袋需要以可能亏损的价格在其他地方出售的以太坊。


总结

本节课中,我们一起学习了Radix分布式账本技术的核心原理。我们从项目背景出发,了解了其从早期迭代到当前Cerberus共识的发展历程。我们深入探讨了构建可扩展区块链平台的四个关键支柱:

  1. 数据模型:基于类似比特币UTXO的Particle和Spin状态,实现了确定性的状态生命周期管理,为高效分片奠定了基础。
  2. 分片模型:采用巨大的固定但稀疏的分片空间,结合验证者集合和Epoch轮换机制,实现了状态的高效定位与负载均衡。
  3. 共识机制:结合分片内的本地共识(如HotStuff)和跨分片的Cerberus协议,确保了交易的安全提交与原子性。
  4. 女巫攻击防护:通过权益证明和经济激励设计,使得攻击网络变得极其昂贵且不切实际,保障了网络的安全基础。

最后,我们重点讨论了原子性对于复杂DeFi应用和良好用户体验的至关重要性。Radix通过其整体设计,旨在提供一个可扩展、安全且开发者友好的平台,以支持下一代去中心化应用。

感谢大家的聆听。

017:零知识证明入门 🧠

在本节课中,我们将要学习零知识证明(Zero-Knowledge Proofs, ZKP)的基本概念、工作原理及其在区块链技术中的应用。零知识证明是一种强大的密码学工具,它允许一方向另一方证明某个陈述是真实的,而无需透露任何关于该陈述本身的信息。这对于在保持区块链公开可验证性的同时,实现交易隐私至关重要。

概述:区块链的挑战与零知识证明的解决方案

区块链的核心原则之一是公开可验证性。这意味着所有写入区块链的数据都是公开的,任何人都可以验证每笔交易的有效性。然而,这一特性似乎与隐私保护相矛盾,因为交易细节(如发送方、接收方、金额)的公开会暴露用户信息。

零知识证明提供了一种巧妙的解决方案。它允许用户在不泄露交易细节的情况下,向网络证明其交易是有效的。这通过将交易数据加密,并附上一个证明(Proof)来实现。网络中的验证者(如矿工)只需验证这个简短的证明,而无需知晓交易的具体内容,从而在保持公开可验证性的同时,实现了隐私保护。

算术电路:零知识证明的计算基础

在深入零知识证明之前,我们需要理解算术电路的概念。算术电路是零知识证明系统所处理的计算模型。

一个算术电路接收一些数字作为输入,其中一部分是公开的,另一部分是私有的(称为“见证”Witness)。电路内部由一系列“门”(Gates)组成,这些门对输入执行加法、减法、乘法等运算。电路的布线决定了哪些输入流入哪些门。

公式示例:一个简单的算术电路可能计算 输出 = (x1 * (x1 + x2 + 1)) * (x2 - 1)。这里,x1x2 是变量输入。

这些运算通常在有限域上进行(例如模一个质数 p),以确保所有数字都在可控范围内。电路的复杂度通常由其乘法门的数量来衡量,因为乘法运算是证明系统中开销最大的部分。

算术电路非常强大,可以表达任何计算(前提是电路大小固定,不能有依赖于输入的变长循环)。例如,我们可以设计一个电路来验证SHA-256哈希值,或者验证一个数字签名。

代码概念示例(布尔运算转算术运算)

  • 与(AND)门x AND y 可以表示为 x * y(当输入为0或1时)。
  • 或(OR)门x OR y 可以表示为 x + y - x*y
  • 非(NOT)门NOT x 可以表示为 1 - x

零知识证明系统:定义与目标

一个零知识证明系统针对一个算术电路 C 工作。电路接收一个公开的陈述(Statement) x 和一个私有的见证(Witness) w。当电路输出为0时,我们称电路“接受”这个输入对 (x, w)

证明系统的目标是让证明者(Prover) 能够向验证者(Verifier) 证明:“我知道一个见证 w,使得 C(x, w) = 0”。这比仅仅证明“存在一个 w 使得 C(x, w) = 0”更强,因为它要求证明者确实“知道”这个 w

最简单的证明系统(非零知识):证明者直接将见证 w 发送给验证者。验证者自行计算 C(x, w) 并检查结果是否为0。这种方法的问题是暴露了全部隐私信息 w,并且当 w 很大时效率低下。

我们期望的证明系统应具备以下关键属性:

  1. 完备性(Completeness):如果陈述为真(即存在有效的 w),那么诚实的证明者总能说服验证者。
  2. 知识可靠性(Proof of Knowledge):如果验证者被说服(接受证明),那么证明者必定知道一个有效的见证 w
  3. 零知识性(Zero-Knowledge):证明本身(以及与公开陈述 x 的结合)不会泄露关于见证 w 的任何信息。
  4. 简洁性(Succinctness)(可选但重要):证明的长度很短,且验证证明所需的时间远小于直接执行电路计算所需的时间。具备简洁性的非交互式知识论证被称为 SNARK

SNARKs:简洁的非交互式知识论证

SNARK(Succinct Non-interactive Argument of Knowledge)是一种特殊的零知识证明系统,它同时具备简洁性非交互性

  • 非交互性:证明者生成一个证明后,可以将其发布出去。任何验证者都可以在无需与证明者进行额外交互的情况下验证该证明。
  • 简洁性:证明的大小非常小(例如,只有几百字节),并且验证证明所需的时间极短(例如,几毫秒),且与原始计算的复杂度仅呈对数关系。

SNARK的工作流程

  1. 设置(Setup):针对特定的电路 C,运行一次性的设置算法,生成一个证明密钥(Proving Key) 和一个验证密钥(Verification Key)
  2. 证明(Prove):证明者使用证明密钥、公开陈述 x 和私有见证 w,生成一个简短的证明 π
  3. 验证(Verify):验证者使用验证密钥、公开陈述 x 和收到的证明 π,运行验证算法。算法输出“接受”或“拒绝”,而验证者完全不需要知道见证 w

SNARK的威力:它允许我们将复杂的计算验证工作外包。例如,一个需要运行一年的计算,其正确性可以通过一个仅需20毫秒即可验证的SNARK来证明。在区块链中,这意味着节点无需重放所有历史交易来验证当前状态,只需验证一个关于状态转换有效性的SNARK即可,这极大地提升了可扩展性。

应用一:区块链中的隐私交易

现在,我们来看看零知识证明如何具体应用于区块链以实现隐私交易。我们将从隐藏交易金额开始。

机密交易(Confidential Transactions)

在比特币等系统中,交易金额是公开的。机密交易旨在隐藏这些金额。

核心工具:密码学承诺(Commitment)
承诺就像一个密封的信封。发送方可以将一个值(如金额)放入信封并密封(生成承诺)。这个承诺不会泄露信封内的值(隐藏性),但发送方日后只能打开信封展示之前放入的那个值(绑定性)。

实现方式

  1. 在交易中,将公开的金额替换为对这些金额的密码学承诺(例如,Comm(30), Comm(1), Comm(29))。
  2. 为了验证交易有效性(例如,确保输入总额等于输出总额,且没有创建负金额),发送方需要生成一个零知识SNARK证明
  3. 这个证明的公开陈述是这些承诺值,私有见证是实际的金额和生成承诺时使用的随机数。证明所基于的电路会验证:
    • 所有承诺都是正确生成的。
    • 输入承诺对应的金额之和等于输出承诺对应的金额之和。
    • 所有输出金额都非负(防止凭空创造价值)。

矿工收到交易后,只需验证附带的SNARK证明是否有效。如果有效,他们就接受这笔交易,并将其承诺更新到区块链状态中。这样,矿工和所有观察者都知道交易有效,但完全不知道涉及的具体金额。

应用二:Zcash——完全匿名的交易

机密交易隐藏了金额,但交易双方(输入和输出地址)的关联仍然可能被分析。Zcash等项目使用更强大的零知识证明(zk-SNARKs)来实现完全匿名的交易,类似于数字现金。

核心机制

  1. 屏蔽地址与币:用户拥有屏蔽地址。收到的资金被表示为一种“屏蔽币”,它是对(地址公钥,金额,随机数)的承诺。只有拥有对应私钥的人才能花费这个币。
  2. 花费币:当用户要花费一个屏蔽币时,他需要:
    • 创建一个新的屏蔽币给接收方。
    • 生成一个“作废码(Nullifier)”(例如,基于私钥和币的索引计算出的哈希值),并公开它。每个币的作废码是唯一的。
    • 生成一个zk-SNARK证明。
  3. 零知识证明的内容:证明的公开部分包括:新的屏蔽币承诺、作废码、以及任何非屏蔽的输出。私有见证包括:要花费的旧币的详细信息(私钥、金额等)、旧币在全局币列表(Merkle树)中的成员证明、以及新币的构成细节。证明电路验证:
    • 旧币确实存在于全局币列表中(通过Merkle证明)。
    • 用户有权花费该旧币(知道私钥)。
    • 新币被正确构造。
    • 作废码被正确计算。
    • 输入输出金额平衡等条件得到满足。
  4. 防止双花:网络维护一个所有已公开作废码的列表。如果同一个作废码出现两次,则意味着试图双花,交易会被拒绝。

通过这种方式,矿工和网络观察者只能看到:一个新的(看似随机的)承诺被创建,一个作废码被公开,以及一个有效的zk-SNARK证明。他们无法将花费的旧币与创建的新币联系起来,也无法知道发送方、接收方和交易金额,从而实现了完全的支付隐私。

总结与展望

本节课我们一起学习了零知识证明的核心概念。我们从区块链面临的隐私与可验证性矛盾出发,引入了零知识证明作为解决方案。我们了解了其计算基础——算术电路,以及理想证明系统应具备的属性,特别是简洁非交互式知识论证(SNARK)。

我们探讨了零知识证明的两个关键区块链应用:机密交易(隐藏金额)和Zcash式的完全匿名交易(隐藏交易图)。这些应用展示了如何在不牺牲区块链公开可验证这一核心原则的前提下,为用户提供强大的隐私保护。

零知识证明是一个快速发展的领域,新的、更高效、无需可信设置的证明系统不断涌现。它们不仅是实现区块链隐私的关键,也在提升区块链可扩展性(如Rollup技术)、安全身份认证、去中心化机器学习等众多领域展现出巨大潜力。理解零知识证明,是深入理解现代密码学和下一代区块链架构的重要一步。

posted @ 2026-03-29 09:28  布客飞龙II  阅读(30)  评论(0)    收藏  举报