diff options
author | MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> | 2023-01-31 18:04:44 +0100 |
---|---|---|
committer | MarcoFalke <*~=`'#}+{/-|&$^_@721217.xyz> | 2023-09-05 10:13:25 +0200 |
commit | fac81affb527132945773a5315bd27fec61ec52f (patch) | |
tree | 90aa401bd50bf12519a45737f335856256ff614e /src/protocol.h | |
parent | faec591d64e40ba7ec7656cbfdda1a05953bde13 (diff) | |
download | bitcoin-fac81affb527132945773a5315bd27fec61ec52f.tar.xz |
Use serialization parameters for CAddress serialization
This also cleans up the addrman (de)serialization code paths to only
allow `Disk` serialization. Some unit tests previously forced a
`Network` serialization, which does not make sense, because Bitcoin Core
in production will always `Disk` serialize.
This cleanup idea was suggested by Pieter Wuille and implemented by Anthony
Towns.
Co-authored-by: Pieter Wuille <pieter@wuille.net>
Co-authored-by: Anthony Towns <aj@erisian.com.au>
Diffstat (limited to 'src/protocol.h')
-rw-r--r-- | src/protocol.h | 36 |
1 files changed, 22 insertions, 14 deletions
diff --git a/src/protocol.h b/src/protocol.h index 316b7a11f2..a7ca0c6f3e 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -390,35 +390,43 @@ public: CAddress(CService ipIn, ServiceFlags nServicesIn) : CService{ipIn}, nServices{nServicesIn} {}; CAddress(CService ipIn, ServiceFlags nServicesIn, NodeSeconds time) : CService{ipIn}, nTime{time}, nServices{nServicesIn} {}; - SERIALIZE_METHODS(CAddress, obj) + enum class Format { + Disk, + Network, + }; + struct SerParams : CNetAddr::SerParams { + const Format fmt; + }; + static constexpr SerParams V1_NETWORK{{CNetAddr::Encoding::V1}, Format::Network}; + static constexpr SerParams V2_NETWORK{{CNetAddr::Encoding::V2}, Format::Network}; + static constexpr SerParams V1_DISK{{CNetAddr::Encoding::V1}, Format::Disk}; + static constexpr SerParams V2_DISK{{CNetAddr::Encoding::V2}, Format::Disk}; + + SERIALIZE_METHODS_PARAMS(CAddress, obj, SerParams, params) { - // CAddress has a distinct network serialization and a disk serialization, but it should never - // be hashed (except through CHashWriter in addrdb.cpp, which sets SER_DISK), and it's - // ambiguous what that would mean. Make sure no code relying on that is introduced: - assert(!(s.GetType() & SER_GETHASH)); bool use_v2; - if (s.GetType() & SER_DISK) { + if (params.fmt == Format::Disk) { // In the disk serialization format, the encoding (v1 or v2) is determined by a flag version // that's part of the serialization itself. ADDRV2_FORMAT in the stream version only determines // whether V2 is chosen/permitted at all. uint32_t stored_format_version = DISK_VERSION_INIT; - if (s.GetVersion() & ADDRV2_FORMAT) stored_format_version |= DISK_VERSION_ADDRV2; + if (params.enc == Encoding::V2) stored_format_version |= DISK_VERSION_ADDRV2; READWRITE(stored_format_version); stored_format_version &= ~DISK_VERSION_IGNORE_MASK; // ignore low bits if (stored_format_version == 0) { use_v2 = false; - } else if (stored_format_version == DISK_VERSION_ADDRV2 && (s.GetVersion() & ADDRV2_FORMAT)) { - // Only support v2 deserialization if ADDRV2_FORMAT is set. + } else if (stored_format_version == DISK_VERSION_ADDRV2 && params.enc == Encoding::V2) { + // Only support v2 deserialization if V2 is set. use_v2 = true; } else { throw std::ios_base::failure("Unsupported CAddress disk format version"); } } else { + assert(params.fmt == Format::Network); // In the network serialization format, the encoding (v1 or v2) is determined directly by - // the value of ADDRV2_FORMAT in the stream version, as no explicitly encoded version + // the value of enc in the stream params, as no explicitly encoded version // exists in the stream. - assert(s.GetType() & SER_NETWORK); - use_v2 = s.GetVersion() & ADDRV2_FORMAT; + use_v2 = params.enc == Encoding::V2; } READWRITE(Using<LossyChronoFormatter<uint32_t>>(obj.nTime)); @@ -432,8 +440,8 @@ public: READWRITE(Using<CustomUintFormatter<8>>(obj.nServices)); } // Invoke V1/V2 serializer for CService parent object. - OverrideStream<Stream> os(&s, s.GetType(), use_v2 ? ADDRV2_FORMAT : 0); - SerReadWriteMany(os, ser_action, AsBase<CService>(obj)); + const auto ser_params{use_v2 ? CNetAddr::V2 : CNetAddr::V1}; + READWRITE(WithParams(ser_params, AsBase<CService>(obj))); } //! Always included in serialization. The behavior is unspecified if the value is not representable as uint32_t. |