# 🎓 导入:浙江大学演讲 — JAM 全景介绍

🎬 视频链接 (opens new window)

Gavin Wood 2025 年在浙江大学的 JAM Tour 第八站演讲。这是理解 JAM 的最佳入口——从 Web3 的哲学基础讲起,覆盖区块链的技术演进(专业化→泛化→商品化)、Polkadot 的 block space 质量指标、JAM 协议设计(refine/accumulate 模型、CoreVM、PVM)、以及现场演示在区块链上运行 Doom 游戏。

欢迎加入 JAM,带着长期思维来参与。欢迎。[掌声] 谢谢博士。所以我们来到了 2025 年 JAM 巡回演讲的第八站。感谢大家前来。这是一场比较长的演讲,所以如果你们需要出去喝杯水什么的,我不会介意的。好的。我感谢 Obie 为这次演讲提供了一些背景介绍。我认为理解我们为什么要做这件事的历史背景很重要,我们从哪里来。我将继续沿着这个方向,进一步把事情放到我们当下的时代背景中来。我们这个行业,区块链 web3 行业,正在日益分化。一方面我们看到长期思维的团队,那些真正在努力用这项技术解决难题的团队。另一方面,我们看到那些真正出来——如果我要刻薄一点的话,我会说是在榨取市场的团队,他们更关注短期成果。实际上我在两三个星期前的早期 JAM 演讲中就用了这同一张幻灯片,那是在 Bybit 被黑之前。除了底部关于盲签名的加粗文字外,内容没有变化。我当时告诉大家不应该为了短期利益而盲签名,而 Bybit 真的给了我一个非常有帮助的例子,说明为什么我们不应该盲签名。那个清单上还有各种其他东西,我认为可以说大多数区块链和大多数区块链团队并没有对它们给予太多关注。我们经常看到一些非常大的、日益受到某些相当强大的人物支持的区块链网络,它们的验证者集合非常小,高度中心化,运行它们需要高算力节点。我们看到桥接仍然使用 N-of-M 多重签名,就等着被黑。我们看到大量专注于投机性代币的做法。我们看到越来越多地迎合现有利益,忽视技术存在的目的。那些真正在努力解决难题的团队,是在尝试做到扩展的同时保持去中心化,而不仅仅是让他们的节点跑得更快。他们试图构建轻量客户端以避免 RPC 黑客攻击。试图构建真正无信任的桥接以避免治理黑客攻击或 N-of-M 多重签名黑客攻击。试图真正将可维护的、可持续的经济学注入他们的代币中,或者在代币根本不必要的情况下完全移除代币。试图以无信任的方式将丰富的元数据打包到交易中,以便在某个安全的冷签名设备上被读取,而不是直接假设没问题就盲签名。

这四个东西不是同一个东西。它们是相关的。它们确实是这个行业中使用的术语,但它们不是同一个术语。它们没有相同的含义。加密货币可以被描述为一种资源,或者至少是广泛的 web3 行业、区块链行业中的一个垂直领域。区块链是一种技术,我稍后会尝试向你们精确解释这项技术是什么。在这个行业中,DeFi 是另一个垂直领域。它不是唯一的垂直领域,它当然也不涵盖所有的 web3。它只是 web3 的一个小角落。Web3 整体而言是一种方法。一种方法。它是一种技术方法,一种新的技术方法。据我所知,这不是过去曾经被追求过的方法。那么什么是 web3?嗯,有几种方式来解释什么是 web3。Web3 可以被描述为构建——或者说一种构建有弹性的公共数字基础设施的方法。以前的技术或方法与 web3 之间的主要区别在于弹性。Web3 是有弹性的。确实,一些 web3 系统可以合理地被描述为反脆弱的,也就是说在某种程度上从混乱和多样性中受益。这里的弹性意味着对很多不同事物的弹性。我们构建 web3 不是为了特别强大地抵御某种特定的恶意力量。Web3 系统被设计为能够抵御——本质上是每一种可能试图篡改其输出的力量。包括一些非常重要的力量,比如系统的所有者或部署者。我的意思是 web3 系统通常没有所有者,但它们通常有某种创建者,一个创建它的团队,或者部署它的个人。大多数时候当我们想到数字系统时,我们不会认为它需要对创建或部署它的实体有弹性。但在 web3 中我们认为是这样,因为 web3 系统是公共系统,在非常广泛的意义上。我们还必须使它们对我们不期望发生的情况具有弹性——未知的未知。所以在某种意义上,web3 真正是一场我们与世界互动方式的革命,就像互联网也是一场我们与世界互动方式的革命一样。如果我们试图非常宏观地思考,web3 是一种试图在互联网内部创建那种有弹性的基础设施、公共基础设施的方式。

现在,web3 有几个要素,我在大约 10 年前的一篇博客文章中写过这些。大致来说,web3 的服务可以分为三个部分。一个是静态数据的发布。一个是消息传递——即瞬态数据通信。第三个是共识——经济信号。我的主张是,如果我们拥有这三样东西,而且它们都是有弹性的,那么我们就可以在这个新模型中部署任何 web2 应用程序。它们需要重新架构以利用这些服务,但原则上它们应该可以被部署到这个新平台上。但这些资源中最重要的可能是第三个——这种共识计算。它被称为 block space。我是说其他人也叫它 block space。从历史上看有点傻,指的是比特币区块链内部的空间,这有点傻因为比特币的 block space 特别不灵活,但事实就是如此。所以我们使用这个术语。现在,所有各种不同区块链产生的 block space 在许多我们可以衡量的不同属性上差异很大。Block space 不是一样的。有些比其他的更有价值得多。

所以区块链实际上就是一台去中心化计算机。是的。什么是去中心化计算机?这是一个有点奇怪的术语,因为计算机不是去中心化的。这是一台计算机。你可以看到它。它显然不是去中心化的。我把它拿在手里。它在物理形态上非常中心化。任何能接触到其物理形态的人都对它有完全的控制权。我可以拿锤子砸碎计算机,然后不管谁在试图使用它,它都会停止工作。那么我们说去中心化计算机是什么意思?我们如何将计算机去中心化?嗯,我认为很明显,一个人无法将物理计算机去中心化,对吧?它是物理的这一事实意味着它是中心化的。但当我们说去中心化计算机时,我们指的是一个计算机的模型。我们为计算机的基本部分建模——本质上是计算元素。用这个模型,我们进行去中心化。所以我们通过许多不同物理实例的合并或涌现效应来实现这个模型。这就是我们所说的去中心化计算机。它去中心化的主要意义在于,我们可以移除或损坏这些物理实例中的一些,这些帮助我们创建这个虚拟去中心化计算机的节点中的一些。而这不会影响这个模型的正确性、它的表现。它不需要所有节点都是正确的。只需要一部分。一般来说,它需要三分之二。

随着时间的推移,如果我们回顾历史,我们会发现新技术通常有三个阶段。第一阶段是技术最初被引入时,它非常专注于解决一个特定的问题。通常这个问题有足够大的经济效益,使得开发新技术的成本是值得的。对吧?所以技术是为了解决一个特定的紧迫的重要有价值的问题而开发的。因此最初当我们创新时,技术往往非常非常专注于一个特定的领域或一个特定的问题集或一个特定的用例。随着时间的推移,相邻领域、其他背景、其他行业、其他情况中的人们意识到这种创新可以帮助他们解决他们的问题。于是这种创新就变异到了其他领域。不久之后,通常有人意识到这种创新的关键要素实际上在许多不同领域都有用,于是他们进行了泛化。他们进行了抽象,创造了一种适用于平等地解决所有领域问题的技术——泛化。我们在计算机上看到了这一点。最早的计算机是非常领域特定的计算机。它们的创建通常是为了求解一个特定的数学方程、一个特定的公式。随着时间的推移,其他计算机为其他公式被创建出来,最终有人意识到也许我们可以让它可编程。这样我们就可以改变计算机执行哪个公式。这成为了第一台可编程计算机,实际上就是计算器,因为运算非常特定。最终,有人意识到计算机适用的问题集超越了求解非常特定的数学方程,可以用于诸如商业之类的事情。我们看到了可编程大型机。我们看到学术界开始引入计算机。随着时间的推移,它泛化了,直到最终我们落在了某些指令集上,比如 ARM64 或 x86、x64。在这个阶段,我们不仅拥有了一台通用问题解决机器,还拥有了一台标准化的问题解决机器,这使我们能够进行商品化。这就是我们到达的第三阶段。就计算机而言,这基本上就是 PC 兼容机,然后是后来的云革命,对吧?本质上是能够从任何供应商那里购买标准化资源的能力,然后市场在这个标准的小偏差上竞争,附加功能或成本价格。

我们在区块链上也看到了同样的模式。早期的区块链是非常领域特定的。比特币是最明显的例子,但还有其他的。Namecoin 是第二个。后来有了一些泛化,比如 Ethereum,再后来有更多的泛化,比如 Polkadot,它利用了 WebAssembly,不仅能够做智能合约,还能做各种其他事情,比如验证其他区块链。我们现在正在进行进一步的泛化。在我看来,不久之后我们就会达到商品化的阶段,能够从任何供应商那里购买通用的 block space。而 Polkadot 的创建就是为了制造最高质量的 block space。

