mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-21 14:34:49 +01:00
Merge bitcoin/bitcoin#22112: Force port 0 in I2P
4101ec9d2e
doc: mention that we enforce port=0 in I2P (Vasil Dimov)e0a2b390c1
addrman: reset I2P ports to 0 when loading from disk (Vasil Dimov)41cda9d075
test: ensure I2P ports are handled as expected (Vasil Dimov)4f432bd738
net: do not connect to I2P hosts on port!=0 (Vasil Dimov)1f096f091e
net: distinguish default port per network (Vasil Dimov)aeac3bce3e
net: change I2P seeds' ports to 0 (Vasil Dimov)38f900290c
net: change assumed I2P port to 0 (Vasil Dimov) Pull request description: _This is an alternative to https://github.com/bitcoin/bitcoin/pull/21514, inspired by https://github.com/bitcoin/bitcoin/pull/21514#issuecomment-815049933. They are mutually exclusive. Just one of them should be merged._ Change assumed ports for I2P to 0 (instead of the default 8333) as this is closer to what actually happens underneath with SAM 3.1 (https://github.com/bitcoin/bitcoin/pull/21514#issuecomment-812632520, https://github.com/bitcoin/bitcoin/pull/21514#issuecomment-816564719). Don't connect to I2P peers with advertised port != 0 (we don't specify a port to our SAM 3.1 proxy and it always connects to port = 0). Note, this change: * Keeps I2P addresses with port != 0 in addrman and relays them to others via P2P gossip. There may be non-bitcoin-core-22.0 peers using SAM 3.2 and for them such addresses may be useful. * Silently refuses to connect to I2P hosts with port != 0. This is ok for automatically chosen peers from addrman. Not so ok for peers provided via `-addnode` or `-connect` - a user who specifies `foo.b32.i2p:1234` (non zero port) may wonder why "nothing is happening". Fixes #21389 ACKs for top commit: laanwj: Code review ACK4101ec9d2e
jonatack: re-ACK4101ec9d2e
per `git range-diffefff9c3
0b0ee03 4101ec9`, built with DDEBUG_ADDRMAN, did fairly extensive testing on mainnet both with and without a peers.dat / -dnsseeds=0 to test boostrapping. Tree-SHA512: 0e3c019e1dc05e54f559275859d3450e0c735596d179e30b66811aad9d5b5fabe3dcc44571e8f7b99f9fe16453eee393d6e153454dd873b9ff14907d4e6354fe
This commit is contained in:
commit
d8f1e1327f
13 changed files with 329 additions and 22 deletions
|
@ -678,11 +678,11 @@ vi5bnbxkleeqi6hfccjochnn65lcxlfqs4uwgmhudph554zibiusqnad.onion:8333
|
|||
xqt25cobm5zqucac3634zfght72he6u3eagfyej5ellbhcdgos7t2had.onion:8333
|
||||
|
||||
# manually added 2021-05 for minimal i2p bootstrap support
|
||||
72l3ucjkuscrbiiepoehuwqgknyzgo7zuix5ty4puwrkyhtmnsga.b32.i2p:8333
|
||||
c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:8333
|
||||
gehtac45oaghz54ypyopim64mql7oad2bqclla74l6tfeolzmodq.b32.i2p:8333
|
||||
h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p:8333
|
||||
hnbbyjpxx54623l555sta7pocy3se4sdgmuebi5k6reesz5rjp6q.b32.i2p:8333
|
||||
pjs7or2ctvteeo5tu4bwyrtydeuhqhvdprtujn4daxr75jpebjxa.b32.i2p:8333
|
||||
wwbw7nqr3ahkqv62cuqfwgtneekvvpnuc4i4f6yo7tpoqjswvcwa.b32.i2p:8333
|
||||
zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p:8333
|
||||
72l3ucjkuscrbiiepoehuwqgknyzgo7zuix5ty4puwrkyhtmnsga.b32.i2p:0
|
||||
c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p:0
|
||||
gehtac45oaghz54ypyopim64mql7oad2bqclla74l6tfeolzmodq.b32.i2p:0
|
||||
h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p:0
|
||||
hnbbyjpxx54623l555sta7pocy3se4sdgmuebi5k6reesz5rjp6q.b32.i2p:0
|
||||
pjs7or2ctvteeo5tu4bwyrtydeuhqhvdprtujn4daxr75jpebjxa.b32.i2p:0
|
||||
wwbw7nqr3ahkqv62cuqfwgtneekvvpnuc4i4f6yo7tpoqjswvcwa.b32.i2p:0
|
||||
zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p:0
|
||||
|
|
15
doc/i2p.md
15
doc/i2p.md
|
@ -70,3 +70,18 @@ RPC.
|
|||
|
||||
Bitcoin Core uses the [SAM v3.1](https://geti2p.net/en/docs/api/samv3) protocol
|
||||
to connect to the I2P network. Any I2P router that supports it can be used.
|
||||
|
||||
## Ports in I2P and Bitcoin Core
|
||||
|
||||
Bitcoin Core uses the [SAM v3.1](https://geti2p.net/en/docs/api/samv3)
|
||||
protocol. One particularity of SAM v3.1 is that it does not support ports,
|
||||
unlike newer versions of SAM (v3.2 and up) that do support them and default the
|
||||
port numbers to 0. From the point of view of peers that use newer versions of
|
||||
SAM or other protocols that support ports, a SAM v3.1 peer is connecting to them
|
||||
on port 0, from source port 0.
|
||||
|
||||
To allow future upgrades to newer versions of SAM, Bitcoin Core sets its
|
||||
listening port to 0 when listening for incoming I2P connections and advertises
|
||||
its own I2P address with port 0. Furthermore, it will not attempt to connect to
|
||||
I2P addresses with a non-zero port number because with SAM v3.1 the destination
|
||||
port (`TO_PORT`) is always set to 0 and is not in the control of Bitcoin Core.
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <addrman.h>
|
||||
|
||||
#include <hash.h>
|
||||
#include <i2p.h>
|
||||
#include <logging.h>
|
||||
#include <netaddress.h>
|
||||
#include <serialize.h>
|
||||
|
@ -731,3 +732,100 @@ std::vector<bool> CAddrMan::DecodeAsmap(fs::path path)
|
|||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
void CAddrMan::ResetI2PPorts()
|
||||
{
|
||||
for (int bucket = 0; bucket < ADDRMAN_NEW_BUCKET_COUNT; ++bucket) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
|
||||
const auto id = vvNew[bucket][i];
|
||||
if (id == -1) {
|
||||
continue;
|
||||
}
|
||||
auto it = mapInfo.find(id);
|
||||
if (it == mapInfo.end()) {
|
||||
return;
|
||||
}
|
||||
auto& addr_info = it->second;
|
||||
if (!addr_info.IsI2P() || addr_info.GetPort() == I2P_SAM31_PORT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto addr_info_newport = addr_info;
|
||||
// The below changes addr_info_newport.GetKey(), which is used in finding a
|
||||
// bucket and a position within that bucket. So a re-bucketing may be necessary.
|
||||
addr_info_newport.port = I2P_SAM31_PORT;
|
||||
|
||||
// Reposition entries of vvNew within the same bucket because we don't know the source
|
||||
// address which led to the decision to store the entry in vvNew[bucket] so we can't
|
||||
// re-evaluate that decision, but even if we could, CAddrInfo::GetNewBucket() does not
|
||||
// use CAddrInfo::GetKey() so it would end up in the same bucket as before the port
|
||||
// change.
|
||||
const auto i_target = addr_info_newport.GetBucketPosition(nKey, true, bucket);
|
||||
|
||||
if (i_target == i) { // No need to re-position.
|
||||
addr_info = addr_info_newport;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reposition from i to i_target, removing the entry from i_target (if any).
|
||||
ClearNew(bucket, i_target);
|
||||
vvNew[bucket][i_target] = id;
|
||||
vvNew[bucket][i] = -1;
|
||||
addr_info = addr_info_newport;
|
||||
}
|
||||
}
|
||||
|
||||
for (int bucket = 0; bucket < ADDRMAN_TRIED_BUCKET_COUNT; ++bucket) {
|
||||
for (int i = 0; i < ADDRMAN_BUCKET_SIZE; ++i) {
|
||||
const auto id = vvTried[bucket][i];
|
||||
if (id == -1) {
|
||||
continue;
|
||||
}
|
||||
auto it = mapInfo.find(id);
|
||||
if (it == mapInfo.end()) {
|
||||
return;
|
||||
}
|
||||
auto& addr_info = it->second;
|
||||
if (!addr_info.IsI2P() || addr_info.GetPort() == I2P_SAM31_PORT) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto addr_info_newport = addr_info;
|
||||
// The below changes addr_info_newport.GetKey(), which is used in finding a
|
||||
// bucket and a position within that bucket. So a re-bucketing may be necessary.
|
||||
addr_info_newport.port = I2P_SAM31_PORT;
|
||||
|
||||
const auto bucket_target = addr_info_newport.GetTriedBucket(nKey, m_asmap);
|
||||
const auto i_target = addr_info_newport.GetBucketPosition(nKey, false, bucket_target);
|
||||
|
||||
if (bucket_target == bucket && i_target == i) { // No need to re-position.
|
||||
addr_info = addr_info_newport;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Reposition from (bucket, i) to (bucket_target, i_target). If the latter is
|
||||
// occupied, then move the entry from there to vvNew.
|
||||
|
||||
const auto old_target_id = vvTried[bucket_target][i_target];
|
||||
if (old_target_id != -1) {
|
||||
CAddrInfo& old_target_info = mapInfo[old_target_id];
|
||||
|
||||
old_target_info.fInTried = false;
|
||||
vvTried[bucket_target][i_target] = -1;
|
||||
--nTried;
|
||||
|
||||
const auto new_bucket = old_target_info.GetNewBucket(nKey, m_asmap);
|
||||
const auto new_bucket_i = old_target_info.GetBucketPosition(nKey, true, new_bucket);
|
||||
ClearNew(new_bucket, new_bucket_i);
|
||||
|
||||
old_target_info.nRefCount = 1;
|
||||
vvNew[new_bucket][new_bucket_i] = old_target_id;
|
||||
++nNew;
|
||||
}
|
||||
|
||||
vvTried[bucket_target][i_target] = id;
|
||||
vvTried[bucket][i] = -1;
|
||||
addr_info = addr_info_newport;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -452,6 +452,8 @@ public:
|
|||
|
||||
RemoveInvalid();
|
||||
|
||||
ResetI2PPorts();
|
||||
|
||||
Check();
|
||||
}
|
||||
|
||||
|
@ -767,6 +769,14 @@ private:
|
|||
//! Remove invalid addresses.
|
||||
void RemoveInvalid() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
/**
|
||||
* Reset the ports of I2P peers to 0.
|
||||
* This is needed as a temporary measure because now we enforce port 0 and
|
||||
* only connect to I2P hosts if the port is 0, but in the early days some
|
||||
* I2P addresses with port 8333 were rumoured and persisted into addrmans.
|
||||
*/
|
||||
void ResetI2PPorts() EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
||||
friend class CAddrManTest;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,11 +8,13 @@
|
|||
|
||||
#include <chainparamsbase.h>
|
||||
#include <consensus/params.h>
|
||||
#include <netaddress.h>
|
||||
#include <primitives/block.h>
|
||||
#include <protocol.h>
|
||||
#include <util/hash_type.h>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef std::map<int, uint256> MapCheckpoints;
|
||||
|
@ -80,6 +82,15 @@ public:
|
|||
const Consensus::Params& GetConsensus() const { return consensus; }
|
||||
const CMessageHeader::MessageStartChars& MessageStart() const { return pchMessageStart; }
|
||||
uint16_t GetDefaultPort() const { return nDefaultPort; }
|
||||
uint16_t GetDefaultPort(Network net) const
|
||||
{
|
||||
return net == NET_I2P ? I2P_SAM31_PORT : GetDefaultPort();
|
||||
}
|
||||
uint16_t GetDefaultPort(const std::string& addr) const
|
||||
{
|
||||
CNetAddr a;
|
||||
return a.SetSpecial(addr) ? GetDefaultPort(a.GetNetwork()) : GetDefaultPort();
|
||||
}
|
||||
|
||||
const CBlock& GenesisBlock() const { return genesis; }
|
||||
/** Default value for -checkmempool and -checkblockindex argument */
|
||||
|
|
|
@ -683,14 +683,14 @@ static const uint8_t chainparams_seed_main[] = {
|
|||
0x04,0x20,0x98,0xc6,0x44,0x27,0x90,0x41,0xa6,0x98,0xf9,0x25,0x6c,0x59,0x0f,0x06,0x6d,0x44,0x59,0x0e,0xb2,0x46,0xb0,0xa4,0x37,0x88,0x69,0x8f,0xc1,0x32,0xcd,0x9f,0x15,0xd7,0x20,0x8d,
|
||||
0x04,0x20,0xaa,0x3a,0x16,0x86,0xea,0x59,0x09,0x04,0x78,0xe5,0x10,0x92,0xe1,0x1d,0xad,0xf7,0x56,0x2b,0xac,0xb0,0x97,0x29,0x63,0x30,0xf4,0x1b,0xcf,0xde,0xf3,0x28,0x0a,0x29,0x20,0x8d,
|
||||
0x04,0x20,0xbc,0x27,0xae,0x89,0xc1,0x67,0x73,0x0a,0x08,0x02,0xdf,0xb7,0xcc,0x94,0xc7,0x9f,0xf4,0x72,0x7a,0x9b,0x20,0x0c,0x5c,0x11,0x3d,0x22,0xd6,0x13,0x88,0x66,0x74,0xbf,0x20,0x8d,
|
||||
0x05,0x20,0xfe,0x97,0xba,0x09,0x2a,0xa4,0x85,0x10,0xa1,0x04,0x7b,0x88,0x7a,0x5a,0x06,0x53,0x71,0x93,0x3b,0xf9,0xa2,0x2f,0xd9,0xe3,0x8f,0xa5,0xa2,0xac,0x1e,0x6c,0x6c,0x8c,0x20,0x8d,
|
||||
0x05,0x20,0x17,0x0c,0x56,0xce,0x72,0xa5,0xa0,0xe6,0x23,0x06,0xa3,0xc7,0x08,0x43,0x18,0xee,0x3a,0x46,0x35,0x5d,0x17,0xf6,0x78,0x96,0xa0,0x9c,0x51,0xef,0xbe,0x23,0xfd,0x71,0x20,0x8d,
|
||||
0x05,0x20,0x31,0x0f,0x30,0x0b,0x9d,0x70,0x0c,0x7c,0xf7,0x98,0x7e,0x1c,0xf4,0x33,0xdc,0x64,0x17,0xf7,0x00,0x7a,0x0c,0x04,0xb5,0x83,0xfc,0x5f,0xa6,0x52,0x39,0x79,0x63,0x87,0x20,0x8d,
|
||||
0x05,0x20,0x3e,0xe3,0xe0,0xa9,0xbc,0xf4,0x2e,0x59,0xd9,0x20,0xee,0xdf,0x74,0x61,0x4d,0x99,0x0c,0x5c,0x15,0x30,0x9b,0x72,0x16,0x79,0x15,0xf4,0x7a,0xca,0x34,0xcc,0x81,0x99,0x20,0x8d,
|
||||
0x05,0x20,0x3b,0x42,0x1c,0x25,0xf7,0xbf,0x79,0xed,0x6d,0x7d,0xef,0x65,0x30,0x7d,0xee,0x16,0x37,0x22,0x72,0x43,0x33,0x28,0x40,0xa3,0xaa,0xf4,0x48,0x49,0x67,0xb1,0x4b,0xfd,0x20,0x8d,
|
||||
0x05,0x20,0x7a,0x65,0xf7,0x47,0x42,0x9d,0x66,0x42,0x3b,0xb3,0xa7,0x03,0x6c,0x46,0x78,0x19,0x28,0x78,0x1e,0xa3,0x7c,0x67,0x44,0xb7,0x83,0x05,0xe3,0xfe,0xa5,0xe4,0x0a,0x6e,0x20,0x8d,
|
||||
0x05,0x20,0xb5,0x83,0x6f,0xb6,0x11,0xd8,0x0e,0xa8,0x57,0xda,0x15,0x20,0x5b,0x1a,0x6d,0x21,0x15,0x5a,0xbd,0xb4,0x17,0x11,0xc2,0xfb,0x0e,0xfc,0xde,0xe8,0x26,0x56,0xa8,0xac,0x20,0x8d,
|
||||
0x05,0x20,0xcc,0xaf,0x6c,0x3b,0xd0,0x13,0x76,0x23,0xc3,0x36,0xbb,0x64,0x4a,0x4a,0x06,0x93,0x69,0x6d,0xb0,0x10,0x6e,0x66,0xa4,0x61,0xf8,0x2d,0xe7,0x80,0x72,0x4d,0x53,0x94,0x20,0x8d,
|
||||
0x05,0x20,0xfe,0x97,0xba,0x09,0x2a,0xa4,0x85,0x10,0xa1,0x04,0x7b,0x88,0x7a,0x5a,0x06,0x53,0x71,0x93,0x3b,0xf9,0xa2,0x2f,0xd9,0xe3,0x8f,0xa5,0xa2,0xac,0x1e,0x6c,0x6c,0x8c,0x00,0x00,
|
||||
0x05,0x20,0x17,0x0c,0x56,0xce,0x72,0xa5,0xa0,0xe6,0x23,0x06,0xa3,0xc7,0x08,0x43,0x18,0xee,0x3a,0x46,0x35,0x5d,0x17,0xf6,0x78,0x96,0xa0,0x9c,0x51,0xef,0xbe,0x23,0xfd,0x71,0x00,0x00,
|
||||
0x05,0x20,0x31,0x0f,0x30,0x0b,0x9d,0x70,0x0c,0x7c,0xf7,0x98,0x7e,0x1c,0xf4,0x33,0xdc,0x64,0x17,0xf7,0x00,0x7a,0x0c,0x04,0xb5,0x83,0xfc,0x5f,0xa6,0x52,0x39,0x79,0x63,0x87,0x00,0x00,
|
||||
0x05,0x20,0x3e,0xe3,0xe0,0xa9,0xbc,0xf4,0x2e,0x59,0xd9,0x20,0xee,0xdf,0x74,0x61,0x4d,0x99,0x0c,0x5c,0x15,0x30,0x9b,0x72,0x16,0x79,0x15,0xf4,0x7a,0xca,0x34,0xcc,0x81,0x99,0x00,0x00,
|
||||
0x05,0x20,0x3b,0x42,0x1c,0x25,0xf7,0xbf,0x79,0xed,0x6d,0x7d,0xef,0x65,0x30,0x7d,0xee,0x16,0x37,0x22,0x72,0x43,0x33,0x28,0x40,0xa3,0xaa,0xf4,0x48,0x49,0x67,0xb1,0x4b,0xfd,0x00,0x00,
|
||||
0x05,0x20,0x7a,0x65,0xf7,0x47,0x42,0x9d,0x66,0x42,0x3b,0xb3,0xa7,0x03,0x6c,0x46,0x78,0x19,0x28,0x78,0x1e,0xa3,0x7c,0x67,0x44,0xb7,0x83,0x05,0xe3,0xfe,0xa5,0xe4,0x0a,0x6e,0x00,0x00,
|
||||
0x05,0x20,0xb5,0x83,0x6f,0xb6,0x11,0xd8,0x0e,0xa8,0x57,0xda,0x15,0x20,0x5b,0x1a,0x6d,0x21,0x15,0x5a,0xbd,0xb4,0x17,0x11,0xc2,0xfb,0x0e,0xfc,0xde,0xe8,0x26,0x56,0xa8,0xac,0x00,0x00,
|
||||
0x05,0x20,0xcc,0xaf,0x6c,0x3b,0xd0,0x13,0x76,0x23,0xc3,0x36,0xbb,0x64,0x4a,0x4a,0x06,0x93,0x69,0x6d,0xb0,0x10,0x6e,0x66,0xa4,0x61,0xf8,0x2d,0xe7,0x80,0x72,0x4d,0x53,0x94,0x00,0x00,
|
||||
};
|
||||
|
||||
static const uint8_t chainparams_seed_test[] = {
|
||||
|
|
11
src/i2p.cpp
11
src/i2p.cpp
|
@ -159,7 +159,7 @@ bool Session::Accept(Connection& conn)
|
|||
const std::string& peer_dest =
|
||||
conn.sock->RecvUntilTerminator('\n', MAX_WAIT_FOR_IO, *m_interrupt, MAX_MSG_SIZE);
|
||||
|
||||
conn.peer = CService(DestB64ToAddr(peer_dest), Params().GetDefaultPort());
|
||||
conn.peer = CService(DestB64ToAddr(peer_dest), I2P_SAM31_PORT);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -172,6 +172,13 @@ bool Session::Accept(Connection& conn)
|
|||
|
||||
bool Session::Connect(const CService& to, Connection& conn, bool& proxy_error)
|
||||
{
|
||||
// Refuse connecting to arbitrary ports. We don't specify any destination port to the SAM proxy
|
||||
// when connecting (SAM 3.1 does not use ports) and it forces/defaults it to I2P_SAM31_PORT.
|
||||
if (to.GetPort() != I2P_SAM31_PORT) {
|
||||
proxy_error = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
proxy_error = true;
|
||||
|
||||
std::string session_id;
|
||||
|
@ -366,7 +373,7 @@ void Session::CreateIfNotCreatedAlready()
|
|||
SendRequestAndGetReply(*sock, strprintf("SESSION CREATE STYLE=STREAM ID=%s DESTINATION=%s",
|
||||
session_id, private_key_b64));
|
||||
|
||||
m_my_addr = CService(DestBinToAddr(MyDestination()), Params().GetDefaultPort());
|
||||
m_my_addr = CService(DestBinToAddr(MyDestination()), I2P_SAM31_PORT);
|
||||
m_session_id = session_id;
|
||||
m_control_sock = std::move(sock);
|
||||
|
||||
|
|
|
@ -442,7 +442,7 @@ void SetupServerArgs(ArgsManager& argsman)
|
|||
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);
|
||||
argsman.AddArg("-permitbaremultisig", strprintf("Relay non-P2SH multisig (default: %u)", DEFAULT_PERMIT_BAREMULTISIG), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, signet: %u, regtest: %u) are unlikely to get incoming connections.", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-port=<port>", strprintf("Listen for connections on <port>. Nodes not using the default ports (default: %u, testnet: %u, signet: %u, regtest: %u) are unlikely to get incoming connections. Not relevant for I2P (see doc/i2p.md).", defaultChainParams->GetDefaultPort(), testnetChainParams->GetDefaultPort(), signetChainParams->GetDefaultPort(), regtestChainParams->GetDefaultPort()), ArgsManager::ALLOW_ANY | ArgsManager::NETWORK_ONLY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-proxy=<ip:port>", "Connect through SOCKS5 proxy, set -noproxy to disable (default: disabled)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-proxyrandomize", strprintf("Randomize credentials for every proxy connection. This enables Tor stream isolation (default: %u)", DEFAULT_PROXYRANDOMIZE), ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
argsman.AddArg("-seednode=<ip>", "Connect to a node to retrieve peer addresses, and disconnect. This option can be specified multiple times to connect to multiple nodes.", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION);
|
||||
|
|
|
@ -402,7 +402,8 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
|
|||
pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
|
||||
|
||||
// Resolve
|
||||
const uint16_t default_port{Params().GetDefaultPort()};
|
||||
const uint16_t default_port{pszDest != nullptr ? Params().GetDefaultPort(pszDest) :
|
||||
Params().GetDefaultPort()};
|
||||
if (pszDest) {
|
||||
std::vector<CService> resolved;
|
||||
if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
|
||||
|
@ -2059,8 +2060,9 @@ void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
|
|||
// from advertising themselves as a service on another host and
|
||||
// port, causing a DoS attack as nodes around the network attempt
|
||||
// to connect to it fruitlessly.
|
||||
if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
|
||||
if (addr.GetPort() != Params().GetDefaultPort(addr.GetNetwork()) && nTries < 50) {
|
||||
continue;
|
||||
}
|
||||
|
||||
addrConnect = addr;
|
||||
break;
|
||||
|
@ -2123,7 +2125,7 @@ std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo() const
|
|||
}
|
||||
|
||||
for (const std::string& strAddNode : lAddresses) {
|
||||
CService service(LookupNumeric(strAddNode, Params().GetDefaultPort()));
|
||||
CService service(LookupNumeric(strAddNode, Params().GetDefaultPort(strAddNode)));
|
||||
AddedNodeInfo addedNode{strAddNode, CService(), false, false};
|
||||
if (service.IsValid()) {
|
||||
// strAddNode is an IP:port
|
||||
|
|
|
@ -112,6 +112,9 @@ static constexpr size_t ADDR_CJDNS_SIZE = 16;
|
|||
/// Size of "internal" (NET_INTERNAL) address (in bytes).
|
||||
static constexpr size_t ADDR_INTERNAL_SIZE = 10;
|
||||
|
||||
/// SAM 3.1 and earlier do not support specifying ports and force the port to 0.
|
||||
static constexpr uint16_t I2P_SAM31_PORT{0};
|
||||
|
||||
/**
|
||||
* Network address.
|
||||
*/
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#include <addrman.h>
|
||||
#include <i2p.h>
|
||||
#include <test/data/asmap.raw.h>
|
||||
#include <test/util/setup_common.h>
|
||||
#include <util/asmap.h>
|
||||
|
@ -966,5 +967,121 @@ BOOST_AUTO_TEST_CASE(addrman_evictionworks)
|
|||
BOOST_CHECK(addrman.SelectTriedCollision().ToString() == "[::]:0");
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(reset_i2p_ports)
|
||||
{
|
||||
CAddrManTest addrman1;
|
||||
CAddrManTest addrman2;
|
||||
const uint32_t good_time{static_cast<uint32_t>(GetAdjustedTime())};
|
||||
constexpr uint16_t port = 8333;
|
||||
|
||||
// Has its port changed, will be re-positioned within the same bucket in vvNew.
|
||||
const CAddress i2p_new1{
|
||||
ResolveService("72l3ucjkuscrbiiepoehuwqgknyzgo7zuix5ty4puwrkyhtmnsga.b32.i2p", port),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Has its port changed, will not be re-positioned in vvNew because ports 0 and 10075 result in
|
||||
// the same bucket position.
|
||||
const CAddress i2p_new2{
|
||||
ResolveService("gehtac45oaghz54ypyopim64mql7oad2bqclla74l6tfeolzmodq.b32.i2p", 10075),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Remains unchanged, port is already as it should be.
|
||||
const CAddress i2p_new3{
|
||||
ResolveService("c4gfnttsuwqomiygupdqqqyy5y5emnk5c73hrfvatri67prd7vyq.b32.i2p",
|
||||
I2P_SAM31_PORT),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Has its port changed, re-positioning in vvNew will cause i2p_new3 to be evicted.
|
||||
const CAddress i2p_new4{
|
||||
ResolveService("c4cbbkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p", port),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Remains unchanged.
|
||||
const CAddress ipv4_new{ResolveService("1.2.3.4", port), NODE_NONE, good_time};
|
||||
|
||||
// Has its port changed, will be re-positioned in vvTried.
|
||||
const CAddress i2p_tried1{
|
||||
ResolveService("h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p", port),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Has its port changed, will not be re-positioned in vvTried because ports 0 and 10537
|
||||
// result in the same position (bucket, i).
|
||||
const CAddress i2p_tried2{
|
||||
ResolveService("pjs7or2ctvteeo5tu4bwyrtydeuhqhvdprtujn4daxr75jpebjxa.b32.i2p", 10537),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Remains unchanged, port is already as it should be.
|
||||
const CAddress i2p_tried3{
|
||||
ResolveService("hnbbyjpxx54623l555sta7pocy3se4sdgmuebi5k6reesz5rjp6q.b32.i2p",
|
||||
I2P_SAM31_PORT),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Has its port changed, re-positioning in vvTried will cause i2p_tried3 to be moved to vvNew.
|
||||
const CAddress i2p_tried4{
|
||||
ResolveService("hna37nqr3ahkqv62cuqfwgtneekvvpnuc4i4f6yo7tpoqjswvcwa.b32.i2p", port),
|
||||
NODE_NONE,
|
||||
good_time};
|
||||
|
||||
// Remains unchanged.
|
||||
const CAddress ipv4_tried{ResolveService("2.3.4.5", port), NODE_NONE, good_time};
|
||||
|
||||
const CNetAddr source;
|
||||
|
||||
CDataStream stream(SER_NETWORK, PROTOCOL_VERSION);
|
||||
|
||||
addrman1.Add(i2p_new1, source);
|
||||
addrman1.Add(i2p_new2, source);
|
||||
addrman1.Add(i2p_new3, source);
|
||||
addrman1.Add(i2p_new4, source);
|
||||
addrman1.Add(ipv4_new, source);
|
||||
|
||||
addrman1.Add(i2p_tried1, source);
|
||||
addrman1.Good(i2p_tried1);
|
||||
addrman1.Add(i2p_tried2, source);
|
||||
addrman1.Good(i2p_tried2);
|
||||
addrman1.Add(i2p_tried3, source);
|
||||
addrman1.Good(i2p_tried3);
|
||||
addrman1.Add(i2p_tried4, source);
|
||||
addrman1.Good(i2p_tried4);
|
||||
addrman1.Add(ipv4_tried, source);
|
||||
addrman1.Good(ipv4_tried);
|
||||
|
||||
stream << addrman1;
|
||||
stream >> addrman2;
|
||||
|
||||
const size_t max_addresses{0};
|
||||
const size_t max_pct{0};
|
||||
|
||||
auto addresses = addrman2.GetAddr(max_addresses, max_pct, NET_I2P);
|
||||
BOOST_REQUIRE_EQUAL(addresses.size(), 7UL);
|
||||
std::sort(addresses.begin(), addresses.end()); // Just some deterministic order.
|
||||
BOOST_CHECK_EQUAL(addresses[0].ToStringIP(), i2p_new4.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[0].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[1].ToStringIP(), i2p_new2.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[1].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[2].ToStringIP(), i2p_tried4.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[2].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[3].ToStringIP(), i2p_tried3.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[3].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[4].ToStringIP(), i2p_tried1.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[4].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[5].ToStringIP(), i2p_tried2.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[5].GetPort(), I2P_SAM31_PORT);
|
||||
BOOST_CHECK_EQUAL(addresses[6].ToStringIP(), i2p_new1.ToStringIP());
|
||||
BOOST_CHECK_EQUAL(addresses[6].GetPort(), I2P_SAM31_PORT);
|
||||
|
||||
addresses = addrman2.GetAddr(max_addresses, max_pct, NET_IPV4);
|
||||
BOOST_REQUIRE_EQUAL(addresses.size(), 2UL);
|
||||
std::sort(addresses.begin(), addresses.end()); // Just some deterministic order.
|
||||
BOOST_CHECK_EQUAL(addresses[0].ToStringIPPort(), ipv4_new.ToStringIPPort());
|
||||
BOOST_CHECK_EQUAL(addresses[1].ToStringIPPort(), ipv4_tried.ToStringIPPort());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
|
43
test/functional/p2p_i2p_ports.py
Executable file
43
test/functional/p2p_i2p_ports.py
Executable file
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2021-2021 The Bitcoin Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
"""
|
||||
Test ports handling for I2P hosts
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from test_framework.test_framework import BitcoinTestFramework
|
||||
|
||||
|
||||
class I2PPorts(BitcoinTestFramework):
|
||||
def set_test_params(self):
|
||||
self.num_nodes = 1
|
||||
# The test assumes that an I2P SAM proxy is not listening here.
|
||||
self.extra_args = [["-i2psam=127.0.0.1:60000"]]
|
||||
|
||||
def run_test(self):
|
||||
node = self.nodes[0]
|
||||
|
||||
self.log.info("Ensure we don't try to connect if port!=0")
|
||||
addr = "zsxwyo6qcn3chqzwxnseusqgsnuw3maqnztkiypyfxtya4snkoka.b32.i2p:8333"
|
||||
raised = False
|
||||
try:
|
||||
with node.assert_debug_log(expected_msgs=[f"Error connecting to {addr}"]):
|
||||
node.addnode(node=addr, command="onetry")
|
||||
except AssertionError as e:
|
||||
raised = True
|
||||
if not re.search(r"Expected messages .* does not partially match log", str(e)):
|
||||
raise AssertionError(f"Assertion raised as expected, but with an unexpected message: {str(e)}")
|
||||
if not raised:
|
||||
raise AssertionError("Assertion should have been raised")
|
||||
|
||||
self.log.info("Ensure we try to connect if port=0 and get an error due to missing I2P proxy")
|
||||
addr = "h3r6bkn46qxftwja53pxiykntegfyfjqtnzbm6iv6r5mungmqgmq.b32.i2p:0"
|
||||
with node.assert_debug_log(expected_msgs=[f"Error connecting to {addr}"]):
|
||||
node.addnode(node=addr, command="onetry")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
I2PPorts().main()
|
|
@ -293,6 +293,7 @@ BASE_SCRIPTS = [
|
|||
'p2p_permissions.py',
|
||||
'feature_blocksdir.py',
|
||||
'wallet_startup.py',
|
||||
'p2p_i2p_ports.py',
|
||||
'feature_config_args.py',
|
||||
'feature_settings.py',
|
||||
'rpc_getdescriptorinfo.py',
|
||||
|
|
Loading…
Add table
Reference in a new issue