Skip to content

Commit

Permalink
Merge bitcoin#27114: p2p: Allow whitelisting manual connections
Browse files Browse the repository at this point in the history
0a53361 docs: add release notes for bitcoin#27114 (brunoerg)
e6b8f19 test: add coverage for whitelisting manual connections (brunoerg)
c985eb8 test: add option to speed up tx relay/mempool sync (brunoerg)
66bc6e2 Accept "in" and "out" flags to -whitelist to allow whitelisting manual connections (Luke Dashjr)
8e06be3 net_processing: Move extra service flag into InitializeNode (Luke Dashjr)
9133fd6 net: Move `NetPermissionFlags::Implicit` verification to `AddWhitelistPermissionFlags` (Luke Dashjr)
2863d7d net: store `-whitelist{force}relay` values in `CConnman` (brunoerg)

Pull request description:

  Revives bitcoin#17167. It allows whitelisting manual connections. Fixes bitcoin#9923

  Since there are some PRs/issues around this topic, I'll list some motivations/comments for whitelisting outbound connections from them:
  - Speed-up tx relay/mempool sync for testing purposes (my personal motivation for this) - In bitcoin#26970, theStack pointed out that we whitelist peers to speed up tx relay for fast mempool synchronization, however, since it applies only for inbound connections and considering the topology `node0 <--- node1 <---- node2 <--- ... <-- nodeN`,  if a tx is submitted from any node other than node0, the mempool synchronization can take quite long.
  - bitcoin#29058 (comment) - "Before enabling -v2transport by default (which I'd image may happen after bitcoin#24748) we could consider a way to force manual connections to be only-v1 or even only-v2 (disabling reconnect-with-v1). A possibility could be through a net permission flag, if bitcoin#27114 makes it in."
  - bitcoin#17167 (comment) - "This would allow us to use bitcoin#25355 when making outgoing connections to all nodes, except to whitelisted ones for which we would use our persistent I2P address."
  - Force-relay/mempool permissions for a node you intentionally connected to.

ACKs for top commit:
  achow101:
    ACK 0a53361
  sr-gi:
    re-ACK [0a53361](bitcoin@0a53361)
  pinheadmz:
    ACK 0a53361

Tree-SHA512: 97a79bb854110da04540897d2619eda409d829016aafdf1825ab5515334b0b42ef82f33cd41587af235b3af6ddcec3f2905ca038b5ab22e4c8a03d34f27aebe1
  • Loading branch information
