外部确认哈希率

  • rsksmart
  • 发布于 2022-04-26 21:12
  • 阅读 11

该提案(RSKIP 178)旨在改进RSK区块链的安全性,通过引入“外部确认哈希率”机制,使RSK节点能够计算活跃的SHA256哈希率,检测与攻击相关的活跃哈希率变化,并将所有活跃的SHA256哈希率累积到RSK区块链中,从而提高抵抗双重支付攻击的能力。该机制不仅包括比特币哈希率,还可能包括来自比特币分叉的哈希率,以此增强RSK的安全性。

RSKIP 178
Title 外部确认哈希率
Created 2020年9月
Author SDL
Purpose Sec
Layer Core
Complexity 2
Status Draft
discussions-to

摘要

兼容分叉的包含式联合挖矿(IFAMM)协议提出了一种适用于联合挖矿区块链的新安全模型。如果区块链实现了 IFAMM 协议,并且满足模型的假设,则该模型可确保防止大型双花攻击,通过使攻击可见、可归因、需要至少 51% 的比特币矿工合谋,更重要的是,需要一个有界的时间,其中界限取决于攻击者的哈希率,但可以提前知道。可以调整界限参数,以便在发生攻击时,社区可以协调行动,例如安排手动使区块无效,或通过侧链(例如社交网络和论坛)执行硬分叉,以阻止攻击。

此 RSKIP 代表了实现 IFAMM 模型下的安全性所需的对 RSK 共识的更改之一。

动机

对没有补贴的独立工作量证明链的密码经济安全的主要贡献是高额的交易费用。然而,在像 RSK 这样受联合挖矿保护的比特币侧链中,比特币矿工和联合矿工之间存在战略激励对齐,从而为侧链的安全性提供了两个额外的保证。首先,如果侧链的哈希率接近主链的哈希率,则可以继承诚实多数属性。其次,由于比特币矿工在区块中识别自己,因此对侧链的攻击变得可归因,或者通过直接识别参与攻击的矿池,或者通过突然删除区块中恶意矿池的识别信息。尽管如此,RSK 更进一步,部署了 Armadillo 系统以提供分叉感知。Armadillo 创建了一个时间窗口,以在发生长时间的重组尝试时触发社区的紧急响应。但是,Armadillo 需要单独的通信通道,并且至少需要一个诚实的节点来监控比特币网络的分叉。 IFAMM 协议(此 RSKIP 只是其中的一部分)基于一个安全模型,该模型捕获了 Armadillo 的优势,但将其去中心化。IFAMM 协议非常适合 RSK,因为它不仅关注攻击者的哈希率能力,还关注成功攻击所需的处理时间。

此 RSKIP 提出了一项共识变更,使 RSK 节点能够:

  • 计算活跃的 SHA256 哈希率并检测与正在进行的攻击兼容的活跃哈希率的变化

  • 将所有活跃的 SHA256 哈希率累积到 RSK 区块链中,而与直接参与联合挖矿的哈希率数量无关。这种额外的哈希率确认侧链区块,从而提高了基于长区块链重组的双花攻击的安全性。此外,累积的哈希率不仅可以捕获 100% 的比特币哈希率,还可以捕获来自比特币分叉的哈希率。

规范

RSK 区块头是以下元素的列表:

parentHash, unclesHash, coinbase,stateRoot, txTrieRoot, receiptTrieRoot, logsBloom, difficulty, number, gasLimit, gasUsed, timestamp, extraData, paidFees, minimumGasPrice, uncleCount, ummRoot [, mergeMiningFields ] 

mergeMiningFields 如下:

bitcoinMergedMiningHeader,
bitcoinMergedMiningMerkleProof,
bitcoinMergedMiningCoinbaseTransaction

我们将 mergeMiningProof 定义为一个包含 mergeMiningFields 的列表。

区块编码为:

blockHeader, transactions, uncles

uncles 是 RSK 区块头的列表。我们将 heavyblock 定义为一个具有某些属性的 mergeMiningProof,这些属性将在共识中得到验证。

我们扩展 uncle 列表,以在所有 RSK 区块头之后包含多个 heavyblock 元素(稍后定义)。为了保持语义连贯性,uncles 字段被重命名为 difficultyContributors。字段 uncleCount 被重命名为 difficultyContribution

difficultyContributors 将是一个包含两个元素的 RLP 列表:第一个是旧的 uncles 列表。下一个是新的 heavyblocks 列表。

difficultyContributors  = { uncles  , heavyblocks }

difficultyContributors 也将是一个包含两个元素的 RLP 列表:第一个称为 immediateContribution,表示 uncle 贡献的难度。第二个称为 delayedContribution,表示确认 heavyblock 所做的贡献。

