aboutsummaryrefslogtreecommitdiff
path: root/src/addrman.h
diff options
context:
space:
mode:
authorVasil Dimov <vd@FreeBSD.org>2020-05-19 17:39:05 +0200
committerVasil Dimov <vd@FreeBSD.org>2020-10-09 16:42:49 +0200
commit201a4596d92d640d5eb7e76cc8d959228fa09dbb (patch)
tree1f0641dfee1f4d475336a32f3fea930eded9d629 /src/addrman.h
parent1d3ec2a1fda7446323786a52da1fd109c01aa6fb (diff)
net: CAddress & CAddrMan: (un)serialize as ADDRv2
Change the serialization of `CAddrMan` to serialize its addresses in ADDRv2/BIP155 format by default. Introduce a new `CAddrMan` format version (3). Add support for ADDRv2 format in `CAddress` (un)serialization. Co-authored-by: Carl Dong <contact@carldong.me>
Diffstat (limited to 'src/addrman.h')
-rw-r--r--src/addrman.h60
1 files changed, 46 insertions, 14 deletions
diff --git a/src/addrman.h b/src/addrman.h
index ca045b91cd..b4089dc894 100644
--- a/src/addrman.h
+++ b/src/addrman.h
@@ -12,6 +12,7 @@
#include <random.h>
#include <sync.h>
#include <timedata.h>
+#include <tinyformat.h>
#include <util/system.h>
#include <fs.h>
@@ -264,6 +265,14 @@ protected:
void SetServices_(const CService &addr, ServiceFlags nServices) EXCLUSIVE_LOCKS_REQUIRED(cs);
public:
+ //! Serialization versions.
+ enum class Format : uint8_t {
+ V0_HISTORICAL = 0, //!< historic format, before commit e6b343d88
+ V1_DETERMINISTIC = 1, //!< for pre-asmap files
+ V2_ASMAP = 2, //!< for files including asmap version
+ V3_BIP155 = 3, //!< same as V2_ASMAP plus addresses are in BIP155 format
+ };
+
// Compressed IP->ASN mapping, loaded from a file when a node starts.
// Should be always empty if no file was provided.
// This mapping is then used for bucketing nodes in Addrman.
@@ -285,8 +294,8 @@ public:
/**
- * serialized format:
- * * version byte (1 for pre-asmap files, 2 for files including asmap version)
+ * Serialized format.
+ * * version byte (@see `Format`)
* * 0x20 + nKey (serialized as if it were a vector, for backward compatibility)
* * nNew
* * nTried
@@ -313,13 +322,16 @@ public:
* We don't use SERIALIZE_METHODS since the serialization and deserialization code has
* very little in common.
*/
- template<typename Stream>
- void Serialize(Stream &s) const
+ template <typename Stream>
+ void Serialize(Stream& s_) const
{
LOCK(cs);
- unsigned char nVersion = 2;
- s << nVersion;
+ // Always serialize in the latest version (currently Format::V3_BIP155).
+
+ OverrideStream<Stream> s(&s_, s_.GetType(), s_.GetVersion() | ADDRV2_FORMAT);
+
+ s << static_cast<uint8_t>(Format::V3_BIP155);
s << ((unsigned char)32);
s << nKey;
s << nNew;
@@ -370,14 +382,34 @@ public:
s << asmap_version;
}
- template<typename Stream>
- void Unserialize(Stream& s)
+ template <typename Stream>
+ void Unserialize(Stream& s_)
{
LOCK(cs);
Clear();
- unsigned char nVersion;
- s >> nVersion;
+
+ Format format;
+ s_ >> Using<CustomUintFormatter<1>>(format);
+
+ static constexpr Format maximum_supported_format = Format::V3_BIP155;
+ if (format > maximum_supported_format) {
+ throw std::ios_base::failure(strprintf(
+ "Unsupported format of addrman database: %u. Maximum supported is %u. "
+ "Continuing operation without using the saved list of peers.",
+ static_cast<uint8_t>(format),
+ static_cast<uint8_t>(maximum_supported_format)));
+ }
+
+ int stream_version = s_.GetVersion();
+ if (format >= Format::V3_BIP155) {
+ // Add ADDRV2_FORMAT to the version so that the CNetAddr and CAddress
+ // unserialize methods know that an address in addrv2 format is coming.
+ stream_version |= ADDRV2_FORMAT;
+ }
+
+ OverrideStream<Stream> s(&s_, s_.GetType(), stream_version);
+
unsigned char nKeySize;
s >> nKeySize;
if (nKeySize != 32) throw std::ios_base::failure("Incorrect keysize in addrman deserialization");
@@ -386,7 +418,7 @@ public:
s >> nTried;
int nUBuckets = 0;
s >> nUBuckets;
- if (nVersion != 0) {
+ if (format >= Format::V1_DETERMINISTIC) {
nUBuckets ^= (1 << 30);
}
@@ -449,7 +481,7 @@ public:
supplied_asmap_version = SerializeHash(m_asmap);
}
uint256 serialized_asmap_version;
- if (nVersion > 1) {
+ if (format >= Format::V2_ASMAP) {
s >> serialized_asmap_version;
}
@@ -457,13 +489,13 @@ public:
CAddrInfo &info = mapInfo[n];
int bucket = entryToBucket[n];
int nUBucketPos = info.GetBucketPosition(nKey, true, bucket);
- if (nVersion == 2 && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 &&
+ if (format >= Format::V2_ASMAP && nUBuckets == ADDRMAN_NEW_BUCKET_COUNT && vvNew[bucket][nUBucketPos] == -1 &&
info.nRefCount < ADDRMAN_NEW_BUCKETS_PER_ADDRESS && serialized_asmap_version == supplied_asmap_version) {
// Bucketing has not changed, using existing bucket positions for the new table
vvNew[bucket][nUBucketPos] = n;
info.nRefCount++;
} else {
- // In case the new table data cannot be used (nVersion unknown, bucket count wrong or new asmap),
+ // In case the new table data cannot be used (format unknown, bucket count wrong or new asmap),
// try to give them a reference based on their primary source address.
LogPrint(BCLog::ADDRMAN, "Bucketing method was updated, re-bucketing addrman entries from disk\n");
bucket = info.GetNewBucket(nKey, m_asmap);