EIP-3076: 保护性削减交换格式
一种 JSON 交换格式,供权益证明验证者在客户端之间迁移保护性削减数据。
Authors | Michael Sproul (@michaelsproul), Sacha Saint-Leger (@sachayves), Danny Ryan (@djrtwo) |
---|---|
Created | 2020-10-27 |
Last Call Deadline | 2021-11-03 |
Table of Contents
摘要
密钥签名历史的标准格式允许验证者轻松地在客户端之间切换,而不会有签署冲突消息的风险。虽然通用的 keystore 格式提供了一部分解决方案,但它不包含有关密钥签名历史的任何信息。对于将其密钥从客户端 A 移动到客户端 B 的验证者来说,这可能导致客户端 B 无意中签署与客户端 A 签署的早期消息相冲突的消息的情况。此处描述的交换格式提供了解决此问题的方法。
动机
权益证明(PoS)协议会惩罚以可能导致链的两个不同版本最终确定的方式进行投票的验证者。这些类型的惩罚称为削减。
对于正确遵循协议的验证者来说,原则上没有被削减的风险。但是,如果客户端 B 不知道使用客户端 A 签署的区块和证明,则更改客户端(例如,从客户端 A 更改为客户端 B)可能会导致削减风险。
如果客户端 A 和客户端 B 在当前时间上存在分歧,则可能会发生这种情况。例如,假设客户端 A 的时间意外设置为未来的一天(225 个 epoch),并且验证者在未向 B 提供使用 A 签署的区块和证明的记录的情况下,从客户端 A 切换到客户端 B。现在,有问题的验证者面临在同一 epoch 中证明两个不同区块(可削减的违规行为)的风险,这会持续 225 个 epoch(因为他们已经使用客户端 A 对这些 epoch 进行了投票,并且现在可能会再次使用客户端 B 对它们进行投票)。在实际应用中已经观察到这种时间偏差错误。
削减保护至关重要的另一种情况是在重组的情况下。在重组期间,验证者可能会被分配新的证明职责,用于其已经签署证明的 epoch。在这种情况下,即使验证者在一个 epoch 的空间内刚从一个客户端移动到另一个客户端,先前证明的记录也必须可用。
规范
JSON 模式
有效的交换文件是符合以下 JSON 模式,并根据条件进行解释的文件。
{
"title": "签名历史",
"description": "此模式提供了由一组验证者签署的区块和证明的记录",
"type": "object",
"properties": {
"metadata": {
"type": "object",
"properties": {
"interchange_format_version": {
"type": "string",
"description": "此文档所符合的交换格式的版本"
},
"genesis_validators_root": {
"type": "string",
"description": "在创世时间计算;用于唯一标识链"
}
},
"required": [
"interchange_format_version",
"genesis_validators_root"
]
},
"data": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"pubkey": {
"type": "string",
"description": "验证者的 BLS 公钥(编码为带有 0x 前缀的十六进制字符串)"
},
"signed_blocks": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"slot": {
"type": "string",
"description": "已签名区块的槽号"
},
"signing_root": {
"type": "string",
"description": "compute_signing_root(block, domain) 的输出"
}
},
"required": [
"slot"
]
}
]
},
"signed_attestations": {
"type": "array",
"items": [
{
"type": "object",
"properties": {
"source_epoch": {
"type": "string",
"description": "已签名证明的 attestation.data.source.epoch"
},
"target_epoch": {
"type": "string",
"description": "已签名证明的 attestation.data.target.epoch"
},
"signing_root": {
"type": "string",
"description": "compute_signing_root(attestation, domain) 的输出"
}
},
"required": [
"source_epoch",
"target_epoch"
]
}
]
}
},
"required": [
"pubkey",
"signed_blocks",
"signed_attestations"
]
}
]
}
},
"required": [
"metadata",
"data"
]
}
JSON 实例示例
{
"metadata": {
"interchange_format_version": "5",
"genesis_validators_root": "0x04700007fabc8282644aed6d1c7c9e21d38a03a0c4ba193f3afe428824b3a673"
},
"data": [
{
"pubkey": "0xb845089a1457f811bfc000588fbb4e713669be8ce060ea6be3c6ece09afc3794106c91ca73acda5e5457122d58723bed",
"signed_blocks": [
{
"slot": "81952",
"signing_root": "0x4ff6f743a43f3b4f95350831aeaf0a122a1a392922c45d804280284a69eb850b"
},
{
"slot": "81951"
}
],
"signed_attestations": [
{
"source_epoch": "2290",
"target_epoch": "3007",
"signing_root": "0x587d6a4f59a58fe24f406e0502413e77fe1babddee641fda30034ed37ecc884d"
},
{
"source_epoch": "2290",
"target_epoch": "3008"
}
]
}
]
}
条件
导入带有数据字段 data
的交换文件后,签名者必须遵守以下条件:
-
拒绝签署任何相对于
data.signed_blocks
中包含的区块而言可被削减的区块。有关构成可削减区块的详细信息,请参见process_proposer_slashing
(来自consensus-specs
)。如果区块中缺少signing_root
,则签名者必须假定任何具有相同slot
的新区块相对于导入的区块而言都是可削减的。 -
拒绝签署任何
slot <= min(b.slot for b in data.signed_blocks if b.pubkey == proposer_pubkey)
的区块,除非它是由signing_root
确定的重复签名。 -
拒绝签署任何相对于
data.signed_attestations
中包含的证明而言可被削减的证明。有关构成可削减证明的详细信息,请参见is_slashable_attestation_data
。 -
拒绝签署任何源 epoch 小于该签名者的证明(如
data.signed_attestations
中所示)中存在的最小源 epoch 的证明。用伪代码表示:
source.epoch <
min(att.source_epoch
for att in data.signed_attestations
if att.pubkey == attester_pubkey)
- 拒绝签署任何目标 epoch 小于或等于该签名者的证明(如
data.signed_attestations
中所示)中存在的最小目标 epoch 的证明,除非它是由signing_root
确定的重复签名。用伪代码表示:
target_epoch <=
min(att.target_epoch
for att in data.signed_attestations
if att.pubkey == attester_pubkey)
补充信息
-
interchange_format_version
版本设置为 5。 -
已签名区块或证明的
signing_root
是指使用 BLS 签名签署的消息数据(哈希树根)。它允许验证者在被要求时重新签名和重新广播区块或证明。 -
signed_blocks
的signing_root
使用compute_signing_root(block, domain)
计算:其中block
是已签署的区块(类型为BeaconBlock
或BeaconBlockHeader
),domain
等于compute_domain(DOMAIN_BEACON_PROPOSER, fork, metadata.genesis_validators_root)
。 -
signed_attestations
的signing_root
使用compute_signing_root(attestation, domain)
计算:其中attestation
是已签署的证明(类型为AttestationData
),domain
等于compute_domain(DOMAIN_BEACON_ATTESTER, fork, metadata.genesis_validators_root)
。
理由
支持不同的策略
交换格式的设计足够灵活,可以支持客户端可能实现的各种削减保护策略,这些策略可以分为两种主要类型:
- 完整:包含每个验证者签名的所有消息的数据库。
- 最小:仅包含每个验证者签名的最新消息的数据库。
最小策略的优点是其简单性和简洁性。仅使用每个验证者的最新消息,可以通过拒绝为先前的槽或 epoch 签名消息来实现安全的削减保护。
另一方面,完整策略可以提供安全的削减保护,同时还可以避免误报(这意味着它仅在这样做会保证削减时才阻止验证者进行签名)。
这两种策略通过包含条件(2)、(4)和(5)在交换格式中统一。这允许根据需要传输详细或简洁的信息。
整数表示
JSON 模式中的大多数字段都是字符串。对于可以以字符串或整数形式编码值的字段,选择了字符串。做出此选择是为了避免不同语言支持不同整数范围的问题(特别是 JavaScript,其中 number
类型是 64 位浮点数)。如果验证者尚未签署区块或证明,则只需将相关列表留空。
版本控制
interchange_format_version
设置为 5,因为该规范在其设计过程中经历了多次重大更改,并吸收了实施者的反馈。
向后兼容性
此规范与使用小于 5 的版本号的先前草案版本不向后兼容。
安全考虑
为了最大程度地降低风险和复杂性,该格式旨在干净地映射到实施者使用的内部数据库格式。但是,有一些陷阱值得指出。
完整数据库的建议
对于使用已签名消息的完整记录来实现其削减保护数据库的实施者,我们提出以下建议:
- 您必须确保除了从交换导入所有消息之外,还必须强制执行所有条件。尤其是,在采用交换格式之前,您的实现可能尚未强制执行条件(2)、(4)和(5)。我们的建议是始终强制执行这些规则,以保持实现的清洁并最大程度地减少攻击面。例如:您的削减保护机制不应签署槽号小于或等于先前已签名区块的最小槽号的区块,_无论_该最小槽区块是从交换文件中导入的还是作为数据库常规操作的一部分插入的。
- 如果您的数据库除了记录消息的槽/epoch 之外还记录消息的签名根,则应确保为没有签名根的导入消息在内部分配合适的虚拟签名根。我们建议使用特殊的“空”值,该值不同于所有其他签名根,但是也可以使用类似
0x0
的值(因为它极不可能与任何实际签名根发生冲突)。 - 必须注意避免在数据库中的间隙(未知签名活动的区域)内签署消息。如果两个交换导入的消息之间存在很大的间隙,第一个交换的最后一个条目和第二个交换的第一个条目之间存在很大的间隙,则可能发生这种情况。在此间隙中签名是不安全的,并且会违反条件(2)、(4)和(5)。可以通过在削减保护数据库的实际消息之外存储显式的低水位线,或者通过在导入时进行修剪,以使交换中最旧的消息成为数据库中最旧的消息来避免这种情况。
最小数据库的建议
对于希望通过仅存储每个验证者的最新区块和证明来实现其削减保护数据库的实施者,我们提出以下建议:
- 在导入期间,请确保获取每个验证者的_最大_槽区块以及_最大_源和目标证明。尽管条件要求强制执行最小值,但是建议的方法是从交换文件中获取最大值,然后将其与数据库中的任何现有值合并。例如,如果交换文件包含验证者
V
在槽 4、98 和 243 处的区块,则验证者V
的最新签名区块应更新为来自槽 243 的区块。但是,如果数据库已经包含此验证者在大于 243 的槽处的区块(例如,槽 351),则数据库的现有值应保持不变。
一般建议
- 为了避免导出过时的交换文件(此操作会产生削减的风险),您的实现应仅在验证者客户端或签名者_停止_时才允许导出削减保护数据库,换句话说,当客户端或签名者不再向数据库中添加新消息时。
- 同样,您的实现应仅在验证者客户端停止时才允许导入交换文件。
版权
在 CC0 下放弃版权及相关权利。
Citation
Please cite this document as:
Michael Sproul (@michaelsproul), Sacha Saint-Leger (@sachayves), Danny Ryan (@djrtwo), "EIP-3076: 保护性削减交换格式 [DRAFT]," Ethereum Improvement Proposals, no. 3076, October 2020. [Online serial]. Available: https://eips.ethereum.org/EIPS/eip-3076.