aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Atack <jon@atack.com>2021-08-30 12:11:47 +0200
committerJon Atack <jon@atack.com>2021-09-15 16:38:03 +0200
commitcdaab90662a54e331de0e49a89596bbb94a8ac45 (patch)
treef22e4783df286743470e34ab6b22a256ef1d033f
parent869f136816c6900ce84bc4b5a9c93c0deab85193 (diff)
Add test for addrman consistency check on restart with asmap
PR #22697 introduced a reproducible issue in commit 181a1207 that causes the addrman tried table to fail consistency checks and significantly lose peer entries when the `-asmap` configuration option is used. The issue occurs on bitcoind restart due to an initialization order change in `src/init.cpp` in that commit whereby CAddrman asmap is set after deserializing `peers.dat`, rather than before. Issue reported on the `#bitcoin-core-dev` IRC channel starting at https://www.erisian.com.au/bitcoin-core-dev/log-2021-08-23.html#l-263. ``` addrman lost 22813 new and 2 tried addresses due to collisions or invalid addresses ADDRMAN CONSISTENCY CHECK FAILED!!! err=-17 bitcoind: ./addrman.h:707: void CAddrMan::Check() const: Assertion `false' failed. Aborted ``` How to reproduce: - `git checkout 181a1207` and recompile - launch bitcoind with `-asmap` and `-checkaddrman=1` config options - restart bitcoind - bitcoind aborts on second call to `CAddrMan::Check()` This commit adds a regression test to reproduce the case; it passes or fails with the same error. Co-authored-by: John Newbery <john@johnnewbery.com> Co-authored-by: Martin Zumsande <mzumsande@gmail.com>
-rwxr-xr-xtest/functional/feature_asmap.py29
1 files changed, 27 insertions, 2 deletions
diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py
index 704dd6126b..2dc1e3a7cb 100755
--- a/test/functional/feature_asmap.py
+++ b/test/functional/feature_asmap.py
@@ -14,9 +14,11 @@ Verify node behaviour and debug log when launching bitcoind in these cases:
4. `bitcoind -asmap/-asmap=` with no file specified, using the default asmap
-5. `bitcoind -asmap` with no file specified and a missing default asmap file
+5. `bitcoind -asmap` restart with an addrman containing new and tried entries
-6. `bitcoind -asmap` with an empty (unparsable) default asmap file
+6. `bitcoind -asmap` with no file specified and a missing default asmap file
+
+7. `bitcoind -asmap` with an empty (unparsable) default asmap file
The tests are order-independent.
@@ -37,6 +39,12 @@ def expected_messages(filename):
class AsmapTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ self.extra_args = [["-checkaddrman=1"]] # Do addrman checks on all operations.
+
+ def fill_addrman(self, node_id):
+ """Add 2 tried addresses to the addrman, followed by 2 new addresses."""
+ for addr, tried in [[0, True], [1, True], [2, False], [3, False]]:
+ self.nodes[node_id].addpeeraddress(address=f"101.{addr}.0.0", tried=tried, port=8333)
def test_without_asmap_arg(self):
self.log.info('Test bitcoind with no -asmap arg passed')
@@ -72,6 +80,22 @@ class AsmapTest(BitcoinTestFramework):
self.start_node(0, [arg])
os.remove(self.default_asmap)
+ def test_asmap_interaction_with_addrman_containing_entries(self):
+ self.log.info("Test bitcoind -asmap restart with addrman containing new and tried entries")
+ self.stop_node(0)
+ shutil.copyfile(self.asmap_raw, self.default_asmap)
+ self.start_node(0, ["-asmap", "-checkaddrman=1"])
+ self.fill_addrman(node_id=0)
+ self.restart_node(0, ["-asmap", "-checkaddrman=1"])
+ with self.node.assert_debug_log(
+ expected_msgs=[
+ "Addrman checks started: new 2, tried 2, total 4",
+ "Addrman checks completed successfully",
+ ]
+ ):
+ self.node.getnodeaddresses() # getnodeaddresses re-runs the addrman checks
+ os.remove(self.default_asmap)
+
def test_default_asmap_with_missing_file(self):
self.log.info('Test bitcoind -asmap with missing default map file')
self.stop_node(0)
@@ -97,6 +121,7 @@ class AsmapTest(BitcoinTestFramework):
self.test_asmap_with_absolute_path()
self.test_asmap_with_relative_path()
self.test_default_asmap()
+ self.test_asmap_interaction_with_addrman_containing_entries()
self.test_default_asmap_with_missing_file()
self.test_empty_asmap()