BigBang icon indicating copy to clipboard operation
BigBang copied to clipboard

优化向钱包导入地址的性能

Open sunhantao opened this issue 5 years ago • 2 comments

当前的实现

  • 向钱包导入地址后,对于每个分支,从创世块开始向下遍历长链。
  • 将每个块从block.dat读取出来,再序列化
  • 从交易集合中选择与导入地址相关的放入到wallet中

优点

  • 当地址相关的交易非常多时,效率高
  • 使用resyncwallet时,如果wallet中地址较多、关联的交易较多,效率高

缺点

  • 当地址相关的交易较少时,效率很低
  • 实际情况下,单个地址导入的平均效率低

改进方案

  • 扩展block.dat的结构在CBlockEx基础上增加一个相关地址前序交易位置的数组
  • block.dat中每个交易对应数组中的一项,每项数据包含两个二元组,第一个二元组是from地址的,第二个二元组是to地址的。每个二元组有两个数据(PrevDiskPos, txDiskPos),PrevDiskPos表示该地址上一个交易索引的位置,txDiskPos表示当前交易内容的位置
  • 对于每一条分支创建一个leveldb数据库AddrTxIndex,key是上链的地址,value是最后一个交易索引的位置
  • 当长链发生变化时,需要回滚更新AddrTxIndex(类似unspent表)
  • 兼容性:
    • 需要根据原block.dat重构所有文件和数据库
    • 重构依据是block.dat中是否使用了新的nMagicNum,重构入口在checkrepair之前
    • 首选清除原数据库(除block.dat,votedata.dat)
    • 依次读取block.dat的块,不验证交易、块,写入到newblock.dat中
    • 全部更新后,将newblock.dat改名为block.dat

查询某个地址的所有交易

  • 查询每个fork的AddrTxIndex,如果没有则没有交易,如果有记录获得最后一个交易索引位置IndexPos
  • 读取文件索引位置的二元组(PrevDiskPos, txDiskPos),获得了最后一个交易的位置txDiskPos保存下来,和上一个交易索引的位置
  • 依次类推,直到PrevDiskPos = 0表明再无交易
  • 将交易的位置信息由早到晚将交易从block.dat中取出,交由wallet。

优点

  • 扩展性强
  • 精准度高,检索的仅仅是该地址的交易所有交易
  • 对于交易不多的地址效率高

缺点

  • 交易量大的地址效率低于原实现

两种方案同时存在

  • 在RPC importprivkey, importpubkey, importkey, importtemplate中增加参数synctype,在参数sync开启时,默认使用新方式,也可以设置为旧方式(交易量大的地址)
  • 优化RPC importwallet,在地址全部导入后调用resyncwallet(旧方式)
  • 再RPC resyncwallet 中增加参数synctype,默认使用旧方式,也可以设置为新方式

sunhantao avatar Sep 16 '20 07:09 sunhantao

过滤器的方案

  • 在CBlockIndex中增加一个过滤器字段,将该块中所有交易涉及的地址集合放到过滤器上。根据交易的大小该字段的大小范围约为0 - 5k
  • 在检索时遍历CBlockIndex并判断地址是否有可能在这个块中,如在将块读出来筛选交易

优点

  • 效率比原方案快的多
  • 代码容易编写,改动量小
  • 处理简单,不用考虑回滚

缺点

  • 占用内存大,需要考虑blockindex无法在内存全放下的情况(原代码随着时间推移也有blockindex不能全放内存的时候,只是该方案加快了这个临界点的到来)
  • 有误报率,且过滤器的容量和误报率成反比,这个误报率的数值需要考虑
  • blockindexdb数据库数据比较大可能有读取速度问题

sunhantao avatar Sep 16 '20 07:09 sunhantao

全局过滤器方案

  • 对于每一个fork有一个全局过滤器
  • 过滤器hash的内容是addr + blockhash
  • 通过内存中计算该地址是否可能在某个block中有交易,读取block数据,筛选其中的交易

优点

  • 效率高
  • 支持多地址索引

缺点

  • 占用内存大,未来可能考虑将过滤器部分放在文件中
  • 有误报率

sunhantao avatar Sep 16 '20 08:09 sunhantao