difficultyContributors = { immediateContribution , delayedContribution }

uncles 中引用的 uncle 的最大数量将从 10 减少到 6。

heavyblocks 中引用的 heavyblock 的最大数量将为 2。

比特币区块头包含以下字段:

字段 目的 大小(字节)
Version 区块版本号 4
hashPrevBlock 前一个区块头的 256 位哈希值 32
hashMerkleRoot 基于区块中所有交易的 256 位哈希值 32
Time 自 1970-01-01T00:00 UTC 以来的当前区块时间戳,以秒为单位 4
Bits 当前的目标,采用紧凑格式 4
Nonce 32 位数字 4

我们定义如何将 Bits 字段转换为可以与 RSK 区块难度进行比较的目标难度。

Bits 字段以紧凑格式存储。设 Bits 为字节数组 { E,Q1,Q2,Q3 }。设 M 为整数值 (Q1 << 16 + Q2 << 8 + Q3)(即以大端方式解释的 Q 数组)。比特币目标计算为 M*2^(8(E-3))。我们定义 btcDifficulty0 = 2^256 / target。请注意,btcDifficulty0 比比特币区块难度高 2^32 倍。

验证

我们定义函数 getPoWInfo() 来检查所有类型的区块(主链、uncle 和 heavyblocks 列表中的元素)的有效性。这意味着检查普通 RSK 区块的工作量证明有效性的函数已更改为调用 getPoWInfo()。这是因为一些 RSK 区块可以是锚定 heavyblock。

首先,我们定义一个辅助函数 getMMInfo()

function getMMInfo()

参数:

  • mergeMiningFields

返回值:

  • boolean mergeMined
  • boolean isMMValid
x = bitcoinMergedMiningCoinbaseTransaction of mergeMiningFields

midstate40 = x 的前 40 个字节
tail = 跳过前 40 个字节后 x 的剩余字节

lastTag = tail 中 "RSKBLOCK:" 的最后一个 Index
byteCount = bigEndianToInt64(从偏移量 8 开始提取 midstate40 的 4 个字节)
mergeMined = (lastTag>=0)

if (not mergeMined) then
    if ((tail.length>=169) and (tail.length&lt;233)) or (byteCount==0)
        return (false,false)
    else
        return (false,true)
else    
    expected = "RSKBLOCK:"+ RSKHashForMergedMining
    rskTagPosition = expected 在 tail 中的最后一个 Index
    if (rskTagPosition == -1)  return (true,false)
    if (rskTagPosition >= 64)  return (true,false)
    if (rskTagPosition !=lastTag) return (true,false)
    if (tail.length - rskTagPosition > 169) return (true,false)

coinbaseLength = tail.length + byteCount;
if (coinbaseLength &lt;= 64) return (mergeMined,false)

transactionHash = SHA256(tail) 从 midstate40 开始
coinbaseTransactionHash = reverseBytes(transactionHash)

if (not validMerkleTree(merkleRoot,coinbaseTransactionHash)) return (mergeMined,false)
return (mergeMined,true)

getMMInfo() 函数的逻辑与 rskj 中的 ProofOfWorkRule 中现有的逻辑非常相似,ProofOfWorkRule 必须更改为使用此函数。

如果 (isMMValid==true) 且 (mergeMined==true),则输入表示一个 锚定 heavyblock(它也可以是内部 uncle、外部 uncle 或主链区块)。

如果 (isMMValid==true) 且 (mergeMined==false),则输入表示一个 确认 heavyblock

锚定 heavyblock 可以通过三种不同的方式引用:

  • 在普通主链 RSK 区块中,使用主链区块联合挖矿证明
  • 在 RSK uncle 区块头中,使用 uncle 的联合挖矿证明,表示 内部 uncle 锚定 heavyblock
  • heavyblocks 列表中,也表示一个 外部 uncle 锚定 heavyblock,但该 heavyblock 是从比特币区块链中提取的,而不是从 RSK 网络中提取的。

为了从比特币区块链中识别 外部 uncle 锚定 heavyblock,必须扩展 ARMADILLO 数据以至少包含 14 个字节的 RSK 父区块 ID,或者与之关联的 4 个字节的比特币区块 ID。在 ARMADILLO 得到改进之前,此 RSKIP 建议使用当前的 ARMADILLO 标签来识别 uncle。这将使 uncle 的范围扩展到最多 64 的深度,这有助于在深度 64 以内的“无利害关系”双花。通过在 ARMADILLO 数据中仅包含先前 RSK 区块的比特币 pow 的两个字节,攻击概率降低了 2^16 倍。换句话说,考虑到 50% 的哈希率联合挖矿 RSK,攻击机会只会每 2.5 年自发发生一次。

