叔块验证与网络安全性

这篇文章主要介绍了叔块验证与网络安全性 ,文中通过代码以及文档配合进行讲解,很详细,它对在座的每个人的研究和工作具有很经典的参考价值。 如果需要,让我们与区块链资料网一起学习。

https://www.interchains.cc/21622.html

叔块验证与网络安全性是很好的区块链资料,他说明了区块链当中的经典原理,可以给我们提供资料,叔块验证与网络安全性学习起来其实是很简单的,

不多的几个较为抽象的概念也很容易理解,之所以很多人感觉叔块验证与网络安全性比较复杂,一方面是因为大多数的文档没有做到由浅入深地讲解,概念上没有注意先后顺序,给读者的理解带来困难

叔块验证与网络安全性

  • 叔块验证
  • Geth

每一种参与同一个共识协议的客户端,都必须有同样的行动,因此,一些看起来完全无害的操作可能正是导致一半网络相互隔离的罪魁祸首。

原题为:1 月挖出的那个块,584942419325

在一个共识协议中,最简单的错误也会导致灾难。 叔块验证与网络安全性

我准备开一个系列,讲解我在 go-ethereum(Geth 客户端)(以太坊eth协议的正式 Go 语言实现)中发现的 Bug,本篇是第一篇。虽然阅读这系列文章不需要你对 Geth 有多深的理解,但懂得以太坊eth协议是怎么运行的,会很有帮助。

这篇文章讲的是 Geth 客户端叔块验证程序中的一个 bug,传入一个专门构造的叔块后,该程序的行动是错误的。如果该漏洞被利用,会导致 Geth 节点和 Parity 节点发生分叉。

区块与叔块

每一条区块链blockchain都会在运行中产生一条大家都认可的主链(canonical chain);而主链的辨识方法也是协议定义好的:最长的链,或者总工作量最大的链,等等。不过,网络的延迟意味着,可能会有两个区块在同一时间生成。那么,只有其中一个能最终成为主链的一部分,而另一个则必须被抛弃。

某些区块链blockchain协议,比如BTC,会完全无视掉这些被落败的区块,让它们成为主链的 “孤块(orphan)”。另一些区块链blockchain协议,比如以太坊eth,依然会奖励挖出这些落败区块并努力传播它的矿工。在以太坊eth的语境中,这些仍然成为了主链一部分的孤块叫做 “叔块(uncle block)”。

但一个块要成为一个有效的叔块,还需满足一些条件:(1)该区块本身的所有内容都必须是有效的(根据正常的共识规则);(2)区块与其意图标记的叔块,两者的块高度相差不超过 6(一个叔块挖出后,只有在未来的 6 个区块以内被标记为叔块,才是有效的)。但是,这里有个例外:虽然正常的区块的时间戳间隔不应超过 15 秒,但叔块则无此限制。

关于整数的一个小插曲

大部分的编程语言都有依赖于平台的整数(platform-dependent integer)和定长整数(fixed-width integer)两种概念。依赖于平台的整数可能是 32 位或者 64 位的(等等),取决于程序所在的编译平台。在 C/C++ 和 Go 语言中,你可能会使用 uint,而在 Rust 中,你会使用 usize

但是,有些时候程序员想要保证其程序变量可以存储 64 位的数据,即使程序运行在 32 位的平台上。这时候,程序员可以使用定长的整数类型。在 C/C++ 中就是 uint64_t,Go 语言是 uint64,而在 Rust 中是 u64

使用这些语言自带的整数型的好处是,它们都具备最高优先级(first-class citizen),使用起来都非常简单。来看看这个支持 64 位整数的 Collatz Conjecture 实现:

func collatz(n uint64) uint64 {     if n % 2 == 0 {         return n / 2     } else {         return 3 * n + 1     } }

但是,这个实现有个瑕疵:它不支持超过 64 位的整数。因此,我们需要 大整数(big integers)。大多数语言都支持大整数,要么是用自带的标准库(比如 Go 的 big.Int),要么是通过外部代码库(比如 C/C++ 和 Rust 都是如此)。

难搞的是,使用大整数有一个很大的缺点:很不灵活。我们用支持任意大整数类型的 Collatz Conjecture 把上面的程序再实现一遍:

