以太坊fast sync时,currentBlock跟不上highestBlock

来自issue

https://github.com/ethereum/go-ethereum/issues/16875

对很多人来说,同步以太坊是一个痛点,所以我会试着详细描述发生在幕后的事情,这样可能会少一些困惑。

Geth的当前默认同步模式称为快速同步。不是从创世块开始并重新处理所有发生过的交易(执行交易可能需要数周时间),而是快速同步下载这些块,并且只验证相关的工作证明。下载所有块是一个简单和快速的过程,将相对快速地重新组装整个链。

许多人错误地认为,因为他们有区块,所以他们是同步的。不幸的是,情况并非如此,因为没有执行任何交易,所以我们没有任何可用的帐户状态(例如,余额,nonces,智能合约代码和数据)。这些需要单独下载,并与最新的块交叉检查。这个阶段称为状态trie下载,它实际上与块下载同时运行;唉,现在下载这些数据比下载块花的时间要长得多。

状态树是什么?在以太坊主网中,已经有大量的帐户跟踪每个用户/合约的余额、nonce(发起转账的次数)等。然而,帐户本身不足以运行一个节点,它们需要以密码方式链接到每个块,以便节点能够实际验证帐户没有被篡改。这种加密链接是通过在帐户上方创建树数据结构来完成的,每一层都将其下的层聚合到一个更小的层中,直到到达单个根(叶子结点)。这种包含所有帐户和中间加密证明的巨大数据结构称为状态树。

为什么会有问题呢?这个树数据结构是由数亿个微小的加密证明(trie节点)组成的复杂的链接。要真正拥有同步节点,您需要下载所有帐户数据,以及所有微小的加密证明,以验证网络中没有人试图欺骗您。这本身已经是非常多的数据项了。更糟糕的是,这些数据在不断变化:在每一个块(15秒)中,从这个trie中删除大约1000个节点,并添加大约2000个新节点。这意味着您的节点需要同步每秒更改200次的数据集。最糟糕的是,当您同步时,网络正在向前移动,并且在您下载时开始下载的状态可能会消失,因此您的节点需要在收集所有最新数据时不断地跟踪网络。但是,在实际收集所有数据之前,本地节点是不可用的,因为它无法以加密方式证明任何帐户的任何信息。

如果您发现您落后于mainnet 64个块,那么您还没有同步,甚至还没有接近。您刚刚完成了块下载阶段,并且仍然在运行状态下载。您可以通过看似无穷无尽的导入状态项[…][日志流。在您的节点真正联机之前,您还需要等待。

 

问:节点只是挂在导入状态enties?

答:节点不会挂起,它只是事先不知道状态trie有多大,所以它会一直挂起,挂起,直到发现下载了所有的状态

原因是Ethereum中的块只包含状态根,即根节点的单个散列。当节点开始同步时,它确切地知道1个节点并尝试下载它。该节点最多可以引用16个新节点,因此在下一步中,我们将了解大约16个新节点并尝试下载它们。在下载过程中,大多数节点都会引用到之前不知道的新节点。这就是为什么你可能会认为它卡在相同的数字上。它不是,而是在过程中发现并下载trie。

 

我落后主网64个区块?!

答:如上所述,您没有被卡住,只是完成了块下载阶段,等待状态下载阶段也完成。现在,后一个阶段的时间比仅仅获取数据块要长得多。

 

问:为什么下载状态需要这么长时间,我有很好的带宽?

状态同步主要受限于磁盘IO,而不是带宽。

Ethereum中的状态trie包含数亿个节点,其中大多数以引用最多16个其他散列的单个散列的形式存在。这是一种在磁盘上存储数据的糟糕方法,因为它几乎没有结构,只有引用更多随机数的随机数。这使得任何底层数据库都在哭泣,因为它无法以任何有意义的方式优化存储和查找数据。

不仅存储数据非常不理想,而且由于200次/秒的修改和对过去数据的删除,我们甚至无法下载它,这是一种正确的预处理方式,使其导入速度更快,而不需要底层数据库对其进行太多的移动。最终的结果是,即使是快速同步,现在也会带来巨大的磁盘IO成本,这对于一个机械硬盘驱动器来说是太多了。

 

问: 所以我不能在机械硬盘上运行一个完整的节点?

不幸的是不能。在硬盘上进行快速同步所花费的时间比使用当前数据模式等待的时间要长。即使您等待它结束,硬盘驱动器也无法满足主网上交易处理的读/写需求。

然而,您应该能够在对系统资源影响最小的情况下在硬盘上运行轻节点客户机。但是,如果希望运行全节点,那么固态硬盘是惟一的选择。

你可能感兴趣的:(以太坊,快速同步fast,sync,以太坊开发,以太坊杂谈)