mirror of
https://github.com/ElementsProject/elements.git
synced 2026-08-16 13:01:19 +02:00
Merge b103fdcb3b into merged_master (Bitcoin PR #19763)
This commit is contained in:
commit
e511e8717f
2 changed files with 48 additions and 13 deletions
|
|
@ -1410,7 +1410,23 @@ void RelayTransaction(const uint256& txid, const uint256& wtxid, const CConnman&
|
|||
});
|
||||
}
|
||||
|
||||
static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman& connman)
|
||||
/**
|
||||
* Relay (gossip) an address to a few randomly chosen nodes.
|
||||
* We choose the same nodes within a given 24h window (if the list of connected
|
||||
* nodes does not change) and we don't relay to nodes that already know an
|
||||
* address. So within 24h we will likely relay a given address once. This is to
|
||||
* prevent a peer from unjustly giving their address better propagation by sending
|
||||
* it to us repeatedly.
|
||||
* @param[in] originator The peer that sent us the address. We don't want to relay it back.
|
||||
* @param[in] addr Address to relay.
|
||||
* @param[in] fReachable Whether the address' network is reachable. We relay unreachable
|
||||
* addresses less.
|
||||
* @param[in] connman Connection manager to choose nodes to relay to.
|
||||
*/
|
||||
static void RelayAddress(const CNode& originator,
|
||||
const CAddress& addr,
|
||||
bool fReachable,
|
||||
const CConnman& connman)
|
||||
{
|
||||
if (!fReachable && !addr.IsRelayable()) return;
|
||||
|
||||
|
|
@ -1427,8 +1443,8 @@ static void RelayAddress(const CAddress& addr, bool fReachable, const CConnman&
|
|||
std::array<std::pair<uint64_t, CNode*>,2> best{{{0, nullptr}, {0, nullptr}}};
|
||||
assert(nRelayNodes <= best.size());
|
||||
|
||||
auto sortfunc = [&best, &hasher, nRelayNodes](CNode* pnode) {
|
||||
if (pnode->RelayAddrsWithConn()) {
|
||||
auto sortfunc = [&best, &hasher, nRelayNodes, &originator](CNode* pnode) {
|
||||
if (pnode->RelayAddrsWithConn() && pnode != &originator) {
|
||||
uint64_t hashKey = CSipHasher(hasher).Write(pnode->GetId()).Finalize();
|
||||
for (unsigned int i = 0; i < nRelayNodes; i++) {
|
||||
if (hashKey > best[i].first) {
|
||||
|
|
@ -2570,7 +2586,7 @@ void PeerManager::ProcessMessage(CNode& pfrom, const std::string& msg_type, CDat
|
|||
if (addr.nTime > nSince && !pfrom.fGetAddr && vAddr.size() <= 10 && addr.IsRoutable())
|
||||
{
|
||||
// Relay to a limited number of other nodes
|
||||
RelayAddress(addr, fReachable, m_connman);
|
||||
RelayAddress(pfrom, addr, fReachable, m_connman);
|
||||
}
|
||||
// Do not store addresses outside our network
|
||||
if (fReachable)
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@ from test_framework.util import (
|
|||
)
|
||||
import time
|
||||
|
||||
# Keep this with length <= 10. Addresses from larger messages are not relayed.
|
||||
ADDRS = []
|
||||
for i in range(10):
|
||||
num_ipv4_addrs = 10
|
||||
|
||||
for i in range(num_ipv4_addrs):
|
||||
addr = CAddress()
|
||||
addr.time = int(time.time()) + i
|
||||
addr.nServices = NODE_NETWORK | NODE_WITNESS
|
||||
|
|
@ -30,11 +33,15 @@ for i in range(10):
|
|||
|
||||
|
||||
class AddrReceiver(P2PInterface):
|
||||
num_ipv4_received = 0
|
||||
|
||||
def on_addr(self, message):
|
||||
for addr in message.addrs:
|
||||
assert_equal(addr.nServices, 9)
|
||||
if not 8333 <= addr.port < 8343:
|
||||
raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
|
||||
assert addr.ip.startswith('123.123.123.')
|
||||
assert (8333 <= addr.port < 8343)
|
||||
self.num_ipv4_received += 1
|
||||
|
||||
|
||||
class AddrTest(BitcoinTestFramework):
|
||||
|
|
@ -48,21 +55,33 @@ class AddrTest(BitcoinTestFramework):
|
|||
msg = msg_addr()
|
||||
|
||||
self.log.info('Send too-large addr message')
|
||||
msg.addrs = ADDRS * 101
|
||||
msg.addrs = ADDRS * 101 # more than 1000 addresses in one message
|
||||
with self.nodes[0].assert_debug_log(['addr message size = 1010']):
|
||||
addr_source.send_and_ping(msg)
|
||||
|
||||
self.log.info('Check that addr message content is relayed and added to addrman')
|
||||
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
|
||||
num_receivers = 7
|
||||
receivers = []
|
||||
for _ in range(num_receivers):
|
||||
receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver()))
|
||||
msg.addrs = ADDRS
|
||||
with self.nodes[0].assert_debug_log([
|
||||
'Added 10 addresses from 127.0.0.1: 0 tried',
|
||||
with self.nodes[0].assert_debug_log(
|
||||
[
|
||||
'Added {} addresses from 127.0.0.1: 0 tried'.format(num_ipv4_addrs),
|
||||
'received: addr (301 bytes) peer=0',
|
||||
'sending addr (301 bytes) peer=1',
|
||||
]):
|
||||
]
|
||||
):
|
||||
addr_source.send_and_ping(msg)
|
||||
self.nodes[0].setmocktime(int(time.time()) + 30 * 60)
|
||||
addr_receiver.sync_with_ping()
|
||||
for receiver in receivers:
|
||||
receiver.sync_with_ping()
|
||||
|
||||
total_ipv4_received = sum(r.num_ipv4_received for r in receivers)
|
||||
|
||||
# Every IPv4 address must be relayed to two peers, other than the
|
||||
# originating node (addr_source).
|
||||
ipv4_branching_factor = 2
|
||||
assert_equal(total_ipv4_received, num_ipv4_addrs * ipv4_branching_factor)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue