从LevelDB数据库获取所有密钥

Mik*_*ike 5 haskell leveldb

我正在编写一个脚本来收集所有比特币块的哈希值.程序bitcoind,如果更改某个设置,则存储LevelDB数据库中所有块的元数据.每组元数据的关键是块的散列,它通常用作它的标识符.本质上,我试图从每个块中获取元数据的特定部分(事务ID).我正在写的脚本是在Haskell中,尽管我可以在必要时总是执行shell命令.总而言之,我不确定最简单的方法是找到所有块哈希(键),然后调用bitcoind来获取每个块的元数据.如果有任何方法可以直接从LevelDB数据库中获取每个值,那么也可以.什么是最简单有效的方法?

Kir*_*ril 5

我不知道如何使用 haskell 完成此操作,但使用 C++ 执行此操作的最有效方法是使用 leveldb::Iterator 并在整个键范围内进行迭代

0x00000000 -> 0xFFFFFFFF(32 位密钥)
0x0000000000000000 -> 0xFFFFFFFFFFFFFFFF(64 位密钥)

示例中

leveldb::Slice start = ...; // 0x00000000
leveldb::Slice end = ...; // 0xFFFFFFFFFFFFFFFF
Run Code Online (Sandbox Code Playgroud)

该示例显示,当您迭代时,可以加载键和值:

leveldb::Slice key = it->key();
leveldb::Slice value = it->value();
Run Code Online (Sandbox Code Playgroud)

由于您不关心值,因此您可以跳过查询 的部分it->value(),只需收集您需要的键(在本例中为所有键),您应该会很好。我不会担心不必要地加载值会影响性能。

但是,这里要注意一件大事:当 bitcoind 正在运行时,您不能这样做!!!

之所以会出现这种情况,是因为在任何给定时间只能打开一个级别 DB 的实时实例,而 bitcoind 很可能已经将 db 实例保持打开状态,尝试打开另一个实例(即使只是为了读取)将导致一个错误。您可以获取数据库的快照迭代快照 tho。快照允许您保证 bitcoind 的最短停机时间。

最后,如果您无法承受 bitcoind 客户端的任何停机时间,那么您可能需要为 bitcoind 或 leveldb 编写一个包装器。您必须在某处引入抽象级别。

包装比特币:

  1. 在制作快照时关闭bitcoind。
  2. 缓冲对 bitcoind 的任何请求,直到您完成快照。
  3. 再次启动bitcoind。

围绕 leveldb 的包装:

level db 的包装器有点困难,你必须保持对数据库实例的控制,你必须实际进入并修改 bitcoind 代码,然后构建 bitcoind 并运行它。