V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
fox1751
V2EX  ›  Bitcoin

比特币核心钱包(Bitcoin Core)中部分交易记录没有了,可能是什么原因?

  •  
  •   fox1751 · 2021-02-23 08:59:38 +08:00 · 1006 次点击
    这是一个创建于 1401 天前的主题,其中的信息可能已经有所发展或是发生改变。

    2013 年接触到比特币,当时随便玩了下。2014 年底 2015 年初的时候,都卖掉了,但是当时比特币核心钱包里面还有零点几个的比特币,因为当时卖的时候比特币最低才两千来块人民币,零点几个不值多少钱就放着没管后面也几年都没再关注比特币了,但是 wallet.dat 文件一直加密备份存在百度网盘。然后我清楚的记得,在 2019 年的时候,因为偶然听说比特币涨到十万人民币一个了,就又找出 wallet.dat 备份文件,同步区块,然后把剩下的零点几个冲到火币网给卖了提现 rmb 了。然后里面还剩下零点零零几个。最近比特币一路飙升,又找出来 wallet.dat 备份文件同步完后发现,交易记录中最后只有 2015 年的记录了。2019 年卖出那零点几个的记录没有了。可能的原因是什么? 交易记录:

    12 条回复    2021-03-02 23:52:53 +08:00
    pkwenda
        1
    pkwenda  
       2021-02-23 20:34:58 +08:00
    还是同步区块的问题,之前 dogecoin,IFC 等山寨币我都出现过这个问题,甚至 IFC 没有矿工了,自己当了把矿工给交易了,你这个问题看着像客户端同步的问题,毕竟 19 年的都没了,0.0x 估计也有几千块了,慢慢研究吧,应该有解
    acess
        2
    acess  
       2021-02-23 22:19:28 +08:00
    非开发者,来啰嗦几句……

    Bitcoin Core 全节点钱包的工作原理我记得非常简单粗暴、也非常低效:直接扫描几十上百 GB 的区块文件,从里面匹配过滤出与自己有关的交易,然后保存到 wallet.dat 里面。
    这某种程度上也是无奈之举,因为如果要编制索引的话( txindex 那个太简陋了,完全不够用),虽然可以达到在线区块浏览器那种几乎是秒速查到结果的速度,但是占硬盘又太大——比特币不是讲究去中心化嘛……于是,实际上还是这个最简单粗暴也是最低效的办法来维护钱包交易记录。

    所以,如果 wallet.dat 里面漏了什么交易没扫描进去,那就比较麻烦,需要重新把几十上百 GB 的区块扫描一遍。

    于是我啰嗦了那么半天,才终于触及到楼主的问题(应该是这样):为啥 wallet.dat 里会漏掉一些交易没扫描呢?

    额,坦白说,我也不是很清楚。


    按理说,wallet.dat 里也会记录上次扫描到的区块位置,这样下一次打开钱包进行同步(扫描区块),就不需要重复扫描那个时间点之前了,毕竟之前已经扫过了嘛。

    “重新把几十上百 GB 的区块扫描一遍”——具体要扫多少,就取决于钱包里标记的时间点,时间点距离现在越久远,涉及的区块就越多,扫描量当然就更大、更费时了。


    所以……也许楼主是触发了什么 bug 吧。

    比如,如果是区块同步已经完成后加载 wallet.dat ,那按理说应该会有一个耗时挺久的区块扫描过程,几分钟到几十分钟不等。也许就是这里触发了 bug,明明还没扫完新区块,钱包文件里却标记了新的时间点,结果就是跳过了这些区块,压根没扫描……

    再比如,也许楼主不是先同步完区块再加载 wallet.dat 的,而是先加载 wallet.dat ,然后同步区块——这样的话,bug 性质就更严重了,说明 Bitcoin Core 明明睁着眼扫描过了所有新区块,却仍然对区块中与自己有关的交易视而不见。


    还有一种可能,并不是 Bitcoin Core 软件的 bug,而是楼主自己操作失误,跳过了自动扫描、又忘记执行手动扫描。
    也许楼主用 JSON-RPC 命令行控制台进行过 importprivkey 之类导入操作。导入私钥 /公钥 /地址之后,当然也需要重新扫描区块,不扫描区块就无法恢复出正确的交易记录和余额;但是扫描区块又很费劲,所以这些导入命令也提供参数,可以跳过自动的、从创世块开始的扫描(然后用户可以手动指定一个比较小的范围来扫描)。如果楼主也是这样,导入私钥时设置了不自动扫描,然后完全忘记了手动执行区块扫描,那也会出现钱包漏掉交易的情况。


    啰嗦这么多,如果楼主只是想解决问题,那我推荐楼主用命令行控制台执行 rescanblockchain 命令来重新扫描区块(就如上文所说,这个命令可以指定扫描范围,这样扫描起来就会轻松一些)。

    如果楼主还有兴趣帮 Bitcoin Core 找 bug,那可以回忆一下操作流程,试试看是不是能发现 bug 并稳定重现,然后可以去 Github 上报告。
    acess
        3
    acess  
       2021-02-23 22:53:39 +08:00
    “也许楼主不是先同步完区块再加载 wallet.dat 的,而是先加载 wallet.dat ,然后同步区块”这种情况下,也有可能不是 Bitcoin Core 的软件 bug (我其实不太相信 Bitcoin Core 会有这种恶性 bug ),而是楼主自己的操作失误,比如实际存币的交易其实不在那个 wallet.dat 里面,是需要导入进去的,但楼主忘了导入,这样能扫描出来反而就有鬼了。
    在这个“实际存币的私钥不在 wallet.dat 里,需要导入进去”基础上,还可以脑补其他情况,比如同一个私钥其实是对应压缩和非压缩两种公钥的,压缩公钥功能一样,字节数更少,所以现在一般都用压缩公钥了。但是这样的话,一个私钥就可以对应两种 1 开头的地址,一个是压缩的,另一种是非压缩的。一般私钥都是 WIF 格式,为了避免这个问题,WIF 格式规定了一个标志位来区分压缩和非压缩,比特币的压缩私钥开头的 K/L,非压缩私钥开头是 5,但是有些工具也提供这两种格式的转换……也有可能楼主是掉进这个“压缩 /非压缩”的坑里了。
    acess
        4
    acess  
       2021-02-23 22:57:44 +08:00
    啊,不好意思,打错了,“实际存币的交易”应该是“实际存币的私钥”,纠正一下。
    acess
        5
    acess  
       2021-02-23 23:08:09 +08:00
    哎,想想都觉得蛋疼……如果楼主在同步区块时开启了区块修剪,那么老区块在处理完毕之后,其实是直接被删掉的,删掉了,当然就没办法扫描啦……如果要扫描,那不好意思,请从头重新同步一遍区块……

    这个问题未来应该可以借助 block filter index 得到缓解,block filter index 只有完整区块的几十分之一大,现在只有大约 6GB,用这 6GB 的数据就可以知道 306GB 的区块里,哪些区块才是可能和自己有关的(这里不会有漏报,大可以放心;只会有误报),然后只扫描这一部分与自己有关的区块即可。

    前几天 Bitcoin Core 刚刚把允许在启用修剪时生成 block filter index 的 PR 合并进去。但是用这个 block filter index 进行快速扫描,还有让全节点像轻钱包一样,只(重新)下载与自己有关的区块,这些功能貌似还没搞定……

    (还有,Bitcoin Core 的 block filter index 在未来应该仍然是只允许自己生成,仍然不能从别人那里直接下载现成的。这个归根到底是开发者坚持的理念,而不是技术原因,技术上,现在的 Neutrino 轻钱包已经是直接下载现成的了。所以说未来同步一个全节点还是逃不掉至少要把几百 GB 的区块完整下载一遍——这里的改善,就是启用修剪后,如果要执行区块扫描,就不再需要把这几百 GB 重复下载第 2 、3 、4 、5……遍了,只要有第一遍留下来的 block filter index 就可以免去这个负担)
    acess
        6
    acess  
       2021-02-23 23:19:13 +08:00
    还有,现在实现的修剪,和白皮书并没有什么关系,白皮书上那个修剪貌似也没有什么实际意义。

    其实我觉得中本聪在白皮书里貌似是有意无意地把“交易记录”和“账户余额”这两个不同的概念混淆到一起、混为一谈了。比特币里面确实没有形式上的账户,但公钥 /地址实质上就是账户,UTXO 集合则是实质上的账户余额。并不是说,我把这个东西叫做“电子币”,换一个名字称呼这一坨,实际上的问题性质就会发生神奇的转变。

    同步区块的过程,其实就是对 UTXO 集合进行查询和增删,比特币全节点实际上就是这么做的,chainstate 里保存的就是 UTXO 集合数据库,而且同步区块时的性能瓶颈一般也在这里,因为随机读写压力很大,尤其是机械硬盘,完全吃不消。

    如果按照白皮书上那种修剪方案,首先就是麻烦,说难听点,脱裤子放屁——已经有 UTXO 集合了,为啥还要回过头去折腾区块呢?
    其次,这样修剪完了,其实是存在信任问题的——站在其他人的、尤其是新入网节点的视角,别人怎么知道你是诚实地执行了 Merkle 树剪枝呢?没办法知道。如果你恶意地把本来还没花掉的币( UTXO )剪掉了,或者把本来已经花掉的币又加回去了(这两种做法都不会破坏 Merkle 树的结构,其实 SPV 本来就是挑选出 Merkle 树的一个小分支;这里讨论的就是恶意挑选 Merkle 树的分支),那就可以误导别人。除非把区块完整下载验证一遍,否则无法排除这种恶意挑选 Merkle 树分支的行为。
    pkwenda
        7
    pkwenda  
       2021-02-23 23:30:28 +08:00
    我被楼上大佬折服了
    acess
        8
    acess  
       2021-02-24 00:18:59 +08:00   ❤️ 2
    其实从实用角度讲……我啰嗦这么多,不如直接建议楼主在 Bitcoin Core 的命令行控制台用 dumpprivkey 命令导出 wallet.dat 钱包文件里的所有私钥,然后再导入 Electrum 轻钱包。

    Electrum 的钱包服务器就有相对完善得多的索引,所以同步很快,交易少的话几乎就是秒速完成。

    (当然,这里也涉及安全问题,比如复制粘贴操作,剪贴板是不是被其他应用监听、上传;或者说打开从钱包 dump 出来的 txt 时,如果用了带云同步的 office,是不是也会“云同步”上传;或者说机器是不是干脆就中了木马;再或者是不是下载到的 Electrum 软件不是官方的,而是钓鱼冒充的,直接偷币……Electrum 是支持冷热分离的,分两台机器操作,离线机器保存私钥,自始至终可以永远不联网(可以用 Tails 、Ubuntu Live CD 之类“用后即焚”的环境);在线机器只有地址 /公钥,永远不碰私钥,可以很大程度上缓解安全风险,但不可能完全高枕无忧,比如非官方钓鱼假冒的 Electrum 这种情况,其实冷钱包也救不了)


    我觉得跑全节点很大程度上只是坚持一种理念……参见 /t/754054#reply5
    fox1751
        9
    fox1751  
    OP
       2021-02-24 13:08:12 +08:00
    @acess 感谢回复,虽然我没太看懂。
    wangkun025
        10
    wangkun025  
       2021-02-27 16:21:42 +08:00
    @fox1751 他的意思是,比特币就是个字符串,也算是个密码。
    你把密码从 bitcoin core 里导出来,导进另外一个钱包试试看。
    acess
        11
    acess  
       2021-03-02 21:01:16 +08:00
    @wangkun025
    我的意思:
    1.有私钥就是有币。有了私钥就相当于有了账户密码,就能把钱转走。
    2.但是光有私钥很显然还不够,还得知道账上有多少钱。就是在这一点上,Bitcoin Core 全节点钱包很慢很笨重很蛋疼,远不如 Electrum 这样的轻钱包高效快捷(其实轻钱包也有的快有的慢,像 Electrum 这样是可以秒速同步的,因为 Electrum 钱包服务器提供了比较完善的索引)。
    3.不过,轻钱包依赖别人查询交易信息,所以理论上隐私较差,而且不太符合去中心化的精神。
    wangkun025
        12
    wangkun025  
       2021-03-02 23:52:53 +08:00
    @acess 你说得对。我有 electrum,也有 bitcoin core 的
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1055 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 19:40 · PVG 03:40 · LAX 11:40 · JFK 14:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.