This commit is contained in:
Fabian Jahr 2024-04-29 04:28:02 +02:00 committed by GitHub
commit 87d61bec04
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 138698 additions and 27 deletions

View File

@ -169,6 +169,7 @@ BITCOIN_CORE_H = \
indirectmap.h \
init.h \
init/common.h \
init/ip_asn.h \
interfaces/chain.h \
interfaces/echo.h \
interfaces/handler.h \

View File

@ -31,6 +31,7 @@
#include <index/coinstatsindex.h>
#include <index/txindex.h>
#include <init/common.h>
#include <init/ip_asn.h>
#include <interfaces/chain.h>
#include <interfaces/init.h>
#include <interfaces/node.h>
@ -66,6 +67,7 @@
#include <rpc/util.h>
#include <scheduler.h>
#include <script/sigcache.h>
#include <span.h>
#include <sync.h>
#include <timedata.h>
#include <torcontrol.h>
@ -1230,22 +1232,35 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
{
// Read asmap file if configured
// Read asmap file or embedded data if configured
std::vector<bool> asmap;
if (args.IsArgSet("-asmap")) {
const bool asmap_file_set{args.GetPathArg("-asmap") != ""};
fs::path asmap_path = args.GetPathArg("-asmap", DEFAULT_ASMAP_FILENAME);
if (!asmap_path.is_absolute()) {
asmap_path = args.GetDataDirNet() / asmap_path;
}
if (!fs::exists(asmap_path)) {
if (!fs::exists(asmap_path) && asmap_file_set) {
InitError(strprintf(_("Could not find asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
return false;
}
asmap = DecodeAsmap(asmap_path);
if (asmap.size() == 0) {
InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
return false;
if (fs::exists(asmap_path)) {
asmap = DecodeAsmap(asmap_path);
if (asmap.size() == 0) {
InitError(strprintf(_("Could not parse asmap file %s"), fs::quoted(fs::PathToString(asmap_path))));
return false;
}
} else {
Span<const unsigned char> asmap_data(reinterpret_cast<const unsigned char*>(ip_asn), static_cast<size_t>(ip_asn_len));
asmap = DecodeAsmap(asmap_data);
if (asmap.size() == 0) {
InitError(strprintf(_("Could not read embedded asmap data")));
return false;
}
}
const uint256 asmap_version = (HashWriter{} << asmap).GetHash();
LogPrintf("Using asmap version %s for IP bucketing\n", asmap_version.ToString());
} else {

138642
src/init/ip_asn.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@
#include <clientversion.h>
#include <logging.h>
#include <serialize.h>
#include <span.h>
#include <streams.h>
#include <util/fs.h>
@ -194,30 +195,46 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits)
return false; // Reached EOF without RETURN instruction
}
std::vector<bool> DecodeAsmap(fs::path path)
{
std::vector<bool> Decode(const Span<const uint8_t>& data) {
std::vector<bool> bits;
FILE *filestr = fsbridge::fopen(path, "rb");
AutoFile file{filestr};
if (file.IsNull()) {
LogPrintf("Failed to open asmap file from disk\n");
if (data.empty()) {
return bits;
}
fseek(filestr, 0, SEEK_END);
int length = ftell(filestr);
LogPrintf("Opened asmap file %s (%d bytes) from disk\n", fs::quoted(fs::PathToString(path)), length);
fseek(filestr, 0, SEEK_SET);
uint8_t cur_byte;
for (int i = 0; i < length; ++i) {
file >> cur_byte;
for (auto cur_byte : data) {
for (int bit = 0; bit < 8; ++bit) {
bits.push_back((cur_byte >> bit) & 1);
}
}
if (!SanityCheckASMap(bits, 128)) {
LogPrintf("Sanity check of asmap file %s failed\n", fs::quoted(fs::PathToString(path)));
LogPrintf("Sanity check of asmap data failed\n");
return {};
}
return bits;
}
std::vector<bool> DecodeAsmap(fs::path path) {
FILE *filestr = fsbridge::fopen(path, "rb");
AutoFile file{filestr};
if (file.IsNull()) {
LogPrintf("Failed to open asmap file from disk\n");
return {};
}
fseek(filestr, 0, SEEK_END);
int length = ftell(filestr);
LogPrintf("Opened asmap file %s (%d bytes) from disk\n", fs::quoted(fs::PathToString(path)), length);
fseek(filestr, 0, SEEK_SET);
std::vector<uint8_t> buffer(length);
size_t length_read = fread(buffer.data(), 1, length, file.Get());
assert(length_read == static_cast<size_t>(length));
return Decode(buffer);
}
std::vector<bool> DecodeAsmap(Span<const uint8_t> data) {
LogPrintf("Opened asmap data (%zu bytes) from embedded byte array\n", data.size());
return Decode(data);
}

View File

@ -6,6 +6,7 @@
#define BITCOIN_UTIL_ASMAP_H
#include <util/fs.h>
#include <span.h>
#include <cstdint>
#include <vector>
@ -16,5 +17,7 @@ bool SanityCheckASMap(const std::vector<bool>& asmap, int bits);
/** Read asmap from provided binary file */
std::vector<bool> DecodeAsmap(fs::path path);
/** Read asmap from embedded byte array */
std::vector<bool> DecodeAsmap(Span<const uint8_t> data);
#endif // BITCOIN_UTIL_ASMAP_H

View File

@ -97,12 +97,6 @@ class AsmapTest(BitcoinTestFramework):
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)
msg = f"Error: Could not find asmap file \"{self.default_asmap}\""
self.node.assert_start_raises_init_error(extra_args=['-asmap'], expected_msg=msg)
def test_empty_asmap(self):
self.log.info('Test bitcoind -asmap with empty map file')
self.stop_node(0)
@ -131,7 +125,6 @@ class AsmapTest(BitcoinTestFramework):
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()
self.test_asmap_health_check()