那么我们如何衡量 block space 的质量呢?有几种不同的方式。Block space 本质上是去中心化计算机上的时间。所以我们可以衡量的方式之一是,去中心化计算机在任何给定时间段内能做多少计算。Polkadot 通过其本质上在节点网络中扩展问题的能力,而不仅仅是把问题给每个节点让它们都重新计算,Polkadot 能够大幅扩展,因此提供更多的计算吞吐量。每秒交易量是衡量计算吞吐量的一种非常低效和模糊的方式,但尽管如此,它似乎在行业中引起了很大共鸣,所以我们配合这个调子。如你所见,Polkadot 在活跃网络上记录的最快每秒交易量远高于所有其他区块链。它还恰好拥有最高的带宽。

衡量 block space 的另一种方式是它能引入多少数据、能处理多少数据、能存储多少数据。你可以通过所谓的可用性带宽或其可用性系统能处理的数据量来衡量。如你所见,Polkadot 的可用性系统实际上不仅比 Ethereum 这样的常规区块链好得多,而且比那些主要或唯一目的是提供数据带宽的领域特定区块链也要好得多。

衡量弹性的一种方式是通过其节点网络的去中心化程度。具体来说,在网络本身崩溃之前,需要多少不同的经济独立节点——我应该说是经济独立行为者——需要串谋或被攻破。我们称之为中本聪系数,以比特币作者的化名中本聪命名。如你所见,Polkadot 的中本聪系数远高于任何其他主要区块链,使其对潜在被攻破的节点或串谋的验证者具有更强的弹性。

Polkadot 还恰好是最节能的。能源效率也可以作为另一种衡量标准的代理指标,即计算成本。这是运行交易可以达到多便宜的一个基础阈值。随着交易量的增加,每笔交易的成本最终将接近与此成比例的某个值。原则上,这意味着 Polkadot 可以提供比其他生态系统便宜得多的交易——大约便宜 20 倍——比某些其他生态系统更是便宜得多。它能做到这一点的方式是通过横向扩展而不是纵向扩展其节点。我将——我希望这能引起共鸣——在这次讲座中我会不断回到这个主题。

正如我所说,Polkadot 能够通过并行化做到这一点——将工作负载分布到多个节点上,而不是让每个节点做所有事情。我们本质上称之为分片。Polkadot 受益于共享安全。这一点应该不言而喻,但不幸的是,一些网络,特别是 Cosmos,试图暗示拥有多个没有共享安全的链在某种程度上可以与共享安全的情况相比。关键的是,共享安全允许我们实现经济规模——让多个不同生态系统的经济体联合起来,各自承担所有生态系统安全的一部分负担。这给你带来了规模经济。Polkadot 还通过其 XCM 格式——跨共识消息格式——真正推动了跨链互操作性的概念。这允许领域特定的链在共同语言中宣传和接受服务。如我提到的,Polkadot 的 data availability 超过了其他链的 data availability,甚至是那些专门为 data availability 制作的链,这对 Polkadot 上的用户来说是免费提供的。

现在,我提到 Polkadot 在 Ethereum 之外正在尝试构建一个 web3 云。你如何构建一个 web3 云?这是一个有点奇怪的概念。Web3 云就像一个有弹性的 web2 云。我们如何看待 web2 云?它们是如何开始的?它们从一台计算机开始。通常,它们从一台非常快的计算机开始,然后随着云需要服务更多客户,添加更多计算机。那么,我们如何构建 web3 云?嗯,我们需要从一台 web3 超级计算机开始,一台非常强大的 web3 计算机,然后我们需要能够随着需求超过供给而添加更多 web3 计算机。所以,这意味着这些计算机原则上必须能够被连接和组合在一起。我不会过多讨论这个,但我会讨论 JAM,它是提供 web3 超级计算机的协议的基础。演讲的其余部分将聚焦于 JAM,但以上应该提供了一些背景,说明我们为什么要开发 JAM。JAM 是创建 web3 云所必需的。

所以 JAM 不仅仅是另一个区块链网络。实际上,JAM 根本不是一个区块链网络。它是一个协议。它预期部署为的区块链网络是 Polkadot。对吧?所以 JAM 真正是一个协议定义。它纯粹是一种技术,而这个协议不是一段代码。它是一个规范,写在一份叫做灰皮书的文档中。JAM 是我所说的协议优先,而不是软件优先。你会看到其他完全围绕其软件实现的区块链。通常只有一个实现,有时两个,对吧?非常少的网络有超过两个实现。很少有协议提供正式的协议规范。Ethereum 是第一个,实际上是我 2014 年用黄皮书做的。如果你熟悉黄皮书,那么灰皮书作为 JAM 的正式定义,正如你可能预期的那样,采用了黄皮书的一些元素,比如格式,一些符号相当像黄皮书。结构也是——如果你能读懂黄皮书,你大概也能很好地尝试阅读灰皮书。通过使其协议优先,我们避免了——或者至少大大降低了——某个特定开发团队成为唯一可行的开发团队,或某个特定的协议实现成为唯一可行的协议实现的可能性。如果一个协议真的只有一个实现,或者如果网络上的绝大多数节点只使用一个协议实现,那就是中心化。正是因为这个原因,我们创建了黄皮书。Ethereum 是协议优先而不是软件优先。这是为了避免单一实现在网络中占据主导地位。而在 JAM 中,我们真的非常想避免这种情况。所以对于 JAM,灰皮书将在任何特定实现之前发布,以便给很多开发团队一个机会在任何对特定实现的整合发生之前实现它。为了尝试激励团队实现这个协议,有一个相当大的奖金池——1000 万 DOT——这适用于能够证明他们已经正确实现了 JAM 协议的团队。除了这种相当大的财务激励之外,团队在实现 JAM 时还能获得一些其他支持——链上工资作为 Polkadot fellowship 系统的一部分,国际研讨会的邀请,对其代码库的专业安全审计,以及硬件访问权限,以便他们可以在真正的最终验证器硬件上测试他们的节点——这可能不是每个人都特别想投资的。他们还可以使用一台叫做 JAM Toaster 的机器。我稍后会详细说明。

已经有 30 多个独立团队站出来说他们正在实现这个灰皮书。他们正在实现 JAM,他们使用了大约 15 或 16 种不同的编程语言。我的意思是他们不是每个人都用 15 或 16 种。他们每个人使用 15 或 16 种不同编程语言中的一种。编程语言的多样性也很重要。在区块链网络中,有很多中心化的领域可能会成为真正的问题,重要的是我们尽量避免这种单点故障。

所以,JAM Toaster 是一台小型超级计算机。它并不是一台可以与任何现代大型超级计算机相比的超级计算机,但它也不仅仅是一台普通服务器。它介于两者之间。它有大约 16,500 个 AMD Thread Ripper 5 GHz 核心,32 TB 八通道 RAM,以及每个处理器 16 GB 的 L2 缓存,还有一些相当强大的网络和存储设备。我们为什么要建造这台小型超级计算机?嗯,这是 JAM 的一个非常重要的元素。像 Ethereum 这样的简单区块链系统并不特别依赖节点的涌现效应。如果我运行一个单节点 Ethereum 网络,它做的事情基本上和运行一个 10,000 节点 Ethereum 网络差不多——也就是说,它会处理一个区块中的交易,然后。它会出块,允许新交易进来并更新其状态。两者都会这样做。只是在 10,000 节点网络中,这些节点的状态被复制了 9,999 次。而如果只有一个节点,它根本没有被复制。只是我的节点在运行。当我们构建像 JAM 这样的网络时,事情变得更复杂了,因为网络整体所做的事情并不是单个节点简单做的事情。相反,节点们一起工作,做不同的事情,网络的结果就是我们所说的涌现效应。我们依赖于网络上节点的涌现效应。这种涌现效应与单个节点的效应非常不同。这有点像试图想象一个市场。价格是从哪里来的?比如说苹果在一个常规市场中的价格来自卖苹果的人和想买苹果的人的涌现效应——他们都各自做自己的事情,最终就价格达成了共识。没有个体行为者设定价格。是的。如果我们从市场中找一个人问苹果的价格,他们将无法给出相同的答案。不。实际上,答案来自于系统中充满行为者时的涌现行为。JAM 也是一样。

这给我们带来了一个问题。当一个由一个人编写的系统时,机器执行的指令是专门设计来产生我们想要的行为的。在编写的软件和我们想要的行为之间有一个清晰的映射。我们通过单元测试来做这件事,我们编写单元测试来确保软件产生我们想要的行为,然后我们可以使用调试器来检查软件的执行,在软件的行为偏离我们的预期效果——我们的期望行为时进行检查。但是,当我们有一个涌现系统时,我们就不能这样做了,因为每一块软件本身并不能给我们想要的效果。只有整个系统一起才能给我们想要的效果。我们实际上已经把节点的运作与系统的结果分离了。运作和结果现在是分开的。这使得工程化变得非常困难。通常当你依赖涌现行为时,你会发现你的系统运行得不太理想。它变慢了。它有 bug。它可能停止。如果你一次只能看一个节点,就很难理解为什么。确实非常困难。甚至几乎不可能。这就像你试图通过只看一棵树来了解整个森林是如何变化的。也许你能看出那棵树在当前环境中是否有问题,也许它在为其他树让路什么的。但仅仅通过看一棵树来理解森林的动态是非常困难的。同样,仅仅通过看一两个节点来理解涌现系统是如何工作或如何失败的也是非常困难的。

