diff --git a/src/init.cpp b/src/init.cpp index a44cdf807e0..6cbeea3ccdb 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -119,6 +119,10 @@ #include #endif +#ifdef ENABLE_EMBEDDED_ASMAP +#include +#endif + using common::AmountErrMsg; using common::InvalidPortErrMsg; using common::ResolveErrMsg; @@ -1560,29 +1564,50 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info) ApplyArgsManOptions(args, peerman_opts); { - // Read asmap file if configured and initialize + // Read asmap file if configured or embedded asmap data and initialize // Netgroupman with or without it assert(!node.netgroupman); if (args.IsArgSet("-asmap") && !args.IsArgNegated("-asmap")) { - fs::path asmap_path = args.GetPathArg("-asmap"); - if (asmap_path.empty()) { - InitError(_("-asmap requires a file path. Use -asmap=.")); - return false; + uint256 asmap_version{}; + if (!args.GetBoolArg("-asmap", false)) { + fs::path asmap_path = args.GetPathArg("-asmap"); + if (!asmap_path.is_absolute()) { + asmap_path = args.GetDataDirNet() / asmap_path; + } + + // If a specific path was passed with the asmap argument check if + // the file actually exists in that location + if (!fs::exists(asmap_path)) { + InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path)))); + return false; + } + + // If a file exists at the path, try to read the file + std::vector asmap{DecodeAsmap(asmap_path)}; + if (asmap.empty()) { + InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path)))); + return false; + } + asmap_version = AsmapVersion(asmap); + node.netgroupman = std::make_unique(NetGroupManager::WithLoadedAsmap(std::move(asmap))); + } else { + #ifdef ENABLE_EMBEDDED_ASMAP + // Use the embedded asmap data + std::span asmap{node::data::ip_asn}; + if (asmap.empty() || !CheckStandardAsmap(asmap)) { + InitError(strprintf(_("Could not read embedded asmap data"))); + return false; + } + node.netgroupman = std::make_unique(NetGroupManager::WithEmbeddedAsmap(asmap)); + asmap_version = AsmapVersion(asmap); + LogInfo("Opened asmap data (%zu bytes) from embedded byte array\n", asmap.size()); + #else + // If there is no embedded data, fail and report it since + // the user tried to use it + InitError(strprintf(_("Embedded asmap data not available"))); + return false; + #endif } - if (!asmap_path.is_absolute()) { - asmap_path = args.GetDataDirNet() / asmap_path; - } - if (!fs::exists(asmap_path)) { - InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path)))); - return false; - } - std::vector asmap{DecodeAsmap(asmap_path)}; - if (asmap.size() == 0) { - InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path)))); - return false; - } - const uint256 asmap_version = AsmapVersion(asmap); - node.netgroupman = std::make_unique(NetGroupManager::WithLoadedAsmap(std::move(asmap))); LogInfo("Using asmap version %s for IP bucketing", asmap_version.ToString()); } else { node.netgroupman = std::make_unique(NetGroupManager::NoAsmap()); diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py index 8ad59c82ccf..310788f2cbf 100755 --- a/test/functional/feature_asmap.py +++ b/test/functional/feature_asmap.py @@ -66,12 +66,19 @@ class AsmapTest(BitcoinTestFramework): self.start_node(0, [f'-asmap={name}']) os.remove(filename) - def test_unspecified_asmap(self): - msg = "Error: -asmap requires a file path. Use -asmap=." - for arg in ['-asmap', '-asmap=']: - self.log.info(f'Test bitcoind {arg} (and no filename specified)') - self.stop_node(0) - self.node.assert_start_raises_init_error(extra_args=[arg], expected_msg=msg) + def test_embedded_asmap(self): + if self.is_embedded_asmap_compiled(): + self.log.info('Test bitcoind -asmap (using embedded map data)') + for arg in ['-asmap', '-asmap=1']: + self.stop_node(0) + with self.node.assert_debug_log(["Opened asmap data", "from embedded byte array"]): + self.start_node(0, [arg]) + else: + self.log.info('Test bitcoind -asmap (compiled without embedded map data)') + for arg in ['-asmap', '-asmap=1']: + self.stop_node(0) + msg = "Error: Embedded asmap data not available" + self.node.assert_start_raises_init_error(extra_args=[arg], expected_msg=msg) def test_asmap_interaction_with_addrman_containing_entries(self): self.log.info("Test bitcoind -asmap restart with addrman containing new and tried entries") @@ -127,7 +134,7 @@ class AsmapTest(BitcoinTestFramework): self.test_noasmap_arg() self.test_asmap_with_absolute_path() self.test_asmap_with_relative_path() - self.test_unspecified_asmap() + self.test_embedded_asmap() self.test_asmap_interaction_with_addrman_containing_entries() self.test_asmap_with_missing_file() self.test_empty_asmap()