achow101 committed Mar 12, 2024
2 parents 12dae63 + 0a53361 commit bef9917
Show file tree
Hide file tree
Showing 41 changed files with 199 additions and 108 deletions.
2 changes: 2 additions & 0 deletions doc/release-notes-27114.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- Additional flags "in" and "out" have been added to `-whitelist` to control whether
permissions apply to incoming connections and/or manual (default: incoming only).
24 changes: 17 additions & 7 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ void SetupServerArgs(ArgsManager& argsman)
argsman.AddArg("-blocknotify=<cmd>", "Execute command when the best block changes (%s in cmd is replaced by block hash)", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#endif
argsman.AddArg("-blockreconstructionextratxn=<n>", strprintf("Extra transactions to keep in memory for compact block reconstructions (default: %u)", DEFAULT_BLOCK_RECONSTRUCTION_EXTRA_TXN), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Automatic broadcast and rebroadcast of any transactions from inbound peers is disabled, unless the peer has the 'forcerelay' permission. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-blocksonly", strprintf("Whether to reject transactions from network peers. Disables automatic broadcast and rebroadcast of transactions, unless the source peer has the 'forcerelay' permission. RPC transactions are not affected. (default: %u)", DEFAULT_BLOCKSONLY), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-coinstatsindex", strprintf("Maintain coinstats index used by the gettxoutsetinfo RPC (default: %u)", DEFAULT_COINSTATSINDEX), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-conf=<file>", strprintf("Specify path to read-only configuration file. Relative paths will be prefixed by datadir location (only useable from command line, not configuration file) (default: %s)", BITCOIN_CONF_FILENAME), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
Expand Down Expand Up @@ -571,9 +571,11 @@ void SetupServerArgs(ArgsManager& argsman)
"Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". "
"Specify multiple permissions separated by commas (default: download,noban,mempool,relay). Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);

argsman.AddArg("-whitelist=<[permissions@]IP address or network>", "Add permission flags to the peers connecting from the given IP address (e.g. 1.2.3.4) or "
argsman.AddArg("-whitelist=<[permissions@]IP address or network>", "Add permission flags to the peers using the given IP address (e.g. 1.2.3.4) or "
"CIDR-notated network (e.g. 1.2.3.0/24). Uses the same permissions as "
"-whitebind. Can be specified multiple times." , ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
"-whitebind. "
"Additional flags \"in\" and \"out\" control whether permissions apply to incoming connections and/or manual (default: incoming only). "
"Can be specified multiple times.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);

g_wallet_init_interface.AddWalletOptions(argsman);

Expand Down Expand Up @@ -643,8 +645,8 @@ void SetupServerArgs(ArgsManager& argsman)
OptionsCategory::NODE_RELAY);
argsman.AddArg("-minrelaytxfee=<amt>", strprintf("Fees (in %s/kvB) smaller than this are considered zero fee for relaying, mining and transaction creation (default: %s)",
CURRENCY_UNIT, FormatMoney(DEFAULT_MIN_RELAY_TX_FEE)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted inbound peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted inbound peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-whitelistforcerelay", strprintf("Add 'forcerelay' permission to whitelisted peers with default permissions. This will relay transactions even if the transactions were already in the mempool. (default: %d)", DEFAULT_WHITELISTFORCERELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-whitelistrelay", strprintf("Add 'relay' permission to whitelisted peers with default permissions. This will accept relayed transactions even when not relaying transactions (default: %d)", DEFAULT_WHITELISTRELAY), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);


argsman.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
Expand Down Expand Up @@ -1800,6 +1802,8 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
connOptions.m_added_nodes = args.GetArgs("-addnode");
connOptions.nMaxOutboundLimit = *opt_max_upload;
connOptions.m_peer_connect_timeout = peer_connect_timeout;
connOptions.whitelist_forcerelay = args.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY);
connOptions.whitelist_relay = args.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY);

// Port to bind to if `-bind=addr` is provided without a `:port` suffix.
const uint16_t default_bind_port =
Expand Down Expand Up @@ -1884,9 +1888,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)

for (const auto& net : args.GetArgs("-whitelist")) {
NetWhitelistPermissions subnet;
ConnectionDirection connection_direction;
bilingual_str error;
if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(error);
connOptions.vWhitelistedRange.push_back(subnet);
if (!NetWhitelistPermissions::TryParse(net, subnet, connection_direction, error)) return InitError(error);
if (connection_direction & ConnectionDirection::In) {
connOptions.vWhitelistedRangeIncoming.push_back(subnet);
}
if (connection_direction & ConnectionDirection::Out) {
connOptions.vWhitelistedRangeOutgoing.push_back(subnet);
}
}

connOptions.vSeedNodes = args.GetArgs("-seednode");
Expand Down
38 changes: 20 additions & 18 deletions src/net.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return nullptr;
}

NetPermissionFlags permission_flags = NetPermissionFlags::None;
std::vector<NetWhitelistPermissions> whitelist_permissions = conn_type == ConnectionType::MANUAL ? vWhitelistedRangeOutgoing : std::vector<NetWhitelistPermissions>{};
AddWhitelistPermissionFlags(permission_flags, addrConnect, whitelist_permissions);

// Add node
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
Expand All @@ -530,6 +534,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
conn_type,
/*inbound_onion=*/false,
CNodeOptions{
.permission_flags = permission_flags,
.i2p_sam_session = std::move(i2p_transient_session),
.recv_flood_size = nReceiveFloodSize,
.use_v2transport = use_v2transport,
Expand All @@ -553,9 +558,18 @@ void CNode::CloseSocketDisconnect()
m_i2p_sam_session.reset();
}

void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const {
for (const auto& subnet : vWhitelistedRange) {
if (subnet.m_subnet.Match(addr)) NetPermissions::AddFlag(flags, subnet.m_flags);
void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr, const std::vector<NetWhitelistPermissions>& ranges) const {
for (const auto& subnet : ranges) {
if (subnet.m_subnet.Match(addr)) {
NetPermissions::AddFlag(flags, subnet.m_flags);
}
}
if (NetPermissions::HasFlag(flags, NetPermissionFlags::Implicit)) {
NetPermissions::ClearFlag(flags, NetPermissionFlags::Implicit);
if (whitelist_forcerelay) NetPermissions::AddFlag(flags, NetPermissionFlags::ForceRelay);
if (whitelist_relay) NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
NetPermissions::AddFlag(flags, NetPermissionFlags::Mempool);
NetPermissions::AddFlag(flags, NetPermissionFlags::NoBan);
}
}

Expand Down Expand Up @@ -1721,14 +1735,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
{
int nInbound = 0;

AddWhitelistPermissionFlags(permission_flags, addr);
if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::Implicit)) {
NetPermissions::ClearFlag(permission_flags, NetPermissionFlags::Implicit);
if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::ForceRelay);
if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Relay);
NetPermissions::AddFlag(permission_flags, NetPermissionFlags::Mempool);
NetPermissions::AddFlag(permission_flags, NetPermissionFlags::NoBan);
}
AddWhitelistPermissionFlags(permission_flags, addr, vWhitelistedRangeIncoming);