JAM Toaster 被设计为 JAM 的全尺寸测试网络。所以我们可以在这一台机器中以完整性能运行整个 JAM 作为测试网络。与我们实际拥有 1,023 个不同验证者都运行正确配置的节点具有完全相同的性能特征。主要区别在于,所有这些都包含在一个房间里,这让我们可以将所有东西连接到日志系统,实际分析和创建网络条件,以便我们真正理解 JAM 网络的涌现行为。据我所知,这是第一次为区块链做这件事。但如果我们想让区块链超越分布式账本的概念,这是绝对必要的。

那么 JAM 是什么?这是一张 JAM 的小图片。它有点像一朵花。有一个中心部分,然后是花瓣。实际上有几百个花瓣。在当前预期的单个 JAM 机器、单个 JAM 实例中,有 341 个花瓣。花瓣周围是存储——去中心化存储、去中心化的分布式数据湖。如你所见,数据从外部通过花瓣进入中间,在那里它可以与来自其他花瓣的所有其他数据交互。这是 JAM 的基本架构。但在我们深入讨论之前,让我们看看之前有什么,并尝试理解为什么这是一个合理的设计。

我在工程化区块链时已经确定了五个驱动因素。第一个是最重要的,那就是弹性。这是中本聪展示的至关重要的东西。比特币实际上没有——它可能有其他几项中的一些,但它没有通用性,也没有性能,但它有弹性。比特币仍在运行,对吧?它经历了很多。它必须有弹性,因为它存活了如此多的东西。如我之前提到的,比特币是第一种技术——非常领域特定。通用性在某种程度上是下一步。Ethereum 提供了一个更通用的系统,后来 Polkadot 将区块链的性能提高了几个数量级。连贯性是另一个非常重要的元素,而 Polkadot 并没有提供。事实上,Polkadot 提供了一个性能-连贯性的权衡。

所以如果我们试图想象一下 Ethereum 1——我们知道它非常不可扩展。我在那里画了一张小图。你可以尝试基本上把同样的东西做大,对吧?这就是一些网络试图做的事情。采用相同的模型,然后把它放大,只是让节点更快,对吧?EOS 就是一个很好的例子。还有其他的。这些也是不可扩展的,对吧?它们最终会达到一个极限——你可以合理要求单个节点有多快,减去基本上是状态复制开销的网络同步。它们往往也非常脆弱,因为它们依赖于非常特定的优化技术,通常只能由一个团队在一个软件中实现。很多时候只有一两个人知道优化技术是如何工作的,这可能造成巨大的脆弱性。而且你提高运行节点的门槛越高,你就越会使网络中心化。我的意思是这不言而喻。所以我们最终为了换取一些额外的性能而忽视了 web3 的一些关键要素。

好的。如果我们不能纵向扩展,那就横向扩展。创建新的网络。这就是例如 Cosmos 一直在推动做的事情。问题是,真的直接部署具有其他验证者集合和资本池的新网络,没有充分的理由相信任何新网络实际上是安全的,或者像已经有相当多资本支撑其验证者的网络那样安全。这是一个问题。另一个问题实际上我们在整个可扩展区块链方法中都看到了——那就是持续的状态分区。我这是什么意思?本质上,当我们添加一个不同的网络时,在那个新网络中运行比在旧网络中运行更难,如果我们想要与旧网络中的其他东西互操作的话。假设一个网络里有一个 DEX,那个网络变得拥堵了,所以有人想出了一个主意——让我们启动自己的链。那很好,你自己的链确实不会遭受那种拥堵,因为它是自己的链。它最初不会有任何流量。但如果旧链中的任何人,或者新链中的一个合约想要与 DEX 交互,他们就有问题了,因为他们不再与 DEX 相邻了。他们不在与 DEX 相同的网络中。他们实际上必须桥接过去并发送消息,然后等待一段时间。如果他们在新网络中有闪电贷系统,它将不会与 DEX 原子可组合。它将不会普遍可用。此外,创建新网络往往比部署智能合约更困难。在 Cosmos 模型中,你实际上还必须创建自己的验证者集合,门槛确实非常高。

让我们看看 Ethereum。Ethereum 有这种非常——我是说这是一张稍微旧一些的 Ethereum 路线图。这些幻灯片大概是我在一个月前做的,Ethereum 在过去一个月里又做了 U 型转弯,决定将其 L2 rollup 路线图换成原生 rollup 路线图。但无论如何,即使原生 rollup 与 L2 rollup 在某种程度上减少了整体扩展方案的碎片化。我的意思是,如果是 L2 rollup,我们会看到各种不同的属性,取决于 rollup——可能有不同的最终性延迟,使用的 EVM 版本不同,安全特性不同,中心化因素不同,等等等等。但即使如此,即使这些东西被修复了,我们仍然受困于这种持续的状态分区。如果你在一个 rollup 里,你就不在另一个 rollup 里。在你的 rollup 内交互很容易。在 rollup 之间交互很难。

Polkadot。在 Polkadot 中,我们在每个不同的 rollup 或平行链之间有同构的安全保证,但我们仍然有这种持续的状态分区。如果你在一个平行链里,你就不在另一个平行链里。是的。那么我们为什么要做持续的状态分区呢?如果它真的对我们伤害这么大,这是一件奇怪的事情。答案实际上非常简单。它是系统规模和其能保持多大程度的连贯性之间的根本对立。随着系统扩大,系统的各个元素、系统状态的各个部分变得更远了。是的,距离在增长。平均距离在增长,有趣的是距离的方差也随着系统的扩大而增长。如果我们想象所有项目之间所有距离的分布,那么该分布可能看起来像一条钟形曲线。但均值会增加,钟形曲线的总体值会变得更高,同时钟形曲线也会开始展宽。是的,状态的某些部分,这台机器的某些部件仍然彼此相当接近。但有些部件彼此真的很远,而大多数东西会相当远。鉴于我们知道因果关系在物理学中有基本的速度——光速。因此我们可以理解,如果我们想创建一个允许我们在可编程基础上拥有因果关系的计算系统,那么随着该系统增长并处理更多状态,它要么必须减速以给远处的东西一个解决的机会、一个让效应解决的机会,要么我们必须将其分区,这样就没有远处的东西,所有东西都只与所有其他东西接近。如果我们有太多数据,我们不能那样做。所以我们基本上必须把它分割成独立的东西。这实际上就是持续分区的来源。我们把我们的大系统——整个 Polkadot、整个 Ethereum 和 L2——打包成更小的系统——平行链、L2、那些不能直接影响彼此但至少可以通过消息以低带宽异步通信的系统。这就是我们管理这种规模-连贯性对立的方式。

这完全不是区块链特有的东西。如果你去寻找,你会到处看到它。你在生物学中看到它。你可以在化学中看到它。你可以在 CPU 设计中到处看到它。这只是世界的一个基本组成部分。

所以如果我们能得到我们想要的,那会是什么?我们会怎么画它?这是我画理想情况的努力。理想的状况,外面的粗边框代表共享状态。它是一个单一的状态机。从上到下的箭头表示这有许多不同的行为者或智能合约在其中运行——如果我们谈论操作系统级别的东西,就是进程。我只画了九个就烦了。但有很多箭头这一事实表明可以有很多很多这样的行为者或进程或智能合约。它们共享这个盒子,所以它们可以选择原子性地互相交互。这是我们想要的,对吧?这是我们想要的。我们得到了什么?嗯,对于 Ethereum 1,基本上就是我们得到的。所以,我们有一个盒子。很好。它们都在共享同一个环境。但在那之后,它有点崩溃了。我们有几个箭头。很好。现在,如果你注意到箭头不重叠,表示一次只有一个智能合约在运行,而且这些箭头之间有很大的空间。这表示在区块之间有大量的空闲时间。Ethereum 网络实际上并没有做那么多计算。一个平均的 Ethereum 节点有 95% 以上的时间什么都不做,不是真正做什么,不是处理任何交易。大多数时候甚至更多。95% 是一个相当低的估计。这远远不是理想的。我把它画成蓝色而不是橙色,表示内存和存储不是那么正常的,对吧?我们在 Ethereum 中的系统中有非常特殊的内存和存储,对吧?存储是这种疯狂的 32 字节到 32 字节的映射。看起来完全不像文件什么的。内存也是如此,都是 32 字节的东西。它不像普通计算机,普通的编程语言也不真正理解这个。

如果一次只有其中一个箭头运行,那么实际上我们可以简化这个,因为如果有多个小状态机一次只运行一个并不重要,因为我们也可以把它画成一个更大的状态机只是连续运行。是的。所以对我来说画成右边那样更简单。如我所说,有一些高性能同步网络——Solana、EOS 之类的东西——保持基本的 Ethereum 计算模型并做一些小改动,比如可能有一些多线程支持,这样如果两个东西不在同一块内存上操作,可以通过让它们在同一时间执行或者至少在 CPU 上并行化来挤出更多的处理时间。所以它们通过优化从硬件中挤出更多。所以我把箭头画得稍粗了一些,但基本上仍然是一次一个。运气好的话,你可能会同时有两三个。区块之间的空闲时间少了。是的。所以右边两个箭头之间的空间少了一些,但仍然是同样的模型,同样的计算模型。是的,我们仍然在所有节点上复制所有东西。我们并没有真正利用我们的大节点网络来做任何有用的事情。

