node: Add PeerStackTest, fix bug where we could have the same ip address multiple times in PeerStack (#5848)

* node: Add PeerStackTest, fix bug where we could have the same ip address multiple times in PeerStack

* make implicit Ordering private in PeerStack

* Rename PeerOrdering.peer -> PeerOrdering.peerData
This commit is contained in:
Chris Stewart 2025-01-15 11:16:58 -06:00 committed by GitHub
parent 3925098872
commit a94fc3a92d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 65 additions and 6 deletions

View file

@ -0,0 +1,56 @@
package org.bitcoins.node
import org.apache.pekko.stream.OverflowStrategy
import org.apache.pekko.stream.scaladsl.{Source, SourceQueue}
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.core.api.node.Peer
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.networking.peer.{PeerConnection, PeerMessageSender}
import org.bitcoins.testkit.util.BitcoinSAsyncTest
import java.net.InetSocketAddress
import java.nio.file.Files
class PeerStackTest extends BitcoinSAsyncTest {
behavior of "PeerStack"
val tempDir = Files.createTempDirectory("bitcoin-s")
private implicit val nodeAppConfig: NodeAppConfig =
NodeAppConfig(baseDatadir = tempDir, Vector.empty)
private implicit val chainAppConfig: ChainAppConfig = {
ChainAppConfig(tempDir, Vector.empty)
}
it must "not push the same ip address twice" in {
val stack = PeerStack()
val queue: SourceQueue[NodeStreamMessage] = Source
.queue[NodeStreamMessage](1, OverflowStrategy.backpressure)
.preMaterialize()
._1
val peer0 =
Peer(InetSocketAddress.createUnresolved("127.0.0.1", 8333), None, None)
val peerMessageSender0 = PeerMessageSender(PeerConnection(peer0, queue))
val pd0: PeerData =
PersistentPeerData(peer = peer0, peerMessageSender = peerMessageSender0)
stack.pushAll(Vector(pd0, pd0))
assert(stack.size == 1)
val peer1 =
Peer(InetSocketAddress.createUnresolved("128.0.0.1", 8333), None, None)
val peerMessageSender1 = PeerMessageSender(PeerConnection(peer1, queue))
val pd1: PeerData =
PersistentPeerData(peer = peer1, peerMessageSender = peerMessageSender1)
stack.pushAll(Vector(pd1, pd1))
assert(stack.size == 2)
val popPd1 = stack.pop()
assert(popPd1 == pd1)
val popPd0 = stack.pop()
assert(popPd0 == pd0)
assert(stack.size == 0)
}
}

View file

@ -421,11 +421,11 @@ case class PeerFinder(
}
}
case class PeerOrdering(peer: PeerData, priority: Int, id: Int)
case class PeerOrdering(peerData: PeerData, priority: Int, id: Int)
case class PeerStack() {
implicit def ordering: Ordering[PeerOrdering] =
implicit private def ordering: Ordering[PeerOrdering] =
(x: PeerOrdering, y: PeerOrdering) => {
if (x.priority != y.priority) x.priority.compare(y.priority)
else x.id.compare(y.id)
@ -439,7 +439,10 @@ case class PeerStack() {
mutable.SortedSet[PeerOrdering]().empty
def push(peer: PeerData, priority: Int = 0): Unit = {
if (set.size == maxSize) {
if (set.toVector.map(_.peerData.peer).contains(peer.peer)) {
// noop, we already have this peer in our stack
()
} else if (set.size == maxSize) {
if (set.head.priority < priority) {
set.remove(set.head)
set.add(PeerOrdering(peer, priority, id))
@ -453,7 +456,7 @@ case class PeerStack() {
}
def pop(): PeerData = {
val res = set.last.peer
val res = set.last.peerData
set.remove(set.last)
res
}
@ -462,7 +465,7 @@ case class PeerStack() {
def clear(): Unit = set.clear()
def pushAll(peers: Vector[PeerData], priority: Int = 0): Unit = {
peers.foreach(push(_, priority))
def pushAll(peerDatas: Vector[PeerData], priority: Int = 0): Unit = {
peerDatas.foreach(push(_, priority))
}
}