Skip to content

Commit d5a2123

Browse files
authored
Merge pull request #110 from input-output-hk/ETCM-443-fix-discovery-key-not-found
ETCM-443: Fix the KTable and the kademlia ID mapping getting out of sync
2 parents dc8142a + b00832b commit d5a2123

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed

scalanet/discovery/src/io/iohk/scalanet/discovery/ethereum/v4/DiscoveryService.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,13 @@ object DiscoveryService {
188188
)
189189
}
190190

191+
/** Update the timestamp of the peer in the K-table, if it's still part of it. */
191192
def withTouch(peer: Peer[A]): State[A] =
192-
copy(kBuckets = kBuckets.touch(peer.kademliaId))
193+
if (kBuckets.contains(peer.kademliaId))
194+
copy(kBuckets = kBuckets.touch(peer.kademliaId))
195+
else
196+
// Not adding because `kademliaIdToNodeId` and `nodeMap` may no longer have this peer.
197+
this
193198

194199
def clearBondingResults(peer: Peer[A]): State[A] =
195200
copy(bondingResultsMap = bondingResultsMap - peer)

scalanet/discovery/ut/src/io/iohk/scalanet/discovery/ethereum/v4/DiscoveryServiceSpec.scala

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,30 @@ class DiscoveryServiceSpec extends AsyncFlatSpec with Matchers {
10031003
}
10041004
}
10051005
}
1006+
1007+
behavior of "withTouch"
1008+
1009+
it should "not touch a peer not already in the k-table" in test {
1010+
new Fixture {
1011+
override val test = for {
1012+
state0 <- stateRef.get
1013+
state1 = state0.withTouch(remotePeer)
1014+
state2 = state1.withEnrAndAddress(remotePeer, remoteENR, remoteNode.address)
1015+
_ <- Task.sleep(1.milli) // If we're too quick then TimeSet will assign the same timestamp.
1016+
state3 = state2.withTouch(remotePeer)
1017+
} yield {
1018+
val peerId = remotePeer.kademliaId
1019+
1020+
state0.kBuckets.contains(peerId) shouldBe false
1021+
state1.kBuckets.contains(peerId) shouldBe false
1022+
state2.kBuckets.contains(peerId) shouldBe true
1023+
1024+
val (_, bucket2) = state2.kBuckets.getBucket(peerId)
1025+
val (_, bucket3) = state3.kBuckets.getBucket(peerId)
1026+
bucket2.timestamps should not equal bucket3.timestamps
1027+
}
1028+
}
1029+
}
10061030
}
10071031

10081032
object DiscoveryServiceSpec {

scalanet/discovery/ut/src/io/iohk/scalanet/kademlia/KBucketsSpec.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ class KBucketsSpec extends FlatSpec {
3636
kb.add(v).contains(v) shouldBe true
3737
}
3838

39+
they should "retrieve any node added via touch" in forAll(genBitVector()) { v =>
40+
kb.touch(v).contains(v) shouldBe true
41+
}
42+
3943
they should "not retrieve any node removed via remove" in forAll(genBitVector()) { v =>
4044
kb.add(v).remove(v).contains(v) shouldBe false
4145
}

0 commit comments

Comments
 (0)