Raise InitError when peers.dat is invalid or corrupted #22762

pull MarcoFalke wants to merge 3 commits into bitcoin:master from MarcoFalke:2108-InitErrorAddrmanCorrupt changing 6 files +88 −67
  1. MarcoFalke commented at 12:41 PM on August 21, 2021: member

    peers.dat is silently erased when it can not be parsed or when it appears corrupted. Fix that by notifying the user. This might help in the following examples:

    • The user provided the database, but picked the wrong one.
    • A future version of Bitcoin Core wrote the file and it can't be read.
    • The file was corrupted by a logic bug in Bitcoin Core.
    • The file was corrupted by a disk failure.
  2. MarcoFalke cross-referenced this on Aug 21, 2021 from issue addrman: Avoid crash on corrupt data, Force Check after deserialize by MarcoFalke
  3. DrahtBot added the label GUI on Aug 21, 2021
  4. DrahtBot added the label P2P on Aug 21, 2021
  5. MarcoFalke removed the label GUI on Aug 21, 2021
  6. MarcoFalke force-pushed on Aug 21, 2021
  7. MarcoFalke force-pushed on Aug 21, 2021
  8. DrahtBot cross-referenced this on Aug 21, 2021 from issue refactor: Clarify and disable unused ArgsManager flags by ryanofsky
  9. DrahtBot commented at 9:56 PM on August 21, 2021: contributor

    <!--e57a25ab6845829454e8d69fc972939a-->

    The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

    <!--174a7506f384e20aa4161008e828411d-->

    Conflicts

    Reviewers, this pull request conflicts with the following ones:

    • #22937 (refactor: Add fs::PathToString, fs::PathFromString, u8string, u8path functions by ryanofsky)
    • #22831 (test, bugfix: addrman tried table corruption on restart with asmap by jonatack)

    If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

  10. DrahtBot cross-referenced this on Aug 22, 2021 from issue Add syscall sandboxing using seccomp-bpf (Linux secure computing mode) by practicalswift
  11. in src/addrdb.cpp:184 in fa50c25b1a outdated
     244 | -    return DeserializeFileDB(pathAddr, addr, CLIENT_VERSION);
     245 | +    DeserializeDB(ssPeers, addr, false);
     246 |  }
     247 |  
     248 | -bool CAddrDB::Read(CAddrMan& addr, CDataStream& ssPeers)
     249 | +std::optional<bilingual_str> LoadAddrman(const ArgsManager& args, std::unique_ptr<CAddrMan>& addrman)
    


    vasild commented at 11:53 AM on August 24, 2021:

    I would expect LoadAddrman() to return, eh... addrman, no? Like Foo x = LoadFoo();. Consider this (or ignore it):

    std::unique_ptr<CAddrMan> LoadAddrman(const ArgsManager& args, bilingual_str& error);
    
    bilingual_str error;
    node.addrman = LoadAddrman(args, error);
    if (!node.addrman) {
        return InitError(error);
    }
    

    MarcoFalke commented at 8:53 AM on August 26, 2021:

    This would make the code more verbose. In general I rather standardize error handling how it is done in rust, which the current code is closer to than yours, I think.

  12. in src/addrdb.cpp:254 in fa50c25b1a outdated
     259 | +        DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
     260 | +        LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman->size(), GetTimeMillis() - nStart);
     261 | +    } catch (const DbNotFoundError&) {
     262 | +        // Addrman can be in an inconsistent state after failure, reset it
     263 | +        addrman = std::make_unique<CAddrMan>(/* deterministic */ false, /* consistency_check_ratio */ check_addrman);
     264 | +        LogPrintf("Recreating peers.dat because it was not found\n");
    


    vasild commented at 12:01 PM on August 24, 2021:

    nit: there is no re-creating if the file is missing:

            LogPrintf("Creating peers.dat because it was not found\n");
    

    or just "Creating peers.dat" or "peers.dat not found, creating an empty one"


    MarcoFalke commented at 9:03 AM on August 26, 2021:

    Thanks, fixed

  13. in src/addrdb.cpp:174 in fa50c25b1a outdated
     197 |      FILE* file = fsbridge::fopen(path, "rb");
     198 |      CAutoFile filein(file, SER_DISK, version);
     199 |      if (filein.IsNull()) {
     200 | -        LogPrintf("Missing or invalid file %s\n", path.string());
     201 | -        return false;
     202 | +        throw DbNotFoundError{""};
    


    vasild commented at 12:07 PM on August 24, 2021:

    The string argument is excessive. Maybe inherit DbNotFoundError from std::exception and use throw DbNotFoundError;? Or, I guess, the proper C++ way to do that is:

    try {
        throw std::system_error(std::make_error_code(std::errc::no_such_file_or_directory));
    } catch (const std::exception& e) {
        auto se = dynamic_cast<const std::system_error*>(&e);
        if (se != nullptr && se->code() == std::errc::no_such_file_or_directory) {
            std::cout << "no peers.dat" << std::endl;
        } else {
            std::cout << e.what() << std::endl;
        }
    }
    

    MarcoFalke commented at 9:03 AM on August 26, 2021:

    Thanks, removed "".

  14. ghost commented at 5:18 PM on August 24, 2021: none

    Concept ACK

  15. DrahtBot cross-referenced this on Aug 25, 2021 from issue init: Fix asmap/addrman initialization order bug by jnewbery
  16. MarcoFalke force-pushed on Aug 26, 2021
  17. MarcoFalke commented at 9:04 AM on August 26, 2021: member

    force pushed to address review comments

  18. DrahtBot cross-referenced this on Aug 27, 2021 from issue refactor: Implement missing error checking for ArgsManager flags by ryanofsky
  19. vasild approved
  20. vasild commented at 9:25 AM on August 27, 2021: contributor

    ACK fa1704a2f49eaedf5788d82294485f3a8e17a6c8

  21. in src/addrdb.cpp:118 in fa1704a2f4 outdated
     197 |      FILE* file = fsbridge::fopen(path, "rb");
     198 |      CAutoFile filein(file, SER_DISK, version);
     199 |      if (filein.IsNull()) {
     200 | -        LogPrintf("Missing or invalid file %s\n", path.string());
     201 | -        return false;
     202 | +        throw DbNotFoundError{};
    


    vasild commented at 9:27 AM on August 27, 2021:

    nit: {} is not necessary


    MarcoFalke commented at 3:58 PM on September 1, 2021:

    Not for me:

    addrdb.cpp:174:15: error: 'DbNotFoundError' does not refer to a value
            throw DbNotFoundError;
                  ^
    

    vasild commented at 5:58 AM on September 2, 2021:

    ah, oh, yes of course, sorry for the noise

  22. DrahtBot cross-referenced this on Aug 30, 2021 from issue test: add addpeeraddress "tried", test addrman checks on restart with asmap by jonatack
  23. DrahtBot cross-referenced this on Sep 1, 2021 from issue Remove unused SERIALIZE_METHODS for CBanEntry by MarcoFalke
  24. DrahtBot cross-referenced this on Sep 1, 2021 from issue MOVEONLY: Expose BanMapToJson / BanMapFromJson by ryanofsky
  25. DrahtBot added the label Needs rebase on Sep 1, 2021
  26. MarcoFalke force-pushed on Sep 1, 2021
  27. MarcoFalke force-pushed on Sep 1, 2021
  28. DrahtBot removed the label Needs rebase on Sep 1, 2021
  29. DrahtBot cross-referenced this on Sep 1, 2021 from issue Multiprocess bitcoin by ryanofsky
  30. vasild approved
  31. vasild commented at 5:59 AM on September 2, 2021: contributor

    ACK faff4fd4e00621a02554233effa8f144990f3dd8

  32. jonatack commented at 10:40 AM on September 3, 2021: contributor

    Concept ACK.

    Like other open pulls to change or fix addrman behavior, it might be good to have functional/regression test coverage in place first.

  33. MarcoFalke cross-referenced this on Sep 3, 2021 from issue test: Add addrman peers.dat test by MarcoFalke
  34. DrahtBot added the label Needs rebase on Sep 6, 2021
  35. MarcoFalke force-pushed on Sep 6, 2021
  36. vasild approved
  37. vasild commented at 10:35 AM on September 6, 2021: contributor

    ACK b4cc1c52e103f6fc3969daefc1ba11ac4af4d606

  38. MarcoFalke removed the label Needs rebase on Sep 6, 2021
  39. DrahtBot added the label Needs rebase on Sep 6, 2021
  40. MarcoFalke force-pushed on Sep 6, 2021
  41. DrahtBot removed the label Needs rebase on Sep 6, 2021
  42. vasild approved
  43. vasild commented at 3:52 PM on September 6, 2021: contributor

    ACK faa75278d076874194073a6cb3974f45de051ffc

  44. in src/addrman.h:20 in faa75278d0 outdated
      16 |  #include <random.h>
      17 |  #include <streams.h>
      18 |  #include <sync.h>
      19 |  #include <timedata.h>
      20 |  #include <tinyformat.h>
      21 | -#include <util/system.h>
    


    jonatack commented at 4:45 PM on September 6, 2021:

    fa9aed72 while fixing the addrman includes may as well do these too: #22740 (comment)


    MarcoFalke commented at 9:06 AM on September 7, 2021:

    Thanks, done

  45. in src/test/addrman_tests.cpp:1046 in faa75278d0 outdated
    1042 |      CDataStream ssPeers2 = AddrmanToStream(addrmanUncorrupted);
    1043 |  
    1044 |      CAddrMan addrman2(/* asmap */ std::vector<bool>(), /* deterministic */ false, /* consistency_check_ratio */ 100);
    1045 |      BOOST_CHECK(addrman2.size() == 0);
    1046 | -    BOOST_CHECK(CAddrDB::Read(addrman2, ssPeers2));
    1047 | +    ReadFromStream(addrman2, ssPeers2);
    


    jonatack commented at 4:57 PM on September 6, 2021:

    fa63ebb21 CAddrDB removed in this commit; update these references

    --- a/src/test/addrman_tests.cpp
    +++ b/src/test/addrman_tests.cpp
    @@ -1002,7 +1002,7 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
         BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
     }
     
    -BOOST_AUTO_TEST_CASE(caddrdb_read)
    +BOOST_AUTO_TEST_CASE(load_addrman)
     {
         CAddrManUncorrupted addrmanUncorrupted;
     
    @@ -1047,7 +1047,7 @@ BOOST_AUTO_TEST_CASE(caddrdb_read)
     }
     
     
    -BOOST_AUTO_TEST_CASE(caddrdb_read_corrupted)
    +BOOST_AUTO_TEST_CASE(load_corrupted_addrman)
     {
         CAddrManCorrupted addrmanCorrupted;
    

    MarcoFalke commented at 9:07 AM on September 7, 2021:

    Thanks, done

  46. in src/addrdb.cpp:202 in faa75278d0 outdated
     207 | +        addrman = std::make_unique<CAddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
     208 | +        LogPrintf("Creating peers.dat because it was not found\n");
     209 | +        DumpPeerAddresses(args, *addrman);
     210 | +    } catch (const std::exception& e) {
     211 | +        addrman = nullptr;
     212 | +        return strprintf(_("Addrman invalid or corrupt (%s). If you believe this is a bug, please report it to %s. As a workaround you can move the database (%s) out of the way (rename, move, or delete) to use a fresh one on the next start."),
    


    jonatack commented at 5:29 PM on September 6, 2021:

    faa75278d076874194073a6cb397 suggestions

            return strprintf(_("Invalid or corrupt peers.dat (%s). If you believe this is a bug, please report it to %s. As a workaround, you can move the file (%s) out of the way (rename, move, or delete) and bitcoind will create a new one on the next start."),
    

    MarcoFalke commented at 9:07 AM on September 7, 2021:

    Thanks, done

  47. in src/addrdb.cpp:198 in faa75278d0 outdated
     203 | +        DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
     204 | +        LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman->size(), GetTimeMillis() - nStart);
     205 | +    } catch (const DbNotFoundError&) {
     206 | +        // Addrman can be in an inconsistent state after failure, reset it
     207 | +        addrman = std::make_unique<CAddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
     208 | +        LogPrintf("Creating peers.dat because it was not found\n");
    


    jonatack commented at 5:37 PM on September 6, 2021:

    faa75278d076874194073a6cb3974f45de051ffc Perhaps also log to the user the location where the file was expected to be (as is currently the case).


    MarcoFalke commented at 9:07 AM on September 7, 2021:

    Good catch, done

  48. jonatack commented at 5:38 PM on September 6, 2021: contributor

    Tested/reviewed approach ACK fabe5b5838812e58cc.

    Cherry-picked #22831 onto this branch and the test coverage passed after the following changes; can update that PR if this is merged first:

    @@ -106,7 +106,7 @@ class AddrmanAsmapTest(BitcoinTestFramework):
             self.log.info('Test bitcoind with missing peers.dat and addrman checks')
             self.stop_node(0)
             os.remove(os.path.join(self.datadir, 'peers.dat'))
    -        with self.node.assert_debug_log([f'Missing or invalid file {self.datadir}/peers.dat', 'Recreating peers.dat']):
    +        with self.node.assert_debug_log(['Creating peers.dat because it was not found']):
                 self.start_node(0, ['-checkaddrman=1'])
                 self.node.getnodeaddresses()
     
    @@ -114,9 +114,12 @@ class AddrmanAsmapTest(BitcoinTestFramework):
             self.log.info('Test bitcoind with peers.dat having invalid network magic and addrman checks')
             self.stop_node(0)
             shutil.copyfile(self.asmap_raw, os.path.join(self.datadir, 'peers.dat'))
    -        with self.node.assert_debug_log(['Invalid network magic number', 'Recreating peers.dat']):
    -            self.start_node(0, ['-checkaddrman=1'])
    -            self.node.getnodeaddresses()
    +        msg = (
    +            'Error: Addrman invalid or corrupt (Invalid network magic number). If you believe this is a bug, please '
    +            'report it to https://github.com/bitcoin/bitcoin/issues. As a workaround you can move the database '
    +            f'("{self.datadir}/peers.dat") out of the way (rename, move, or delete) to use a fresh one on the next start.'
    +            )
    +        self.node.assert_start_raises_init_error(extra_args=['-checkaddrman=1'], expected_msg=msg)
     
         def run_test(self):
             self.node = self.nodes[0]
    
  49. MarcoFalke force-pushed on Sep 7, 2021
  50. MarcoFalke force-pushed on Sep 7, 2021
  51. vasild approved
  52. vasild commented at 10:12 AM on September 7, 2021: contributor

    ACK fa7003f949f21a0ba81388caff1ff986d8b43eed

  53. MarcoFalke closed this on Sep 7, 2021

  54. MarcoFalke reopened this on Sep 7, 2021

  55. in src/addrdb.h:50 in fa7003f949 outdated
      46 | @@ -52,6 +47,9 @@ class CBanDB
      47 |      bool Read(banmap_t& banSet);
      48 |  };
      49 |  
      50 | +/** Returns an error string on failure */
    


    jonatack commented at 2:26 PM on September 7, 2021:

    fa035c1 suggestion if you retouch

    /** Load addresses from peers.dat into addrman. Returns an error string on failure */
    

    MarcoFalke commented at 4:02 PM on September 7, 2021:

    I don't think other modules care much about the exact file name, so I didn't mention it, as it is self-documented in the addrdb implementation file (cpp) already. And the "Load addresses" part should already be clear from the function name.

  56. in src/init.cpp:1206 in fa7003f949 outdated
    1199 | @@ -1200,20 +1200,9 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
    1200 |              LogPrintf("Using /16 prefix for IP bucketing\n");
    1201 |          }
    1202 |  
    1203 | -        auto check_addrman = std::clamp<int32_t>(args.GetArg("-checkaddrman", DEFAULT_ADDRMAN_CONSISTENCY_CHECKS), 0, 1000000);
    1204 | -        node.addrman = std::make_unique<CAddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
    1205 | -
    1206 | -        // Load addresses from peers.dat
    


    jonatack commented at 2:27 PM on September 7, 2021:

    fa035c1 perhaps keep this comment


    MarcoFalke commented at 4:00 PM on September 7, 2021:

    I don't think it is important to document the file name in init.cpp, so I removed it

  57. jonatack commented at 3:54 PM on September 7, 2021: contributor

    ACK fa7003f949f21a0ba81388caff1ff986d8b43eed review / debug build clean on each commit, verified the test coverage of #22831 passes on this branch with the following changes

    --- a/test/functional/feature_addrman_asmap.py
    +++ b/test/functional/feature_addrman_asmap.py
    @@ -106,17 +106,21 @@ class AddrmanAsmapTest(BitcoinTestFramework):
             self.log.info('Test bitcoind with missing peers.dat and addrman checks')
             self.stop_node(0)
             os.remove(os.path.join(self.datadir, 'peers.dat'))
    -        with self.node.assert_debug_log([f'Missing or invalid file {self.datadir}/peers.dat', 'Recreating peers.dat']):
    +        msg = f'Creating peers.dat because the file was not found ("{self.datadir}/peers.dat")'
    +        with self.node.assert_debug_log(expected_msgs=[msg]):
                 self.start_node(0, ['-checkaddrman=1'])
     
         def test_peers_dat_with_invalid_network_magic(self):
             self.log.info('Test bitcoind with peers.dat having invalid network magic and addrman checks')
             self.stop_node(0)
             shutil.copyfile(self.asmap_raw, os.path.join(self.datadir, 'peers.dat'))
    -        with self.node.assert_debug_log(['Invalid network magic number', 'Recreating peers.dat']):
    -            self.start_node(0, ['-checkaddrman=1'])
    -            self.node.getnodeaddresses()
    +        msg = (
    +            'Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please '
    +            'report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file '
    +            f'("{self.datadir}/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.'
    +            )
    +        self.node.assert_start_raises_init_error(extra_args=['-checkaddrman=1'], expected_msg=msg)
    
  58. ghost commented at 7:05 PM on September 7, 2021: none

    Tested on Pop!_OS and everything works as expected and mentioned in PR description.

    Master Branch:

    peers.dat is replaced with a new file if it is corrupt or other issues.

    <details> <summary>Details</summary>

    image

    image

    </details>

    PR Branch:

    A. Corrupt peers.dat file

    1. Open peers.dat add random characters in beginning and save.
    2. Run bitcoind
    2021-09-07T18:05:46Z init message: Loading P2P addresses…
    2021-09-07T18:05:46Z Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/home/prayank/.bitcoin/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
    Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/home/prayank/.bitcoin/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
    2021-09-07T18:05:46Z Shutdown: In progress...
    

    :warning: Not sure why same error printed twice in terminal running bitcoind. I see only one error message in debug.log:

    2021-09-07T18:05:46Z init message: Loading P2P addresses…
    2021-09-07T18:05:46Z Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/home/prayank/.bitcoin/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
    2021-09-07T18:05:46Z Shutdown: In progress...
    

    B. peers.dat from testnet used in regtest

    1. Delete regtest/peers.dat and copy testnet3/peers.dat in regtest/
    2. Run bitcoind
    2021-09-07T18:14:33Z init message: Loading P2P addresses…
    2021-09-07T18:14:33Z Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/home/prayank/.bitcoin/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
    Error: Invalid or corrupt peers.dat (Invalid network magic number). If you believe this is a bug, please report it to https://github.com/bitcoin/bitcoin/issues. As a workaround, you can move the file ("/home/prayank/.bitcoin/regtest/peers.dat") out of the way (rename, move, or delete) to have a new one created on the next start.
    2021-09-07T18:14:33Z Shutdown: In progress...
    

    Fix the issue by following the things mentioned in error: Delete peers.dat and restart bitcoind. No issues. :white_check_mark:

  59. DrahtBot cross-referenced this on Sep 7, 2021 from issue net: Encapsulate asmap in NetGroupManager by jnewbery
  60. MarcoFalke cross-referenced this on Sep 8, 2021 from issue Remove confusing CAddrDB by MarcoFalke
  61. MarcoFalke referenced this in commit 896649996b on Sep 9, 2021
  62. Move LoadAddrman from init to addrdb
    Init should only concern itself with the initialization order, not the
    detailed initialization logic of every module.
    
    Also, inlining logic into a method that is ~800 lines of code, makes it
    impossible to unit test on its own.
    fa5aeec80c
  63. Inline ReadPeerAddresses
    No need to have a function that is only called in one place
    fa4e2ccfd8
  64. MarcoFalke force-pushed on Sep 9, 2021
  65. Raise InitError when peers.dat is invalid or corrupted fa55c3dc1b
  66. MarcoFalke force-pushed on Sep 9, 2021
  67. MarcoFalke commented at 7:25 AM on September 9, 2021: member

    Rebased (only change is in tests)

  68. jonatack commented at 8:44 AM on September 9, 2021: contributor

    Code review re-ACK fa55c3dc1b4bbdc6a53bd11fa6c0b2ec6bbb64ae per git range-diff eb1f570 fa59c6d fa55c3 and verified the new tests fail on master, except "Check mocked addrman is valid", as expected

  69. in test/functional/feature_addrman.py:68 in fa55c3dc1b
      69 | -        assert_equal(self.nodes[0].getnodeaddresses(), [])
      70 | +        self.nodes[0].assert_start_raises_init_error(
      71 | +            expected_msg=init_error(
      72 | +                "Unsupported format of addrman database: 1. It is compatible with "
      73 | +                "formats >=111, but the maximum supported by this version of "
      74 | +                f"{self.config['environment']['PACKAGE_NAME']} is 3.: (.+)"
    


    vasild commented at 10:02 AM on September 9, 2021:

    This is somewhat confusing or designates a corrupted file, not one from the future. How could the file be format=1 and only be compatible with formats larger than 111? If the above is changed as:

    -write_addrman(peers_dat, lowest_compatible=111)
    +write_addrman(peers_dat, format=115, lowest_compatible=111)
    

    it will be a bit more realistic.

    Feel free to ignore as out of the scope of this PR, given that a similar message is already in master.


    MarcoFalke commented at 10:58 AM on September 9, 2021:

    Instead of "fixing" the test, I think rejecting formats that are less than lowest_compatible seems like a good sanity check. Though, this would be an unrelated fix in a separate pull:

    diff --git a/src/addrman.cpp b/src/addrman.cpp
    index 174b3a654c..bcffe64de3 100644
    --- a/src/addrman.cpp
    +++ b/src/addrman.cpp
    @@ -243,7 +243,7 @@ void CAddrMan::Unserialize(Stream& s_)
         uint8_t compat;
         s >> compat;
         const uint8_t lowest_compatible = compat - INCOMPATIBILITY_BASE;
    -    if (lowest_compatible > FILE_FORMAT) {
    +    if (format < lowest_compatible || lowest_compatible > FILE_FORMAT) {
             throw std::ios_base::failure(strprintf(
                 "Unsupported format of addrman database: %u. It is compatible with formats >=%u, "
                 "but the maximum supported by this version of %s is %u.",
    

    vasild commented at 11:25 AM on September 9, 2021:

    +1, maybe each condition deserves its own error message.

  70. vasild approved
  71. vasild commented at 10:03 AM on September 9, 2021: contributor

    ACK fa55c3dc1b4bbdc6a53bd11fa6c0b2ec6bbb64ae

  72. ghost commented at 12:44 PM on September 9, 2021: none

    tACK https://github.com/bitcoin/bitcoin/commit/fa55c3dc1b4bbdc6a53bd11fa6c0b2ec6bbb64ae

    nit: Will be better if error message was printed only once #22762 (comment)

  73. MarcoFalke commented at 12:50 PM on September 9, 2021: member

    nit: Will be better if error message was printed only once #22762 (comment)

    InitErrors are printed to the debug log and stderr. I think it makes sense to print them to both instead of only one.

  74. DrahtBot cross-referenced this on Sep 10, 2021 from issue refactor: Forbid calling unsafe fs::path(std::string) constructor and fs::path::string() method by ryanofsky
  75. MarcoFalke merged this on Sep 10, 2021
  76. MarcoFalke closed this on Sep 10, 2021

  77. MarcoFalke deleted the branch on Sep 10, 2021
  78. in src/addrdb.cpp:195 in fa55c3dc1b
     195 | +    const auto path_addr{args.GetDataDirNet() / "peers.dat"};
     196 | +    try {
     197 | +        DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
     198 | +        LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman->size(), GetTimeMillis() - nStart);
     199 | +    } catch (const DbNotFoundError&) {
     200 | +        // Addrman can be in an inconsistent state after failure, reset it
    


    MarcoFalke commented at 11:06 AM on September 10, 2021:

    Just to clarify that, strictly, this isn't needed. DbNotFoundError means that the file wasn't found, so addrman shouldn't be touched at all.

    Does anyone have opinions on whether to remove it or not?


    vasild commented at 11:34 AM on September 10, 2021:

    But we need to distinguish somehow this from the other error case, so that we don't signal an error to the caller in this case?


    MarcoFalke commented at 11:37 AM on September 10, 2021:

    I meant recreating the addrman can be skipped, because it wasn't touched. Saves two lines of code:

    diff --git a/src/addrdb.cpp b/src/addrdb.cpp
    index 1e73750ce3..a86f4c3789 100644
    --- a/src/addrdb.cpp
    +++ b/src/addrdb.cpp
    @@ -192,8 +192,6 @@ std::optional<bilingual_str> LoadAddrman(const std::vector<bool>& asmap, const A
             DeserializeFileDB(path_addr, *addrman, CLIENT_VERSION);
             LogPrintf("Loaded %i addresses from peers.dat  %dms\n", addrman->size(), GetTimeMillis() - nStart);
         } catch (const DbNotFoundError&) {
    -        // Addrman can be in an inconsistent state after failure, reset it
    -        addrman = std::make_unique<CAddrMan>(asmap, /* deterministic */ false, /* consistency_check_ratio */ check_addrman);
             LogPrintf("Creating peers.dat because the file was not found (%s)\n", path_addr);
             DumpPeerAddresses(args, *addrman);
         } catch (const std::exception& e) {
    

    vasild commented at 12:01 PM on September 10, 2021:

    This would leave the unique_ptr empty and not signal error to the caller. So the caller will continue, possibly dereferencing the empty unique_ptr, leading to undefined behavior?


    MarcoFalke commented at 12:21 PM on September 10, 2021:

    The pointer is initialized in the beginning of the function. Otherwise DumpPeerAddresses(args, *addrman); wouldn't work either.


    jonatack commented at 1:01 PM on September 10, 2021:

    Removal LGTM. Built with the suggested diff and tested.


    vasild commented at 1:09 PM on September 10, 2021:

    The pointer is initialized in the beginning of the function

    ah, well, then it is ok. ACK.

  79. sidhujag referenced this in commit 78b1e983ae on Sep 11, 2021
  80. sipa commented at 3:50 PM on October 25, 2021: member

    I'm not sure it's entirely desirable to require user intervention when downgrading. When there is actual corruption, this may make sense as it's a sign of a deeper problem, but wiping peers.dat when downgrading to an incompatible version seems entirely expected to me.

  81. MarcoFalke cross-referenced this on Jan 28, 2022 from issue Avoid InitError when downgrading peers.dat by MarcoFalke
  82. junderw cross-referenced this on Jan 30, 2022 from issue p2p: Avoid InitError when downgrading peers.dat by junderw
  83. MarcoFalke referenced this in commit b00b60ed4f on Feb 25, 2022
  84. sidhujag referenced this in commit 7da3620dbe on Feb 25, 2022
  85. Fabcien referenced this in commit dc148fa4ac on Oct 19, 2022
  86. bitcoin locked this on Oct 30, 2022

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-05-20 06:53 UTC