mirror of
https://github.com/status-im/nimbus-eth2.git
synced 2025-02-20 02:08:12 +00:00
The peer cycling takes into accounts the syncnets ENR fields
This commit is contained in:
parent
855d0257ff
commit
02372849f1
@ -899,9 +899,11 @@ proc toPeerAddr(node: Node): Result[PeerAddr, cstring] =
|
|||||||
let peerAddr = ? nodeRecord.toPeerAddr(tcpProtocol)
|
let peerAddr = ? nodeRecord.toPeerAddr(tcpProtocol)
|
||||||
ok(peerAddr)
|
ok(peerAddr)
|
||||||
|
|
||||||
proc queryRandom*(d: Eth2DiscoveryProtocol, forkId: ENRForkID,
|
proc queryRandom*(
|
||||||
attnets: BitArray[ATTESTATION_SUBNET_COUNT]):
|
d: Eth2DiscoveryProtocol,
|
||||||
Future[seq[Node]] {.async.} =
|
forkId: ENRForkID,
|
||||||
|
wantedAttnets: BitArray[ATTESTATION_SUBNET_COUNT],
|
||||||
|
wantedSyncnets: BitArray[SYNC_COMMITTEE_SUBNET_COUNT]): Future[seq[Node]] {.async.} =
|
||||||
## Perform a discovery query for a random target
|
## Perform a discovery query for a random target
|
||||||
## (forkId) and matching at least one of the attestation subnets.
|
## (forkId) and matching at least one of the attestation subnets.
|
||||||
|
|
||||||
@ -910,24 +912,38 @@ proc queryRandom*(d: Eth2DiscoveryProtocol, forkId: ENRForkID,
|
|||||||
|
|
||||||
var filtered: seq[(int, Node)]
|
var filtered: seq[(int, Node)]
|
||||||
for n in nodes:
|
for n in nodes:
|
||||||
let res = n.record.tryGet(enrAttestationSubnetsField, seq[byte])
|
var score: int = 0
|
||||||
|
|
||||||
if res.isSome():
|
let attnetsBytes = n.record.tryGet(enrAttestationSubnetsField, seq[byte])
|
||||||
|
if attnetsBytes.isSome():
|
||||||
let attnetsNode =
|
let attnetsNode =
|
||||||
try:
|
try:
|
||||||
SSZ.decode(res.get(), BitArray[ATTESTATION_SUBNET_COUNT])
|
SSZ.decode(attnetsBytes.get(), BitArray[ATTESTATION_SUBNET_COUNT])
|
||||||
except SszError as e:
|
except SszError as e:
|
||||||
debug "Could not decode attestation subnet bitfield of peer",
|
debug "Could not decode the attnets ERN bitfield of peer",
|
||||||
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
||||||
continue
|
continue
|
||||||
|
|
||||||
var score: int = 0
|
|
||||||
for i in 0..<ATTESTATION_SUBNET_COUNT:
|
for i in 0..<ATTESTATION_SUBNET_COUNT:
|
||||||
if attnets[i] and attnetsNode[i]:
|
if wantedAttnets[i] and attnetsNode[i]:
|
||||||
inc score
|
score += 1
|
||||||
|
|
||||||
if score > 0:
|
let syncnetsBytes = n.record.tryGet(enrSyncSubnetsField, seq[byte])
|
||||||
filtered.add((score, n))
|
if syncnetsBytes.isSome():
|
||||||
|
let syncnetsNode =
|
||||||
|
try:
|
||||||
|
SSZ.decode(syncnetsBytes.get(), BitArray[SYNC_COMMITTEE_SUBNET_COUNT])
|
||||||
|
except SszError as e:
|
||||||
|
debug "Could not decode the syncnets ENR bitfield of peer",
|
||||||
|
peer = n.record.toURI(), exception = e.name, msg = e.msg
|
||||||
|
continue
|
||||||
|
|
||||||
|
for i in 0..<SYNC_COMMITTEE_SUBNET_COUNT:
|
||||||
|
if wantedSyncnets[i] and syncnetsNode[i]:
|
||||||
|
score += 10 # connecting to the right syncnet is urgent
|
||||||
|
|
||||||
|
if score > 0:
|
||||||
|
filtered.add((score, n))
|
||||||
|
|
||||||
d.rng[].shuffle(filtered)
|
d.rng[].shuffle(filtered)
|
||||||
return filtered.sortedByIt(it[0]).mapIt(it[1])
|
return filtered.sortedByIt(it[0]).mapIt(it[1])
|
||||||
@ -990,54 +1006,64 @@ proc trimConnections(node: Eth2Node, count: int) {.async.} =
|
|||||||
dec toKick
|
dec toKick
|
||||||
if toKick <= 0: return
|
if toKick <= 0: return
|
||||||
|
|
||||||
proc getLowAttnets(node: Eth2Node): BitArray[ATTESTATION_SUBNET_COUNT] =
|
proc getLowSubnets(node: Eth2Node):
|
||||||
|
(BitArray[ATTESTATION_SUBNET_COUNT],
|
||||||
|
BitArray[SYNC_COMMITTEE_SUBNET_COUNT]) =
|
||||||
# Returns the subnets required to have a healthy mesh
|
# Returns the subnets required to have a healthy mesh
|
||||||
# The subnets are computed, to, in order:
|
# The subnets are computed, to, in order:
|
||||||
# - Have 0 subscribed subnet below `dLow`
|
# - Have 0 subscribed subnet below `dLow`
|
||||||
# - Have 0 subnet with < `d` peers from topic subscription
|
# - Have 0 subnet with < `d` peers from topic subscription
|
||||||
# - Have 0 subscribed subnet below `dOut` outgoing peers
|
# - Have 0 subscribed subnet below `dOut` outgoing peers
|
||||||
|
|
||||||
var
|
template findLowSubnets(topicNameGenerator: untyped,
|
||||||
lowOutgoingSubnets: BitArray[ATTESTATION_SUBNET_COUNT]
|
SubnetIdType: type,
|
||||||
belowDLowSubnets: BitArray[ATTESTATION_SUBNET_COUNT]
|
totalSubnets: static int): auto =
|
||||||
belowDOutSubnets: BitArray[ATTESTATION_SUBNET_COUNT]
|
var
|
||||||
|
lowOutgoingSubnets: BitArray[totalSubnets]
|
||||||
|
belowDLowSubnets: BitArray[totalSubnets]
|
||||||
|
belowDOutSubnets: BitArray[totalSubnets]
|
||||||
|
|
||||||
for subNetId in 0..<ATTESTATION_SUBNET_COUNT:
|
for subNetId in 0 ..< totalSubnets:
|
||||||
let topic =
|
let topic =
|
||||||
getAttestationTopic(node.forkId.forkDigest, SubnetId(subNetId)) & "_snappy"
|
topicNameGenerator(node.forkId.forkDigest, SubnetIdType(subNetId)) & "_snappy"
|
||||||
|
|
||||||
if node.pubsub.gossipsub.peers(topic) < node.pubsub.parameters.d:
|
if node.pubsub.gossipsub.peers(topic) < node.pubsub.parameters.d:
|
||||||
lowOutgoingSubnets.setBit(subNetId)
|
lowOutgoingSubnets.setBit(subNetId)
|
||||||
|
|
||||||
# Not subscribed
|
# Not subscribed
|
||||||
if topic notin node.pubsub.mesh: continue
|
if topic notin node.pubsub.mesh: continue
|
||||||
|
|
||||||
if node.pubsub.mesh.peers(topic) < node.pubsub.parameters.dLow:
|
if node.pubsub.mesh.peers(topic) < node.pubsub.parameters.dLow:
|
||||||
belowDlowSubnets.setBit(subNetId)
|
belowDlowSubnets.setBit(subNetId)
|
||||||
|
|
||||||
let outPeers = node.pubsub.mesh.getOrDefault(topic).toSeq().filterIt(it.outbound)
|
let outPeers = node.pubsub.mesh.getOrDefault(topic).toSeq().filterIt(it.outbound)
|
||||||
if outPeers.len() < node.pubsub.parameters.dOut:
|
if outPeers.len() < node.pubsub.parameters.dOut:
|
||||||
belowDOutSubnets.setBit(subNetId)
|
belowDOutSubnets.setBit(subNetId)
|
||||||
|
|
||||||
if belowDLowSubnets.countOnes() > 0:
|
if belowDLowSubnets.countOnes() > 0:
|
||||||
return belowDLowSubnets
|
belowDLowSubnets
|
||||||
|
elif lowOutgoingSubnets.countOnes() > 0:
|
||||||
if lowOutgoingSubnets.countOnes() > 0:
|
lowOutgoingSubnets
|
||||||
return lowOutgoingSubnets
|
else:
|
||||||
|
belowDOutSubnets
|
||||||
return belowDOutSubnets
|
|
||||||
|
|
||||||
|
return (
|
||||||
|
findLowSubnets(getAttestationTopic, SubnetId, ATTESTATION_SUBNET_COUNT),
|
||||||
|
findLowSubnets(getSyncCommitteeTopic, SyncCommitteeIndex, SYNC_COMMITTEE_SUBNET_COUNT)
|
||||||
|
)
|
||||||
|
|
||||||
proc runDiscoveryLoop*(node: Eth2Node) {.async.} =
|
proc runDiscoveryLoop*(node: Eth2Node) {.async.} =
|
||||||
debug "Starting discovery loop"
|
debug "Starting discovery loop"
|
||||||
|
|
||||||
while true:
|
while true:
|
||||||
let
|
let
|
||||||
wantedAttnets = node.getLowAttnets()
|
(wantedAttnets, wantedSyncnets) = node.getLowSubnets()
|
||||||
wantedAttnetsCount = wantedAttnets.countOnes()
|
wantedAttnetsCount = wantedAttnets.countOnes()
|
||||||
|
wantedSyncnetsCount = wantedSyncnets.countOnes()
|
||||||
|
|
||||||
if wantedAttnetsCount > 0:
|
if wantedAttnetsCount > 0 or wantedSyncnetsCount > 0:
|
||||||
let discoveredNodes = await node.discovery.queryRandom(node.forkId, wantedAttnets)
|
let discoveredNodes = await node.discovery.queryRandom(
|
||||||
|
node.forkId, wantedAttnets, wantedSyncnets)
|
||||||
|
|
||||||
var newPeers = 0
|
var newPeers = 0
|
||||||
for discNode in discoveredNodes:
|
for discNode in discoveredNodes:
|
||||||
|
@ -30,6 +30,9 @@ proc generateNode(rng: ref BrHmacDrbgContext, port: Port,
|
|||||||
Eth2DiscoveryProtocol.new(keys.PrivateKey.random(rng[]),
|
Eth2DiscoveryProtocol.new(keys.PrivateKey.random(rng[]),
|
||||||
some(ip), some(port), some(port), port, ip, enrFields, rng = rng)
|
some(ip), some(port), some(port), port, ip, enrFields, rng = rng)
|
||||||
|
|
||||||
|
# TODO: Add tests with a syncnets preference
|
||||||
|
const noSyncnetsPreference = BitArray[SYNC_COMMITTEE_SUBNET_COUNT]()
|
||||||
|
|
||||||
suite "Eth2 specific discovery tests":
|
suite "Eth2 specific discovery tests":
|
||||||
let
|
let
|
||||||
rng = keys.newRng()
|
rng = keys.newRng()
|
||||||
@ -59,7 +62,8 @@ suite "Eth2 specific discovery tests":
|
|||||||
attnetsSelected.setBit(42)
|
attnetsSelected.setBit(42)
|
||||||
attnetsSelected.setBit(34)
|
attnetsSelected.setBit(34)
|
||||||
|
|
||||||
let discovered = await node1.queryRandom(enrForkId, attnetsSelected)
|
let discovered = await node1.queryRandom(
|
||||||
|
enrForkId, attnetsSelected, noSyncnetsPreference)
|
||||||
check discovered.len == 1
|
check discovered.len == 1
|
||||||
|
|
||||||
await node1.closeWait()
|
await node1.closeWait()
|
||||||
@ -96,7 +100,8 @@ suite "Eth2 specific discovery tests":
|
|||||||
attnetsSelected.setBit(15)
|
attnetsSelected.setBit(15)
|
||||||
attnetsSelected.setBit(42)
|
attnetsSelected.setBit(42)
|
||||||
|
|
||||||
let discovered = await node1.queryRandom(enrForkId, attnetsSelected)
|
let discovered = await node1.queryRandom(
|
||||||
|
enrForkId, attnetsSelected, noSyncnetsPreference)
|
||||||
check discovered.len == 1
|
check discovered.len == 1
|
||||||
|
|
||||||
await node1.closeWait()
|
await node1.closeWait()
|
||||||
@ -123,7 +128,8 @@ suite "Eth2 specific discovery tests":
|
|||||||
attnetsSelected.setBit(2)
|
attnetsSelected.setBit(2)
|
||||||
|
|
||||||
block:
|
block:
|
||||||
let discovered = await node1.queryRandom(enrForkId, attnetsSelected)
|
let discovered = await node1.queryRandom(
|
||||||
|
enrForkId, attnetsSelected, noSyncnetsPreference)
|
||||||
check discovered.len == 0
|
check discovered.len == 0
|
||||||
|
|
||||||
block:
|
block:
|
||||||
@ -137,7 +143,8 @@ suite "Eth2 specific discovery tests":
|
|||||||
check nodes.isOk() and nodes[].len > 0
|
check nodes.isOk() and nodes[].len > 0
|
||||||
discard node1.addNode(nodes[][0])
|
discard node1.addNode(nodes[][0])
|
||||||
|
|
||||||
let discovered = await node1.queryRandom(enrForkId, attnetsSelected)
|
let discovered = await node1.queryRandom(
|
||||||
|
enrForkId, attnetsSelected, noSyncnetsPreference)
|
||||||
check discovered.len == 1
|
check discovered.len == 1
|
||||||
|
|
||||||
await node1.closeWait()
|
await node1.closeWait()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user