Repository navigation
net: open $DOG Mode connections after feelers and network-specific peers - #10
dogofbitcoin wants to merge 1 commit into
Conversation
ThreadOpenConnections chooses one connection type per pass. The $DOG Mode choice sat above the feeler and network-specific choices and has no timer of its own, so while any of the MAX_DOG_MODE_CONNECTIONS slots is empty, every pass that reaches it is taken by it, and no feeler or extra network-specific connection is ever made. While few peers advertise NODE_DOG_MODE, the slots can stay empty for hours. Move the choice below the network-specific one, so every choice Bitcoin Core makes keeps its order and its timer, and the $DOG Mode slots take every pass those leave free. p2p_dogmode_feelers.py fills the full-relay and block-relay slots, moves the clock past every timer with no address advertising NODE_DOG_MODE known, and requires a feeler and a network-specific connection; then a "dog" connection made automatically once such an address is learned. Without the change it fails at the first requirement.
|
A mainnet reading, 2026-09-22: six new nodes, an hour each from an empty datadir (pruned, no port open, a home connection), three on #7 merged and three with this change on top.
Core's feeler timer averages about 30 an hour. The one feeler without the change came at minute 3.3 of its hour, seconds after a sample showed three |
|
An independent regtest reproduction of the feeler starvation, on the merge commit ( Setup: 24 peer nodes on one host reached through a SOCKS5 mapper, one observer, addrman seeded with the peers' addresses in the
With a Two things this does not show. It is one run per build, so the I did not run the new functional test. Scripts, raw JSON and the build notes are in https://github.com/tialkan/bitcoin-dust-utxo-lab (finding 5, section added 10 October 2026, |
Independent Apple Silicon validation — PR #10 (2026-10-27)I tested the new Revisions and build
On the base revision, the scenario reached the intended assertion after filling the 8 full-relay and 2 block-relay slots: On the PR head, the test confirmed that feeler and network-specific attempts still occur with empty DOG slots, and that an outbound DOG connection opens after a Reproduction (after configuring/building python3 test/functional/p2p_dogmode_feelers.py --configfile=build-pr10/test/config.ini --cachedir=build-pr10/cache-clean --timeout-factor=2
python3 test/functional/p2p_dogmode_peering.py --configfile=build-pr10/test/config.ini --cachedir=build-pr10/cache-clean --v1transport --timeout-factor=2
python3 test/functional/p2p_dogmode_peering.py --configfile=build-pr10/test/config.ini --cachedir=build-pr10/cache-clean --v2transport --timeout-factor=2Local macOS build caveat: CMake initially detected This is independent local regtest validation, not a mainnet test or full-suite run. Within this scope, the fix resolves the reproduced starvation and I found no regression in the DOG peering checks. — @krsnak |
In
ThreadOpenConnectionsthedogchoice sits above the feeler and network-specific choices in the if / else if chain and has no timer of its own. So while any of the fourdogslots is empty, every pass that reaches it becomes adogattempt, and no feeler or extra network-specific connection is made. While few reachable peers advertiseNODE_DOG_MODE, the slots stay empty, so on today's network that is the steady state.This moves the
dogchoice below the network-specific one. Every choice Bitcoin Core makes keeps its place and its timer, and thedogslots take every pass those leave free, which is still nearly all of them: a feeler is due about every 2 minutes, a network-specific connection at most about every 5.Measured on mainnet, on
7503240091(the merged tip), our node with its 4dogslots empty andnetdebug on for 15 min 42 s (2026-09-21, 22:18 to 22:33 UTC): 0 feeler connections, where the 2 minute feeler timer averages about 8 in that window (the chance of none is about 1 in 2,500); 3 extra block-relay attempts on their own timer (that choice sits abovedog, so it still runs); 2dogattempts, both to the same address last seen 451 hours earlier, both timing out.Test.
p2p_dogmode_feelers.pyfills the full-relay and block-relay slots, puts IPv4 and onion addresses withoutNODE_DOG_MODEin addrman, moves the clock past every connection timer, and requires a feeler and a network-specific connection. Then it teaches the node one address advertisingNODE_DOG_MODEand requires adogconnection made automatically. Every outbound connection goes through the test framework's SOCKS5 proxy, so nothing reaches the network. On7503240091it fails at the first requirement (3 of 3 runs: no feeler, no network-specific connection); with this change it passes (13 of 13 runs).Also run with this change, all passing:
p2p_dogmode_peering.py(both transports),mempool_dust.py,mempool_accept.py,p2p_node_network_limited.py,p2p_add_connections.py,p2p_handshake.py,feature_anchors.py,p2p_seednode.py,p2p_dns_seeds.py,p2p_private_broadcast.py,p2p_eviction.py,p2p_outbound_eviction.py,p2p_addrfetch.py,feature_proxy.py,p2p_i2p_ports.py,p2p_disconnect_ban.py,rpc_net.py,p2p_addr_relay.py,p2p_addrv2_relay.py,feature_addrman.py, and thenet_tests,net_peer_connection_testsandaddrman_testsunit tests.A timer of its own for the
dogchoice would work too; this is the smaller change. It is independent of #7, and found while reading the connection loop for #3.