请注意,rskj 中 SHA256Digest 类的 midstate 使用与此描述中使用的格式不同的格式。我们调用我们的变量 midstate40 以区分它们。

同样重要的是要注意,上述算法要求对于没有联合挖矿的区块,tail 大小必须等于或大于 169 个字节,但小于 233 个字节,否则 midstate 实际上是 SHA256 初始状态,而对于具有联合挖矿标签的标头,tail 大小必须小于 169 个字节。最后一次检查与当前检查 ProofOfWorkRule 执行的方式相同:

    remainingByteCount = tail.length - rskTagPosition - 41
    if (remainingByteCount > 128) return (true,false)

需要 169 个字节的 tail 是为了防止攻击者通过在之后指定起始位置来隐藏 RSK 标签。

function getPoWInfo()

参数:

  • rskBlockHeader,
  • mergeMiningProof,
  • boolean fromHeavyblocksArray,
  • boolean mainchain,
  • boolean uncle

返回值:

  • boolean isValid
  • uint immediateDifficultyContribution
  • uint delayedDifficultyContribution
  • boolean includeInBtcBlockReferences
isValid = false
immediateDifficultyContribution =0
delayedDifficultyControbution =0
includeInBtcBlockReferences = false

if not fromHeavyblocksArray
    // 所有 RSK 区块(uncle 或主链)都必须在
    // RSK 区块难度下具有有效的工作量证明
    if not rskProofOfWorkValid(rskBlockHeader,bitcoinMergedMiningHeader) then return

(mergeMined,isMMValid) =getMMInfo(mergeMiningProof)
if not isMMValid return

isHBTimeValid = abs( bitcoinMergedMiningHeader.timeStamp - rskBlockHeader.timeStamp) &lt; 300
if not isHBTimeValid return

btcDifficulty0 =getBtcDifficulty0(bitcoinMergedMiningHeader)
isPotentialHeavyBlock=(btcDifficulty0 >= difficulty) 
if  (isPotentialHeavyBlock) 
    isHeavyblock = btcProofOfWorkValid(bitcoinMergedMiningHeader) return
else
    isHeavyblock = false

if not mergemined
    // 这只能是一个确认 heavyBlock
    if (not fromHeavyblocksArray) return
    if (not isHeavyblock) return
    // 我们检查是否注册了一个 btc 父级
    if btcBlockpreviouslyIncluded(bitcoinMergedMiningHeader.getBlockHash()) return
    delayedDifficultyControbution = C(rskBlockHeader,bitcoinMergedMiningHeader)
    includeInBtcBlockReferences = true

if not isHeavyblock and mergemined
    if (fromHeavyblocksArray) return
    // 这是一个正常区块或 uncle 区块
    immediateDifficultyContribution = R(rskBlockHeader,bitcoinMergedMiningHeader)
    if not previouslyIncluded(bitcoinMergedMiningHeader.parent) return
    // uncle 已经检查了以前的包含,并且 uncle 包含深度
    // 短于 IFAMM 深度,因此我们不需要再次检查。
    // 此检查不应更改任何内容,并且可以用作断言
    if btcBlockpreviouslyIncluded(bitcoinMergedMiningHeader.getBlockHash()) return

if isHeavyblock and mergemined
    // 这是:
    // * 内部 uncle 锚定 heavyblock 或
    // * 外部 uncle 锚定 heavyblock
    // * 主链锚定 heavyblock
    includeInBtcBlockReferences = true
    if (fromHeavyblocksArray)
        // 外部 uncle 锚定 heavyblock
        immediateDifficultyContribution = C(RSKblockHeader,bitcoinMergedMiningHeader)
    else
        // 内部锚定 heavyblock 或 uncle 锚定 heavyblock
        immediateDifficultyContribution = A(rskBlockHeader,bitcoinMergedMiningHeader)
else
    // fromHeavyblocksArray 中的元素必须是以比特币难度解决的区块
    if fromHeavyblocksArray return

isValid = true
return

在所示的伪代码中,btcProofOfWorkValid() 检查比特币标头的工作量证明是否与比特币标头中指定的难度匹配。该算法计算比特币标头指定的 btcDifficulty0,并检查它是否高于包含它的 RSK 区块的难度。调用函数 getMMInfo() 检查 bitcoinMergedMiningMerkleProof 与 mergeMiningProof 的其他两个字段是否正确,根据用于验证联合挖矿的相同共识规则。

