init: introduce a new option to enable/disable private broadcast
Co-authored-by: brunoerg <brunoely.gc@gmail.com> Co-authored-by: Lőrinc <pap.lorinc@gmail.com>
This commit is contained in:
3 files changed
+64
-3
No files matched your search
+38
-3
@@ -670,6 +670,15 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
|
|||||||
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("-privatebroadcast",
|
||||||
|
strprintf(
|
||||||
|
"Broadcast transactions submitted via sendrawtransaction RPC using short-lived "
|
||||||
|
"connections through the Tor or I2P networks, without putting them in the mempool first. "
|
||||||
|
"Transactions submitted through the wallet are not affected by this option "
|
||||||
|
"(default: %u)",
|
||||||
|
DEFAULT_PRIVATE_BROADCAST),
|
||||||
|
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("-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("-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);
|
||||||
|
|
||||||
@@ -1732,13 +1741,13 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool listenonion{args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
|
||||||
if (onion_proxy.IsValid()) {
|
if (onion_proxy.IsValid()) {
|
||||||
SetProxy(NET_ONION, onion_proxy);
|
SetProxy(NET_ONION, onion_proxy);
|
||||||
} else {
|
} else {
|
||||||
// If -listenonion is set, then we will (try to) connect to the Tor control port
|
// If -listenonion is set, then we will (try to) connect to the Tor control port
|
||||||
// later from the torcontrol thread and may retrieve the onion proxy from there.
|
// later from the torcontrol thread and may retrieve the onion proxy from there.
|
||||||
const bool listenonion_disabled{!args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)};
|
if (onlynet_used_with_onion && !listenonion) {
|
||||||
if (onlynet_used_with_onion && listenonion_disabled) {
|
|
||||||
return InitError(
|
return InitError(
|
||||||
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
|
_("Outbound connections restricted to Tor (-onlynet=onion) but the proxy for "
|
||||||
"reaching the Tor network is not provided: none of -proxy, -onion or "
|
"reaching the Tor network is not provided: none of -proxy, -onion or "
|
||||||
@@ -2119,7 +2128,7 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
connOptions.onion_binds.push_back(onion_service_target);
|
connOptions.onion_binds.push_back(onion_service_target);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.GetBoolArg("-listenonion", DEFAULT_LISTEN_ONION)) {
|
if (listenonion) {
|
||||||
if (connOptions.onion_binds.size() > 1) {
|
if (connOptions.onion_binds.size() > 1) {
|
||||||
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "
|
InitWarning(strprintf(_("More than one onion bind address is provided. Using %s "
|
||||||
"for the automatically created Tor onion service."),
|
"for the automatically created Tor onion service."),
|
||||||
@@ -2192,6 +2201,32 @@ bool AppInitMain(NodeContext& node, interfaces::BlockAndHeaderTipInfo* tip_info)
|
|||||||
conflict->ToStringAddrPort()));
|
conflict->ToStringAddrPort()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.GetBoolArg("-privatebroadcast", DEFAULT_PRIVATE_BROADCAST)) {
|
||||||
|
// If -listenonion is set, then NET_ONION may not be reachable now
|
||||||
|
// but may become reachable later, thus only error here if it is not
|
||||||
|
// reachable and will not become reachable for sure.
|
||||||
|
const bool onion_may_become_reachable{listenonion && (!args.IsArgSet("-onlynet") || onlynet_used_with_onion)};
|
||||||
|
if (!g_reachable_nets.Contains(NET_I2P) &&
|
||||||
|
!g_reachable_nets.Contains(NET_ONION) &&
|
||||||
|
!onion_may_become_reachable) {
|
||||||
|
return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "
|
||||||
|
"but none of Tor or I2P networks is reachable"));
|
||||||
|
}
|
||||||
|
if (!connOptions.m_use_addrman_outgoing) {
|
||||||
|
return InitError(_("Private broadcast of own transactions requested (-privatebroadcast), "
|
||||||
|
"but -connect is also configured. They are incompatible because the "
|
||||||
|
"private broadcast needs to open new connections to randomly "
|
||||||
|
"chosen Tor or I2P peers. Consider using -maxconnections=0 -addnode=... "
|
||||||
|
"instead"));
|
||||||
|
}
|
||||||
|
if (!proxyRandomize && (g_reachable_nets.Contains(NET_ONION) || onion_may_become_reachable)) {
|
||||||
|
InitWarning(_("Private broadcast of own transactions requested (-privatebroadcast) and "
|
||||||
|
"-proxyrandomize is disabled. Tor circuits for private broadcast connections "
|
||||||
|
"may be correlated to other connections over Tor. For maximum privacy set "
|
||||||
|
"-proxyrandomize=1."));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!node.connman->Start(scheduler, connOptions)) {
|
if (!node.connman->Start(scheduler, connOptions)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,6 +83,8 @@ static const std::string DEFAULT_MAX_UPLOAD_TARGET{"0M"};
|
|||||||
static const bool DEFAULT_BLOCKSONLY = false;
|
static const bool DEFAULT_BLOCKSONLY = false;
|
||||||
/** -peertimeout default */
|
/** -peertimeout default */
|
||||||
static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60;
|
static const int64_t DEFAULT_PEER_CONNECT_TIMEOUT = 60;
|
||||||
|
/** Default for -privatebroadcast. */
|
||||||
|
static constexpr bool DEFAULT_PRIVATE_BROADCAST{false};
|
||||||
/** Number of file descriptors required for message capture **/
|
/** Number of file descriptors required for message capture **/
|
||||||
static const int NUM_FDS_MESSAGE_CAPTURE = 1;
|
static const int NUM_FDS_MESSAGE_CAPTURE = 1;
|
||||||
/** Interval for ASMap Health Check **/
|
/** Interval for ASMap Health Check **/
|
||||||
|
|||||||
@@ -411,6 +411,29 @@ class ConfArgsTest(BitcoinTestFramework):
|
|||||||
self.restart_node(0, extra_args=[connect_arg, '-dnsseed', '-proxy=localhost:1080'])
|
self.restart_node(0, extra_args=[connect_arg, '-dnsseed', '-proxy=localhost:1080'])
|
||||||
self.stop_node(0)
|
self.stop_node(0)
|
||||||
|
|
||||||
|
def test_privatebroadcast(self):
|
||||||
|
self.log.info("Test that an invalid usage of -privatebroadcast throws an init error")
|
||||||
|
self.stop_node(0)
|
||||||
|
# -privatebroadcast init error: Tor/I2P not reachable at startup
|
||||||
|
self.nodes[0].assert_start_raises_init_error(
|
||||||
|
extra_args=["-privatebroadcast"],
|
||||||
|
expected_msg=(
|
||||||
|
"Error: Private broadcast of own transactions requested (-privatebroadcast), "
|
||||||
|
"but none of Tor or I2P networks is reachable"))
|
||||||
|
# -privatebroadcast init error: incompatible with -connect
|
||||||
|
self.nodes[0].assert_start_raises_init_error(
|
||||||
|
extra_args=["-privatebroadcast", "-connect=127.0.0.1:8333", "-onion=127.0.0.1:9050"],
|
||||||
|
expected_msg=(
|
||||||
|
"Error: Private broadcast of own transactions requested (-privatebroadcast), but -connect is also configured. "
|
||||||
|
"They are incompatible because the private broadcast needs to open new connections to randomly "
|
||||||
|
"chosen Tor or I2P peers. Consider using -maxconnections=0 -addnode=... instead"))
|
||||||
|
# Warning case: private broadcast allowed, but -proxyrandomize=0 triggers a privacy warning
|
||||||
|
self.start_node(0, extra_args=["-privatebroadcast", "-onion=127.0.0.1:9050", "-proxyrandomize=0"])
|
||||||
|
self.stop_node(0, expected_stderr=(
|
||||||
|
"Warning: Private broadcast of own transactions requested (-privatebroadcast) and "
|
||||||
|
"-proxyrandomize is disabled. Tor circuits for private broadcast connections may "
|
||||||
|
"be correlated to other connections over Tor. For maximum privacy set -proxyrandomize=1."))
|
||||||
|
|
||||||
def test_ignored_conf(self):
|
def test_ignored_conf(self):
|
||||||
self.log.info('Test error is triggered when the datadir in use contains a bitcoin.conf file that would be ignored '
|
self.log.info('Test error is triggered when the datadir in use contains a bitcoin.conf file that would be ignored '
|
||||||
'because a conflicting -conf file argument is passed.')
|
'because a conflicting -conf file argument is passed.')
|
||||||
@@ -496,6 +519,7 @@ class ConfArgsTest(BitcoinTestFramework):
|
|||||||
self.test_seed_peers()
|
self.test_seed_peers()
|
||||||
self.test_networkactive()
|
self.test_networkactive()
|
||||||
self.test_connect_with_seednode()
|
self.test_connect_with_seednode()
|
||||||
|
self.test_privatebroadcast()
|
||||||
|
|
||||||
self.test_dir_config()
|
self.test_dir_config()
|
||||||
self.test_negated_config()
|
self.test_negated_config()
|
||||||
|
|||||||
Reference in new issue
Block a user