看看 Cosmos。Cosmos 在这种图形语言中是什么样的?嗯,我们基本上有了右边那里有的东西。也许箭头没那么粗,因为我们没有那么多优化,但基本上我们有几个箭头,它们可以互相通信。但当它们互相通信时,它们必须走出共识然后再回来。桥接的强度只和两个通信实体中较弱的那个一样强。整体来看,当把系统作为一个整体来看时,我们实际上在分割我们的安全。我们在分割我们的资本基础——我们归属安全的经济基础。如果我们在多个网络之间分割我们的资本,我们实际上在降低它。

那么 Polkadot 1 呢?嗯,它更复杂一些。我们在外面有一个粗边框,箭头都在里面。这很好。这意味着我们在做一些有意义的事情。箭头在某种意义上共享一些状态空间。然而,我们有从上到下的竖线,表明实际上我们已经将状态空间分区了。是的。现在,箭头不能直接跨越那条粗线交互。所以,代替跨越粗线交互,它们发送消息。哦,像 Cosmos。是的,像 Cosmos。但它们的消息留在粗边框内。它们的消息是安全的。是的。它们不需要出去。它们留在里面。所以这基本上是对 Polkadot 中发生的事情的一个合理的图形表示——或者 Polkadot 原始概念的平行链——在一些事情的修正下,这可能或多或少就是 Ethereum 的原生 rollup 方向。

那么 JAM 是什么?这是一张关于 JAM 如何工作的图形表示。JAM 内部发生了什么?在左边我们有 DA——如果用 Ethereum 术语来说的话。我称之为数据湖或去中心化的分布式数据湖。这是 JAM 软件用于存储数据和取回数据的大规模数据存储。右边基本上是一个完全同步的状态,正如我们已经知道的那样。我们可以看到这些蓝色箭头。它们不重叠。它们实际上可以在 JAM 的未来版本中重叠,但目前没有。中间是 JAM 变得有趣的地方。中间是我们所说的协处理器核心,或简称 core。这些是计算元素。它们彼此独立,但它们都可以从数据湖读取——你可以看到数据湖有向下的箭头——它们都可以写入——向数据湖提交数据——你可以看到箭头回到数据湖。此外,当它们执行时,它们将结果提交到区块链中。所以你可以看到箭头从数据湖开始,通过这些大型计算协处理器之一,然后在最后分叉——一些数据回到数据湖,其他数据进入区块链。这就是 JAM。这就是基本架构。

所以 JAM 引入了一种新的计算模型,我称之为瞬态去连贯。它大部分是连贯的。所以系统整体保持大部分连贯,大部分从相同的状态空间运行。但它的一小部分状态——也就是最近的计算——可能是不连贯的,但它会在有限的时间内被解决——事实证明是六秒内。这是对扩展系统并管理它必须在某种程度上变得不连贯这个问题的另一种回答。我们必须以某种方式管理规模-连贯性对立的问题。这是这个问题的另一种解决方案。在某种意义上,它实际上与现代多核 CPU 设计非常相似。JAM 中存在的一些想法可以直接被识别为现代 CPU 设计中的模式。

所以 JAM 有两个计算环境,两个执行环境。一个我们称之为 in-core 或使用这些协处理器。这就是中间那些粗箭头中的计算——in-core。右边的计算——细箭头、蓝色背景——那是 on-chain。所以我们有这两种计算模型。In-core 计算可以访问那个巨大的数据湖,但在其他方面是无状态的,而 on-chain 计算是有状态的,是同步的,但它没有大量的计算能力,也没有对巨大数据湖的访问权。数据湖有 1.5 PB。非常大。它有 6 秒的 in-core 同步延迟,基本上意味着如果某个东西从那些粗箭头中的一个写入数据湖,直到 6 秒后其他粗箭头才能看到。这有点像如果你在一个 CPU 核心上工作并写入 RAM,那么其他核心在你的缓存被刷新之前是看不到的。是的,差不多是同样的事情。如果你碰巧想在同一个核心上读取它,那么就像 CPU 设计一样,当你从同一个核心的缓存读取时,它是瞬时的。

分布式的去中心化数据湖——左边那个巨大的矩形——存储数据段。一个数据段是固定的 4 KB 大小。实际上略大于 4 KB——4,104 字节。在常规的 4,096 之外多了 8 个字节。你可以通过使用加密承诺来查找这个数据湖。一个 36 字节的加密承诺。

如果我们用 Ethereum 术语重新表述,如果你已经熟悉那种语言,可能会有帮助。实际上,JAM 提供了 341 个安全的——所谓的——图灵完备——它和区块链中至今的一切一样是图灵完备的——无状态 rollup,还有一个图灵完备的智能合约链,可以接收这些无状态 rollup 的结果并对它们做些什么。无状态 rollup 对一个 1.6 PB 的 DA 存储有共同的访问权,以六秒延迟同步,但如果你碰巧在使用同一个核心,延迟是瞬时的。

那么,我们是怎么做到的?这似乎是一个非常大的技术进步。我们怎么做到的?嗯,我们有一些不同的技巧、不同的机制或算法或设计或创新。第一个是 ELF——或我称之为愤世嫉俗的 rollup。愤世嫉俗的 rollup 是一种非常快速地对某个特定计算报告是否正确做出结论的方式。到目前为止,rollup 通常有两个大的分支。一个是 ZK rollup,另一个是所谓的乐观 rollup。乐观 rollup 是一个令人难以置信的误称。事实上,一个更准确得多的名字应该是悲观 rollup。这种特定的 rollup 技术——乐观 rollup——假设所提议的工作或工作结果是错误的,因此在一个相当长的超时期间内不做任何事情。通常超时期间相当长。从半小时到四天不等。它只是假设它是错误的,是欺诈的。在这个超时期间,它允许任何人或一些验证者站出来提供欺诈的证明。99.9% 的时候它不是欺诈的。但尽管如此,乐观 rollup 采取了非常悲观的观点,认为它将是欺诈的,因此不做任何事情。它们不会对这个工作采取行动。这真的很糟糕。但它们在营销上成功了。

相反,我们有愤世嫉俗的 rollup。愤世嫉俗的 rollup 也假设有欺诈活动,因为我们不能确定没有。然而,我们主动尝试寻求活动不是欺诈的信心——本质上是通过让可能诚实的、可能诚实的参与者重新计算工作负载并检查结果。当我们确信足够多的参与者已经这样做,以至于其中至少有一个是诚实的,那么我们就确信工作报告是有效的,没有欺诈,我们继续前进。通常大约需要 8 秒钟。8 秒钟相比悲观 rollup 或乐观 rollup 的至少 30 分钟。

我们的另一个技巧是 Sassafras。Sassafras 是一个基于零知识证明的区块创作系统,允许我们每六秒钟创作一个无分叉的区块——不知道下一个区块作者是谁——除了下一个区块作者之外没有人知道下一个区块作者是谁。确保下一个区块作者在创作并开始分发区块之前是未知的,如果我们想要避免某类攻击的话是至关重要的。这可以追溯到长期思维与短期结果。如果我们想要构建安全、有弹性的系统,那么就不能让下一个区块作者被广泛知道,因为他们可以被 DDoS 攻击。他们可以被离线,这可能构成攻击的关键部分,例如阻止某些流动性被执行,或者区块链上的一般欺诈证明被提供等等。

我们的下一个技巧是 GRANDPA。GRANDPA 是一个接近即时的最终性小工具,能够适应网络条件。大多数最终性小工具在固定周期的基础上运行。它们要么在区块产生时每个区块都终结,要么在某个多区块周期终结。例如 Ethereum 大约每 15 分钟终结一次。Cosmos 使用 Tendermint 试图在区块产生时就终结。Ethereum 每 15 分钟终结一次的问题是——你在大部分时间里拿不到最终性证明。平均来说你的最终性证明将大约是七分半钟前的。是的。你的最终性证明的预期年龄将是七分半钟,如果你在做一些跨链转移,这是很长的时间。我不想等七分半钟才能看到我的代币从一个网络移到另一个网络。Cosmos 方案的问题是网络条件可能会退化,如果网络条件退化,那么你的出块现在就与你的最终性绑定在一起了。最终性是一个比出块重得多的网络操作。出块是 O(n) 的。基本上是一个节点向 n 个其他节点发送一个区块。而最终性是 O(n²) 的。所有节点必须与所有其他节点分享他们对哪个是最终结区块的意见。如果网络条件退化,最终性是第一个倒下的。如果你把它和出块绑在一起,并且不允许在上一个区块终结之前产生新区块,那么你的出块就成了第一个倒下的。这是一个问题。GRANDPA 是一个独立的协议,这意味着出块永远不会是第一个倒下的。但如果网络条件退化,GRANDPA 最终只是增加延迟。是的。降低它的反应性。它以一种非常数学上聪明的方式做到这一点,使其始终在网络最优延迟下运行。

最后,也是对 JAM 来说即将到来的关键创新,是 PVM——Polkadot 虚拟机。这是一种基于 RISC-V 的新的重编译虚拟机指令集架构。它非常快。让我们稍微谈谈 PVM。