每个联合挖矿证明,在主链中、在 uncle 列表中或在 heavyblocks 列表中都必须使用 getPoWInfo() 方法进行验证。如果该方法返回 isValid==false,则该区块无效。如果该方法返回 iincludeInBtcBlockReferences==true,则这意味着它是一个锚定或确认 heavyblock,因此关联的比特币区块哈希必须包含在 btcBlockReferences 列表中,该列表可以被 btcBlockPreviouslyIncluded() 引用。

如果具有给定哈希的比特币标头包含在 btcBlockReferences 列表中,则函数 btcBlockPreviouslyIncluded() 返回 true。此数组维护过去 256 个区块中包含的所有 heavyblock 的列表。该数组不需要存储,因为每次都可以从过去 256 个区块中的 heavyblock、uncle 和主链区块重新计算它。请注意,引用可能形成 DAG,因此包含的 heavyblock 可能在过去 256 个区块中具有多个子项。

累积难度

让我们将 A 称为锚定 heavyblock 对链累积难度的贡献。

让我们将 R 称为比特币标头难度未达到 btcDifficulty0 的普通 RSK 区块的难度贡献。

让我们将 C 称为确认 heavyblocks 对链累积难度的贡献。

A、R、C 是当前 RSK 区块头和 merge-mining 字段引用的比特币区块头的函数。

我们提出以下函数:

A=btcDifficulty0/2

R=difficulty/2

C=btcDifficulty0

这些公式需要使用 256 位算术。此分配平均最多高估 RSK 区块链累积难度 1/20(RSK 和比特币之间的平均区块间隔的比率),我们认为此误差足够低以优先选择简化的公式。

精确值由以下公式给出:

q = btcDifficulty0/difficulty R = difficultyq/(2q-1) A = btcDifficulty0q/(2q-1)

C=btcDifficulty0

这些公式可能需要高达 512 位的算术运算。

请注意,R 和 C 贡献于 de immediateContribution 字段,但 A 贡献于 delayedContribution 字段。难度贡献不会直接应用于累积难度:这些值被压缩到 difficultyContribution 字段(这可能会导致一定的精度损失),并且只有这个量会被贡献回累积难度。这使得从 difficultyContributiondifficulty 字段轻松计算累积难度。

delayedContribution 在 40 个区块后应用于累积难度。

difficultyContribution 的计算

为了构建 immediateContributiondelayedContribution 字段,将它们的实际值乘以 1024,然后加在一起,然后除以 RSK 区块 difficulty。因此,difficultyContribution 字段将按 1024 缩放存储。这保证了 heavyblock 的 0.1% 精度,而不会占用太多空间。对于比特币区块(其难度约为 RSK 难度的 40 倍),精度为 0.0025%。对于难度在 RSK 的 1 到 2 倍之间的比特币现金区块,精度为 0.1%。

Sha256Digest 类 Midstate

Sha256Digest midstate 的长度为 52 个字节。要初始化以用于 RSK 联合挖矿,它要求前 8 个字节和最后 4 个字节设置为零。这是因为 Sha256Digest midstate 允许从流中的任何点开始,而 RSK 协议要求起始点与 64 字节的边界匹配。

Sha256Digest midstate 的映射:
0: xBuf (4 字节数组) 由 RSK 清零(用于处理子字数据的缓冲区)
4: xBufOff (int32) 由 RSK 清零(填充的 xBuf 的偏移量)
8: byteCount (int64) &lt;--- midstate40 从此处开始
16: H1 (uint64)
20: H2 (uint64)
24: H3 (uint64)
28: H4 (uint64)
32: H5 (uint64)
36: H6 (uint64)
40: H7 (uint64)
44: H8 (uint64) &lt;--- midstate40 在此字段后结束
48: xOff (int32) 由 RSK 清零(在 misdtsate 之后未更新到哈希中的字数(模 64))

交易确认

在 Nakamoto 共识中,如果在交易被包含后有 N 个区块确认,则确认交易。在 IFAMM 模型中,我们建议经济参与者也等待 N*v 时间,其中 v 是平均 RSK 区块间隔(目前为 30 秒)。

基本原理

已经采取了几个设计选择。本节介绍最相关的。

更改区块头

向 RSK 标头添加新字段会增加轻节点的带宽消耗。为了避免向 RSK 区块头添加新字段,heavyblock 与 uncle 一起打包在 difficultyContributors 字段中。这在语义上是有意义的,因为 uncle 和 heavyblock 在协议中具有相似的角色:有助于区块的累积难度。

限制 heavyblock 的数量

