Repository: bitcoin/bitcoin
File: test/functional/feature_anchors.py (Python)

Code before:
        self.log.info("Perturb anchors.dat to test it doesn't throw an error during initialization")
        with self.nodes[0].assert_debug_log(["0 block-relay-only anchors will be tried for connections."]):
            with open(node_anchors_path, "wb") as out_file_handler:
                tweaked_contents = bytearray(anchors)
                tweaked_contents[20:20] = b'1'
                out_file_handler.write(bytes(tweaked_contents))

            self.log.debug("Start node")
            self.start_node(0)

        self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
        assert not os.path.exists(node_anchors_path)

        self.log.info("Ensure addrv2 support")
        # Use proxies to catch outbound connections to networks with 256-bit addresses
        onion_conf = Socks5Configuration()
        onion_conf.auth = True
        onion_conf.unauth = True
        onion_conf.addr = ('127.0.0.1', p2p_port(self.num_nodes))
        onion_conf.keep_alive = True
        onion_proxy = Socks5Server(onion_conf)
        onion_proxy.start()
        self.restart_node(0, extra_args=[f"-onion={onion_conf.addr[0]}:{onion_conf.addr[1]}"])

        self.log.info("Add 256-bit-address block-relay-only connections to node")
        self.nodes[0].addconnection(ONION_ADDR, 'block-relay-only')

        self.log.debug("Stop node")
        with self.nodes[0].assert_debug_log([f"DumpAnchors: Flush 1 outbound block-relay-only peer addresses to anchors.dat"]):
            self.stop_node(0)
        # Manually close keep_alive proxy connection
        onion_proxy.stop()

        self.log.info("Check for addrv2 addresses in anchors.dat")
        caddr = CAddress()
        caddr.net = CAddress.NET_TORV3
        caddr.ip, port_str = ONION_ADDR.split(":")
        caddr.port = int(port_str)
        # TorV3 addrv2 serialization:
        # time(4) | services(1) | networkID(1) | address length(1) | address(32)
        expected_pubkey = caddr.serialize_v2()[7:39].hex()

        # position of services byte of first addr in anchors.dat
        # network magic, vector length, version, nTime
        services_index = 4 + 1 + 4 + 4
        data = bytes()
        with open(node_anchors_path, "rb") as file_handler:
            data = file_handler.read()
            assert_equal(data[services_index], 0x00)  # services == NONE
            anchors2 = data.hex()
            assert expected_pubkey in anchors2

Review comment (suggestion):
Unrelated to this PR, but it could be changed from `False` to `self.options.v2transport` in the future (e.g. in #29358)

Code after:
        self.log.info("Perturb anchors.dat to test it doesn't throw an error during initialization")
        with self.nodes[0].assert_debug_log(["0 block-relay-only anchors will be tried for connections."]):
            with open(node_anchors_path, "wb") as out_file_handler:
                tweaked_contents = bytearray(anchors)
                tweaked_contents[20:20] = b'1'
                out_file_handler.write(bytes(tweaked_contents))

            self.log.debug("Start node")
            self.start_node(0)

        self.log.info("When node starts, check if anchors.dat doesn't exist anymore")
        assert not os.path.exists(node_anchors_path)

        self.log.info("Ensure addrv2 support")
        # Use proxies to catch outbound connections to networks with 256-bit addresses
        onion_conf = Socks5Configuration()
        onion_conf.auth = True
        onion_conf.unauth = True
        onion_conf.addr = ('127.0.0.1', p2p_port(self.num_nodes))
        onion_conf.keep_alive = True
        onion_proxy = Socks5Server(onion_conf)
        onion_proxy.start()
        self.restart_node(0, extra_args=[f"-onion={onion_conf.addr[0]}:{onion_conf.addr[1]}"])

        self.log.info("Add 256-bit-address block-relay-only connections to node")
        self.nodes[0].addconnection(ONION_ADDR, 'block-relay-only', v2transport=False)

        self.log.debug("Stop node")
        with self.nodes[0].assert_debug_log([f"DumpAnchors: Flush 1 outbound block-relay-only peer addresses to anchors.dat"]):
            self.stop_node(0)
        # Manually close keep_alive proxy connection
        onion_proxy.stop()

        self.log.info("Check for addrv2 addresses in anchors.dat")
        caddr = CAddress()
        caddr.net = CAddress.NET_TORV3
        caddr.ip, port_str = ONION_ADDR.split(":")
        caddr.port = int(port_str)
        # TorV3 addrv2 serialization:
        # time(4) | services(1) | networkID(1) | address length(1) | address(32)
        expected_pubkey = caddr.serialize_v2()[7:39].hex()

        # position of services byte of first addr in anchors.dat
        # network magic, vector length, version, nTime
        services_index = 4 + 1 + 4 + 4
        data = bytes()
        with open(node_anchors_path, "rb") as file_handler:
            data = file_handler.read()
            assert_equal(data[services_index], 0x00)  # services == NONE
            anchors2 = data.hex()
            assert expected_pubkey in anchors2