PVM 是 JAM 的关键创新之一,它使 JAM 能够施展其魔力。如我所说,它是一种基于 RISC-V 的指令集架构。如果你不熟悉 RISC-V,它是一种指令集架构,如果我没记错的话,是在斯坦福大学一个特定的学术项目下设计的。我想这是第五次迭代,从 RISC-1 开始,现在到了 RISC-V。RISC-V 已经取得了相当大的成功,你实际上可以买到原生执行 RISC-V 代码的硬件处理器。我们在 JAM 中不需要这个。真的没有必要。但原则上,它们可以买到。它们有市场。RISC-V 代码可以很容易地被重编译或翻译成 PVM 代码。它们非常相似,对吧?有一些重要的区别,所以它是一个新名字。但它们非常相似。它们足够相似,以至于它真的只是一个非常小的简短可执行文件来做翻译。

PVM 有 13 个 64 位寄存器,它的内存模型如果你习惯了在常规计算机上工作的话会非常熟悉。它是 32 位地址空间,4 KB 页面。页面可以被映射或不映射。很简单。它与常规硅片略有不同之处在于它具有哈佛架构。所以代码与所有可寻址数据分开存储——代码不是直接可寻址的,它就在自己的小存储空间旁边。关键的是,PVM 代码由于我们的设计,可以在线性时间内被重编译——实际上非常非常快地在线性时间内被重编译成 x64 代码,在像这台笔记本这样的机器上运行。事实证明,这种代码可以像 EVM 中的 gas 一样被动态计量,以最小的开销——大约 10%。PVM 因为它将栈存储在主内存中——不像 WebAssembly 将栈存储在外部某个不透明的数据结构中——非常适合实现 continuation。我们对 Polkadot 虚拟机的内部实现——它是一个标准规范——实现了大约 45% 的原生 x64 速度。原生 x64 速度——这台我两三天前买的现代笔记本在硅片上自己运行软件的速度。45%。这意味着它比区块链中除 Polkadot 与 WebAssembly 之外的任何东西都快了几个数量级。但与 Polkadot 的 WebAssembly 相比它还有一些额外的优势——线性时间重编译的能力、以最小开销计量的能力和承载 continuation 的能力。要明确的是,这个 45% 的数字是任何给定程序的原生编译版本与编译成 PVM 然后重编译回 x64 的版本之间的时间差异。这就是那种小绕道的代价。而且这包括了重编译成本——重编译成 x64 代码的时间。

好的,让我们更深入地谈谈 JAM 的服务架构。JAM 实例中的共享状态被安排为服务,就像 Ethereum 中的共享状态被安排为智能合约一样,对吧?很简单。所以我们基本上把智能合约称为服务。每个服务有一段代码和三个入口点:refine、accumulate、on-transfer。所以每个智能合约服务有三段代码。Refine 是在中间部分——那些粗箭头上运行的代码。Accumulate 是在右边——那些细箭头上运行的代码。On-transfer 也在右边运行。它只是处理来自其他服务的消息。

服务有点像智能合约,正如我说的,但它们有一些区别。它们的计算是分阶段的。我们已经知道有 refine 和 accumulate——还有 on-transfer。计算的三个不同阶段。计算不仅是分阶段的,还是流水线化的。Refine 在 accumulate 之前。但当一个较早的工作的 accumulate 正在进行时——你可以说是一个较早的交易——一个较新交易的 refine 可以同时执行。不仅如此,它是分布式的——多个甚至同一服务的 refine 可以同时执行。此外,还有批量购买 gas 或 block space 或 core time——你怎么叫都行。JAM 卖给你的东西你是批量购买的。你购买它——我是说 JAM 卖它,或者 Polkadot 会按月卖它。你买一个整个核心一个月。你可以分割它、拆分它并用它做各种事情,当然也可以把它分成更小的部分卖出去,但这是 JAM 资源供给的基础。它更大量。为什么更大量?因为按交易来卖没有意义,因为交易太小了。JAM 会陷入处理交易而不是实际做计算的泥潭。所以在这个 L1 或 L0 层面上只卖大块更有意义。我们就像批发商。此外 JAM 通常是异步的——服务并不同步运行。我一会儿会详细讲。

JAM 是无许可的,对吧?或者至少它被设计为可以在无许可环境中工作。一个示例服务可以是各种东西。引入新服务是无许可的。任何人都可以做,只要他们拿出代币。JAM 对区块链的上层方面是不可知的——质押、经济学、治理。JAM 对这些是不可知的。这不构成 JAM 协议的一部分。JAM 提供一台机器。这就是 JAM 的 M。Join-Accumulate Machine。JAM 是一台去中心化计算机。它不关心这些东西中的一些。

如果我们看看 JAM 的流水线,当 JAM 做工作时实际发生了什么?工作从顶部进来。首先,在我们做任何工作之前,我们检查是否应该做这个工作。在 Ethereum 中,这是通过检查交易账户是否能支付 gas 来完成的。在 JAM 中,我们没有这种即时 gas 购买。我们有一个更通用的东西叫做授权系统。首先我们做这个。我们运行授权系统。我们授权工作被执行。如果我们确信工作已被授权,那么我们进入下一步。Refine。这是非常重度的处理,对吧?中间的粗箭头,能够访问数据湖并有大量计算能力的那个。这两者都发生在 core 中——在我展示的图表的中间部分。授权是 authorizer 代码。这与服务代码是分开的。Refine 是服务代码——我们实际想要与之工作的服务的代码——如果你愿意的话就是智能合约代码。当我们完成 refine 后,我们将其发送到 accumulate 阶段以及任何 transfer。这仍然在服务代码中,但不是在 core 中——不是在粗箭头上运行,而是在所谓的"链上"——在细箭头上运行。这就是 refine 所做的所有不同工作汇集在一起并同步、再次变得连贯的地方。所以对于这个特定的工作,在前两个部分,系统原则上是不连贯的——碰撞的或互不兼容的工作负载可能同时在进行,但 accumulate 使一切变得正常。Accumulate 是我们基本上——如果两个工作负载互不兼容,我们在 accumulate 中丢弃其中一个。我们以某种方式使系统进入某种连贯的整体。

为了进一步解释这一点,我将给你一些小符号。所以我们基本上称一块工作为一个交易,但它没有签名。所以我们称它为一个 item。它是一个工作项,一块我们想要完成的工作。它与一个服务关联,我们给它这个小笔记本符号。现在我们可以拿几个 item 以及一个授权令牌——某种证明——交给某个 authorizer 代码,表示这个工作是我们想要完成的工作,我们用它形成一个包——一个盒子。这就是 work package。work package 往往相当大——大约 12 MB。现在我们还有 digest 的概念。digest 是一小块数据,也与一个服务关联,它是 refine 的输出。所以在我们完成 refine 阶段——这个高强度计算——之后,我们得到一小块相对较小的数据,叫做 digest。

我们不同的阶段如何工作?嗯,authorize 拿一个 work package,给我们一些我们称之为 trace 的东西——一个小标签,告诉我们为什么它被授权了。它是 authorizer 认为对流水线其他部分相关的任何数据。现在,让我们回想一下 work package 实际上只是一个令牌——一个认证令牌、一个授权令牌加上一些工作项——你可以说是一些交易。然后 Refine 拿其中一个交易——假设是红色服务的一个交易——把它与 authorizer 的这个小 trace 组合起来,给我们一个 digest。digest 与同一个服务——红色服务——关联。然后我们连接所有的红色 digest——所有新计算的、关于红色服务的 digest——连同它们所有的 trace,把它们连接在一起,然后 accumulate 它们。所以 accumulation 可能发生在多个 digest 上,但始终来自同一个服务。事实证明 accumulate 给我们某种哈希结果,最终上链。

所以 authorize 可以检查整个包。包包含这个授权令牌。所以它可以用这个令牌来确定包是否有效、是否适合做工作。如果 authorizer 认为包不适合工作,它就 panic,流水线就结束了。到这个点我们还没做多少工作。否则,它提供一些 trace。我们有一种方式来确定一个给定的工作是否被允许在一个 core 上执行。每个 core 都有所谓的 authorizer 池和 authorizer 队列。队列不太重要。它只是补充池。池很重要。池中充满了承诺——对特定 authorizer 的加密承诺。为了让一个 work package 有效,在它将被授权的 core 的池中的一个 authorizer 在被喂给 work package 时不能 panic。它必须以成功退出并给我们一个 trace。假设它这样做了,我们就进入 refine。

现在 refine 在单个工作项上执行。它必须检查——它可以检查 authorizer 阶段的输出——那个 trace——它也可以检查 work package 中的任何其他 item。这至关重要。这使我们能够在一个 core 中同时共同调度两个不同的工作,本质上允许同步组合而不需要太多成本。所以每个工作项能够查看所有其他工作项及其所有数据的能力是一个非常重要的属性。它还可以查看已经放在链上的数据并调用其他 PVM 实例。它可以创建新的虚拟机并启动它们。它可以创建新的虚拟机,把任何它想要的东西放入它们的内存中并启动它们。等待它们停止或完成一定量的计算、一定数量的步骤,然后读取它们的内存。对吧?这非常重要。我一会儿会展示为什么。

现在 item 可以相当大——如我提到的,最多 12 MB 的数据——从数据湖读取或作为额外的完全外部数据输入。它们还可以将 12 MB 的数据放入数据湖中。它们可以执行大约 5 秒的 PVM gas。5 秒的 PVM gas 大约相当于两到两秒半的原生 x64 时间。这每六秒钟发生一次,对吧?每个 JAM core 大约运行原生 AMD Thread Ripper 5 GHz CPU 核心的三分之一左右。这是相当可观的计算量,它们产出最多 48 KB 的 digest。这是输入到 accumulate 的信息。

