Page MenuHomePhabricator

D8200.diff
No OneTemporary

D8200.diff

diff --git a/src/addrman.cpp b/src/addrman.cpp
--- a/src/addrman.cpp
+++ b/src/addrman.cpp
@@ -21,7 +21,7 @@
.GetCheapHash();
int tried_bucket = hash2 % ADDRMAN_TRIED_BUCKET_COUNT;
uint32_t mapped_as = GetMappedAS(asmap);
- LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to tried bucket %i.\n",
+ LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to tried bucket %i\n",
ToStringIP(), mapped_as, tried_bucket);
return tried_bucket;
}
@@ -38,7 +38,7 @@
.GetCheapHash();
int new_bucket = hash2 % ADDRMAN_NEW_BUCKET_COUNT;
uint32_t mapped_as = GetMappedAS(asmap);
- LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to new bucket %i.\n",
+ LogPrint(BCLog::NET, "IP %s mapped to AS%i belongs to new bucket %i\n",
ToStringIP(), mapped_as, new_bucket);
return new_bucket;
}
@@ -744,12 +744,12 @@
FILE *filestr = fsbridge::fopen(path, "rb");
CAutoFile file(filestr, SER_DISK, CLIENT_VERSION);
if (file.IsNull()) {
- LogPrintf("Failed to open asmap file from disk.\n");
+ LogPrintf("Failed to open asmap file from disk\n");
return bits;
}
fseek(filestr, 0, SEEK_END);
int length = ftell(filestr);
- LogPrintf("Opened asmap file %s (%d bytes) from disk.\n", path, length);
+ LogPrintf("Opened asmap file %s (%d bytes) from disk\n", path, length);
fseek(filestr, 0, SEEK_SET);
char cur_byte;
for (int i = 0; i < length; ++i) {
diff --git a/src/init.cpp b/src/init.cpp
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -579,6 +579,12 @@
"open (see the `addnode` RPC command help for more info)",
ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY,
OptionsCategory::CONNECTION);
+ gArgs.AddArg("-asmap=<file>",
+ strprintf("Specify asn mapping used for bucketing of the "
+ "peers (default: %s). Relative paths will be "
+ "prefixed by the net-specific datadir location.",
+ DEFAULT_ASMAP_FILENAME),
+ ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
gArgs.AddArg("-banscore=<n>",
strprintf("Threshold for disconnecting and discouraging "
"misbehaving peers (default: %u)",
@@ -714,10 +720,6 @@
"Tor control port password (default: empty)",
ArgsManager::ALLOW_ANY | ArgsManager::SENSITIVE,
OptionsCategory::CONNECTION);
- gArgs.AddArg("-asmap=<file>",
- "Specify asn mapping used for bucketing of the peers. Path "
- "should be relative to the -datadir path.",
- ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
#ifdef USE_UPNP
#if USE_UPNP
gArgs.AddArg("-upnp",
@@ -2308,6 +2310,33 @@
}
}
+ // Read asmap file if configured
+ if (gArgs.IsArgSet("-asmap")) {
+ fs::path asmap_path = fs::path(gArgs.GetArg("-asmap", ""));
+ if (asmap_path.empty()) {
+ asmap_path = DEFAULT_ASMAP_FILENAME;
+ }
+ if (!asmap_path.is_absolute()) {
+ asmap_path = GetDataDir() / asmap_path;
+ }
+ if (!fs::exists(asmap_path)) {
+ InitError(strprintf(_("Could not find asmap file %s"), asmap_path));
+ return false;
+ }
+ std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
+ if (asmap.size() == 0) {
+ InitError(
+ strprintf(_("Could not parse asmap file %s"), asmap_path));
+ return false;
+ }
+ const uint256 asmap_version = SerializeHash(asmap);
+ node.connman->SetAsmap(std::move(asmap));
+ LogPrintf("Using asmap version %s for IP bucketing\n",
+ asmap_version.ToString());
+ } else {
+ LogPrintf("Using /16 prefix for IP bucketing\n");
+ }
+
#if ENABLE_ZMQ
g_zmq_notification_interface = CZMQNotificationInterface::Create();
@@ -2773,28 +2802,6 @@
return false;
}
- // Read asmap file if configured
- if (gArgs.IsArgSet("-asmap")) {
- std::string asmap_file = gArgs.GetArg("-asmap", "");
- if (asmap_file.empty()) {
- asmap_file = DEFAULT_ASMAP_FILENAME;
- }
- const fs::path asmap_path = GetDataDir() / asmap_file;
- std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
- if (asmap.size() == 0) {
- InitError(
- strprintf(_("Could not find or parse specified asmap: '%s'"),
- asmap_path));
- return false;
- }
- const uint256 asmap_version = SerializeHash(asmap);
- node.connman->SetAsmap(std::move(asmap));
- LogPrintf("Using asmap version %s for IP bucketing.\n",
- asmap_version.ToString());
- } else {
- LogPrintf("Using /16 prefix for IP bucketing.\n");
- }
-
// Step 13: finished
SetRPCWarmupFinished();
diff --git a/src/netaddress.h b/src/netaddress.h
--- a/src/netaddress.h
+++ b/src/netaddress.h
@@ -39,14 +39,12 @@
explicit CNetAddr(const struct in_addr &ipv4Addr);
void SetIP(const CNetAddr &ip);
-private:
/**
* Set raw IPv4 or IPv6 address (in network byte order)
* @note Only NET_IPV4 and NET_IPV6 are allowed for network.
*/
void SetRaw(Network network, const uint8_t *data);
-public:
bool SetInternal(const std::string &name);
// for Tor addresses
@@ -87,6 +85,8 @@
// IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in
// RFC2765)
bool IsRFC6145() const;
+ // IPv6 Hurricane Electric - https://he.net (2001:0470::/36)
+ bool IsHeNet() const;
bool IsTor() const;
bool IsLocal() const;
bool IsRoutable() const;
diff --git a/src/netaddress.cpp b/src/netaddress.cpp
--- a/src/netaddress.cpp
+++ b/src/netaddress.cpp
@@ -200,6 +200,11 @@
(GetByte(12) & 0xF0) == 0x20);
}
+bool CNetAddr::IsHeNet() const {
+ return (GetByte(15) == 0x20 && GetByte(14) == 0x01 && GetByte(13) == 0x04 &&
+ GetByte(12) == 0x70);
+}
+
/**
* @returns Whether or not this is a dummy address that maps an onion address
* into IPv6.
@@ -524,8 +529,7 @@
} else if (IsTor()) {
nStartByte = 6;
nBits = 4;
- } else if (GetByte(15) == 0x20 && GetByte(14) == 0x01 &&
- GetByte(13) == 0x04 && GetByte(12) == 0x70) {
+ } else if (IsHeNet()) {
// for he.net, use /36 groups
nBits = 36;
} else {
diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp
--- a/src/rpc/net.cpp
+++ b/src/rpc/net.cpp
@@ -102,7 +102,9 @@
"(ip:port) Local address as reported by the peer"},
{RPCResult::Type::NUM, "mapped_as",
"The AS in the BGP route to the peer used for "
- "diversifying peer selection\n"},
+ "diversifying\n"
+ "peer selection (only available if the asmap config flag "
+ "is set)\n"},
{RPCResult::Type::STR_HEX, "services",
"The services offered"},
{RPCResult::Type::ARR,
diff --git a/test/functional/feature_asmap.py b/test/functional/feature_asmap.py
new file mode 100755
--- /dev/null
+++ b/test/functional/feature_asmap.py
@@ -0,0 +1,115 @@
+#!/usr/bin/env python3
+# Copyright (c) 2020 The Bitcoin Core developers
+# Distributed under the MIT software license, see the accompanying
+# file COPYING or http://www.opensource.org/licenses/mit-license.php.
+"""Test asmap config argument for ASN-based IP bucketing.
+
+Verify node behaviour and debug log when launching bitcoind in these cases:
+
+1. `bitcoind` with no -asmap arg, using /16 prefix for IP bucketing
+
+2. `bitcoind -asmap=<absolute path>`, using the unit test skeleton asmap
+
+3. `bitcoind -asmap=<relative path>`, using the unit test skeleton asmap
+
+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
+
+6. `bitcoind -asmap` with an empty (unparsable) default asmap file
+
+The tests are order-independent.
+
+"""
+import os
+import shutil
+
+from test_framework.test_framework import BitcoinTestFramework
+
+DEFAULT_ASMAP_FILENAME = 'ip_asn.map' # defined in src/init.cpp
+ASMAP = '../../src/test/data/asmap.raw' # path to unit test skeleton asmap
+VERSION = 'fec61fa21a9f46f3b17bdcd660d7f4cd90b966aad3aec593c99b35f0aca15853'
+
+
+def expected_messages(filename):
+ return ['Opened asmap file "{}" (59 bytes) from disk'.format(filename),
+ 'Using asmap version {} for IP bucketing'.format(VERSION)]
+
+
+class AsmapTest(BitcoinTestFramework):
+ def set_test_params(self):
+ self.setup_clean_chain = False
+ self.num_nodes = 1
+
+ def test_without_asmap_arg(self):
+ self.log.info('Test bitcoind with no -asmap arg passed')
+ self.stop_node(0)
+ with self.node.assert_debug_log(['Using /16 prefix for IP bucketing']):
+ self.start_node(0)
+
+ def test_asmap_with_absolute_path(self):
+ self.log.info('Test bitcoind -asmap=<absolute path>')
+ self.stop_node(0)
+ filename = os.path.join(self.datadir, 'my-map-file.map')
+ shutil.copyfile(self.asmap_raw, filename)
+ with self.node.assert_debug_log(expected_messages(filename)):
+ self.start_node(0, ['-asmap={}'.format(filename)])
+ os.remove(filename)
+
+ def test_asmap_with_relative_path(self):
+ self.log.info('Test bitcoind -asmap=<relative path>')
+ self.stop_node(0)
+ name = 'ASN_map'
+ filename = os.path.join(self.datadir, name)
+ shutil.copyfile(self.asmap_raw, filename)
+ with self.node.assert_debug_log(expected_messages(filename)):
+ self.start_node(0, ['-asmap={}'.format(name)])
+ os.remove(filename)
+
+ def test_default_asmap(self):
+ shutil.copyfile(self.asmap_raw, self.default_asmap)
+ for arg in ['-asmap', '-asmap=']:
+ self.log.info(
+ 'Test bitcoind {} (using default map file)'.format(arg))
+ self.stop_node(0)
+ with self.node.assert_debug_log(expected_messages(self.default_asmap)):
+ self.start_node(0, [arg])
+ 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 = "Error: Could not find asmap file \"{}\"".format(
+ 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)
+ with open(self.default_asmap, "w", encoding="utf-8") as f:
+ f.write("")
+ msg = "Error: Could not parse asmap file \"{}\"".format(
+ self.default_asmap)
+ self.node.assert_start_raises_init_error(
+ extra_args=['-asmap'], expected_msg=msg)
+ os.remove(self.default_asmap)
+
+ def run_test(self):
+ self.node = self.nodes[0]
+ self.datadir = os.path.join(self.node.datadir, self.chain)
+ self.default_asmap = os.path.join(self.datadir, DEFAULT_ASMAP_FILENAME)
+ self.asmap_raw = os.path.join(
+ os.path.dirname(
+ os.path.realpath(__file__)), ASMAP)
+
+ self.test_without_asmap_arg()
+ self.test_asmap_with_absolute_path()
+ self.test_asmap_with_relative_path()
+ self.test_default_asmap()
+ self.test_default_asmap_with_missing_file()
+ self.test_empty_asmap()
+
+
+if __name__ == '__main__':
+ AsmapTest().main()

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 1, 10:59 (15 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187444
Default Alt Text
D8200.diff (11 KB)

Event Timeline