master: `gettxoutsetinfo` -> crash #7890

issue paveljanik opened this issue on April 16, 2016
  1. paveljanik commented at 10:46 AM on April 16, 2016: contributor

    Current master (73fc922ed64333d45f18d8a448f30cfa2ae0281e) crashes at the end of processing RPC gettxoutsetinfo on OS X:

    $ ./bitcoind 
    Assertion failed: (ok), function Next, file txdb.cpp, line 139.
    Abort trap: 6
    $ 
    
  2. paveljanik commented at 10:54 AM on April 16, 2016: contributor

    Works ok on testnet. Hmm.

  3. paveljanik commented at 11:43 AM on April 16, 2016: contributor
    Before GetKey() keyTmp = (c, c9e3a8404fee8c8fe3406f86dec2989d7534a3b0c3548f139698a6f85affffff)!
    GetKey() returned not OK, keyTmp = (d, c9e3a8404fee8c8fe3406f86dec2989d7534a3b0c3548f139698a6f85affffff)!
    

    Notice the 'd'...

  4. laanwj added the label RPC/REST/ZMQ on Apr 16, 2016
  5. paveljanik commented at 12:27 PM on April 16, 2016: contributor

    Keeping the copy of chainstate directory for later investigation and doing -reindex...

  6. laanwj commented at 12:27 PM on April 16, 2016: member

    That's this code

        if (pcursor->Valid()) {
            bool ok = pcursor->GetKey(keyTmp);
            assert(ok); // If GetKey fails here something must be wrong with underlying database, we cannot handle that here
        } ...
    

    I don't get it - why would a GetKey fail when the cursor is valid?

  7. paveljanik commented at 12:29 PM on April 16, 2016: contributor

    I extended dbwrapper.h's template<typename K> bool GetKey(K& key) { and the exception there is:

    PJ: e = CDataStream::read(): end of data: unspecified iostream_category error
    

    End of file?

  8. laanwj commented at 12:29 PM on April 16, 2016: member

    I think the leveldb operation succeeds, but it is unable to deserialize the key:

        template<typename K> bool GetKey(K& key) {
            leveldb::Slice slKey = piter->key();
            try {
                CDataStream ssKey(slKey.data(), slKey.data() + slKey.size(), SER_DISK, CLIENT_VERSION);
                ssKey >> key;
            } catch (const std::exception&) {
                return false;
            }
            return true;
        }
    

    Not sure why this would be the case but unless other people are experiencing this too, I'd say it's database corruption.

  9. laanwj commented at 12:36 PM on April 16, 2016: member

    Can you put a LogPrintf("Failed key: %s\n", HexStr(slKey.data(), slKey.data() + slKey.size())); in the catch() of GetKey to see what key can't be parsed?

  10. paveljanik commented at 12:38 PM on April 16, 2016: contributor

    Yup. Once the reindex finishes. db.log is empty.

  11. paveljanik commented at 2:31 PM on April 16, 2016: contributor

    The db.log was transferred from the other system, where there were some lines about full disk space 8)

    Edit: the chainstate (and other directories) was transferred from other machine. db.log from there is deleted. The file on the new machine is empty.

    Will investigate further once the reindex locally is finished.

  12. sipa commented at 2:35 PM on April 16, 2016: member

    db.log is about bdb

  13. paveljanik commented at 2:35 PM on April 16, 2016: contributor

    I think the corruption in chainstate happened on the source machine.

  14. paveljanik commented at 6:01 AM on April 17, 2016: contributor

    Reindex helped to solve this issue for me.

    I added @laanwj 's debug line and it is printed even on the start of bitcoind:

    2016-04-17 05:48:23 Using obfuscation key for /Users/test/Library/Application Support/Bitcoin/chainstate: 0000000000000000
    2016-04-17 05:48:25 Failed key: 6600000000
    

    But it continues there. The crash happens in gettxoutsetinfo:

    Failed key: 6400000003f13983c3a719c42b25eadf94446075b3
    
  15. paveljanik commented at 9:12 AM on April 17, 2016: contributor

    Closing, the real source of the problem was database corruption.

  16. paveljanik closed this on Apr 17, 2016

  17. laanwj commented at 9:16 AM on April 17, 2016: member

    On second thought: is there a guarantee that keys always deserialize into the (char,uint256) stanza?

    Failed key: 6600000000
    

    'f' → DB_BLOCK_FILES

    Failed key: 6400000003f13983c3a719c42b25eadf94446075b3
    

    'd' → not listed

    No, doesn't seem to be the case, see for example WriteBatchSync:

    batch.Write(make_pair(DB_BLOCK_FILES, it->first), *it->second);
    

    This serializes a char and integer into the key. So: GetKey can legitimately return false, it just means that we've reached a different key type. My interpretation of the meaning of the false return value in this comment was wrong:

    // If GetKey fails here something must be wrong with underlying database, we cannot handle that here
    

    Labeling this as bug!

  18. laanwj reopened this on Apr 17, 2016

  19. laanwj added the label Bug on Apr 17, 2016
  20. paveljanik commented at 9:18 AM on April 17, 2016: contributor

    I still have the chainstate contents. 3.3GB...

  21. laanwj referenced this in commit a3310b4d48 on Apr 18, 2016
  22. laanwj commented at 10:11 AM on April 18, 2016: member
  23. laanwj commented at 10:13 AM on April 19, 2016: member

    #7094 was merged, this was solved

  24. laanwj closed this on Apr 19, 2016

  25. lateminer referenced this in commit 17d8ea7041 on Jan 12, 2018
  26. MarcoFalke locked this on Sep 8, 2021

github-metadata-mirror

This is a metadata mirror of the GitHub repository bitcoin/bitcoin. This site is not affiliated with GitHub. Content is generated from a GitHub metadata backup.
generated: 2026-04-13 15:15 UTC

This site is hosted by @0xB10C
More mirrored repositories can be found on mirror.b10c.me