如我所说,accumulate 可以一次对一个或多个服务的 digest 执行。可以检查所有 trace,查看为什么它被授权了,对于每个 refine 输出——每个进来的 digest——它可以执行最多 10 毫秒的 PVM gas。这听起来不如这里的 5 秒那么多。但我们要记住 accumulate 发生在链上。它是完全连贯的、完全同步的。这就是为什么它不那么多。但你实际上可以在 10 毫秒内做相当多的事情。你可以做大约 10,000 次数据库操作,对吧?我们估计每秒可以做大约一百万次数据库操作。它可以转移资金、修改状态、做你在多行为者环境中通常期望能做的所有常规事情。它可以创建新服务、升级代码。实际上,这是在 JAM 中创建服务的唯一方式。在 Ethereum 中你可以创建一个交易来创建一个新智能合约,对吧?你可以在一个完全空的 Ethereum 系统中创建一个交易来创建一个智能合约。它是内置的。它不是 JAM 内置的。JAM 作为一台机器更加纯粹。如果你想在 JAM 中创建一个服务,需要已经有一个为你提供那种服务的服务。是的。如果没有,你就不能创建一个服务。这为限制任何特定 JAM 实例可能做什么提供了一些非常有趣的可能性。但它基本上意味着,大多数情况下你的创世区块中必须至少有一个提供创建服务功能的服务。

如我所说,JAM 服务通常是异步的。那么当我们在一个连贯的环境中实际执行代码时,这是如何工作的?基本上 transfer 在你所有的 accumulation 完成后处理,而且实际上在其他所有人的 accumulation 也完成后处理。而外部状态读取只在任何执行开始之前被解释。对吧?所以当你读取另一个服务的状态时,就好像那个服务自从你开始执行以来什么都没做过。当你向另一个服务发送消息时,那个服务要到所有执行完成后才能看到它。这使我们能够异步。它还为我们提供了一条潜在的未来路径——在同一台机器内并行化以及组合多个 JAM 实例。但那真的是另一个演讲的话题了。

好的。现在,我想给你们一些将在 JAM 上运行的服务的例子。第一个是 CoreVM。可能更好的名字是 JAM Docker。它本质上是在 JAM 上运行一台 PC,对吧?它在 JAM 内部运行一台基本上正常的计算机。有这样一个服务让你做到这一点。不幸的是,我想给你们的演示还没达到我期望的程度,但我可以给你们做一些演示。不过我想先解释一下。

所以我已经谈了一些关于 JAM 拥有大量计算能力、内存带宽和 DA 等等。但它仍然是一个非常特殊的计算环境,对吧?它有两个部分。它有这个 DA 存储。它有特定的——它很奇怪,对吧?它是一个你需要学习的计算和执行环境。我不认为它那么奇怪,我认为你可能可以很容易地学会它。但尽管如此,它不是任何人至今会习惯的东西,它当然看起来不像我们想要的。这才是我们想要的,对吧?

CoreVM 从何而来?嗯,它来自区块链开发者体验很糟糕这个观点。它很糟糕。我知道有时候很有趣,但这不是一个容易卖给普通开发者的开发者体验。你有奇怪的存储,对吧?32 字节到 32 字节的映射,背后有默克尔化。它很小。它非常奇怪。如果你习惯了基本上有文件可以存储东西或者也许有一个可以推送和拉取东西的服务器的常规机器,这不是你会习惯的东西。它跟那个模型完全不同。它有奇怪的执行,对吧?你有这些疯狂的限制,比如区块 gas 限制——如果一个特定操作花了太长时间,那就行了。你完了。它坏了。你再也不能做任何事了。这也非常奇怪、非常诡异。gas 的事实本身就是奇怪的。它非常诡异。你通常没有语言选择,如果有的话,通常是非常特定的几种语言。语言中可能有非常特定的习语需要使用,如果你不用,它就会崩溃。或者你不能使用执行环境的某些功能,除非你使用这些习语。很多时候它充满了陷阱。看看 2016 年的 DAO 灾难。代码看起来没问题,代码经过了审计但最终是坏的。然后也许最奇怪的事情之一是你不控制你的执行循环。在解释来自外部世界的每一条数据之后,你必须销毁所有的工作状态。这太疯狂了。我不想销毁我的工作状态。如果我需要做一次大型迁移怎么办?这没有意义。这限制了开发者。它限制了开发者市场,限制了潜在的用例,使得创建某些软件变得非常非常困难。

这才是我们想要的。我们不希望箭头在每个区块都被打断。我们不希望收拾起工作状态然后在每个区块开始时拆包。

那么 CoreVM 做什么?嗯,CoreVM 有点像操作系统。它消除了考虑所有这些硬件级东西的需要——所有这些类似于去中心化硬件的东西——gas、区块限制、存储——对吧?这些都被移除了,取而代之的是它给你一台正常的机器,一台你可以编译几乎所有代码的机器。这就是 CoreVM。这是我们画它的方式。竖线仍然在那里,表示每个 CoreVM 进程本质上运行在自己的沙箱中,对吧?但它们可以互相通信。那是虚线,对吧?所以它们可以互相发送消息。有那种进程间消息传递。但你会注意到两个东西使这与我为你画的其他图片不同。第一件事是箭头从顶部一直到底部——表示连续执行。没有区块中断。好的。第二件你会注意到的是箭头有橙色背景而不是蓝色背景——表示完全正常的内存访问。是的。它们也很粗,表示它可以做大量计算。

所以你可以把 CoreVM 想象成 JAM 的 Docker。它为正常软件提供常规执行环境。它模拟一台机器。那台机器有接近原生 x64 的速度。它是 RISC-V 兼容的,这意味着你可以将常规软件定向到这台机器上。它有像正常机器一样的分页内存。有像正常机器一样的连续执行。提供像正常机器一样的进程间消息传递。这是一台可以运行用正常语言、使用正常抽象编译的正常软件的机器。你可以运行任何软件,甚至不是为区块链设计的软件,比如 Doom。

所以,我现在要切换到一台 Intel 机器上,希望它能出现。开始了。我将运行一个脚本。脚本做的事是设置一个小型测试网络——六个节点的网络。它们都是验证者节点。通常我们有三个验证者节点运行一个 core。所以有六个验证者节点,我们有两个 core。这是一个非常小的 JAM 实例。通常我们会有 1,023 个验证者节点运行 341 个 core,但这只是一台小笔记本。所以它们都必须共享同一个 CPU。它还有另外两个进程在运行。一个是 builder 进程,帮助 CoreVM 理解哪些内存页面需要每六秒从 DA 中获取。另一个进程是监视 DA 中的视频帧的。

为什么要监视 DA 中的视频帧?嗯,Doom 需要一个显卡来输出它的图形,对吧?它是一个游戏。如果你玩一个没有任何方式看到游戏在做什么的游戏,那就没什么意义了。当然,区块链并没有真正的显卡。所以在 CoreVM 中我们创建了一个虚拟显卡——一个去中心化的显卡——实际上我们只是把所有的视频帧导出到数据湖中。我们的带宽足够好,我们可以以 30 fps 将视频帧导出到数据湖中,同时获取 Doom 可能需要的任何内存——比如运行 Doom 的那台 PC 的任何 RAM。

所以你看到它正在启动,需要一点时间,因为它本质上在设置以便理解哪些——它必须部署服务,等到它被终结,放入代码等等。所以需要几个区块来做这件事。然后——啊,是的,我确实做了一个代码更改。让我们回退代码。好的。那么 CoreVM 服务——让我们想想这个。它在做什么?它想提供一台常规虚拟机。为了在有区块 gas 限制的情况下提供一台常规的可购买的机器,它需要能够拆包上一批内存。所以我们需要能够拆包内存,创建之前正在运行的虚拟机,让它继续运行,允许它运行一段时间,然后重新打包它,放回 DA 中。放回存储中。嗯,我不确定它是否会放视频帧。是的。好的。我会继续解释这个。我需要两分钟的编码时间来让这个再次工作。但目前我们继续。

所以我们需要从 DA 中取出机器之前的状态,将其输入到我们内部实例的内存中,运行它以生成六秒的帧,打包任何已更改的 RAM 页面,并将其放回 DA 以供下次使用,然后还要将任何视频帧放入 DA 中。然后我们将有显示进程,它会检查是否有新的视频帧到达,根据它们的时间戳和帧索引来显示它们。它显然需要从 DA 中取出那些帧。所以你看到两个箭头进入显示进程。一个箭头是寻找那些帧的加密引用。另一个箭头是实际拉取数据。服务本身不能把帧存储在链上,因为那数据量太大了。所以它必须从 DA 中取出它们。

排序器——如我提到的——基本上只是推动 CoreVM 前进,让它知道下一个六秒需要哪些内存页面。它有自己的 Doom 实例——嗯,它有自己的 PVM 实例,因此也有 Doom 实例在运行——它检查实例正在访问哪些页面,建立一个表格,然后可以用正确的数据 ping 它——这就是我们如何在链上运行常规软件。

所以这只是因为我们有这个高带宽、正确集成的 data availability 系统——分布式去中心化数据湖——才成为可能。流水线化一切也帮了大忙。我们比通常更多地流水线化区块。我们同时使用 refine 和 accumulate,这对获得这种性能水平确实至关重要。当然 PVM 使我们能够做到这一点,因为它能够支持 continuation。

