mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-20 14:05:23 +01:00
init: introduce I2P connectivity options
Introduce two new options to reach the I2P network: * `-i2psam=<ip:port>` point to the I2P SAM proxy. If this is set then the I2P network is considered reachable and we can make outgoing connections to I2P peers via that proxy. We listen for and accept incoming connections from I2P peers if the below is set in addition to `-i2psam=<ip:port>` * `-i2pacceptincoming` if this is set together with `-i2psam=<ip:port>` then we accept incoming I2P connections via the I2P SAM proxy.
This commit is contained in:
parent
c22daa2ecf
commit
76c35c60f3
6 changed files with 76 additions and 8 deletions
|
@ -64,6 +64,7 @@ Subdirectory | File(s) | Description
|
|||
`./` | `ip_asn.map` | IP addresses to Autonomous System Numbers (ASNs) mapping used for bucketing of the peers; path can be specified with the `-asmap` option
|
||||
`./` | `mempool.dat` | Dump of the mempool's transactions
|
||||
`./` | `onion_v3_private_key` | Cached Tor onion service private key for `-listenonion` option
|
||||
`./` | `i2p_private_key` | Private key that corresponds to our I2P address. When `-i2psam=` is specified the contents of this file is used to identify ourselves for making outgoing connections to I2P peers and possibly accepting incoming ones. Automatically generated if it does not exist.
|
||||
`./` | `peers.dat` | Peer IP address database (custom format)
|
||||
`./` | `settings.json` | Read-write settings set through GUI or RPC interfaces, augmenting manual settings from [bitcoin.conf](bitcoin-conf.md). File is created automatically if read-write settings storage is not disabled with `-nosettings` option. Path can be specified with `-settings` option
|
||||
`./` | `.cookie` | Session RPC authentication cookie; if used, created at start and deleted on shutdown; can be specified by `-rpccookiefile` option
|
||||
|
|
20
src/init.cpp
20
src/init.cpp
|
@ -447,6 +447,8 @@ void SetupServerArgs(NodeContext& node)
|
|||
argsman.AddArg("-maxtimeadjustment", strprintf("Maximum allowed median peer time offset adjustment. Local perspective of time may be influenced by peers forward or backward by this amount. (default: %u seconds)", DEFAULT_MAX_TIME_ADJUSTMENT), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-maxuploadtarget=<n>", strprintf("Tries to keep outbound traffic under the given target (in MiB per 24h). Limit does not apply to peers with 'download' permission. 0 = no limit (default: %d)", DEFAULT_MAX_UPLOAD_TARGET), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-onion=<ip:port>", "Use separate SOCKS5 proxy to reach peers via Tor onion services, set -noonion to disable (default: -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-i2psam=<ip:port>", "I2P SAM proxy to reach I2P peers and accept I2P connections (default: none)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-i2pacceptincoming", "If set and -i2psam is also set then incoming I2P connections are accepted via the SAM proxy. If this is not set but -i2psam is set then only outgoing connections will be made to the I2P network. Ignored if -i2psam is not set. Listening for incoming I2P connections is done through the SAM proxy, not by binding to a local address and port (default: 1)", ArgsManager::ALLOW_BOOL, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-onlynet=<net>", "Make outgoing connections only through network <net> (" + Join(GetNetworkNames(), ", ") + "). Incoming connections are not affected by this option. This option can be specified multiple times to allow multiple networks. Warning: if it is used with ipv4 or ipv6 but not onion and the -onion or -proxy option is set, then outbound onion connections will still be made; use -noonion or -onion=0 to disable outbound onion connections in this case.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-peerbloomfilters", strprintf("Support filtering of blocks and transaction with bloom filters (default: %u)", DEFAULT_PEERBLOOMFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-peerblockfilters", strprintf("Serve compact block filters to peers per BIP 157 (default: %u)", DEFAULT_PEERBLOCKFILTERS), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
|
@ -847,6 +849,9 @@ void InitParameterInteraction(ArgsManager& args)
|
|||
LogPrintf("%s: parameter interaction: -listen=0 -> setting -discover=0\n", __func__);
|
||||
if (args.SoftSetBoolArg("-listenonion", false))
|
||||
LogPrintf("%s: parameter interaction: -listen=0 -> setting -listenonion=0\n", __func__);
|
||||
if (args.SoftSetBoolArg("-i2pacceptincoming", false)) {
|
||||
LogPrintf("%s: parameter interaction: -listen=0 -> setting -i2pacceptincoming=0\n", __func__);
|
||||
}
|
||||
}
|
||||
|
||||
if (args.IsArgSet("-externalip")) {
|
||||
|
@ -1990,6 +1995,21 @@ bool AppInitMain(const util::Ref& context, NodeContext& node, interfaces::BlockA
|
|||
connOptions.m_specified_outgoing = connect;
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& i2psam_arg = args.GetArg("-i2psam", "");
|
||||
if (!i2psam_arg.empty()) {
|
||||
CService addr;
|
||||
if (!Lookup(i2psam_arg, addr, 7656, fNameLookup) || !addr.IsValid()) {
|
||||
return InitError(strprintf(_("Invalid -i2psam address or hostname: '%s'"), i2psam_arg));
|
||||
}
|
||||
SetReachable(NET_I2P, true);
|
||||
SetProxy(NET_I2P, proxyType{addr});
|
||||
} else {
|
||||
SetReachable(NET_I2P, false);
|
||||
}
|
||||
|
||||
connOptions.m_i2p_accept_incoming = args.GetBoolArg("-i2pacceptincoming", true);
|
||||
|
||||
if (!node.connman->Start(*node.scheduler, connOptions)) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -2374,6 +2374,12 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
|
|||
return false;
|
||||
}
|
||||
|
||||
proxyType i2p_sam;
|
||||
if (GetProxy(NET_I2P, i2p_sam)) {
|
||||
m_i2p_sam_session = std::make_unique<i2p::sam::Session>(GetDataDir() / "i2p_private_key",
|
||||
i2p_sam.proxy, &interruptNet);
|
||||
}
|
||||
|
||||
for (const auto& strDest : connOptions.vSeedNodes) {
|
||||
AddAddrFetch(strDest);
|
||||
}
|
||||
|
|
14
src/net.h
14
src/net.h
|
@ -14,6 +14,7 @@
|
|||
#include <compat.h>
|
||||
#include <crypto/siphash.h>
|
||||
#include <hash.h>
|
||||
#include <i2p.h>
|
||||
#include <net_permissions.h>
|
||||
#include <netaddress.h>
|
||||
#include <optional.h>
|
||||
|
@ -831,6 +832,7 @@ public:
|
|||
std::vector<std::string> m_specified_outgoing;
|
||||
std::vector<std::string> m_added_nodes;
|
||||
std::vector<bool> m_asmap;
|
||||
bool m_i2p_accept_incoming;
|
||||
};
|
||||
|
||||
void Init(const Options& connOptions) {
|
||||
|
@ -1221,8 +1223,20 @@ private:
|
|||
Mutex mutexMsgProc;
|
||||
std::atomic<bool> flagInterruptMsgProc{false};
|
||||
|
||||
/**
|
||||
* This is signaled when network activity should cease.
|
||||
* A pointer to it is saved in `m_i2p_sam_session`, so make sure that
|
||||
* the lifetime of `interruptNet` is not shorter than
|
||||
* the lifetime of `m_i2p_sam_session`.
|
||||
*/
|
||||
CThreadInterrupt interruptNet;
|
||||
|
||||
/**
|
||||
* I2P SAM session.
|
||||
* Used to accept incoming and make outgoing I2P connections.
|
||||
*/
|
||||
std::unique_ptr<i2p::sam::Session> m_i2p_sam_session;
|
||||
|
||||
std::thread threadDNSAddressSeed;
|
||||
std::thread threadSocketHandler;
|
||||
std::thread threadOpenAddedConnections;
|
||||
|
|
|
@ -546,7 +546,7 @@ static UniValue GetNetworksInfo()
|
|||
UniValue networks(UniValue::VARR);
|
||||
for (int n = 0; n < NET_MAX; ++n) {
|
||||
enum Network network = static_cast<enum Network>(n);
|
||||
if (network == NET_UNROUTABLE || network == NET_I2P || network == NET_CJDNS || network == NET_INTERNAL) continue;
|
||||
if (network == NET_UNROUTABLE || network == NET_CJDNS || network == NET_INTERNAL) continue;
|
||||
proxyType proxy;
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
GetProxy(network, proxy);
|
||||
|
|
|
@ -49,9 +49,10 @@ NET_UNROUTABLE = "not_publicly_routable"
|
|||
NET_IPV4 = "ipv4"
|
||||
NET_IPV6 = "ipv6"
|
||||
NET_ONION = "onion"
|
||||
NET_I2P = "i2p"
|
||||
|
||||
# Networks returned by RPC getnetworkinfo, defined in src/rpc/net.cpp::GetNetworksInfo()
|
||||
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION})
|
||||
NETWORKS = frozenset({NET_IPV4, NET_IPV6, NET_ONION, NET_I2P})
|
||||
|
||||
|
||||
class ProxyTest(BitcoinTestFramework):
|
||||
|
@ -90,11 +91,15 @@ class ProxyTest(BitcoinTestFramework):
|
|||
self.serv3 = Socks5Server(self.conf3)
|
||||
self.serv3.start()
|
||||
|
||||
# We will not try to connect to this.
|
||||
self.i2p_sam = ('127.0.0.1', 7656)
|
||||
|
||||
# Note: proxies are not used to connect to local nodes. This is because the proxy to
|
||||
# use is based on CService.GetNetwork(), which returns NET_UNROUTABLE for localhost.
|
||||
args = [
|
||||
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-proxyrandomize=1'],
|
||||
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),'-proxyrandomize=0'],
|
||||
['-listen', '-proxy=%s:%i' % (self.conf1.addr),'-onion=%s:%i' % (self.conf2.addr),
|
||||
'-i2psam=%s:%i' % (self.i2p_sam), '-i2pacceptincoming=0', '-proxyrandomize=0'],
|
||||
['-listen', '-proxy=%s:%i' % (self.conf2.addr),'-proxyrandomize=1'],
|
||||
[]
|
||||
]
|
||||
|
@ -199,9 +204,16 @@ class ProxyTest(BitcoinTestFramework):
|
|||
n0 = networks_dict(self.nodes[0].getnetworkinfo())
|
||||
assert_equal(NETWORKS, n0.keys())
|
||||
for net in NETWORKS:
|
||||
assert_equal(n0[net]['proxy'], '%s:%i' % (self.conf1.addr))
|
||||
assert_equal(n0[net]['proxy_randomize_credentials'], True)
|
||||
if net == NET_I2P:
|
||||
expected_proxy = ''
|
||||
expected_randomize = False
|
||||
else:
|
||||
expected_proxy = '%s:%i' % (self.conf1.addr)
|
||||
expected_randomize = True
|
||||
assert_equal(n0[net]['proxy'], expected_proxy)
|
||||
assert_equal(n0[net]['proxy_randomize_credentials'], expected_randomize)
|
||||
assert_equal(n0['onion']['reachable'], True)
|
||||
assert_equal(n0['i2p']['reachable'], False)
|
||||
|
||||
n1 = networks_dict(self.nodes[1].getnetworkinfo())
|
||||
assert_equal(NETWORKS, n1.keys())
|
||||
|
@ -211,21 +223,36 @@ class ProxyTest(BitcoinTestFramework):
|
|||
assert_equal(n1['onion']['proxy'], '%s:%i' % (self.conf2.addr))
|
||||
assert_equal(n1['onion']['proxy_randomize_credentials'], False)
|
||||
assert_equal(n1['onion']['reachable'], True)
|
||||
assert_equal(n1['i2p']['proxy'], '%s:%i' % (self.i2p_sam))
|
||||
assert_equal(n1['i2p']['proxy_randomize_credentials'], False)
|
||||
assert_equal(n1['i2p']['reachable'], True)
|
||||
|
||||
n2 = networks_dict(self.nodes[2].getnetworkinfo())
|
||||
assert_equal(NETWORKS, n2.keys())
|
||||
for net in NETWORKS:
|
||||
assert_equal(n2[net]['proxy'], '%s:%i' % (self.conf2.addr))
|
||||
assert_equal(n2[net]['proxy_randomize_credentials'], True)
|
||||
if net == NET_I2P:
|
||||
expected_proxy = ''
|
||||
expected_randomize = False
|
||||
else:
|
||||
expected_proxy = '%s:%i' % (self.conf2.addr)
|
||||
expected_randomize = True
|
||||
assert_equal(n2[net]['proxy'], expected_proxy)
|
||||
assert_equal(n2[net]['proxy_randomize_credentials'], expected_randomize)
|
||||
assert_equal(n2['onion']['reachable'], True)
|
||||
assert_equal(n2['i2p']['reachable'], False)
|
||||
|
||||
if self.have_ipv6:
|
||||
n3 = networks_dict(self.nodes[3].getnetworkinfo())
|
||||
assert_equal(NETWORKS, n3.keys())
|
||||
for net in NETWORKS:
|
||||
assert_equal(n3[net]['proxy'], '[%s]:%i' % (self.conf3.addr))
|
||||
if net == NET_I2P:
|
||||
expected_proxy = ''
|
||||
else:
|
||||
expected_proxy = '[%s]:%i' % (self.conf3.addr)
|
||||
assert_equal(n3[net]['proxy'], expected_proxy)
|
||||
assert_equal(n3[net]['proxy_randomize_credentials'], False)
|
||||
assert_equal(n3['onion']['reachable'], False)
|
||||
assert_equal(n3['i2p']['reachable'], False)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
Loading…
Add table
Reference in a new issue