{
LOCK(m_nodes_mutex);
Expand Down Expand Up @@ -1783,15 +1790,10 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();

ServiceFlags nodeServices = nLocalServices;
if (NetPermissions::HasFlag(permission_flags, NetPermissionFlags::BloomFilter)) {
nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
}

const bool inbound_onion = std::find(m_onion_binds.begin(), m_onion_binds.end(), addr_bind) != m_onion_binds.end();
// The V2Transport transparently falls back to V1 behavior when an incoming V1 connection is
// detected, so use it whenever we signal NODE_P2P_V2.
const bool use_v2transport(nodeServices & NODE_P2P_V2);
const bool use_v2transport(nLocalServices & NODE_P2P_V2);

CNode* pnode = new CNode(id,
std::move(sock),
Expand All @@ -1809,7 +1811,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
.use_v2transport = use_v2transport,
});
pnode->AddRef();
m_msgproc->InitializeNode(*pnode, nodeServices);
m_msgproc->InitializeNode(*pnode, nLocalServices);

LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToStringAddrPort());

Expand Down
33 changes: 24 additions & 9 deletions src/net.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@ class CNode;
class CScheduler;
struct bilingual_str;

/** Default for -whitelistrelay. */
static const bool DEFAULT_WHITELISTRELAY = true;
/** Default for -whitelistforcerelay. */
static const bool DEFAULT_WHITELISTFORCERELAY = false;

/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
static constexpr std::chrono::minutes TIMEOUT_INTERVAL{20};
/** Run the feeler connection loop once every 2 minutes. **/
Expand Down Expand Up @@ -1053,7 +1048,8 @@ class CConnman
uint64_t nMaxOutboundLimit = 0;
int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
std::vector<std::string> vSeedNodes;
std::vector<NetWhitelistPermissions> vWhitelistedRange;
std::vector<NetWhitelistPermissions> vWhitelistedRangeIncoming;
std::vector<NetWhitelistPermissions> vWhitelistedRangeOutgoing;
std::vector<NetWhitebindPermissions> vWhiteBinds;
std::vector<CService> vBinds;
std::vector<CService> onion_binds;
Expand All @@ -1064,6 +1060,8 @@ class CConnman
std::vector<std::string> m_specified_outgoing;
std::vector<std::string> m_added_nodes;
bool m_i2p_accept_incoming;
bool whitelist_forcerelay = DEFAULT_WHITELISTFORCERELAY;
bool whitelist_relay = DEFAULT_WHITELISTRELAY;
};

void Init(const Options& connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_total_bytes_sent_mutex)
Expand All @@ -1087,7 +1085,8 @@ class CConnman
LOCK(m_total_bytes_sent_mutex);
nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
}
vWhitelistedRange = connOptions.vWhitelistedRange;
vWhitelistedRangeIncoming = connOptions.vWhitelistedRangeIncoming;
vWhitelistedRangeOutgoing = connOptions.vWhitelistedRangeOutgoing;
{
LOCK(m_added_nodes_mutex);
// Attempt v2 connection if we support v2 - we'll reconnect with v1 if our
Expand All @@ -1098,6 +1097,8 @@ class CConnman
}
}
m_onion_binds = connOptions.onion_binds;
whitelist_forcerelay = connOptions.whitelist_forcerelay;
whitelist_relay = connOptions.whitelist_relay;
}

CConnman(uint64_t seed0, uint64_t seed1, AddrMan& addrman, const NetGroupManager& netgroupman,
Expand Down Expand Up @@ -1339,7 +1340,7 @@ class CConnman

bool AttemptToEvictConnection();
CNode* ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type, bool use_v2transport) EXCLUSIVE_LOCKS_REQUIRED(!m_unused_i2p_sessions_mutex);
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const;
void AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr, const std::vector<NetWhitelistPermissions>& ranges) const;

void DeleteNode(CNode* pnode);

Expand Down Expand Up @@ -1398,7 +1399,9 @@ class CConnman

// Whitelisted ranges. Any node connecting from these is automatically
// whitelisted (as well as those connecting to whitelisted binds).
std::vector<NetWhitelistPermissions> vWhitelistedRange;
std::vector<NetWhitelistPermissions> vWhitelistedRangeIncoming;
// Whitelisted ranges for outgoing connections.
std::vector<NetWhitelistPermissions> vWhitelistedRangeOutgoing;

unsigned int nSendBufferMaxSize{0};
unsigned int nReceiveFloodSize{0};
Expand Down Expand Up @@ -1551,6 +1554,18 @@ class CConnman
*/
std::vector<CService> m_onion_binds;

/**
* flag for adding 'forcerelay' permission to whitelisted inbound
* and manual peers with default permissions.
*/
bool whitelist_forcerelay;