所以超越 CoreVM,这是什么?CoreVM 的目的是什么?我是说,CoreVM 本身似乎有点浪费时间——没有人会在区块链上玩 Doom——但它让我们能够形成进入下一阶段区块链计算的垫脚石。要理解为什么我们需要或为什么我们朝这个方向前进,我们必须回到之前我谈到的那个东西——持续的状态分区。更多的链解决了什么?它解决了拥有更多计算的问题。这是我们想要的。想要横向扩展。但最大的问题当然是碎片化。当我们横向扩展时,网络效应减少。当我们碎片化我们的生态系统,更不用说整个行业了,网络效应——那些能真正提供非常有趣的组合用例的东西——减少了。它限制了我们可以创建的用例。它限制了原子性的可能性。它限制了可开发性。在异步、松散可组合的系统上开发软件是困难的,对于试图部署它的团队来说,这迫使他们做出决定,投入一个特定的 L2 或特定的子生态系统,而没有特别好的信息知道那个 L2 在一年后、两年后会是什么样子。

这是我们想要的。JAM 不是那个。但 JAM 可以给我们 CorePlay。所以 CorePlay 使用 JAM 来创建这种计算环境。我们有箭头。它们是橙色的。如果你记得,橙色箭头是我们想要的。我们不想要疯狂的内存东西,对吧?我们只想要连续执行。箭头从上到下。连续执行。确实,CorePlay 开始看起来很像我们追求的东西。现在仍然有分区。我们不能避免分区。必须有分区,否则我们会违反物理定律。我们必须分区我们的状态。但我们可以更聪明地分区我们的状态。我们不必以静态的方式、持续的方式、永久的方式分区。我们不必根据 L2 的边界来分区——不同生态系统、不同代币、不同中心化因素、不同标志、不同领导者的边界。不,我们可以以经济上最合理的方式分区,并且可以频繁地重新分区。这就是 CorePlay 被设计来尽可能高效和最优地促进的。你可以把它想成 JAM 的智能合约操作系统。它同时作为服务和 L2 存在。它需要一个 L2。这有点不幸,但这就是现实。

它提供什么?本质上是基于行为者的智能合约。它们不是 Ethereum 智能合约意义上的智能合约,因为它们不是交易性的。我的意思是,它们不需要——它们不是只拿一个交易、执行一小会儿,然后停止,所有东西被打包或工作内存被丢弃。不,这些是正常的软件进程。它们可以是 Doom,但可能不会是 Doom。但它们可能很复杂。它们可能大量使用 DA,而且它们可能看起来很像 actor。如果你想拿你的 Solidity 代码编译成这个,你当然可以。这是一个比 EVM 执行架构强大得多的编程模型。

有趣的是,因为我们在执行时做分区而不是在某个固定的边界——根据 L2 格局的固定边界——当我们添加更多 actor 时,我们只需将它们分区到更多的 core 中。我们可以将 CorePlay 扩展到更多的 core 中。不能真正将一个 actor 扩展到更多的 core 中。Actor 被设计为同步机器,但我们可以有更多的 core 来将我们的 actor 社区分区。这使我们能够横向扩展而不会打破我们之前的任何保证。我们仍然得到全局原子性。我们通过在同一个 core 上共同调度那些 actor 来获得任意一组 actor 之间的原子性——它们可以同步地互相通信,很像 Ethereum 世界中的共同调度区块链——但我们得到零碎片化。为什么?因为我们可以随意频繁地重新分区。怎么做?嗯,我们能够做 CoreVM 的相同原因,加上我们有小的状态原子。Actor 比区块链的状态少得多。加上我们定期重新分区,因此允许与当时需要同步组合的 actor 进行同步可组合性——本质上提供经济高效的共同调度——将那些认为共同调度有价值并愿意为此付费的经济体的 actor 聚集在一起。

那么我们为什么不直接使用区块链的共同调度?嗯,基本上这是一个非常相似的提议,但区块链是巨大的。它们是庞大的,共同调度巨大的状态转换系统会导致巨大的低效和巨大的中心化偏差。我们最终会有一个巨大的共同调度器,基本上是任何正在被共同调度的链中什么能通过的唯一权威。这不是 web3。这不是有弹性的。为什么会这样?嗯,甚至只是跟踪机会——跨区块链共同调度的经济价值——都是困难的。你必须运行全节点并对这些链做很多分析。你还必须跟踪纠缠。对吧?共同调度是因果纠缠的一种形式。本质上,一个区块链上的一个交易的效果——或者一个区块链上的一个交易的效果——必须在另一个区块链上的另一个交易的效果已知并确定终结之后才能被感知。只有在那时那个区块链上的效果才能被感知。现在,这个问题随着你尝试共同调度更多区块链而增长。因为你必须不仅为一个其他区块链跟踪那个因果纠缠,而且为所有其他因果纠缠的区块链跟踪。现在这变成了一个问题,因为它以 O(n²) 的速度增长。每一个参与纠缠的区块链都必须跟踪所有其他区块链,并且不能做任何事情——不影响任何交易后果——直到它确定它在所有其他区块链上都已终结。甚至只是跟踪纠缠就很困难。即使在相对较少的区块链上,这也只在使用非常强大的节点时才可行,而它变得越来越难,因此你需要一个越来越强大的节点,由越来越多的质押支撑,将其共同调度的区块提供给越来越多的验证者——如果你想做多于几个区块链的话。当然,如果我们尝试将此推广到 JAM 的规模——341 个共同调度的区块链——那就疯了。

好的,意图求解器。它们不是通用解决方案。意图求解器接受一个碎片化的世界,它们试图为用户想要做的任何特定事情创建一个利用它的配方。它们不允许位于这些碎片中的单个无信任组件直接交互。通常也不是非常通用的解决方案。它们只适用于意图求解器网络支持的任务。

使用某个东西的多个实例怎么样?那也不太行。你会分割你的资本池。你会在那些不同实例之间分割你的资源。即使你使用再平衡,那些资源一次只会存在于一个实例上。

我们为什么不使用 ZK 来扩展?这是我有时会被问到的问题。嗯,基本上因为愤世嫉俗的 rollup 目前提供了比 ZK rollup 好得多的价格或成本。ZK 是一种有趣的技术,它已经对很多事情有用,但扩展计算正确性不是其中之一。我与之交谈过的关于 ZK 的人甚至不认为它在长期内会超过加密经济学解决方案。对 ZK 的怀疑是它可能会达到大约加密经济学解决方案成本的 50,000 倍然后就停了。进一步的改进在时间和成本上的减少将是最小的。我们看看那会怎样发展。但就目前而言,ZK 扩展方案不是成本高效的。给你一个数字的例子——PVM 需要的时间——如果我们说 PVM 需要这个基本时间量来做一些计算并检查它是正确的——JAM 网络需要大约 30 次 PVM 执行。所以整个网络检查正确性的时间大约是运行本身的 30 倍。而 ZK 生成器——零知识证明生成器——大约需要 600 万倍——600 万倍——生成证明的成本与在 PVM 下执行计算的成本相比。现在对于这个我们使用 RISC-Zero,因为我们想做通用目的计算。如果你将想要做的计算限制在非常特定的、领域特定的、ZK 优化的形式,那么你可能会得到低得多的倍数。但如果你想有一个非常通用的网络——那种能运行 Doom 的网络——那么你将被这个巨大的倍数困住,而这个倍数可能会下降。我们已经看到研究人员在 ZK 上做着非常有趣的工作,但从 600 万倍更贵降到大约相同成本需要一段时间。这不会在一夜之间发生。可能需要几年时间。

好的。我将快速演示一下 JAM 环境,然后如果有时间,我会尝试修复 Doom 的问题。我知道问题出在哪里,但需要一两分钟来修复。所以这是一个 JAM Ripple。它像是 JAM 的一种调试控制台。在这个里面我们可以随时推动链前进、创作新的区块。我们可以引入新的 work package、work item,然后试玩部署在 JAM 上的服务。

所以我想首先展示的是演示服务。这是一个我为演示 JAM 而制作的服务。这是演示服务的代码。我希望你们能读到它。是的,我认为它是可读的。正如我之前提到的,它有这个 refine 和 accumulate 模型。refine 代码做的事不多,对吧?它真的只是展示数据通路。所以它会从授权代理那里获取输出,打印一条调试消息,创建一条显示 payload 和认证输出的小消息,然后基本上把信息消息放入 DA 存储中,并将我们正在处理的数据——payload、认证输出以及在 DA 存储中的这个身份——传递给 accumulate。如果我们进入 accumulate,它会获取这些信息——这三个字段——解码它们,然后放入存储中。所以我们预期这些存储项会被写入。

