dash/src/net_permissions.h
W. J. van der Laan 1b6bd0651c
Merge bitcoin/bitcoin#21644: p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind()
36fb036d25e2a3016b36873456e5a9e6251ffef8 p2p: allow NetPermissions::ClearFlag() only with PF_ISIMPLICIT (Jon Atack)
4e0d5788ba5771c81bc0ff2e6523cf9accddae46 test: add net permissions noban/download unit test coverage (Jon Atack)
dde69f20a01acca64ac21cb13993c6e4f8709f23 p2p, bugfix: use NetPermissions::HasFlag() in CConnman::Bind() (Jon Atack)

Pull request description:

  This is a bugfix follow-up to #16248 and #19191 that was noticed in #21506. Both v0.21 and master are affected.

  Since #19191, noban is a multi-flag that implies download, so the conditional in `CConnman::Bind()` using a bitwise AND on noban will return the same result for both the noban status and the download status. This means that download peers are incorrectly not being added to local addresses because they are mistakenly seen as noban peers.

  The second commit adds unit test coverage to illustrate and test the noban/download relationship and the `NetPermissions` operations involving them.

  The final commit adds documentation and disallows calling `NetPermissions::ClearFlag()` with any second param other than `NetPermissionFlags` "implicit" -- per current usage in the codebase -- because `ClearFlag()` should not be called with any second param that is a subflag of a multiflag, e.g. "relay" or "download," as that would leave the result in an invalid state corresponding to none of the existing NetPermissionFlags. Thanks to Vasil Dimov for noticing this.

ACKs for top commit:
  theStack:
    re-ACK 36fb036d25e2a3016b36873456e5a9e6251ffef8 
  vasild:
    ACK 36fb036d25e2a3016b36873456e5a9e6251ffef8
  hebasto:
    ACK 36fb036d25e2a3016b36873456e5a9e6251ffef8, I have reviewed the code and it looks OK, I agree it can be merged.
  kallewoof:
    Code review ACK 36fb036d25e2a3016b36873456e5a9e6251ffef8

Tree-SHA512: 5fbc7ddbf31d06b35bf238f4d77ef311e6b6ef2e1bb9893f32f889c1a0f65774a3710dcb21d94317fe6166df9334a9f2d42630809e7fe8cbd797dd6f6fc49491
2023-12-03 20:44:58 -06:00

80 lines
2.8 KiB
C++

// Copyright (c) 2009-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.
#include <netaddress.h>
#include <string>
#include <vector>
#ifndef BITCOIN_NET_PERMISSIONS_H
#define BITCOIN_NET_PERMISSIONS_H
struct bilingual_str;
extern const std::vector<std::string> NET_PERMISSIONS_DOC;
enum NetPermissionFlags {
PF_NONE = 0,
// Can query bloomfilter even if -peerbloomfilters is false
PF_BLOOMFILTER = (1U << 1),
// Relay and accept transactions from this peer, even if -blocksonly is true
PF_RELAY = (1U << 3),
// Always relay transactions from this peer, even if already in mempool
// Keep parameter interaction: forcerelay implies relay
PF_FORCERELAY = (1U << 2) | PF_RELAY,
// Allow getheaders during IBD and block-download after maxuploadtarget limit
PF_DOWNLOAD = (1U << 6),
// Can't be banned/disconnected/discouraged for misbehavior
PF_NOBAN = (1U << 4) | PF_DOWNLOAD,
// Can query the mempool
PF_MEMPOOL = (1U << 5),
// Can request addrs without hitting a privacy-preserving cache
PF_ADDR = (1U << 7),
// True if the user did not specifically set fine grained permissions
PF_ISIMPLICIT = (1U << 31),
PF_ALL = PF_BLOOMFILTER | PF_FORCERELAY | PF_RELAY | PF_NOBAN | PF_MEMPOOL | PF_DOWNLOAD | PF_ADDR,
};
class NetPermissions
{
public:
NetPermissionFlags m_flags;
static std::vector<std::string> ToStrings(NetPermissionFlags flags);
static inline bool HasFlag(const NetPermissionFlags& flags, NetPermissionFlags f)
{
return (flags & f) == f;
}
static inline void AddFlag(NetPermissionFlags& flags, NetPermissionFlags f)
{
flags = static_cast<NetPermissionFlags>(flags | f);
}
//! ClearFlag is only called with `f` == NetPermissionFlags::PF_ISIMPLICIT.
//! If that should change in the future, be aware that ClearFlag should not
//! be called with a subflag of a multiflag, e.g. NetPermissionFlags::PF_RELAY
//! or NetPermissionFlags::PF_DOWNLOAD, as that would leave `flags` in an
//! invalid state corresponding to none of the existing flags.
static inline void ClearFlag(NetPermissionFlags& flags, NetPermissionFlags f)
{
assert(f == NetPermissionFlags::PF_ISIMPLICIT);
flags = static_cast<NetPermissionFlags>(flags & ~f);
}
};
class NetWhitebindPermissions : public NetPermissions
{
public:
static bool TryParse(const std::string& str, NetWhitebindPermissions& output, bilingual_str& error);
CService m_service;
};
class NetWhitelistPermissions : public NetPermissions
{
public:
static bool TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error);
CSubNet m_subnet;
};
#endif // BITCOIN_NET_PERMISSIONS_H