Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2021-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test addrman functionality"""7import os8import re10from test_framework.messages import ser_uint256, hash256, MAGIC_BYTES11from test_framework.netutil import ADDRMAN_NEW_BUCKET_COUNT, ADDRMAN_TRIED_BUCKET_COUNT, ADDRMAN_BUCKET_SIZE12from test_framework.test_framework import BitcoinTestFramework13from test_framework.test_node import ErrorMatch14from test_framework.util import assert_equal16def serialize_addrman(17*,18format=1,19lowest_compatible=4,20net_magic="regtest",21bucket_key=1,22len_new=None,23len_tried=None,24mock_checksum=None,25):26new = []27tried = []28INCOMPATIBILITY_BASE = 3229r = MAGIC_BYTES[net_magic]30r += format.to_bytes(1, "little")31r += (INCOMPATIBILITY_BASE + lowest_compatible).to_bytes(1, "little")32r += ser_uint256(bucket_key)33r += (len_new or len(new)).to_bytes(4, "little", signed=True)34r += (len_tried or len(tried)).to_bytes(4, "little", signed=True)35ADDRMAN_NEW_BUCKET_COUNT = 1 << 1036r += (ADDRMAN_NEW_BUCKET_COUNT ^ (1 << 30)).to_bytes(4, "little", signed=True)37for _ in range(ADDRMAN_NEW_BUCKET_COUNT):38r += (0).to_bytes(4, "little", signed=True)39checksum = hash256(r)40r += mock_checksum or checksum41return r44def write_addrman(peers_dat, **kwargs):45with open(peers_dat, "wb") as f:46f.write(serialize_addrman(**kwargs))49class AddrmanTest(BitcoinTestFramework):50def set_test_params(self):51self.num_nodes = 153def run_test(self):54peers_dat = os.path.join(self.nodes[0].chain_path, "peers.dat")55def init_error(reason):56return (57f"Error: Invalid or corrupt peers.dat \\({reason}\\). If you believe this "58f"is a bug, please report it to {self.config['environment']['CLIENT_BUGREPORT']}. "59f'As a workaround, you can move the file \\("{re.escape(peers_dat)}"\\) out of the way \\(rename, '60"move, or delete\\) to have a new one created on the next start."61)63self.log.info("Check that mocked addrman is valid")64self.stop_node(0)65write_addrman(peers_dat)66with self.nodes[0].assert_debug_log(["Loaded 0 addresses from peers.dat"]):67self.start_node(0, extra_args=["-checkaddrman=1"])68assert_equal(self.nodes[0].getnodeaddresses(), [])70self.log.info("Check that addrman with negative lowest_compatible cannot be read")71self.stop_node(0)72write_addrman(peers_dat, lowest_compatible=-32)73self.nodes[0].assert_start_raises_init_error(74expected_msg=init_error(75"Corrupted addrman database: The compat value \\(0\\) is lower "76"than the expected minimum value 32.: (.+)"77),78match=ErrorMatch.FULL_REGEX,79)81self.log.info("Check that addrman from future is overwritten with new addrman")82self.stop_node(0)83write_addrman(peers_dat, lowest_compatible=111)84assert_equal(os.path.exists(peers_dat + ".bak"), False)85with self.nodes[0].assert_debug_log([86f'Creating new peers.dat because the file version was not compatible ("{peers_dat}"). Original backed up to peers.dat.bak',87]):88self.start_node(0)89assert_equal(self.nodes[0].getnodeaddresses(), [])90assert_equal(os.path.exists(peers_dat + ".bak"), True)92self.log.info("Check that corrupt addrman cannot be read (EOF)")93self.stop_node(0)94with open(peers_dat, "wb") as f:95f.write(serialize_addrman()[:-1])96self.nodes[0].assert_start_raises_init_error(97expected_msg=init_error("AutoFile::read: end of file.*"),98match=ErrorMatch.FULL_REGEX,99)101self.log.info("Check that corrupt addrman cannot be read (magic)")102self.stop_node(0)103write_addrman(peers_dat, net_magic="signet")104self.nodes[0].assert_start_raises_init_error(105expected_msg=init_error("Invalid network magic number"),106match=ErrorMatch.FULL_REGEX,107)109self.log.info("Check that corrupt addrman cannot be read (checksum)")110self.stop_node(0)111write_addrman(peers_dat, mock_checksum=b"ab" * 32)112self.nodes[0].assert_start_raises_init_error(113expected_msg=init_error("Checksum mismatch, data corrupted"),114match=ErrorMatch.FULL_REGEX,115)117self.log.info("Check that corrupt addrman cannot be read (len_tried)")118self.stop_node(0)119max_len_tried = ADDRMAN_TRIED_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE120write_addrman(peers_dat, len_tried=-1)121self.nodes[0].assert_start_raises_init_error(122expected_msg=init_error(f"Corrupt AddrMan serialization: nTried=-1, should be in \\[0, {max_len_tried}\\]:.*"),123match=ErrorMatch.FULL_REGEX,124)126self.log.info("Check that corrupt addrman cannot be read (large len_tried)")127write_addrman(peers_dat, len_tried=max_len_tried + 1)128self.nodes[0].assert_start_raises_init_error(129expected_msg=init_error(f"Corrupt AddrMan serialization: nTried={max_len_tried + 1}, should be in \\[0, {max_len_tried}\\]:.*"),130match=ErrorMatch.FULL_REGEX,131)133self.log.info("Check that corrupt addrman cannot be read (len_new)")134self.stop_node(0)135max_len_new = ADDRMAN_NEW_BUCKET_COUNT * ADDRMAN_BUCKET_SIZE136write_addrman(peers_dat, len_new=-1)137self.nodes[0].assert_start_raises_init_error(138expected_msg=init_error(f"Corrupt AddrMan serialization: nNew=-1, should be in \\[0, {max_len_new}\\]:.*"),139match=ErrorMatch.FULL_REGEX,140)142self.log.info("Check that corrupt addrman cannot be read (large len_new)")143self.stop_node(0)144write_addrman(peers_dat, len_new=max_len_new + 1)145self.nodes[0].assert_start_raises_init_error(146expected_msg=init_error(f"Corrupt AddrMan serialization: nNew={max_len_new + 1}, should be in \\[0, {max_len_new}\\]:.*"),147match=ErrorMatch.FULL_REGEX,148)150self.log.info("Check that corrupt addrman cannot be read (failed check)")151self.stop_node(0)152write_addrman(peers_dat, bucket_key=0)153self.nodes[0].assert_start_raises_init_error(154expected_msg=init_error("Corrupt data. Consistency check failed with code -16: .*"),155match=ErrorMatch.FULL_REGEX,156)158self.log.info("Check that missing addrman is recreated")159self.restart_node(0, clear_addrman=True)160assert_equal(self.nodes[0].getnodeaddresses(), [])163if __name__ == "__main__":164AddrmanTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.