让我们看看这个。目前这个链上没有演示服务——如我提到的——你必须在链上创建一个服务才能做任何事情。如果你在 JAM 上没有任何服务,你将永远无法做任何事情。让我们看看我们有什么服务。我们可以用 ls 列出服务,它告诉我们有服务 0。这是创世区块中的——在创世区块中已经有一个服务——这是 bootstrap 服务。Bootstrap 服务是一个服务。它有点像在 PC 上——当你开机时,它不会立即进入 Windows 或 Mac OS 或什么。会先运行一点软件——引导软件。是的。BIOS。基本 IO 服务。它在那里初始化某些东西——比如硬盘——然后从磁盘上读取操作系统的代码,然后开始执行它。嗯,JAM 也差不多是这样,对吧?你会发现 JAM 在很多方面与常规计算机非常相似。它的架构在很多方面像常规计算机。你将会发现的其中一点是它需要这个。它需要这个 bootstrap 服务。Bootstrap 服务本质上允许我们把软件加载到 JAM 中,对吧?我们这样做——我们必须给它一个 work package——里面有一个 work item。那个 work package 使用 bootstrap 服务的指令格式。碰巧这个调试控制台理解这个指令格式,它提供了一个叫做 boot create service 的命令,允许我们加载软件。然后我们可以告诉它我们想要什么软件——我们将使用 demo_service.pvm。这是一个预编译的——我之前把这个文件编译成了 PVM 代码。我们还可以给它一些初始余额——我会这样做因为我们要往它的存储里写东西,写入存储需要给它余额。

好了。所以它告诉我们它已经创建了这个服务,我们看到一些调试消息告诉我们幕后正在发生什么。它在 PVM 内部的授权代码中走了一遍。然后进入了 Bootstrap 服务的 refine,然后又进入了 Bootstrap 服务的 accumulate。所以正如我在幻灯片中提到的,它按 authorize、refine、accumulate 的顺序工作。然后我们在底部得到这条额外的调试消息告诉我们它创建了一个服务——这是服务的 ID。到目前为止一切顺利。看起来很有前途。所以如果我们列出服务,我们看到——是的,老的服务 0——bootstrap 服务——还在那里。但现在我们还有这个新服务 e1a04a...d8——和这个一样——但我们叫它 a 因为输入 a 比输入那串十六进制容易多了。它有一些余额。它有我们给它的一百万以及它额外拿走的——因为它需要存储它的代码。好的,到目前为止很好。

让我们检查一下它的存储。我们可以用 read storage 命令读取存储,读取 a 的存储——默认是 a——我们可以读取存储键。比如说 last_payload——我想是这个。我们可以在这里说 a 但默认就是 a。所以我不用输入。它是空的。当然它是空的因为我们还没有给它任何工作做。让我们给它一些工作。我们要给 work item——我们要告诉 a 我们要给 a 一个 work item。比如说一个 work item。Hello。显示 hello。好的。啊哈。一个待处理的 work item。我们可以一次构建一个 work item 来构建 work package。为了把所有的 work item——一个 work item——放进一个包里然后发送到链上,我们使用 guarantee 命令。所以这将做的是把 hello world 发送到这边的演示服务,进入演示服务的 refine。所以我们预期看到一些调试输出,我们预期当它到达 accumulate 时它会设置 last_payload 的存储。好的,让我们看看这是否有效。[音乐] 看起来可能有效了。让我们再次读取存储。砰,它在那里。所以这就像你的基本交易。现在它没有做任何检查签名的事情——因为 JAM 默认不做那个。要让它检查签名,你会把某种签名检查代码——一些签名检查逻辑——放入 authorizer 或服务代码中。目前我们只是做一些像这样的简单事情。但原则上它支持所有这些,对吧?这只是 JAM 的上层东西,因为 JAM 是虚拟硅。它是去中心化硅。它被设计为一台非常通用的计算机,而不是一个智能合约平台。把智能合约平台放在上面。

好的,再快速做一件事。如果你记得,它还在 DA 中放了一条消息。让我们看看能不能找到那条消息是什么。DA 消息我想在 last_info_ID 里。可能是 last_ID。不记得了。不,last_info_ID。在那里。它告诉我们它是这个区块、这个 core 的 DA 索引 0。让我们看看在我们的 DA 中能不能找到它。ls 给我们 DA 中的段树——目前只有一个段树——只有一个区块——实际上只有一个 work package 导出了任何数据到 DA 中。毫不意外就是我们自己做的那个。它发生在区块时间 4——core 0。这个 work package——如果你看——和那个 work package 一样。相同的 ID。很好。它是我们想到的那个。它有一个特定的根。我们不关心根。Item 0——和这个一样——值为 payload。Hello world 或输出。这就是我们在自己的逻辑中创建的消息,对吧?我们在自己的逻辑中创建了它并实际推送到 DA 中。就这么简单。只是 export slice,对吧?这就是你需要做的全部。它将留在 DA 中。如果你想导入它,非常容易。你只需使用 import slice,你必须给它我们知道的那个零——这两个东西中的任何一个——你只需要其中一个——这些是加密承诺。好的。

我再快速展示一件事——给它发送一条消息。事实证明我们的 Bootstrap 服务有一个 transfer 命令。我们可以向任何我们想要的服务发送一条消息——transfer 一条消息和一些资金。我不需要发送任何资金,但我们会发送一条消息。实际上我不记得是先资金还是先消息。所以让我们 just help。先资金。好的,没有资金。我们说——嗯——money for nothing。我们在给它发送一条消息。我们在使用 Bootstrap 服务来发起消息发送。它将到达我们的演示服务。它会做什么?让我们看看代码。on_transfer。所以这是当我们接收一条消息时。我们得到——这是所有的 item。我们会做一个调试消息来看看它是什么。制作一条消息——这个格式命令——这个格式化的东西。然后设置一个存储项 last_tx。所以在我们做这个之前,让我们检查 last_tx 是空的,没有奇怪的事情在发生。我们可以用 read storage last_tx 来做——确实是空的。所以让我们做 boot transfer——没有资金——money for nothing。希望你们对我单手打字印象深刻。好了。所以再次通过 authorizer。Bootstrap 服务。好的。巴拉巴拉。它要 accumulate。它在尝试 transfer。很好。好的。transfer 完成了,看起来很好。让我们再看看那个存储项。果然,消息在那里告诉我们它知道它从服务 0 那里收到了什么,并且它知道备忘录是什么。

所以这只是向你们展示——这是 JAM 提供的一个连贯的、类智能合约环境——我想要传达的理念是这基本上就是一台非常普通的计算机。我希望你们会看到这种交互比你在 Ethereum 区块链上的交互更常规。对吧?这种交互感觉更像是你在一台控制台前给计算机下达命令。

好的,我会再试一次。让我们解锁这个,看看我能不能——我想我们需要做的就是更改——现在更改——crates doom builder cargo tunnel 并更改——你想做什么。哦是的,谢谢。然后如果我们——这是一件有趣的事。事实证明 SDL——我们用来描述视频——把视频放在屏幕上的那个——如果我们使用捆绑版本的它就完全失败了。所以我们必须使用系统版本。但希望当它实际放到——哦——当它把视频窗口放到屏幕上时,它现在会工作了。我们看看。啊哈。是的。看看能不能把它放大。所以这是如我所说从区块链上来的。区块链每六秒把这些帧输出到 DA 存储中,然后我们有一个 viewer 进程,它使用 SDL 打开了一个 SDL 窗口,根据 CoreVM 放在链上的引用从 DA 存储中读取。它只是在显示那些图形。这些图形是 320x200 像素、8 位调色板。所以每帧大约 16 KB。我想是这样的。如果我们每秒 30 帧,那就是每六秒 180 帧。如果你把 180 乘以 16K——它不是那么大。它不到我们 DA 读写的 12 MB 限制。除此之外,我们还必须保持运行 Doom 的机器的内存——RAM——对吧?Doom 不知道它在区块链上运行。是的,那会违背目的。就 Doom 而言,这只是一台常规的 PC。嗯,它是一台有 PVM 执行——PVM 指令架构的 PC,但仍然是一台 PC——我们可以把 Doom 编译成 PVM——但它期望一个连续的环境。Doom 不理解区块 gas 限制之类的东西。所以我们必须为它提供一个连续的环境。我们必须为它提供 32 位分页内存寻址。所以我们为 Doom 模拟这个——通过创建一个 PVM 实例——然后在每个 work package 的开始——每个区块——我们把上一个区块这台机器的内存拆包到新机器中。然后我们用 Doom 可执行文件启动它——基本上因为栈作为内存的一部分存在——它就像什么都没发生一样继续工作。然后在执行时间结束后——PVM 时间 5 秒或什么的——我们获取所有已更改的页面,记录它们如何更改,获取加密承诺,并将那些承诺存储在 accumulate 中的主服务状态中——然后将实际的 4 KB 内存页面存回 DA 中——然后在所有这些之外,我们当然把视频帧扔进 DA 中,并将引用存储在主服务状态中。

所以这就是你如何在链上创建一个连续执行 CPU 以及一个去中心化显卡,对吧?原则上,你也可以有一个去中心化控制台,对吧?你可以把所有进入调试日志或标准输出的消息也放进 DA 中。如果你想做输入,你可以在 work item 的 extrinsic 数据中——目前基本上是空的——没有什么输入——你可以放用户输入——键盘输入。然后基本上把它作为虚拟键盘驱动器输入给 Doom。这可能是我们将来会扩展 CoreVM 去做的事情,主要是为了好玩。但 CoreVM 是聪明的部分,对吧?实际上 JAM 才是真正聪明的部分——但 CoreVM 是坐在 JAM 上的这个服务,提供这个容器——这个 PVM 执行容器——在这个容器里你可以放入基本上任何软件——只要它能编译成裸机——或者只要你能制作它需要的任何驱动器——你可以制作像样的去中心化对应物——那么它就能运行任何软件。

好的。我希望你们喜欢。就到这里了。感谢你们的注意。[掌声] [音乐]