var big0 = big.NewInt(0) var big1 = big.NewInt(1) var big2 = big.NewInt(2) var big3 = big.NewInt(3)  func collatzBig(n *big.Int) *big.Int {     if new(big.Int).Mod(n, big2).Cmp(big0) == 0 {         return new(big.Int).Div(n, big2)     } else {         v := new(big.Int).Mul(big3, n)         v.Add(v, big1)         return v     } }

显然,64 位的版本既好写,又好读。所以,不意外的是,程序员都会尽可能使用简单的整数型。

例外 vs. 现实

以太坊eth协议中,可以预期大部分数据都不会超过 256 位,虽然某些整数字段的长度是任意的,无法有任何预期。重点是,区块的时间戳 Hs 也定义为一个 256 位的整数。

叔块验证与网络安全性 以太坊eth黄皮书,P6-

Geth 团队尝试通过验证叔块的时间戳是小于 2^256 - 1 的整数来满足这个定义。再次提醒,叔块的出块时间不受任何限制。

// Verify the header's timestamp if uncle {     if header.Time.Cmp(math.MaxBig256) > 0 {         return errLargeBlockTime     } } else {     if header.Time.Cmp(big.NewInt(time.Now().Add(allowedFutureBlockTime).Unix())) > 0 {         return consensus.ErrFutureBlock     } }

-来源-

但是,接下来的代码却要将区块时间戳强制调整为一个 64 位的整数,以计算该区块的正确难度。

// Verify the block's difficulty based in it's timestamp and parent's difficulty expected := ethash.CalcDifficulty(chain, header.Time.Uint64(), parent)

-来源-

如果 Parity 也是一样的做法,那也不会有什么大问题。但是,Parity 的时间戳在 2^64 - 1 就已到达上限,不会再溢出了。

let mut blockheader = Header {     parent_hash: r.val_at(0)?,     uncles_hash: r.val_at(1)?,     author: r.val_at(2)?,     state_root: r.val_at(3)?,     transactions_root: r.val_at(4)?,     receipts_root: r.val_at(5)?,     log_bloom: r.val_at(6)?,     difficulty: r.val_at(7)?,     number: r.val_at(8)?,     gas_limit: r.val_at(9)?,     gas_used: r.val_at(10)?,     timestamp: cmp::min(r.val_at::<U256>(11)?, u64::max_value().into()).as_u64(),     extra_data: r.val_at(12)?,     seal: vec![],     hash: keccak(r.as_raw()).into(), };

-来源-

也就是说,如果有个恶意的矿工,在所出的区块里纳入了一个叔块,该叔块的时间戳是 584942419325-01-27 07:00:16 UTC,也就是 unix 时间 2^64,那么 Geth 会用 Unix 时间 0 来计算难度,而 Parity 会用 unix 时间 2^64 - 1 来计算难度。结果会不一样,所以其中一个客户端会在验证叔块后从主链分裂出去。

Geth 团队在 PR 19372 中修复了这个 Bug,切换到所有时间戳都使用 unit64

结论

每一种参与同一个共识协议的客户端,都必须有同样的行动,因此,一些看起来完全无害的操作可能正是导致一半网络相互隔离的罪魁祸首。

这同样也表明,要发现一个影响巨大的 bug,你并不需要很高的技术水平。如果你对这些东西感兴趣,最好的办法就是立即动手。

下一篇文章,我们会讨论 Geth 客户端如何存储构成以太坊eth的数据,以及一个手段高明的攻击者可以如何规划一个定时炸弹,在引爆时导致链硬分叉。

(完)


原文链接: https://samczsun.com/the-block-mined-in-january-584942419325/ 作者: samczsun 翻译: 阿剑


本文首发于:https://ethfans.org/posts/the-block-mined-in-january

部分转自网络,侵权联系删除www.interchains.cchttps://www.interchains.cc/21622.html

区块链毕设网(www.interchains.cc)全网最靠谱的原创区块链毕设代做网站 部分资料来自网络,侵权联系删除! 最全最大的区块链源码站 ! QQ3039046426
区块链知识分享网, 以太坊dapp资源网, 区块链教程, fabric教程下载, 区块链书籍下载, 区块链资料下载, 区块链视频教程下载, 区块链基础教程, 区块链入门教程, 区块链资源 » 叔块验证与网络安全性

提供最优质的资源集合

立即查看 了解详情