difficultyContributors 字段中引用多个 heavyblock 有两个原因:

  1. 接受来自比特币分叉的 heavyblock,在这种情况下,在相同的 RSK 区块间隔内创建了多个类似比特币的区块。但是,这种情况很少见。大多数比特币分叉具有与比特币相同的区块平均间隔,因此,queued 许多 heavyblock 的风险极低。
  2. 如果由于网络健康问题而暂停 RSK 联合挖矿,则接受从比特币到 RSK 的工作量证明转移。在这种情况下,确认 heavyblock 可能会在一段时间内累积,因此它们会 queued 以添加到 RSK 区块,并且 RSK 区块需要能够尽快处理它们。但是,接受旧的确认 heavyblock 也可能是一种攻击向量,例如,如果存在 RSK 矿工不知道的某个比特币分叉,并且此分叉正在生成区块,则自私的 RSK 分叉可能会尝试引用来自此假设分叉的数百个过去的确认 heavyblock,并重组 RSK 区块链。因此,这个 RSKIP 要求 RSK 区块时间戳也接近确认 heavyblock 时间戳。

虽然平均 RSK 区块现在比比特币现金区块向区块链转移更多的难度,但这归因于 uncle 区块的存在。虽然当前的 RSK 哈希率比比特币现金高 23 倍,但 RSK 区块的实际难度略低于比特币现金区块。因此,RSK 可以引用比特币现金 heavyblock。

延迟确认 heavyblock 的难度贡献

delayedContribution 在 60 个区块后应用于累积难度。这是为了阻止攻击和意外情况。如果所有难度贡献都是立即的,那么:

  • 当恶意矿工在比特币中看到确认 heavyblock 时,它可以创建一个区块模板,该模板具有一个父区块,该父区块落后于最佳区块 10 个区块,并且,如果它首先找到下一个区块,它会立即恢复区块链的 10 个区块,因为 heavyblock 贡献的难度高于 10 个普通 RSK 区块。
  • 如果比特币网络创建一个陈旧区块,一些矿工可能会看到它,而另一些矿工可能不会。如果恶意矿工看到比特币陈旧区块是一个确认 heavyblock 区块,但其他人都没有看到,那么他可以通过在他的私有链中引用该 heavyblock 来恢复 RSK 区块链并执行双花攻击。

通过延迟贡献,第一个问题被消除,因为诚实的分叉也会在恶意分叉增加其难度之前引用确认 heavyblock。

第二个问题得到了缓解,因为通过延迟,攻击者需要通过挖掘自私区块来赶上诚实链才能实现优势。由于陈旧区块的贡献,该优势可能约为 40 个区块,但攻击者也会获得 1 到 40 个区块的劣势,因为他必须恢复已确认的交易才能进行双花。支付金额越高,受害者将等待确认的区块越多。模拟表明,在难度转移延迟 60 个区块的情况下,攻击者仍然需要超过 40% 的 RSK 哈希率才能尝试恢复 20 个区块的双花。

向后兼容性

此更改是硬分叉,因此必须更新所有完整节点。还应更新 SPV 轻客户端和区块浏览器。

测试用例

待定

实施

至少需要在以下位置修改 rskj 代码:

  • 必须修改co/rsk/core/DifficultyCalculator.javagetBlockDifficulty() 现在接收 difficultyContribution 字段。
  • 必须修改 co/rsk/core/bc/SelectionRule.javaisBrokenSelectionRule() 当前考虑 uncle 计数,它应该考虑 difficultyContribution
  • co/rsk/remasc/Sibling.java 必须以与 SelectionRule.java 相同的方式进行修改。
  • 必须修改 co/rsk/mine/ForkDetectionDataCalculator.java。Armadillo 2 不需要此值。因此,如果在该 RSKIP 之前实施 Armadillo 2,则 uncle 的数量将不再存在或针对 Armadillo 进行验证,因为 Armadillo 2 会将完整的累积难度打包到同一空间中。如果在 Armadillo 2 之前实施此 RSKIP,则仍可以验证 uncle 计数,尽管它不会为 Armadillo 分叉检测模块提供任何好处。

安全考虑

通过增加其成本(达到比特币级别的密码经济安全性)或通过迫使攻击者在整个支付确认间隔内公开攻击,在比特币区块中留下锚定 heavyblock 的痕迹并减少转移到 RSK 的累积哈希率,此 RSKIP 可保护 RSK 网络免受大量双花攻击。

但是,某些双花攻击的变体,例如隔离受害者节点,仍然需要进行额外的更改才能防止。IFAMM 模型需要的这些其他更改将在其他 RSKIP 中指定。

版权

通过 CC0 放弃版权和相关权利。

  • 原文链接: github.com/rsksmart/RSKI...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
rsksmart
rsksmart
江湖只有他的大名,没有他的介绍。