0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

Accept "in" and "out" flags to -whitelist to allow whitelisting manual connections

This commit is contained in:
Luke Dashjr 2021-07-07 01:06:27 +00:00 committed by brunoerg
parent 8e06be347c
commit 66bc6e2d17
7 changed files with 71 additions and 21 deletions

View file

@ -473,7 +473,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); 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 #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("-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("-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("-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); argsman.AddArg("-datadir=<dir>", "Specify data directory", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
@ -567,9 +567,11 @@ void SetupServerArgs(ArgsManager& argsman)
"Use [host]:port notation for IPv6. Allowed permissions: " + Join(NET_PERMISSIONS_DOC, ", ") + ". " "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); "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 " "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); g_wallet_init_interface.AddWalletOptions(argsman);
@ -639,8 +641,8 @@ void SetupServerArgs(ArgsManager& argsman)
OptionsCategory::NODE_RELAY); 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)", 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); 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("-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 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("-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); argsman.AddArg("-blockmaxweight=<n>", strprintf("Set maximum BIP141 block weight (default: %d)", DEFAULT_BLOCK_MAX_WEIGHT), ArgsManager::ALLOW_ANY, OptionsCategory::BLOCK_CREATION);
@ -1861,9 +1863,15 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
for (const auto& net : args.GetArgs("-whitelist")) { for (const auto& net : args.GetArgs("-whitelist")) {
NetWhitelistPermissions subnet; NetWhitelistPermissions subnet;
ConnectionDirection connection_direction;
bilingual_str error; bilingual_str error;
if (!NetWhitelistPermissions::TryParse(net, subnet, error)) return InitError(error); if (!NetWhitelistPermissions::TryParse(net, subnet, connection_direction, error)) return InitError(error);
connOptions.vWhitelistedRange.push_back(subnet); 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"); connOptions.vSeedNodes = args.GetArgs("-seednode");

View file

@ -519,6 +519,10 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
return nullptr; 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 // Add node
NodeId id = GetNewNodeId(); NodeId id = GetNewNodeId();
uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize(); uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
@ -535,6 +539,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
conn_type, conn_type,
/*inbound_onion=*/false, /*inbound_onion=*/false,
CNodeOptions{ CNodeOptions{
.permission_flags = permission_flags,
.i2p_sam_session = std::move(i2p_transient_session), .i2p_sam_session = std::move(i2p_transient_session),
.recv_flood_size = nReceiveFloodSize, .recv_flood_size = nReceiveFloodSize,
.use_v2transport = use_v2transport, .use_v2transport = use_v2transport,
@ -1735,7 +1740,7 @@ void CConnman::CreateNodeFromAcceptedSocket(std::unique_ptr<Sock>&& sock,
{ {
int nInbound = 0; int nInbound = 0;
AddWhitelistPermissionFlags(permission_flags, addr, vWhitelistedRange); AddWhitelistPermissionFlags(permission_flags, addr, vWhitelistedRangeIncoming);
{ {
LOCK(m_nodes_mutex); LOCK(m_nodes_mutex);

View file

@ -1048,7 +1048,8 @@ public:
uint64_t nMaxOutboundLimit = 0; uint64_t nMaxOutboundLimit = 0;
int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT; int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;
std::vector<std::string> vSeedNodes; std::vector<std::string> vSeedNodes;
std::vector<NetWhitelistPermissions> vWhitelistedRange; std::vector<NetWhitelistPermissions> vWhitelistedRangeIncoming;
std::vector<NetWhitelistPermissions> vWhitelistedRangeOutgoing;
std::vector<NetWhitebindPermissions> vWhiteBinds; std::vector<NetWhitebindPermissions> vWhiteBinds;
std::vector<CService> vBinds; std::vector<CService> vBinds;
std::vector<CService> onion_binds; std::vector<CService> onion_binds;
@ -1084,7 +1085,8 @@ public:
LOCK(m_total_bytes_sent_mutex); LOCK(m_total_bytes_sent_mutex);
nMaxOutboundLimit = connOptions.nMaxOutboundLimit; nMaxOutboundLimit = connOptions.nMaxOutboundLimit;
} }
vWhitelistedRange = connOptions.vWhitelistedRange; vWhitelistedRangeIncoming = connOptions.vWhitelistedRangeIncoming;
vWhitelistedRangeOutgoing = connOptions.vWhitelistedRangeOutgoing;
{ {
LOCK(m_added_nodes_mutex); LOCK(m_added_nodes_mutex);
// Attempt v2 connection if we support v2 - we'll reconnect with v1 if our // Attempt v2 connection if we support v2 - we'll reconnect with v1 if our
@ -1397,7 +1399,9 @@ private:
// Whitelisted ranges. Any node connecting from these is automatically // Whitelisted ranges. Any node connecting from these is automatically
// whitelisted (as well as those connecting to whitelisted binds). // 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 nSendBufferMaxSize{0};
unsigned int nReceiveFloodSize{0}; unsigned int nReceiveFloodSize{0};

View file

@ -21,9 +21,10 @@ const std::vector<std::string> NET_PERMISSIONS_DOC{
namespace { namespace {
// Parse the following format: "perm1,perm2@xxxxxx" // 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; NetPermissionFlags flags = NetPermissionFlags::None;
ConnectionDirection connection_direction = ConnectionDirection::None;
const auto atSeparator = str.find('@'); const auto atSeparator = str.find('@');
// if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions // if '@' is not found (ie, "xxxxx"), the caller should apply implicit permissions
@ -52,6 +53,15 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All); else if (permission == "all") NetPermissions::AddFlag(flags, NetPermissionFlags::All);
else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay); else if (permission == "relay") NetPermissions::AddFlag(flags, NetPermissionFlags::Relay);
else if (permission == "addr") NetPermissions::AddFlag(flags, NetPermissionFlags::Addr); 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 if (permission.length() == 0); // Allow empty entries
else { else {
error = strprintf(_("Invalid P2P permission: '%s'"), permission); error = strprintf(_("Invalid P2P permission: '%s'"), permission);
@ -61,7 +71,16 @@ bool TryParsePermissionFlags(const std::string& str, NetPermissionFlags& output,
readen++; 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; output = flags;
if (output_connection_direction) *output_connection_direction = connection_direction;
error = Untranslated(""); error = Untranslated("");
return true; return true;
} }
@ -85,7 +104,7 @@ bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermi
{ {
NetPermissionFlags flags; NetPermissionFlags flags;
size_t offset; 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::string strBind = str.substr(offset);
const std::optional<CService> addrBind{Lookup(strBind, 0, false)}; const std::optional<CService> addrBind{Lookup(strBind, 0, false)};
@ -104,11 +123,12 @@ bool NetWhitebindPermissions::TryParse(const std::string& str, NetWhitebindPermi
return true; 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; NetPermissionFlags flags;
size_t offset; 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 std::string net = str.substr(offset);
const CSubNet subnet{LookupSubNet(net)}; const CSubNet subnet{LookupSubNet(net)};

View file

@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <netaddress.h> #include <netaddress.h>
#include <netbase.h>
#include <string> #include <string>
#include <type_traits> #include <type_traits>
@ -88,7 +89,7 @@ public:
class NetWhitelistPermissions : public NetPermissions class NetWhitelistPermissions : public NetPermissions
{ {
public: 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; CSubNet m_subnet;
}; };

View file

@ -3,6 +3,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php. // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net_permissions.h> #include <net_permissions.h>
#include <netbase.h>
#include <test/fuzz/FuzzedDataProvider.h> #include <test/fuzz/FuzzedDataProvider.h>
#include <test/fuzz/fuzz.h> #include <test/fuzz/fuzz.h>
#include <test/fuzz/util.h> #include <test/fuzz/util.h>
@ -31,8 +32,9 @@ FUZZ_TARGET(net_permissions)
} }
NetWhitelistPermissions net_whitelist_permissions; NetWhitelistPermissions net_whitelist_permissions;
ConnectionDirection connection_direction;
bilingual_str error_net_whitelist_permissions; bilingual_str error_net_whitelist_permissions;
if (NetWhitelistPermissions::TryParse(s, net_whitelist_permissions, error_net_whitelist_permissions)) { if (NetWhitelistPermissions::TryParse(s, net_whitelist_permissions, connection_direction, error_net_whitelist_permissions)) {
(void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags); (void)NetPermissions::ToStrings(net_whitelist_permissions.m_flags);
(void)NetPermissions::AddFlag(net_whitelist_permissions.m_flags, net_permission_flags); (void)NetPermissions::AddFlag(net_whitelist_permissions.m_flags, net_permission_flags);
assert(NetPermissions::HasFlag(net_whitelist_permissions.m_flags, net_permission_flags)); assert(NetPermissions::HasFlag(net_whitelist_permissions.m_flags, net_permission_flags));

View file

@ -366,6 +366,7 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
bilingual_str error; bilingual_str error;
NetWhitebindPermissions whitebindPermissions; NetWhitebindPermissions whitebindPermissions;
NetWhitelistPermissions whitelistPermissions; NetWhitelistPermissions whitelistPermissions;
ConnectionDirection connection_direction;
// Detect invalid white bind // Detect invalid white bind
BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error)); BOOST_CHECK(!NetWhitebindPermissions::TryParse("", whitebindPermissions, error));
@ -435,24 +436,33 @@ BOOST_AUTO_TEST_CASE(netpermissions_test)
BOOST_CHECK(NetWhitebindPermissions::TryParse(",,@1.2.3.4:32", whitebindPermissions, error)); BOOST_CHECK(NetWhitebindPermissions::TryParse(",,@1.2.3.4:32", whitebindPermissions, error));
BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, NetPermissionFlags::None); BOOST_CHECK_EQUAL(whitebindPermissions.m_flags, NetPermissionFlags::None);
BOOST_CHECK(!NetWhitebindPermissions::TryParse("out,forcerelay@1.2.3.4:32", whitebindPermissions, error));
BOOST_CHECK(error.original.find("whitebind may only be used for incoming connections (\"out\" was passed)") != std::string::npos);
// Detect invalid flag // Detect invalid flag
BOOST_CHECK(!NetWhitebindPermissions::TryParse("bloom,forcerelay,oopsie@1.2.3.4:32", whitebindPermissions, error)); BOOST_CHECK(!NetWhitebindPermissions::TryParse("bloom,forcerelay,oopsie@1.2.3.4:32", whitebindPermissions, error));
BOOST_CHECK(error.original.find("Invalid P2P permission") != std::string::npos); BOOST_CHECK(error.original.find("Invalid P2P permission") != std::string::npos);
// Check netmask error // Check netmask error
BOOST_CHECK(!NetWhitelistPermissions::TryParse("bloom,forcerelay,noban@1.2.3.4:32", whitelistPermissions, error)); BOOST_CHECK(!NetWhitelistPermissions::TryParse("bloom,forcerelay,noban@1.2.3.4:32", whitelistPermissions, connection_direction, error));
BOOST_CHECK(error.original.find("Invalid netmask specified in -whitelist") != std::string::npos); BOOST_CHECK(error.original.find("Invalid netmask specified in -whitelist") != std::string::npos);
// Happy path for whitelist parsing // Happy path for whitelist parsing
BOOST_CHECK(NetWhitelistPermissions::TryParse("noban@1.2.3.4", whitelistPermissions, error)); BOOST_CHECK(NetWhitelistPermissions::TryParse("noban@1.2.3.4", whitelistPermissions, connection_direction, error));
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, NetPermissionFlags::NoBan); BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, NetPermissionFlags::NoBan);
BOOST_CHECK(NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::NoBan)); BOOST_CHECK(NetPermissions::HasFlag(whitelistPermissions.m_flags, NetPermissionFlags::NoBan));
BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay@1.2.3.4/32", whitelistPermissions, error)); BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay@1.2.3.4/32", whitelistPermissions, connection_direction, error));
BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, NetPermissionFlags::BloomFilter | NetPermissionFlags::ForceRelay | NetPermissionFlags::NoBan | NetPermissionFlags::Relay); BOOST_CHECK_EQUAL(whitelistPermissions.m_flags, NetPermissionFlags::BloomFilter | NetPermissionFlags::ForceRelay | NetPermissionFlags::NoBan | NetPermissionFlags::Relay);
BOOST_CHECK(error.empty()); BOOST_CHECK(error.empty());
BOOST_CHECK_EQUAL(whitelistPermissions.m_subnet.ToString(), "1.2.3.4/32"); BOOST_CHECK_EQUAL(whitelistPermissions.m_subnet.ToString(), "1.2.3.4/32");
BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay,mempool@1.2.3.4/32", whitelistPermissions, error)); BOOST_CHECK(NetWhitelistPermissions::TryParse("bloom,forcerelay,noban,relay,mempool@1.2.3.4/32", whitelistPermissions, connection_direction, error));
BOOST_CHECK(NetWhitelistPermissions::TryParse("in,relay@1.2.3.4", whitelistPermissions, connection_direction, error));
BOOST_CHECK_EQUAL(connection_direction, ConnectionDirection::In);
BOOST_CHECK(NetWhitelistPermissions::TryParse("out,bloom@1.2.3.4", whitelistPermissions, connection_direction, error));
BOOST_CHECK_EQUAL(connection_direction, ConnectionDirection::Out);
BOOST_CHECK(NetWhitelistPermissions::TryParse("in,out,bloom@1.2.3.4", whitelistPermissions, connection_direction, error));
BOOST_CHECK_EQUAL(connection_direction, ConnectionDirection::Both);
const auto strings = NetPermissions::ToStrings(NetPermissionFlags::All); const auto strings = NetPermissions::ToStrings(NetPermissionFlags::All);
BOOST_CHECK_EQUAL(strings.size(), 7U); BOOST_CHECK_EQUAL(strings.size(), 7U);