本文乃与 samwilsn 及 adietrichs 联合撰写而成,亦得到 villanuevawill 和 Quilt 团队的莫大帮助。
简介 以太坊 2.0 的无状态性意味着交易必须携带自己要访问的状态。更准确地说,对于区块提议者(BP) ,除了包含交易,区块还需要包含所有交易访问的所有状态和对应的见证信息。假定创建交易的用户和 BP 都未存储状态数据,那么,网络就需要另一个群体来保存并提供这些状态。这种角色通常被称作状态提供者(SP)。
不管区块提议者和状态提供者是如何交换状态的,用户都可能需要在创建交易之前获取状态。比如通过获取合约的字节码,估计 Gas 的花销或者检查账户的余额。这意味着状态提供者需要为用户暴露一个类似拉取数据功能(pull-like)的接口。尽管没有激励层,只依赖无私的状态提供者也可以为用户提供状态(以太坊1.0 就是这样做的),也可以通过状态通道来实现支付,给状态提供者添加一个激励层。
比较准则 关于如何将状态提供者集成到整个系统中,人们已经提出了多种想法。在下面的章节中,我们将扼要地介绍几种方案。除了概括性的描述,我们还会对比下面的几个性质:
状态访问限制 因为交易的执行基于执行时的状态,所以,如果底层的状态变化了,交易的执行也会跟着变化。特别地,对一些交易来说,其状态访问的位置可能会变化。这可能是因为简单的跳转语句(比如 if),或者所访问的位置是在运行时计算的。我们将两种情况称作动态状态访问(DSA)。在无状态模式下,这会让交易创建过程变得复杂。问题在于可能无法提前为这些交易提供状态(因为无法提前知道这些交易会访问哪些全局状态)。不同的状态提供者模式在支持这些交易的程度上表现不同。
如果某个模式限制了动态状态访问,那么 Eth1 很有可能无法成为 Eth2 执行环境(EE),而且将经常需要特殊的处理。
激励措施 对状态提供者的报酬从下面两方面对比:
一开始是否支持无私状态提供者,如果是这样,激励措施可以之后再加吗? 中心化风险 一个状态提供者可以存储多少状态?需要什么样的硬件? 时间约束 区块生产者广播区块的时间是固定的。因此我们会专门考虑不同模式在该时间限制下的表现。 丢失状态的可归因性 Eth1 中,一旦某个给定交易的签名验证以及余额和 nonce 的检查完成,矿工就可以确信他们会得到打包交易的手续费。Eth2 中, 区块提议者是否可以得到支付依赖于丢失状态是否是可归因的错误(attributable fault)。如果是的话,就算某笔交易是因为状态丢失而失败,区块提议者也依然可以得到支付。否则,丢失状态的交易本身是不可打包的,但区块提议者可能在执行完所有(一般很长)的交易后才可能发现。(译者注:这里的支付指区块提议者要收取打包交易中的交易费,如果是不可归因的错误,那么区块提议者花费成本去打包了交易,却得不到交易中的交易费。) 如果区块提议者又要运行交易才能发现错误,但这些交易又是不可打包的(即不能支付手续费的),那区块提议者就很容易受到成本几乎为零的拒绝服务式攻击。 模式 模式 状态访问 激励措施 中心化风险 时间约束 直推模式 受限 自愿奉献或者支付通道 知名度高的状态提供者将有优势 无 中继推送模式 不受限制 按批次收费或者排他期收费 存在审查可能 需要在一个 slot 内更新并传输一批数据 拉取模式 不受限制 支付通道 知名度高的状态提供者将有优势 要在一个 slot 内请求一批状态
直推模式(Direct Push Model) 用户直接从一个或多个状态提供者处请求必要的状态,然后将带有状态的交易发往网络。节点维护待处理的交易池,每当网络产生新区块就更新见证信息。区块提议者创建区块时, 从交易池中选择待打包交易子集,包含进新的区块。 创建交易的用户实质上成了这笔交易唯一的状态提供方。一般来说,没有办法确保用户所提供的状态能满足日后交易上链时的所有访问需要。因此,在 Direct Push 模式下,只有状态访问可预测的交易才能得到执行。因为交易只能使用静态状态访问,合约创建者也应该设计他们的合约,得到可预测的状态访问:可以使用诸如可访问列表( access lists)的注释,详细说明合约在运行期间可以访问的位置。这种方案与避免动态状态访问的模式 (可参见 Vitalik 在 Eth1.x 版块提出的这篇相关博文 )相结合,产生的新模式应该仍能提供足够的的功能性。 不过,这将会与当前的 Eth1 系统大相径庭。可能会使 Eth1 转换到 Eth2 的计划泡汤。 这个模式只依赖于一般的状态提供者网络。正如上面所说的,似乎没有激励系统也可行。 激励制度也可以通过支付通道来添加。假定每个用户都必须与一个或多个状态提供者建立一个支付通道,这种方法应该会特别复杂。 单个状态提供者是无法审查交易的,因为用户可以向多个状态提供者发送多条查询。 因为状态提供者可以仅保留一部分状态,因此硬件要求可以按需降低。 金钱激励可能会促使一些状态提供者中心化,因此用户通过支付通道购买状态时,需要信任对手。 丢失状态可归因给用户。大部分情况下,区块提供者可以打包状态不足的交易而仍让用户支付。唯一的例外是初始签名验证或手续费支付所需的状态也丢了,这种情况下,交易不会被打包。类比 Eth1 的情况,网络中的节点可以从交易池中丢弃这种交易。对于这些初始交易部分,必须要施加一些限制来最大化 Gas 的利用 。
主要优势:简单。不需专业的状态提供者或激励系统。没有特别的时间约束。 主要缺点:只适用于事先知道所有状态访问需要的交易。这限制了整个系统的功能。尽管可以用一些缓解措施,但兼容性问题无法解决。特别地, 这种模型下,Eth1 无法成为 Eth2 的运行环境。 中继推送模式(Relayed Push Model)
用户自主向某个中继者(Relayer,专业的状态提供者)发送交易。该中继者将多个交易捆绑在一起并附加交易状态,将捆绑的交易包中继至网络。节点维护待处理的交易包池。每当有新区块产生,中继者就为交易包中继更新状态,所有的节点则更新对应的见证信息。BP 在创建区块时,从交易包池中选择最新的待处理交易包,把他们包含进新的区块。 相应地,系统在交易包池中的交易包被证明用不了的情况下,仍然可以运行。中继者只宣告交易包的存在。区块提议者会直接联系中继者,得到交易包并包含进新的区块。 没有限制。只要中继者每个时隙(slot)都能向交易包推送状态,确保状态访问的需要能得到满足,就可以了。此外,每个新区块只包含一个数据包,可以防止交易包间的干扰。 给中继者设计激励机制其实挺复杂的,因为状态和见证信息一旦公开,用户 和/或 BPs 就有机会绕过见证者,自己重新创建交易包。
没有交易池的情况下,交易包是不公开的。中继者向区块提议者售卖附加了状态的交易包(费用比交易费低一点),从而形成交易包市场。对区块提议者来说存在一些风险:某笔交易可能已经被包含在另一个区块中了,成了无效交易;或者收到的交易费比中继者售卖时宣告的要少。 另一种方法是,不论有没有交易池,交易可以包含给某个特定中继者的支付。用户承诺一段排他期(即几个时隙),这段时间内,用户不会创建其他交易。如果用户在排他期同时签署两个或多个交易时,就要遭到惩罚。为此,EE 必须提供 “罚没” 用户的方法。但因为用户没有锁定保证金,那么尚不清楚如何罚没没有足够账户余额的用户。
假定合并交易包是复杂的(因为动态状态访问),交易包市场会导致高中心化,并且允许单独的中继者审查交易。因为上面列出的 BPs 可能遭受的风险,BPs 更倾向于与知名且信任的中继者合作。个人用户与这些知名的中继者相比,是无法提供有足够高交易费的交易包的。 使用排他期以及交易包池会提供高程度的去中心化,但是以用户的便利性和一个更加复杂的交易池实现为代价。理论上来讲,任何用户都可以从交易池中检索到交易包,添加自己的交易去扩充交易包,然后以更高的交易费用中继交易包。
为了支持所有类型的交易,任何包含进区块的交易包都必须包含最新状态。中继者必须下载前面的区块,创建并向区块提议者发送交易包对应的更新, 区块提议者则在新块中包含更新的交易包,所有的这些行为都要在一个 slot 的时间内完成。 状态丢失可归因于中继者。区块提议者可要求中继者(或是中继者自愿选择)为某一笔交易附加 “退款交易”,用于在交易因状态丢失而失败时向区块提议者退款。
光靠一个交易包池可能不够,因为交易包体积较大(与 Eth1 中单个单个交易所组成的交易池相反),而且有严格的时间约束。 没有交易池的情况下,交易包不能被组合起来,那么一个区块就只能包含单个中继者提出的交易包。中继者可能会中心化并引入审查。 就算有交易池,交易包组合功能是否足以完全缓解审查问题依旧是不明朗的。 拉取模式(Pull Model)
用户向网络发送交易,节点维护待处理交易池。创建区块前,区块提议者从交易池中选出部分待处理交易,组成交易包并发送给某个状态提供者,请求这个交易包的状态。接收到状态后,由区块提供者将交易包打包进新的区块。 在状态提供者提供所有状态以前,为了让中间节点和区块提议者能够验证交易的有效性,用户必须在交易上附加验证签名和手续费支付能力所需的见证消息。因此这一部分在不同的执行环境(EE)中必须是标准化的,所有 EE 都必须提供一个最简单验证函数选项。 或者可以使用一个 Value-Holding EE (VHEE)。每笔交易都使用这个 VHEE 来支付费用。网络中的节点会理解 VHEE, 从而可以验证交易有效性。 在这两种情况下,网络中的节点都需要在新区块到达时更新附加状态的见证信息。 区块提议者是预测不了交易包的实际 Gas 花销的。在特殊条件下,交易包中的任意一笔交易都有可能使得这笔交易的所有后序交易无效化,比如将发送方的余额减少为 0。为了缓解这个问题,区块提议者会“超额打包”(overbundle),也就是说,向状态提供者发送多于他们预计要在区块中打包的交易数。状态提供者会提供这些交易的状态,直到达到区块上限。如果使用了 VHEE,交易可能还要额外附加一些数据,其中包含 VHEE 地址的列表,以及可以从这些地址中取走的最大金额数。通过这种方式,区块提议者就能防止前面的交易将后序交易无效化。 对主要交易没有限制。区块提议者只有在创建区块时才会联系状态提供者,确保返回的状态是最新的。更重要的是,通过把交易捆绑在一起并以交易包为单位请求状态,状态被附加在准确的上下文中。这种做法保证了所提供的状态总是充分的。这就包含了与 Direct Push 模式很关键的一个差异,Direct Push 模式中,状态是在交易捆绑 之前 被附加进去的,从而造成了状态访问的限制。 因为用户必须包含验证签名和手续费支付能力的状态,因此从技术上来说,交易部分的限制和 Direct Push 模型中列出的相同。然而这些限制在实际中是无关紧要的。因为 Eth1 中,签名验证和费用支付是可预测的状态访问,因此 Eth1 和 Eth2 之间的兼容性不会被破坏。此外,对 VHEE 来说,它的设计将确保可预测的状态访问,从而没有必要做进一步的限制。 区块提议者可通过支付通道或其他方式为状态提供者提供的状态付费。根据 BP 和对手 SP 的信任程度,可以按交易笔数来支付费用(这是信任最小化的),也可以按交易包来支付费用(这样效率更高) 状态提供者必须保存所有的状态,存储量要求很大。预计状态提供者还要快速执行交易包,因此对计算能力也有要求。 区块提议者可能更倾向于向其信任的状态提供者群体获取状态,减少恶意破坏的风险,从而增加了中心化程度。 然而,单独一个状态提供者无法审查交易,因为负责创建并对交易包排序的是区块提议者。某个状态提供者可能会隐藏某个交易包需要的状态,但是这样做会损害他们的信誉,而区块提议者可以很容易地用另一个状态提供者重试。 区块提议者必须在一个时隙内联系上一个能为 TA 提供待上链交易包所需状态的状态提供者。 状态提供者始终要为所提供的状态负责。区块提议者不可以将状态不充分的交易打包进区块,而且只有在验证了状态充分后,才会支付。
没有显著的中心化风险。尽管可以预计到,某一些状态提供者将专门为区块提议者提供状态,但没有某个状态提供者可以显著地干预整个过程的进行。一个状态提供者可以做的最坏的事情就是在被请求时不提供状态。 主要的缺点:必须对签名验证做一些标准化,或者通过验证脚本,或者使用 VHEE。 延伸讨论
自力更生式见证信息 & Gas 花销
如果交易发起者可以提供足够的见证信息来保证他们的余额,那么状态访问能便宜一点吗?如果见证信息也放在交易中、经过签名,其确定性是可以保证的,但是会增加复杂性。
状态费用
区块提议者和状态提供者对状态的价格是如何协商的呢?由网络设置吗?为生成一个区块,区块提议者应该向多个状态提议者招标,并选择最便宜的那个吗? 价格是按状态访问次数来算呢?还是按见证数据的大小来算呢? 如果按见证数据的数据量来收费,那么 BP 如何知道 SP 没有包含多余的字节? 如果多笔交易使用相同的见证信息,费用应该被均分吗?还是每笔交易都支付全款?还是只有第一笔交易需要支付?
状态抽象
这个提议没有确切地定义执行环境该如何获取状态,但是拉取模型或者中继模型运行时应该需要。
分布式状态网络
试想一下,不去收集交易并向状态提供者发送整个交易包,而是创建一个分布式哈希表,让区块提议者在执行中动态地获取状态可行吗?这种替代方法在网络请求上会阻塞交易的执行,可能让交易的序列化执行 太慢/不可预测。利用 software transactional memory 中的进展也可以实现这种替代方法。
(完)
声明:此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。本网站所提供的信息,只供参考之用。