diff --git a/doc/files.md b/doc/files.md index 58cd234390..a6dea3137a 100644 --- a/doc/files.md +++ b/doc/files.md @@ -56,7 +56,6 @@ Subdirectory | File(s) | Description `./` | `anchors.dat` | Anchor IP address database, created on shutdown and deleted at startup. Anchors are last known outgoing block-relay-only peers that are tried to re-connect to on startup `evodb/` | |special txes and quorums database `llmq/` | |quorum signatures database -`./` | `banlist.dat` | Stores the addresses/subnets of banned nodes (deprecated). `dashd` or `dash-qt` no longer save the banlist to this file, but read it on startup if `banlist.json` is not present. `./` | `banlist.json` | Stores the addresses/subnets of banned nodes. `./` | `dash.conf` | User-defined [configuration settings](dash-conf.md) for `dashd` or `dash-qt`. File is not written to by the software and must be created manually. Path can be specified by `-conf` option `./` | `dashd.pid` | Stores the process ID (PID) of `dashd` or `dash-qt` while running; created at start and deleted on shutdown; can be specified by `-pid` option @@ -116,6 +115,7 @@ These subdirectories and files are no longer used by Dash Core: Path | Description | Repository notes ---------------|-------------|----------------- +`banlist.dat` | Stores the addresses/subnets of banned nodes; completely ignored and superseded by `banlist.json` in 20.0 | [PR #5574](https://github.com/dashpay/dash/pull/5574) `blktree/` | Blockchain index; replaced by `blocks/index/` in [0.8.0](https://github.com/dash/dash/blob/master/doc/release-notes/release-notes-0.8.0.md#improvements) | [PR #2231](https://github.com/dash/dash/pull/2231), [`8fdc94cc`](https://github.com/dash/dash/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) `coins/` | Unspent transaction output database; replaced by `chainstate/` in 0.8.0 | [PR #2231](https://github.com/dash/dash/pull/2231), [`8fdc94cc`](https://github.com/dash/dash/commit/8fdc94cc8f0341e96b1edb3a5b56811c0b20bd15) `blkindex.dat` | Blockchain index BDB database; replaced by {`chainstate/`, `blocks/index/`, `blocks/revNNNNN.dat`[\[2\]](#note2)} in 0.8.0 | [PR #1677](https://github.com/dash/dash/pull/1677) diff --git a/src/addrdb.cpp b/src/addrdb.cpp index 12e1ee4bac..69fcb5464e 100644 --- a/src/addrdb.cpp +++ b/src/addrdb.cpp @@ -198,16 +198,15 @@ bool CBanDB::Write(const banmap_t& banSet) return false; } -bool CBanDB::Read(banmap_t& banSet, bool& dirty) +bool CBanDB::Read(banmap_t& banSet) { - // If the JSON banlist does not exist, then try to read the non-upgraded banlist.dat. - if (!fs::exists(m_banlist_json)) { - // If this succeeds then we need to flush to disk in order to create the JSON banlist. - dirty = true; - return DeserializeFileDB(m_banlist_dat, banSet, CLIENT_VERSION); + if (fs::exists(m_banlist_dat)) { + LogPrintf("banlist.dat ignored because it can only be read by " PACKAGE_NAME " version 19.x. Remove %s to silence this warning.\n", m_banlist_dat); + } + // If the JSON banlist does not exist, then recreate it + if (!fs::exists(m_banlist_json)) { + return false; } - - dirty = false; std::map settings; std::vector errors; diff --git a/src/addrdb.h b/src/addrdb.h index 88dec7db51..9abe4cc769 100644 --- a/src/addrdb.h +++ b/src/addrdb.h @@ -76,7 +76,7 @@ public: static bool Read(CAddrMan& addr, CDataStream& ssPeers); }; -/** Access to the banlist databases (banlist.json and banlist.dat) */ +/** Access to the banlist database (banlist.json) */ class CBanDB { private: @@ -95,11 +95,9 @@ public: * Read the banlist from disk. * @param[out] banSet The loaded list. Set if `true` is returned, otherwise it is left * in an undefined state. - * @param[out] dirty Indicates whether the loaded list needs flushing to disk. Set if - * `true` is returned, otherwise it is left in an undefined state. * @return true on success */ - bool Read(banmap_t& banSet, bool& dirty); + bool Read(banmap_t& banSet); }; /** diff --git a/src/banman.cpp b/src/banman.cpp index ba1db11577..9599c41e2e 100644 --- a/src/banman.cpp +++ b/src/banman.cpp @@ -18,7 +18,7 @@ BanMan::BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist...").translated); int64_t n_start = GetTimeMillis(); - if (m_ban_db.Read(m_banned, m_is_dirty)) { + if (m_ban_db.Read(m_banned)) { SweepBanned(); // sweep out unused entries LogPrint(BCLog::NET, "Loaded %d banned node addresses/subnets %dms\n", m_banned.size(), diff --git a/src/banman.h b/src/banman.h index 06f18ea826..956729e497 100644 --- a/src/banman.h +++ b/src/banman.h @@ -89,7 +89,7 @@ private: RecursiveMutex m_cs_banned; banmap_t m_banned GUARDED_BY(m_cs_banned); - bool m_is_dirty GUARDED_BY(m_cs_banned); + bool m_is_dirty GUARDED_BY(m_cs_banned){false}; CClientUIInterface* m_client_interface = nullptr; CBanDB m_ban_db; const int64_t m_default_ban_time; diff --git a/src/netaddress.h b/src/netaddress.h index a2b8418ad4..87fbb39efe 100644 --- a/src/netaddress.h +++ b/src/netaddress.h @@ -41,8 +41,7 @@ static constexpr int ADDRV2_FORMAT = 0x20000000; * over all enum values and also `GetExtNetwork()` "extends" this enum by * introducing standalone constants starting from `NET_MAX`. */ -enum Network -{ +enum Network { /// Addresses from these networks are not publicly routable on the global Internet. NET_UNROUTABLE = 0, @@ -72,16 +71,14 @@ enum Network /// Prefix of an IPv6 address when it contains an embedded IPv4 address. /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). static const std::array IPV4_IN_IPV6_PREFIX{ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF -}; + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF}; /// Prefix of an IPv6 address when it contains an embedded TORv2 address. /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). /// Such dummy IPv6 addresses are guaranteed to not be publicly routable as they /// fall under RFC4193's fc00::/7 subnet allocated to unique-local addresses. static const std::array TORV2_IN_IPV6_PREFIX{ - 0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43 -}; + 0xFD, 0x87, 0xD8, 0x7E, 0xEB, 0x43}; /// Prefix of an IPv6 address when it contains an embedded "internal" address. /// Used when (un)serializing addresses in ADDRv1 format (pre-BIP155). @@ -119,455 +116,438 @@ static constexpr uint16_t I2P_SAM31_PORT{0}; */ class CNetAddr { - protected: - /** - * Raw representation of the network address. - * In network byte order (big endian) for IPv4 and IPv6. - */ - prevector m_addr{ADDR_IPV6_SIZE, 0x0}; +protected: + /** + * Raw representation of the network address. + * In network byte order (big endian) for IPv4 and IPv6. + */ + prevector m_addr{ADDR_IPV6_SIZE, 0x0}; - /** - * Network to which this address belongs. - */ - Network m_net{NET_IPV6}; + /** + * Network to which this address belongs. + */ + Network m_net{NET_IPV6}; - /** - * Scope id if scoped/link-local IPV6 address. - * See https://tools.ietf.org/html/rfc4007 - */ - uint32_t m_scope_id{0}; + /** + * Scope id if scoped/link-local IPV6 address. + * See https://tools.ietf.org/html/rfc4007 + */ + uint32_t m_scope_id{0}; - public: - CNetAddr(); - explicit CNetAddr(const struct in_addr& ipv4Addr); - void SetIP(const CNetAddr& ip); +public: + CNetAddr(); + explicit CNetAddr(const struct in_addr& ipv4Addr); + void SetIP(const CNetAddr& ip); - /** - * Set from a legacy IPv6 address. - * Legacy IPv6 address may be a normal IPv6 address, or another address - * (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy - * `addr` encoding. - */ - void SetLegacyIPv6(Span ipv6); + /** + * Set from a legacy IPv6 address. + * Legacy IPv6 address may be a normal IPv6 address, or another address + * (e.g. IPv4) disguised as IPv6. This encoding is used in the legacy + * `addr` encoding. + */ + void SetLegacyIPv6(Span ipv6); - /** - * 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); + /** + * 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); +public: + bool SetInternal(const std::string& name); - /** - * Parse a Tor or I2P address and set this object to it. - * @param[in] addr Address to parse, for example - * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion or - * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p. - * @returns Whether the operation was successful. - * @see CNetAddr::IsTor(), CNetAddr::IsI2P() - */ - bool SetSpecial(const std::string& addr); + /** + * Parse a Tor or I2P address and set this object to it. + * @param[in] addr Address to parse, for example + * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion or + * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p. + * @returns Whether the operation was successful. + * @see CNetAddr::IsTor(), CNetAddr::IsI2P() + */ + bool SetSpecial(const std::string& addr); - bool IsBindAny() const; // INADDR_ANY equivalent - bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) - bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) - bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) - bool IsRFC2544() const; // IPv4 inter-network communications (198.18.0.0/15) - bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) - bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) - bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) - bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) - bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) - bool IsRFC4193() const; // IPv6 unique local (FC00::/7) - bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) - bool IsRFC4843() const; // IPv6 ORCHID (deprecated) (2001:10::/28) - bool IsRFC7343() const; // IPv6 ORCHIDv2 (2001:20::/28) - bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) - bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96) - bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765) - bool IsHeNet() const; // IPv6 Hurricane Electric - https://he.net (2001:0470::/36) - bool IsTor() const; - bool IsI2P() const; - bool IsCJDNS() const; - bool IsLocal() const; - bool IsRoutable() const; - bool IsInternal() const; - bool IsValid() const; + bool IsBindAny() const; // INADDR_ANY equivalent + bool IsIPv4() const; // IPv4 mapped address (::FFFF:0:0/96, 0.0.0.0/0) + bool IsIPv6() const; // IPv6 address (not mapped IPv4, not Tor) + bool IsRFC1918() const; // IPv4 private networks (10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12) + bool IsRFC2544() const; // IPv4 inter-network communications (198.18.0.0/15) + bool IsRFC6598() const; // IPv4 ISP-level NAT (100.64.0.0/10) + bool IsRFC5737() const; // IPv4 documentation addresses (192.0.2.0/24, 198.51.100.0/24, 203.0.113.0/24) + bool IsRFC3849() const; // IPv6 documentation address (2001:0DB8::/32) + bool IsRFC3927() const; // IPv4 autoconfig (169.254.0.0/16) + bool IsRFC3964() const; // IPv6 6to4 tunnelling (2002::/16) + bool IsRFC4193() const; // IPv6 unique local (FC00::/7) + bool IsRFC4380() const; // IPv6 Teredo tunnelling (2001::/32) + bool IsRFC4843() const; // IPv6 ORCHID (deprecated) (2001:10::/28) + bool IsRFC7343() const; // IPv6 ORCHIDv2 (2001:20::/28) + bool IsRFC4862() const; // IPv6 autoconfig (FE80::/64) + bool IsRFC6052() const; // IPv6 well-known prefix for IPv4-embedded address (64:FF9B::/96) + bool IsRFC6145() const; // IPv6 IPv4-translated address (::FFFF:0:0:0/96) (actually defined in RFC2765) + bool IsHeNet() const; // IPv6 Hurricane Electric - https://he.net (2001:0470::/36) + bool IsTor() const; + bool IsI2P() const; + bool IsCJDNS() const; + bool IsLocal() const; + bool IsRoutable() const; + bool IsInternal() const; + bool IsValid() const; - /** - * Check if the current object can be serialized in pre-ADDRv2/BIP155 format. - */ - bool IsAddrV1Compatible() const; + /** + * Check if the current object can be serialized in pre-ADDRv2/BIP155 format. + */ + bool IsAddrV1Compatible() const; - enum Network GetNetwork() const; - std::string ToString() const; - std::string ToStringIP(bool fUseGetnameinfo = true) const; - uint64_t GetHash() const; - bool GetInAddr(struct in_addr* pipv4Addr) const; - Network GetNetClass() const; + enum Network GetNetwork() const; + std::string ToString() const; + std::string ToStringIP(bool fUseGetnameinfo = true) const; + uint64_t GetHash() const; + bool GetInAddr(struct in_addr* pipv4Addr) const; + Network GetNetClass() const; - //! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32. - uint32_t GetLinkedIPv4() const; - //! Whether this address has a linked IPv4 address (see GetLinkedIPv4()). - bool HasLinkedIPv4() const; + //! For IPv4, mapped IPv4, SIIT translated IPv4, Teredo, 6to4 tunneled addresses, return the relevant IPv4 address as a uint32. + uint32_t GetLinkedIPv4() const; + //! Whether this address has a linked IPv4 address (see GetLinkedIPv4()). + bool HasLinkedIPv4() const; - // The AS on the BGP path to the node we use to diversify - // peers in AddrMan bucketing based on the AS infrastructure. - // The ip->AS mapping depends on how asmap is constructed. - uint32_t GetMappedAS(const std::vector &asmap) const; - std::vector GetGroup(const std::vector &asmap) const; - std::vector GetAddrBytes() const; - int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; + // The AS on the BGP path to the node we use to diversify + // peers in AddrMan bucketing based on the AS infrastructure. + // The ip->AS mapping depends on how asmap is constructed. + uint32_t GetMappedAS(const std::vector &asmap) const; - explicit CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); - bool GetIn6Addr(struct in6_addr* pipv6Addr) const; + std::vector GetGroup(const std::vector &asmap) const; + std::vector GetAddrBytes() const; + int GetReachabilityFrom(const CNetAddr *paddrPartner = nullptr) const; - friend bool operator==(const CNetAddr& a, const CNetAddr& b); - friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); } - friend bool operator<(const CNetAddr& a, const CNetAddr& b); + explicit CNetAddr(const struct in6_addr& pipv6Addr, const uint32_t scope = 0); + bool GetIn6Addr(struct in6_addr* pipv6Addr) const; - /** - * Serialize to a stream. - */ - template - void Serialize(Stream& s) const - { - if (s.GetVersion() & ADDRV2_FORMAT) { - SerializeV2Stream(s); - } else { - SerializeV1Stream(s); - } + friend bool operator==(const CNetAddr& a, const CNetAddr& b); + friend bool operator!=(const CNetAddr& a, const CNetAddr& b) { return !(a == b); } + friend bool operator<(const CNetAddr& a, const CNetAddr& b); + + /** + * Serialize to a stream. + */ + template + void Serialize(Stream& s) const + { + if (s.GetVersion() & ADDRV2_FORMAT) { + SerializeV2Stream(s); + } else { + SerializeV1Stream(s); + } + } + + /** + * Unserialize from a stream. + */ + template + void Unserialize(Stream& s) + { + if (s.GetVersion() & ADDRV2_FORMAT) { + UnserializeV2Stream(s); + } else { + UnserializeV1Stream(s); + } + } + + friend class CSubNet; + +private: + /** + * Parse a Tor address and set this object to it. + * @param[in] addr Address to parse, must be a valid C string, for example + * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion. + * @returns Whether the operation was successful. + * @see CNetAddr::IsTor() + */ + bool SetTor(const std::string& addr); + + /** + * Parse an I2P address and set this object to it. + * @param[in] addr Address to parse, must be a valid C string, for example + * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p. + * @returns Whether the operation was successful. + * @see CNetAddr::IsI2P() + */ + bool SetI2P(const std::string& addr); + + /** + * BIP155 network ids recognized by this software. + */ + enum BIP155Network : uint8_t { + IPV4 = 1, + IPV6 = 2, + TORV2 = 3, + TORV3 = 4, + I2P = 5, + CJDNS = 6, + }; + + /** + * Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes). + */ + static constexpr size_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE; + + /** + * Maximum size of an address as defined in BIP155 (in bytes). + * This is only the size of the address, not the entire CNetAddr object + * when serialized. + */ + static constexpr size_t MAX_ADDRV2_SIZE = 512; + + /** + * Get the BIP155 network id of this address. + * Must not be called for IsInternal() objects. + * @returns BIP155 network id, except TORV2 which is no longer supported. + */ + BIP155Network GetBIP155Network() const; + + /** + * Set `m_net` from the provided BIP155 network id and size after validation. + * @retval true the network was recognized, is valid and `m_net` was set + * @retval false not recognised (from future?) and should be silently ignored + * @throws std::ios_base::failure if the network is one of the BIP155 founding + * networks (id 1..6) with wrong address size. + */ + bool SetNetFromBIP155Network(uint8_t possible_bip155_net, size_t address_size); + + /** + * Serialize in pre-ADDRv2/BIP155 format to an array. + */ + void SerializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const + { + size_t prefix_size; + + switch (m_net) { + case NET_IPV6: + assert(m_addr.size() == sizeof(arr)); + memcpy(arr, m_addr.data(), m_addr.size()); + return; + case NET_IPV4: + prefix_size = sizeof(IPV4_IN_IPV6_PREFIX); + assert(prefix_size + m_addr.size() == sizeof(arr)); + memcpy(arr, IPV4_IN_IPV6_PREFIX.data(), prefix_size); + memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); + return; + case NET_INTERNAL: + prefix_size = sizeof(INTERNAL_IN_IPV6_PREFIX); + assert(prefix_size + m_addr.size() == sizeof(arr)); + memcpy(arr, INTERNAL_IN_IPV6_PREFIX.data(), prefix_size); + memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); + return; + case NET_ONION: + case NET_I2P: + case NET_CJDNS: + break; + case NET_UNROUTABLE: + case NET_MAX: + assert(false); + } // no default case, so the compiler can warn about missing cases + + // Serialize ONION, I2P and CJDNS as all-zeros. + memset(arr, 0x0, V1_SERIALIZATION_SIZE); + } + +public: + /** + * Serialize in pre-ADDRv2/BIP155 format to a stream. + */ + template + void SerializeV1Stream(Stream& s) const + { + uint8_t serialized[V1_SERIALIZATION_SIZE]; + + SerializeV1Array(serialized); + + s << serialized; + } + + /** + * Serialize as ADDRv2 / BIP155. + */ + template + void SerializeV2Stream(Stream& s) const + { + if (IsInternal()) { + // Serialize NET_INTERNAL as embedded in IPv6. We need to + // serialize such addresses from addrman. + s << static_cast(BIP155Network::IPV6); + s << COMPACTSIZE(ADDR_IPV6_SIZE); + SerializeV1Stream(s); + return; } - /** - * Unserialize from a stream. - */ - template - void Unserialize(Stream& s) - { - if (s.GetVersion() & ADDRV2_FORMAT) { - UnserializeV2Stream(s); - } else { - UnserializeV1Stream(s); - } + s << static_cast(GetBIP155Network()); + s << m_addr; + } + + /** + * Unserialize from a pre-ADDRv2/BIP155 format from an array. + */ + void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) + { + // Use SetLegacyIPv6() so that m_net is set correctly. For example + // ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4). + SetLegacyIPv6(arr); + } + + /** + * Unserialize from a pre-ADDRv2/BIP155 format from a stream. + */ + template + void UnserializeV1Stream(Stream& s) + { + uint8_t serialized[V1_SERIALIZATION_SIZE]; + + s >> serialized; + + UnserializeV1Array(serialized); + } + + /** + * Unserialize from a ADDRv2 / BIP155 format. + */ + template + void UnserializeV2Stream(Stream& s) + { + uint8_t bip155_net; + s >> bip155_net; + + size_t address_size; + s >> COMPACTSIZE(address_size); + + if (address_size > MAX_ADDRV2_SIZE) { + throw std::ios_base::failure(strprintf( + "Address too long: %u > %u", address_size, MAX_ADDRV2_SIZE)); } - friend class CSubNet; + m_scope_id = 0; - private: - /** - * Parse a Tor address and set this object to it. - * @param[in] addr Address to parse, must be a valid C string, for example - * pg6mmjiyjmcrsslvykfwnntlaru7p5svn6y2ymmju6nubxndf4pscryd.onion. - * @returns Whether the operation was successful. - * @see CNetAddr::IsTor() - */ - bool SetTor(const std::string& addr); + if (SetNetFromBIP155Network(bip155_net, address_size)) { + m_addr.resize(address_size); + s >> MakeSpan(m_addr); - /** - * Parse an I2P address and set this object to it. - * @param[in] addr Address to parse, must be a valid C string, for example - * ukeu3k5oycgaauneqgtnvselmt4yemvoilkln7jpvamvfx7dnkdq.b32.i2p. - * @returns Whether the operation was successful. - * @see CNetAddr::IsI2P() - */ - bool SetI2P(const std::string& addr); - - /** - * BIP155 network ids recognized by this software. - */ - enum BIP155Network : uint8_t { - IPV4 = 1, - IPV6 = 2, - TORV2 = 3, - TORV3 = 4, - I2P = 5, - CJDNS = 6, - }; - - /** - * Size of CNetAddr when serialized as ADDRv1 (pre-BIP155) (in bytes). - */ - static constexpr size_t V1_SERIALIZATION_SIZE = ADDR_IPV6_SIZE; - - /** - * Maximum size of an address as defined in BIP155 (in bytes). - * This is only the size of the address, not the entire CNetAddr object - * when serialized. - */ - static constexpr size_t MAX_ADDRV2_SIZE = 512; - - /** - * Get the BIP155 network id of this address. - * Must not be called for IsInternal() objects. - * @returns BIP155 network id, except TORV2 which is no longer supported. - */ - BIP155Network GetBIP155Network() const; - - /** - * Set `m_net` from the provided BIP155 network id and size after validation. - * @retval true the network was recognized, is valid and `m_net` was set - * @retval false not recognised (from future?) and should be silently ignored - * @throws std::ios_base::failure if the network is one of the BIP155 founding - * networks (id 1..6) with wrong address size. - */ - bool SetNetFromBIP155Network(uint8_t possible_bip155_net, size_t address_size); - - /** - * Serialize in pre-ADDRv2/BIP155 format to an array. - */ - void SerializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) const - { - size_t prefix_size; - - switch (m_net) { - case NET_IPV6: - assert(m_addr.size() == sizeof(arr)); - memcpy(arr, m_addr.data(), m_addr.size()); - return; - case NET_IPV4: - prefix_size = sizeof(IPV4_IN_IPV6_PREFIX); - assert(prefix_size + m_addr.size() == sizeof(arr)); - memcpy(arr, IPV4_IN_IPV6_PREFIX.data(), prefix_size); - memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); - return; - case NET_INTERNAL: - prefix_size = sizeof(INTERNAL_IN_IPV6_PREFIX); - assert(prefix_size + m_addr.size() == sizeof(arr)); - memcpy(arr, INTERNAL_IN_IPV6_PREFIX.data(), prefix_size); - memcpy(arr + prefix_size, m_addr.data(), m_addr.size()); - return; - case NET_ONION: - case NET_I2P: - case NET_CJDNS: - break; - case NET_UNROUTABLE: - case NET_MAX: - assert(false); - } // no default case, so the compiler can warn about missing cases - - // Serialize ONION, I2P and CJDNS as all-zeros. - memset(arr, 0x0, V1_SERIALIZATION_SIZE); - } - - public: - /** - * Serialize in pre-ADDRv2/BIP155 format to a stream. - */ - template - void SerializeV1Stream(Stream& s) const - { - uint8_t serialized[V1_SERIALIZATION_SIZE]; - - SerializeV1Array(serialized); - - s << serialized; - } - - /** - * Serialize as ADDRv2 / BIP155. - */ - template - void SerializeV2Stream(Stream& s) const - { - if (IsInternal()) { - // Serialize NET_INTERNAL as embedded in IPv6. We need to - // serialize such addresses from addrman. - s << static_cast(BIP155Network::IPV6); - s << COMPACTSIZE(ADDR_IPV6_SIZE); - SerializeV1Stream(s); + if (m_net != NET_IPV6) { return; } - s << static_cast(GetBIP155Network()); - s << m_addr; - } + // Do some special checks on IPv6 addresses. - /** - * Unserialize from a pre-ADDRv2/BIP155 format from an array. - */ - void UnserializeV1Array(uint8_t (&arr)[V1_SERIALIZATION_SIZE]) - { - // Use SetLegacyIPv6() so that m_net is set correctly. For example - // ::FFFF:0102:0304 should be set as m_net=NET_IPV4 (1.2.3.4). - SetLegacyIPv6(arr); - } - - /** - * Unserialize from a pre-ADDRv2/BIP155 format from a stream. - */ - template - void UnserializeV1Stream(Stream& s) - { - uint8_t serialized[V1_SERIALIZATION_SIZE]; - - s >> serialized; - - UnserializeV1Array(serialized); - } - - /** - * Unserialize from a ADDRv2 / BIP155 format. - */ - template - void UnserializeV2Stream(Stream& s) - { - uint8_t bip155_net; - s >> bip155_net; - - size_t address_size; - s >> COMPACTSIZE(address_size); - - if (address_size > MAX_ADDRV2_SIZE) { - throw std::ios_base::failure(strprintf( - "Address too long: %u > %u", address_size, MAX_ADDRV2_SIZE)); + // Recognize NET_INTERNAL embedded in IPv6, such addresses are not + // gossiped but could be coming from addrman, when unserializing from + // disk. + if (HasPrefix(m_addr, INTERNAL_IN_IPV6_PREFIX)) { + m_net = NET_INTERNAL; + memmove(m_addr.data(), m_addr.data() + INTERNAL_IN_IPV6_PREFIX.size(), + ADDR_INTERNAL_SIZE); + m_addr.resize(ADDR_INTERNAL_SIZE); + return; } - m_scope_id = 0; - - if (SetNetFromBIP155Network(bip155_net, address_size)) { - m_addr.resize(address_size); - s >> MakeSpan(m_addr); - - if (m_net != NET_IPV6) { - return; - } - - // Do some special checks on IPv6 addresses. - - // Recognize NET_INTERNAL embedded in IPv6, such addresses are not - // gossiped but could be coming from addrman, when unserializing from - // disk. - if (HasPrefix(m_addr, INTERNAL_IN_IPV6_PREFIX)) { - m_net = NET_INTERNAL; - memmove(m_addr.data(), m_addr.data() + INTERNAL_IN_IPV6_PREFIX.size(), - ADDR_INTERNAL_SIZE); - m_addr.resize(ADDR_INTERNAL_SIZE); - return; - } - - if (!HasPrefix(m_addr, IPV4_IN_IPV6_PREFIX) && - !HasPrefix(m_addr, TORV2_IN_IPV6_PREFIX)) { - return; - } - - // IPv4 and TORv2 are not supposed to be embedded in IPv6 (like in V1 - // encoding). Unserialize as !IsValid(), thus ignoring them. - } else { - // If we receive an unknown BIP155 network id (from the future?) then - // ignore the address - unserialize as !IsValid(). - s.ignore(address_size); + if (!HasPrefix(m_addr, IPV4_IN_IPV6_PREFIX) && + !HasPrefix(m_addr, TORV2_IN_IPV6_PREFIX)) { + return; } - // Mimic a default-constructed CNetAddr object which is !IsValid() and thus - // will not be gossiped, but continue reading next addresses from the stream. - m_net = NET_IPV6; - m_addr.assign(ADDR_IPV6_SIZE, 0x0); + // IPv4 and TORv2 are not supposed to be embedded in IPv6 (like in V1 + // encoding). Unserialize as !IsValid(), thus ignoring them. + } else { + // If we receive an unknown BIP155 network id (from the future?) then + // ignore the address - unserialize as !IsValid(). + s.ignore(address_size); } + + // Mimic a default-constructed CNetAddr object which is !IsValid() and thus + // will not be gossiped, but continue reading next addresses from the stream. + m_net = NET_IPV6; + m_addr.assign(ADDR_IPV6_SIZE, 0x0); + } }; class CSubNet { - protected: - /// Network (base) address - CNetAddr network; - /// Netmask, in network byte order - uint8_t netmask[16]; - /// Is this value valid? (only used to signal parse errors) - bool valid; +protected: + /// Network (base) address + CNetAddr network; + /// Netmask, in network byte order + uint8_t netmask[16]; + /// Is this value valid? (only used to signal parse errors) + bool valid; - bool SanityCheck() const; + bool SanityCheck() const; - public: - /** - * Construct an invalid subnet (empty, `Match()` always returns false). - */ - CSubNet(); +public: + /** + * Construct an invalid subnet (empty, `Match()` always returns false). + */ + CSubNet(); - /** - * Construct from a given network start and number of bits (CIDR mask). - * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is - * created. - * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for - * IPv6 addresses. Otherwise an invalid subnet is created. - */ - CSubNet(const CNetAddr& addr, uint8_t mask); + /** + * Construct from a given network start and number of bits (CIDR mask). + * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is + * created. + * @param[in] mask CIDR mask, must be in [0, 32] for IPv4 addresses and in [0, 128] for + * IPv6 addresses. Otherwise an invalid subnet is created. + */ + CSubNet(const CNetAddr& addr, uint8_t mask); - /** - * Construct from a given network start and mask. - * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is - * created. - * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits - * followed by 1-bits. Otherwise an invalid subnet is created. - */ - CSubNet(const CNetAddr& addr, const CNetAddr& mask); + /** + * Construct from a given network start and mask. + * @param[in] addr Network start. Must be IPv4 or IPv6, otherwise an invalid subnet is + * created. + * @param[in] mask Network mask, must be of the same type as `addr` and not contain 0-bits + * followed by 1-bits. Otherwise an invalid subnet is created. + */ + CSubNet(const CNetAddr& addr, const CNetAddr& mask); - /** - * Construct a single-host subnet. - * @param[in] addr The sole address to be contained in the subnet, can also be non-IPv[46]. - */ - explicit CSubNet(const CNetAddr& addr); + /** + * Construct a single-host subnet. + * @param[in] addr The sole address to be contained in the subnet, can also be non-IPv[46]. + */ + explicit CSubNet(const CNetAddr& addr); - bool Match(const CNetAddr &addr) const; + bool Match(const CNetAddr &addr) const; - std::string ToString() const; - bool IsValid() const; + std::string ToString() const; + bool IsValid() const; - friend bool operator==(const CSubNet& a, const CSubNet& b); - friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); } - friend bool operator<(const CSubNet& a, const CSubNet& b); - - SERIALIZE_METHODS(CSubNet, obj) - { - READWRITE(obj.network); - if (obj.network.IsIPv4()) { - // Before commit 102867c587f5f7954232fb8ed8e85cda78bb4d32, CSubNet used the last 4 bytes of netmask - // to store the relevant bytes for an IPv4 mask. For compatibility reasons, keep doing so in - // serialized form. - unsigned char dummy[12] = {0}; - READWRITE(dummy); - READWRITE(MakeSpan(obj.netmask).first(4)); - } else { - READWRITE(obj.netmask); - } - READWRITE(obj.valid); - // Mark invalid if the result doesn't pass sanity checking. - SER_READ(obj, if (obj.valid) obj.valid = obj.SanityCheck()); - } + friend bool operator==(const CSubNet& a, const CSubNet& b); + friend bool operator!=(const CSubNet& a, const CSubNet& b) { return !(a == b); } + friend bool operator<(const CSubNet& a, const CSubNet& b); }; /** A combination of a network address (CNetAddr) and a (TCP) port */ class CService : public CNetAddr { - protected: - uint16_t port; // host order +protected: + uint16_t port; // host order - public: - CService(); - CService(const CNetAddr& ip, uint16_t port); - CService(const struct in_addr& ipv4Addr, uint16_t port); - explicit CService(const struct sockaddr_in& addr); - void SetPort(uint16_t portIn); - uint16_t GetPort() const; - bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; - bool SetSockAddr(const struct sockaddr* paddr); - friend bool operator==(const CService& a, const CService& b); - friend bool operator!=(const CService& a, const CService& b) { return !(a == b); } - friend bool operator<(const CService& a, const CService& b); - std::vector GetKey() const; - std::string ToString(bool fUseGetnameinfo = true) const; - std::string ToStringPort() const; - std::string ToStringIPPort(bool fUseGetnameinfo = true) const; +public: + CService(); + CService(const CNetAddr& ip, uint16_t port); + CService(const struct in_addr& ipv4Addr, uint16_t port); + explicit CService(const struct sockaddr_in& addr); + void SetPort(uint16_t portIn); + uint16_t GetPort() const; + bool GetSockAddr(struct sockaddr* paddr, socklen_t *addrlen) const; + bool SetSockAddr(const struct sockaddr* paddr); + friend bool operator==(const CService& a, const CService& b); + friend bool operator!=(const CService& a, const CService& b) { return !(a == b); } + friend bool operator<(const CService& a, const CService& b); + std::vector GetKey() const; + std::string ToString(bool fUseGetnameinfo = true) const; + std::string ToStringPort() const; + std::string ToStringIPPort(bool fUseGetnameinfo = true) const; - CService(const struct in6_addr& ipv6Addr, uint16_t port); - explicit CService(const struct sockaddr_in6& addr); + CService(const struct in6_addr& ipv6Addr, uint16_t port); + explicit CService(const struct sockaddr_in6& addr); - SERIALIZE_METHODS(CService, obj) - { - READWRITEAS(CNetAddr, obj); - READWRITE(Using>(obj.port)); - } + SERIALIZE_METHODS(CService, obj) + { + READWRITEAS(CNetAddr, obj); + READWRITE(Using>(obj.port)); + } }; bool SanityCheckASMap(const std::vector& asmap); diff --git a/src/test/fuzz/banman.cpp b/src/test/fuzz/banman.cpp index 5fd53b2d58..5540ee14f2 100644 --- a/src/test/fuzz/banman.cpp +++ b/src/test/fuzz/banman.cpp @@ -43,8 +43,7 @@ FUZZ_TARGET_INIT(banman, initialize_banman) const bool start_with_corrupted_banlist{fuzzed_data_provider.ConsumeBool()}; if (start_with_corrupted_banlist) { - const std::string sfx{fuzzed_data_provider.ConsumeBool() ? ".dat" : ".json"}; - assert(WriteBinaryFile(banlist_file.string() + sfx, + assert(WriteBinaryFile(banlist_file.string() + ".json", fuzzed_data_provider.ConsumeRandomLengthString())); } else { const bool force_read_and_write_to_err{fuzzed_data_provider.ConsumeBool()}; @@ -93,6 +92,5 @@ FUZZ_TARGET_INIT(banman, initialize_banman) }); } } - fs::remove(banlist_file.string() + ".dat"); fs::remove(banlist_file.string() + ".json"); } diff --git a/src/test/fuzz/deserialize.cpp b/src/test/fuzz/deserialize.cpp index 39ed4d464a..7a90d9d79d 100644 --- a/src/test/fuzz/deserialize.cpp +++ b/src/test/fuzz/deserialize.cpp @@ -100,231 +100,220 @@ void AssertEqualAfterSerializeDeserialize(const T& obj, const int version = INIT /* FUZZ_TARGET_DESERIALIZE(block_filter_deserialize, { - BlockFilter block_filter; - DeserializeFromFuzzingInput(buffer, block_filter); + BlockFilter block_filter; + DeserializeFromFuzzingInput(buffer, block_filter); }) */ FUZZ_TARGET_DESERIALIZE(addr_info_deserialize, { - CAddrInfo addr_info; - DeserializeFromFuzzingInput(buffer, addr_info); + CAddrInfo addr_info; + DeserializeFromFuzzingInput(buffer, addr_info); }) FUZZ_TARGET_DESERIALIZE(block_file_info_deserialize, { - CBlockFileInfo block_file_info; - DeserializeFromFuzzingInput(buffer, block_file_info); + CBlockFileInfo block_file_info; + DeserializeFromFuzzingInput(buffer, block_file_info); }) FUZZ_TARGET_DESERIALIZE(block_header_and_short_txids_deserialize, { - CBlockHeaderAndShortTxIDs block_header_and_short_txids; - DeserializeFromFuzzingInput(buffer, block_header_and_short_txids); + CBlockHeaderAndShortTxIDs block_header_and_short_txids; + DeserializeFromFuzzingInput(buffer, block_header_and_short_txids); }) FUZZ_TARGET_DESERIALIZE(fee_rate_deserialize, { - CFeeRate fee_rate; - DeserializeFromFuzzingInput(buffer, fee_rate); - AssertEqualAfterSerializeDeserialize(fee_rate); + CFeeRate fee_rate; + DeserializeFromFuzzingInput(buffer, fee_rate); + AssertEqualAfterSerializeDeserialize(fee_rate); }) FUZZ_TARGET_DESERIALIZE(merkle_block_deserialize, { - CMerkleBlock merkle_block; - DeserializeFromFuzzingInput(buffer, merkle_block); + CMerkleBlock merkle_block; + DeserializeFromFuzzingInput(buffer, merkle_block); }) FUZZ_TARGET_DESERIALIZE(out_point_deserialize, { - COutPoint out_point; - DeserializeFromFuzzingInput(buffer, out_point); - AssertEqualAfterSerializeDeserialize(out_point); + COutPoint out_point; + DeserializeFromFuzzingInput(buffer, out_point); + AssertEqualAfterSerializeDeserialize(out_point); }) FUZZ_TARGET_DESERIALIZE(partial_merkle_tree_deserialize, { - CPartialMerkleTree partial_merkle_tree; - DeserializeFromFuzzingInput(buffer, partial_merkle_tree); + CPartialMerkleTree partial_merkle_tree; + DeserializeFromFuzzingInput(buffer, partial_merkle_tree); }) FUZZ_TARGET_DESERIALIZE(pub_key_deserialize, { - CPubKey pub_key; - DeserializeFromFuzzingInput(buffer, pub_key); - AssertEqualAfterSerializeDeserialize(pub_key); + CPubKey pub_key; + DeserializeFromFuzzingInput(buffer, pub_key); + AssertEqualAfterSerializeDeserialize(pub_key); }) FUZZ_TARGET_DESERIALIZE(script_deserialize, { - CScript script; - DeserializeFromFuzzingInput(buffer, script); -}) -FUZZ_TARGET_DESERIALIZE(subnet_deserialize, { - CSubNet sub_net_1; - DeserializeFromFuzzingInput(buffer, sub_net_1, INIT_PROTO_VERSION); - AssertEqualAfterSerializeDeserialize(sub_net_1, INIT_PROTO_VERSION); - CSubNet sub_net_2; - DeserializeFromFuzzingInput(buffer, sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); - AssertEqualAfterSerializeDeserialize(sub_net_2, INIT_PROTO_VERSION | ADDRV2_FORMAT); - CSubNet sub_net_3; - DeserializeFromFuzzingInput(buffer, sub_net_3); - AssertEqualAfterSerializeDeserialize(sub_net_3, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CScript script; + DeserializeFromFuzzingInput(buffer, script); }) FUZZ_TARGET_DESERIALIZE(tx_in_deserialize, { - CTxIn tx_in; - DeserializeFromFuzzingInput(buffer, tx_in); - AssertEqualAfterSerializeDeserialize(tx_in); + CTxIn tx_in; + DeserializeFromFuzzingInput(buffer, tx_in); + AssertEqualAfterSerializeDeserialize(tx_in); }) /* FUZZ_TARGET_DESERIALIZE(flat_file_pos_deserialize, { - FlatFilePos flat_file_pos; - DeserializeFromFuzzingInput(buffer, flat_file_pos); - AssertEqualAfterSerializeDeserialize(flat_file_pos); + FlatFilePos flat_file_pos; + DeserializeFromFuzzingInput(buffer, flat_file_pos); + AssertEqualAfterSerializeDeserialize(flat_file_pos); }) FUZZ_TARGET_DESERIALIZE(key_origin_info_deserialize, { - KeyOriginInfo key_origin_info; - DeserializeFromFuzzingInput(buffer, key_origin_info); - AssertEqualAfterSerializeDeserialize(key_origin_info); + KeyOriginInfo key_origin_info; + DeserializeFromFuzzingInput(buffer, key_origin_info); + AssertEqualAfterSerializeDeserialize(key_origin_info); }) */ FUZZ_TARGET_DESERIALIZE(partially_signed_transaction_deserialize, { - PartiallySignedTransaction partially_signed_transaction; - DeserializeFromFuzzingInput(buffer, partially_signed_transaction); + PartiallySignedTransaction partially_signed_transaction; + DeserializeFromFuzzingInput(buffer, partially_signed_transaction); }) FUZZ_TARGET_DESERIALIZE(prefilled_transaction_deserialize, { - PrefilledTransaction prefilled_transaction; - DeserializeFromFuzzingInput(buffer, prefilled_transaction); + PrefilledTransaction prefilled_transaction; + DeserializeFromFuzzingInput(buffer, prefilled_transaction); }) FUZZ_TARGET_DESERIALIZE(psbt_input_deserialize, { - PSBTInput psbt_input; - DeserializeFromFuzzingInput(buffer, psbt_input); + PSBTInput psbt_input; + DeserializeFromFuzzingInput(buffer, psbt_input); }) FUZZ_TARGET_DESERIALIZE(psbt_output_deserialize, { - PSBTOutput psbt_output; - DeserializeFromFuzzingInput(buffer, psbt_output); + PSBTOutput psbt_output; + DeserializeFromFuzzingInput(buffer, psbt_output); }) FUZZ_TARGET_DESERIALIZE(block_deserialize, { - CBlock block; - DeserializeFromFuzzingInput(buffer, block); + CBlock block; + DeserializeFromFuzzingInput(buffer, block); }) FUZZ_TARGET_DESERIALIZE(blocklocator_deserialize, { - CBlockLocator bl; - DeserializeFromFuzzingInput(buffer, bl); + CBlockLocator bl; + DeserializeFromFuzzingInput(buffer, bl); }) FUZZ_TARGET_DESERIALIZE(blockmerkleroot, { - CBlock block; - DeserializeFromFuzzingInput(buffer, block); - bool mutated; - BlockMerkleRoot(block, &mutated); + CBlock block; + DeserializeFromFuzzingInput(buffer, block); + bool mutated; + BlockMerkleRoot(block, &mutated); }) FUZZ_TARGET_DESERIALIZE(addrman_deserialize, { - CAddrMan am; - DeserializeFromFuzzingInput(buffer, am); + CAddrMan am; + DeserializeFromFuzzingInput(buffer, am); }) FUZZ_TARGET_DESERIALIZE(blockheader_deserialize, { - CBlockHeader bh; - DeserializeFromFuzzingInput(buffer, bh); + CBlockHeader bh; + DeserializeFromFuzzingInput(buffer, bh); }) FUZZ_TARGET_DESERIALIZE(banentry_deserialize, { - CBanEntry be; - DeserializeFromFuzzingInput(buffer, be); + CBanEntry be; + DeserializeFromFuzzingInput(buffer, be); }) FUZZ_TARGET_DESERIALIZE(txundo_deserialize, { - CTxUndo tu; - DeserializeFromFuzzingInput(buffer, tu); + CTxUndo tu; + DeserializeFromFuzzingInput(buffer, tu); }) FUZZ_TARGET_DESERIALIZE(blockundo_deserialize, { - CBlockUndo bu; - DeserializeFromFuzzingInput(buffer, bu); + CBlockUndo bu; + DeserializeFromFuzzingInput(buffer, bu); }) FUZZ_TARGET_DESERIALIZE(coins_deserialize, { - Coin coin; - DeserializeFromFuzzingInput(buffer, coin); + Coin coin; + DeserializeFromFuzzingInput(buffer, coin); }) FUZZ_TARGET_DESERIALIZE(net_address_deserialize, { - CNetAddr na; - DeserializeFromFuzzingInput(buffer, na); - if (na.IsAddrV1Compatible()) { - AssertEqualAfterSerializeDeserialize(na); - } - AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CNetAddr na; + DeserializeFromFuzzingInput(buffer, na); + if (na.IsAddrV1Compatible()) { + AssertEqualAfterSerializeDeserialize(na); + } + AssertEqualAfterSerializeDeserialize(na, INIT_PROTO_VERSION | ADDRV2_FORMAT); }) FUZZ_TARGET_DESERIALIZE(net_service_deserialize, { - CService s; - DeserializeFromFuzzingInput(buffer, s); - if (s.IsAddrV1Compatible()) { - AssertEqualAfterSerializeDeserialize(s); - } - AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT); - CService s1; - DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION); - AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION); - assert(s1.IsAddrV1Compatible()); - CService s2; - DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); - AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CService s; + DeserializeFromFuzzingInput(buffer, s); + if (s.IsAddrV1Compatible()) { + AssertEqualAfterSerializeDeserialize(s); + } + AssertEqualAfterSerializeDeserialize(s, INIT_PROTO_VERSION | ADDRV2_FORMAT); + CService s1; + DeserializeFromFuzzingInput(buffer, s1, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(s1, INIT_PROTO_VERSION); + assert(s1.IsAddrV1Compatible()); + CService s2; + DeserializeFromFuzzingInput(buffer, s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(s2, INIT_PROTO_VERSION | ADDRV2_FORMAT); }) FUZZ_TARGET_DESERIALIZE(messageheader_deserialize, { - CMessageHeader mh; - DeserializeFromFuzzingInput(buffer, mh); - (void)mh.IsCommandValid(); + CMessageHeader mh; + DeserializeFromFuzzingInput(buffer, mh); + (void)mh.IsCommandValid(); }) FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_notime, { - CAddress a; - DeserializeFromFuzzingInput(buffer, a, INIT_PROTO_VERSION); - // A CAddress without nTime (as is expected under INIT_PROTO_VERSION) will roundtrip - // in all 5 formats (with/without nTime, v1/v2, network/disk) - AssertEqualAfterSerializeDeserialize(a, INIT_PROTO_VERSION); - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); - AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); - AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); + CAddress a; + DeserializeFromFuzzingInput(buffer, a, INIT_PROTO_VERSION); + // A CAddress without nTime (as is expected under INIT_PROTO_VERSION) will roundtrip + // in all 5 formats (with/without nTime, v1/v2, network/disk) + AssertEqualAfterSerializeDeserialize(a, INIT_PROTO_VERSION); + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); + AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); }) FUZZ_TARGET_DESERIALIZE(address_deserialize_v1_withtime, { - CAddress a; - DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION); - // A CAddress in V1 mode will roundtrip in all 4 formats that have nTime. - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); - AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); - AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); + CAddress a; + DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION); + // A CAddress in V1 mode will roundtrip in all 4 formats that have nTime. + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); + AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); }) FUZZ_TARGET_DESERIALIZE(address_deserialize_v2, { - CAddress a; - DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION | ADDRV2_FORMAT); - // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats - // with time if it's V1 compatible. - if (a.IsAddrV1Compatible()) { - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); - AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); - } - AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); - AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); + CAddress a; + DeserializeFromFuzzingInput(buffer, a, PROTOCOL_VERSION | ADDRV2_FORMAT); + // A CAddress in V2 mode will roundtrip in both V2 formats, and also in the V1 formats + // with time if it's V1 compatible. + if (a.IsAddrV1Compatible()) { + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION); + AssertEqualAfterSerializeDeserialize(a, 0, SER_DISK); + } + AssertEqualAfterSerializeDeserialize(a, PROTOCOL_VERSION | ADDRV2_FORMAT); + AssertEqualAfterSerializeDeserialize(a, ADDRV2_FORMAT, SER_DISK); }) FUZZ_TARGET_DESERIALIZE(inv_deserialize, { - CInv i; - DeserializeFromFuzzingInput(buffer, i); + CInv i; + DeserializeFromFuzzingInput(buffer, i); }) FUZZ_TARGET_DESERIALIZE(bloomfilter_deserialize, { - CBloomFilter bf; - DeserializeFromFuzzingInput(buffer, bf); + CBloomFilter bf; + DeserializeFromFuzzingInput(buffer, bf); }) FUZZ_TARGET_DESERIALIZE(diskblockindex_deserialize, { - CDiskBlockIndex dbi; - DeserializeFromFuzzingInput(buffer, dbi); + CDiskBlockIndex dbi; + DeserializeFromFuzzingInput(buffer, dbi); }) FUZZ_TARGET_DESERIALIZE(txoutcompressor_deserialize, { - CTxOut to; - auto toc = Using(to); - DeserializeFromFuzzingInput(buffer, toc); + CTxOut to; + auto toc = Using(to); + DeserializeFromFuzzingInput(buffer, toc); }) FUZZ_TARGET_DESERIALIZE(blocktransactions_deserialize, { - BlockTransactions bt; - DeserializeFromFuzzingInput(buffer, bt); + BlockTransactions bt; + DeserializeFromFuzzingInput(buffer, bt); }) FUZZ_TARGET_DESERIALIZE(blocktransactionsrequest_deserialize, { - BlockTransactionsRequest btr; - DeserializeFromFuzzingInput(buffer, btr); + BlockTransactionsRequest btr; + DeserializeFromFuzzingInput(buffer, btr); }) FUZZ_TARGET_DESERIALIZE(snapshotmetadata_deserialize, { SnapshotMetadata snapshot_metadata; DeserializeFromFuzzingInput(buffer, snapshot_metadata); }) FUZZ_TARGET_DESERIALIZE(uint160_deserialize, { - uint160 u160; - DeserializeFromFuzzingInput(buffer, u160); - AssertEqualAfterSerializeDeserialize(u160); + uint160 u160; + DeserializeFromFuzzingInput(buffer, u160); + AssertEqualAfterSerializeDeserialize(u160); }) FUZZ_TARGET_DESERIALIZE(uint256_deserialize, { - uint256 u256; - DeserializeFromFuzzingInput(buffer, u256); - AssertEqualAfterSerializeDeserialize(u256); + uint256 u256; + DeserializeFromFuzzingInput(buffer, u256); + AssertEqualAfterSerializeDeserialize(u256); }) - // Classes intentionally not covered in this file since their deserialization code is - // fuzzed elsewhere: - // * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp - // * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp +// Classes intentionally not covered in this file since their deserialization code is +// fuzzed elsewhere: +// * Deserialization of CTxOut is fuzzed in test/fuzz/tx_out.cpp +// * Deserialization of CMutableTransaction is fuzzed in src/test/fuzz/transaction.cpp