/**
* flag for adding 'relay' permission to whitelisted inbound
* and manual peers with default permissions.
*/
bool whitelist_relay;

/**
* Mutex protecting m_i2p_sam_sessions.
*/
Expand Down
28 changes: 24 additions & 4 deletions src/net_permissions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@ const std::vector<std::string> NET_PERMISSIONS_DOC{
namespace {

// Parse the following format: "perm1,perm2@xxxxxx"
bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output, size_t& readen, bilingual_str& error)
static bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output, ConnectionDirection* output_connection_direction, size_t& readen, bilingual_str& error)
{
NetPermissionFlags flags = NetPermissionFlags::None;
ConnectionDirection connection_direction = ConnectionDirection::None;
const auto atSeparator = str.find('@');

// if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
Expand Down Expand Up @@ -52,6 +53,15 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All);
else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
else if (permission == "addr") NetPermissions::AddFlag(flags, NetPermissionFlags::Addr);
else if (permission == "in") connection_direction |= ConnectionDirection::In;
else if (permission == "out") {
if (output_connection_direction == nullptr) {
// Only NetWhitebindPermissions() should pass a nullptr.
error = _("whitebind may only be used for incoming connections (\"out\" was passed)");
return false;
}
connection_direction |= ConnectionDirection::Out;
}
else if (permission.length() == 0); // Allow empty entries
else {
error = strprintf(_("Invalid P2P permission: '%s'"), permission);
Expand All @@ -61,7 +71,16 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
readen++;
}

// By default, whitelist only applies to incoming connections
if (connection_direction == ConnectionDirection::None) {
connection_direction = ConnectionDirection::In;
} else if (flags == NetPermissionFlags::None) {
error = strprintf(_("Only direction was set, no permissions: '%s'"), str);
return false;
}

output = flags;
if (output_connection_direction) *output_connection_direction = connection_direction;
error = Untranslated("");
return true;
}
Expand All @@ -85,7 +104,7 @@ bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermi
{
NetPermissionFlags flags;
size_t offset;
if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
if (!TryParsePermissionFlags(str, flags, /*output_connection_direction=*/nullptr, offset, error)) return false;

const std::string strBind = str.substr(offset);
const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
Expand All @@ -104,11 +123,12 @@ bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermi
return true;
}

bool NetWhitelistPermissions::TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error)
bool NetWhitelistPermissions::TryParse(const std::string& str, NetWhitelistPermissions& output, ConnectionDirection& output_connection_direction, bilingual_str& error)
{
NetPermissionFlags flags;
size_t offset;
if (!TryParsePermissionFlags(str, flags, offset, error)) return false;
// Only NetWhitebindPermissions should pass a nullptr for output_connection_direction.
if (!TryParsePermissionFlags(str, flags, &output_connection_direction, offset, error)) return false;

const std::string net = str.substr(offset);
const CSubNet subnet{LookupSubNet(net)};
Expand Down
8 changes: 7 additions & 1 deletion src/net_permissions.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <netaddress.h>
#include <netbase.h>

#include <string>
#include <type_traits>
Expand All @@ -15,6 +16,11 @@ struct bilingual_str;

extern const std::vector<std::string> NET_PERMISSIONS_DOC;

/** Default for -whitelistrelay. */
constexpr bool DEFAULT_WHITELISTRELAY = true;
/** Default for -whitelistforcerelay. */
constexpr bool DEFAULT_WHITELISTFORCERELAY = false;

enum class NetPermissionFlags : uint32_t {
None = 0,
// Can query bloomfilter even if -peerbloomfilters is false
Expand Down Expand Up @@ -83,7 +89,7 @@ class NetWhitebindPermissions : public NetPermissions
class NetWhitelistPermissions : public NetPermissions
{
public:
static bool TryParse(const std::string& str, NetWhitelistPermissions& output, bilingual_str& error);
static bool TryParse(const std::string& str, NetWhitelistPermissions& output, ConnectionDirection& output_connection_direction, bilingual_str& error);
CSubNet m_subnet;
};

Expand Down
5 changes: 5 additions & 0 deletions src/net_processing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1588,6 +1588,11 @@ void PeerManagerImpl::InitializeNode(CNode& node, ServiceFlags our_services)
m_node_states.emplace_hint(m_node_states.end(), std::piecewise_construct, std::forward_as_tuple(nodeid), std::forward_as_tuple(node.IsInboundConn()));
assert(m_txrequest.Count(nodeid) == 0);
}

if (NetPermissions::HasFlag(node.m_permission_flags, NetPermissionFlags::BloomFilter)) {
our_services = static_cast<ServiceFlags>(our_services | NODE_BLOOM);
}

PeerRef peer = std::make_shared<Peer>(nodeid, our_services);
{
LOCK(m_peer_mutex);
Expand Down
Loading

0 comments on commit bef9917

Please sign in to comment.