找回密码
 立即注册
  • QQ空间
  • 回复
  • 收藏

比特币奇葩8问:为何区块620826比区块620825早1秒诞生?

数据区块链 2020-4-2 14:14 2400人围观 资讯

写在前面:

关于比特币,我们有时会遇到一些难以理解的技术问题,例如“新区块比旧区块早1秒诞生”、“同一时间不同全节点的大小不同”等奇葩现象,对于这些问题,就需要求助专业的开发者来帮忙解惑,在本文中,译者便选取了8个相对较有趣的问题,而来自比特币开发社区的大神们也给出了精彩的答案。
(注:以下问题和答案,均来自bitcoin.stackexchange.com)

比特币奇葩8问:为何区块620826比区块620825早1秒诞生(图片来自tuchong.com)

问题1 : 为什么两个完全同步的Bitcoin Core节点在区块链大小上是不同的?

问题具体描述:执行getblockchaininfo时,size_on_disk显示大小比同时(区块)报告的其他节点小1.2 GB。

txindex=1

可能是什么原因导致的?我已经在twitter上问过其它对等节点运营者,看是否有他人也有同样的经历,但每个人的账本数据都要比我多。 (https://twitter.com/bitdov/status/1231915231368163328)

Ugam Kamat答: 区块链大小上的差异,是由于节点存储的陈旧区块数导致的。陈旧区块是曾经构成主链一部分,但现在不属于主链的区块。

例如,如果有矿工同时在高度102挖取2个区块,当矿工通过gossip网络中继区块时,与矿工2开采的区块(102b)相比,更靠近矿工1的网络将首先接收它挖的区块(102a)。Bitcoin core将第一个接收到的有效区块添加到链的顶端。之后在同一高度接收的区块不会被删除,而是保存在数据库中,以防发生重组。因此,如果在区块(102b)之上挖取下一个区块103,则首先接收到102a的节点,会将其链重组为包含区块102b的链,如下图所示。

4

Bitcoin Core不会删除从其对等节点那接收到的任何有效区块。它永远存储在数据库中的blocks/blk****.dat文件中(这对于主链中的区块也是一样的)。但是,软件不会中继陈旧区块。为了接收陈旧区块,当你的对等节点从不同的链视图向你广播区块时,你需要在线。对等节点只会广播他们从当前活动链中看到的那些区块。因此,你只会拥有在线时收到的陈旧区块,由于这种可变性,许多节点的比特币区块链大小就是不同的。

问题2:我试着用bitcoin-core客户端同步整个区块链,然后这花了我大约9天的时间,结果却被破坏了,所以我不得不删除并重新同步。有没有资源可以通过torrent或常规浏览器下载?
chytrik答:如果你用torrent或其它方式下载区块链,但不验证收到的数据,那么你将无法得知收到的数据是否有效。这意味着你可能会轻易下载到一个被攻击者恶意更改的区块链,其中可能纳入了虚假交易,删除了合法交易等,这些都是你无法得知的。

这就是为什么bitcoin-core要花费时间来下载和验证区块链的原因:这是在无需信任的情况下,获得当前网络状态的唯一方法。

请注意,bitcoin-core在下载链数据时最有效,如果你下载一个区块链的torrent,然后尝试使用它进行验证,则需要更长的时间(你需要等待完整的下载,然后进行完整的验证,而不是并行地执行每个部分)。

我不知道有哪个软件能比bitcoin-core更有效地执行这些验证步骤。如果RAM利用率不足,可以尝试增加-dbcache选项。

问题3: 为什么比特币第620826个区块比第620825个区块早一秒诞生?
Andrew Chow答:比特币并没有要求后一个区块的时间戳要晚于前一个区块,唯一的要求是时间戳大于最后11个区块的时间戳中值。因此,这意味着一个区块在某个范围内的时间戳可以低于其父区块。

而第620826个区块早于第620825个,是因为矿工没有完全同步的时钟,它们的内部时钟可能略有不同,因此可能会延迟几秒钟。如果一个矿工真的很幸运,并由于时钟的不同,而很快找到另一个区块,那么由于时钟的不同,他的时钟可能仍落后于父区块的时间戳。这可能就是这里发生的事情。

问题4 :我能用同样的钱包运行两个比特币节点吗?

问题具体描述:我们在服务器上有一个比特币全节点和钱包,问题是我们的大多数钱包很久以前就完成同步了。对于我们来说,似乎此同步任务可能会花费大量时间,而在该时间段内,所有其他请求都将无法访问比特币节点,而用户将无法使用我们的服务器。

我们考虑在单独的服务器上复制当前的比特币节点,并在那里同步钱包。完成此过程后,我们会将钱包复制回原始服务器。

这是可行的吗?或者我们不能在两个不同的比特币节点上有相同的钱包?

Gašper Čefarin答:这是可行的,你可以根据需要运行多个具有相同钱包的节点。我想你之所以要这么做,是因为同步过程在另一个节点上会更快吗?该过程完成后,你必须要复制完整的区块链数据,而不是钱包本身。

你可能需要考虑检查的瓶颈,可能是硬盘、CPU或某些情况下的互联网带宽。

问题5 :为什么哈希公钥实际上对抗量子计算没有帮助?

问题具体描述:在关于taproot的讨论中,有人提到输出将直接包含公钥,而不是对它们进行哈希运算。有人说,目前,哈希运算并不能真正对抗量子计算提供帮助,这是为什么?

Andrew Chow答:虽然哈希一个公钥本身确实对抗量子计算提供了帮助,但实际上,只有在“真空”条件下才会是这样的,公钥哈希并不是存在于这样的环境中的,比特币还有很多其它东西需要考虑。

首先,如果公钥是经过哈希运算的,那么资金只有在使用前才是受到保护的。一旦使用了P2PKH或P2WPKH输出,就会公开公钥。当交易未经确认时,拥有足够快量子计算机的攻击者可以计算私钥并创建冲突的交易,从而将资金发送给自己,而不是预期的接收者。

此外,如果攻击者是一名矿工,他们可以对每一笔交易都这么做,只需拒绝挖取不向自己发送币的交易。

虽然这是一个问题,但人们通常认为,这要比直接花比特币要好,因为他们拥有区块链中的公钥。虽然这是真的,但是有大量公开公钥的输出。

目前有超过550 万 BTC的输出带有公开的公钥,它们要么是因为P2PK输出,要么是因为用户正在重用地址,因此其公钥在其他交易中是公开的。因此,如果存在一台量子计算机,它能够在合理的时间内为公钥生成私钥,则攻击者能够获取的比特币就是这些。

因此,虽然你的特定输出可能受到哈希的保护,但这些输出的值将是0,因为会有数百万BTC会被盗。哈希真正能做的,只是提供一种错误的安全感。

此外,工具和钱包软件也存在一些问题,它们只是在交易和区块链中以其他方式公开公钥。没有现有的工具将公钥视为私有信息,它们没有理由这样做。

涉及公钥的复杂脚本和合约还存在其他问题,这些脚本(如multisigs)并没有哈希公钥,此外,这些合约的存在通常是因为并非所有当事方都必须相互信任(其中一方可能是恶意的),在这种情况下,合约中的恶意参与者将知道所涉及的公钥,并能够窃取与这些输出相关的比特币。现有的公钥哈希无法防止这种情况。

最后,如果发现存在可以破坏ECDLP的量子计算机,就有可能向后量子密码体制过渡。如果及时检测到,但仍然来不及进行适当的升级,所有依赖ECDLP(即ECDSA和Schnorr)签名算法的使用都可以通过软分叉,从而锁定所有的币。然后,这些币可以通过提供一个零知识的证据来证明某些非公开的或抗量子的信息,这些信息会表明私钥的所有权。

例如,用户可以提供一个证据,证明他们拥有用于派生给定公钥对应私钥的BIP 32种子。由于它是零知识证明,种子本身不会公开(请注意,种子不是公私密钥对的一部分,因此不存在共享的公共组件)。由于大多数钱包都使用了BIP 32,这就足够了。或许还有其他方法可以证明所有权,而不必冒着尚未想到的币风险。

当然,这一切都假设有一台量子计算机能够计算出一个公钥的私钥,而公众却不知道这项技术已经存在。实际更可能的情况是,量子计算机的发展将被观察到,而且在它们强大到足以打破ECDLP之前的某个时刻,比特币将软性地引入一种抗量子签名算法。最终,依赖于ECDLP的签名将被删除。所有这些,都将在量子计算机真正成为威胁之前发生。因此在这种情况下,哈希公钥无论如何,都不会提供帮助。

请注意,以上所有内容不仅限于量子计算机,它通常适用于ECDSA(或Schnorr)的任何密码学破坏。

问题6 : 如何通过共享相同k值的两个签名获取私钥?

问题具体描述:为了创建测试,我编写了自己的ECDSA签名算法,使用它我创建了两个签名,从地址1GXFXm3es....发出,产生交易56ec7ca7df...这些签名使用了相同的k值(尽管k值永远不能重复使用)。

后来,有人从1GXFXm3es.... 这个地址偷走了0.0016BTC,并将这笔钱发送到了17WRjamox6VhTUaHsTWfFnMNDYHvwCtWio。

因此,必然有人在监控区块链是否存在此类错误,并在遇到此类错误时窃取资金。

那如何从共享相同k值的两个签名获取私钥?

Pieter Wuille答: ECDSA签名是(r,s)对,其中r=(kG).x mod n,以及s = (m + rx)/k mod n,这里面的x是密钥,k是随机nonce,而m是信息。

对于同一密钥有两个s值s1和s2,并且具有相同的nonce k(从而具有相同的值r),则可以执行以下操作:

  1. s1 = (m1 + r*x)/k
  2. s2 = (m2 + r*x)/k
从中我们可以得出:
  1. s1 * k = m1 + r * x
  2. s2 * k = m2 + r * x
  3. (s1-s2)* k = m1-m2
  4. k =(m1-m2)/(s1-s2)
  5. x =(s1 *(m1-m2)/(s1-s2)-m1)/ r
  6. x =(m1 * s2-m2 * s1)/(r *(s1-s2))(all mod n)
因此,你不仅可以轻松地检测具有相同随机数的签名(它们具有可识别的r值),而且一旦有人看到两个签名,就会有一个简单的公式来计算私钥。

至少从2013年起,这种攻击就已被广为人知了,也有人在积极利用它,不要重复使用k值,使用RFC6979确定但安全地生成它们。

还要注意的是,光k值不同还是不够的,它们也不能以已知的方式关联在一起,例如,你不能将k值用于一个签名,然后将k + 1用于下一个签名。

问题7:为什么比特币选择Merkle证明,而不选择RSA累加器,两者相比有什么优缺点?
Pieter Wuille答:

1、RSA累加器很难正确实施; 2、RSA累加器需要一个可信设置(单个或多个实体必须得到一个足够大的整数,它是2个素数的乘积,然后将这些素数丢弃)。比特币的设计通常是为了避免可信方; 3、对于128位安全级别,你至少需要3000位RSA模块,这意味着证明将是3000位。 与具有超过12层树的Merkle路径相比,这仅仅是一个优点,对于区块中的交易而言,这意味着超过4096笔交易。 通常情况并非如此,即便如此,也只是勉强如此。

问题8 : 三种比特币地址类型是否都可以互操作(legacy、segwit、native segwit)?

问题具体描述:是否可以在所有3种地址类型(legacy、segwit、native segwit-bech32)之间来回发送交易?

或者其中一类不能发送给另一类?

Pieter Wuille:在协议层面,它们都是兼容的,交易可花费其中任何一类,并发送给其中任何一种。

钱包软件当然可能会有限制,但这些限制通常与组合无关。

Murch♦补充回答:
在比特币协议中,从任何类型的输出发送到任何地址类型都没有限制,但是一些较旧的钱包,可能不支持发送到较新的地址类型。

让我们更好地了解一下在发送比特币交易时,具体可能会发生什么:

接收者选择一个他们想接收资金的地址,这就涉及到一个地址格式,而选择一种更有效的地址格式,可以节省开支,这符合接收者的利益。

发送者选择他们想要花费的输入,输入脚本是由这些输出之前接收到的地址类型设置的。然而,发送者被激励为他们的找零输出选择一个有效的地址类型,以节省未来的成本。

然而,较旧的电子钱包软件可能无法发送到较新的地址类型。具体来说,原生隔离见证地址在2017年3月才获得地址标准(BIP-173),并不是所有钱包都支持发送到这类地址。在这种情况下,发送者应该提供一个封装隔离见证地址。所有钱包都应该能够发送到封装隔离见证地址,因为它使用了2012年推出的Pay to Script Hash (p2sh, BIP-16) 地址标准。

在任何情况下,发送到任何特定地址类型的问题,都是由发送方钱包中缺少功能而导致的,而与使用的输入类型没有任何关系。

我有话说......