Peer store refacto (#700)
There is now a global PeerStore structure (instead of having one for libp2p, one for waku, etc) The user can create custom books for new types easily Also add a pruning system to remove dead peers
This commit is contained in:
parent
1696d0c707
commit
60becadcf9
|
@ -48,6 +48,7 @@ type
|
|||
protoVersion: string
|
||||
agentVersion: string
|
||||
nameResolver: NameResolver
|
||||
peerStoreCapacity: Option[int]
|
||||
isCircuitRelay: bool
|
||||
circuitRelayCanHop: bool
|
||||
|
||||
|
@ -130,6 +131,10 @@ proc withMaxConnsPerPeer*(b: SwitchBuilder, maxConnsPerPeer: int): SwitchBuilder
|
|||
b.maxConnsPerPeer = maxConnsPerPeer
|
||||
b
|
||||
|
||||
proc withPeerStore*(b: SwitchBuilder, capacity: int): SwitchBuilder =
|
||||
b.peerStoreCapacity = some(capacity)
|
||||
b
|
||||
|
||||
proc withProtoVersion*(b: SwitchBuilder, protoVersion: string): SwitchBuilder =
|
||||
b.protoVersion = protoVersion
|
||||
b
|
||||
|
@ -195,6 +200,12 @@ proc build*(b: SwitchBuilder): Switch
|
|||
if isNil(b.rng):
|
||||
b.rng = newRng()
|
||||
|
||||
let peerStore =
|
||||
if isSome(b.peerStoreCapacity):
|
||||
PeerStore.new(b.peerStoreCapacity.get())
|
||||
else:
|
||||
PeerStore.new()
|
||||
|
||||
let switch = newSwitch(
|
||||
peerInfo = peerInfo,
|
||||
transports = transports,
|
||||
|
@ -203,7 +214,8 @@ proc build*(b: SwitchBuilder): Switch
|
|||
secureManagers = secureManagerInstances,
|
||||
connManager = connManager,
|
||||
ms = ms,
|
||||
nameResolver = b.nameResolver)
|
||||
nameResolver = b.nameResolver,
|
||||
peerStore = peerStore)
|
||||
|
||||
if b.isCircuitRelay:
|
||||
let relay = Relay.new(switch, b.circuitRelayCanHop)
|
||||
|
@ -227,7 +239,8 @@ proc newStandardSwitch*(
|
|||
maxOut = -1,
|
||||
maxConnsPerPeer = MaxConnectionsPerPeer,
|
||||
nameResolver: NameResolver = nil,
|
||||
sendSignedPeerRecord = false): Switch
|
||||
sendSignedPeerRecord = false,
|
||||
peerStoreCapacity = 1000): Switch
|
||||
{.raises: [Defect, LPError].} =
|
||||
if SecureProtocol.Secio in secureManagers:
|
||||
quit("Secio is deprecated!") # use of secio is unsafe
|
||||
|
@ -242,6 +255,7 @@ proc newStandardSwitch*(
|
|||
.withMaxIn(maxIn)
|
||||
.withMaxOut(maxOut)
|
||||
.withMaxConnsPerPeer(maxConnsPerPeer)
|
||||
.withPeerStore(capacity=peerStoreCapacity)
|
||||
.withMplex(inTimeout, outTimeout)
|
||||
.withTcpTransport(transportFlags)
|
||||
.withNameResolver(nameResolver)
|
||||
|
|
|
@ -307,6 +307,9 @@ proc peerCleanup(c: ConnManager, conn: Connection) {.async.} =
|
|||
await c.triggerConnEvent(
|
||||
peerId, ConnEvent(kind: ConnEventKind.Disconnected))
|
||||
await c.triggerPeerEvents(peerId, PeerEvent(kind: PeerEventKind.Left))
|
||||
|
||||
if not(c.peerStore.isNil):
|
||||
c.peerStore.cleanup(peerId)
|
||||
except CatchableError as exc:
|
||||
# This is top-level procedure which will work as separate task, so it
|
||||
# do not need to propagate CancelledError and should handle other errors
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
{.push raises: [Defect].}
|
||||
|
||||
import
|
||||
std/[tables, sets, options],
|
||||
std/[tables, sets, options, macros],
|
||||
./crypto/crypto,
|
||||
./protocols/identify,
|
||||
./peerid, ./peerinfo,
|
||||
|
@ -22,58 +22,52 @@ type
|
|||
# Handler types #
|
||||
#################
|
||||
|
||||
PeerBookChangeHandler*[T] = proc(peerId: PeerId, entry: T)
|
||||
|
||||
AddrChangeHandler* = PeerBookChangeHandler[HashSet[MultiAddress]]
|
||||
ProtoChangeHandler* = PeerBookChangeHandler[HashSet[string]]
|
||||
KeyChangeHandler* = PeerBookChangeHandler[PublicKey]
|
||||
PeerBookChangeHandler* = proc(peerId: PeerId) {.gcsafe, raises: [Defect].}
|
||||
|
||||
#########
|
||||
# Books #
|
||||
#########
|
||||
|
||||
# Each book contains a book (map) and event handler(s)
|
||||
PeerBook*[T] = object of RootObj
|
||||
BasePeerBook = ref object of RootObj
|
||||
changeHandlers: seq[PeerBookChangeHandler]
|
||||
deletor: PeerBookChangeHandler
|
||||
|
||||
PeerBook*[T] = ref object of BasePeerBook
|
||||
book*: Table[PeerId, T]
|
||||
changeHandlers: seq[PeerBookChangeHandler[T]]
|
||||
|
||||
SetPeerBook*[T] = object of PeerBook[HashSet[T]]
|
||||
SeqPeerBook*[T] = ref object of PeerBook[seq[T]]
|
||||
|
||||
AddressBook* = object of SetPeerBook[MultiAddress]
|
||||
ProtoBook* = object of SetPeerBook[string]
|
||||
KeyBook* = object of PeerBook[PublicKey]
|
||||
AddressBook* = ref object of SeqPeerBook[MultiAddress]
|
||||
ProtoBook* = ref object of SeqPeerBook[string]
|
||||
KeyBook* = ref object of PeerBook[PublicKey]
|
||||
|
||||
AgentBook* = ref object of PeerBook[string]
|
||||
ProtoVersionBook* = ref object of PeerBook[string]
|
||||
SPRBook* = ref object of PeerBook[Envelope]
|
||||
|
||||
####################
|
||||
# Peer store types #
|
||||
####################
|
||||
|
||||
PeerStore* = ref object
|
||||
addressBook*: AddressBook
|
||||
protoBook*: ProtoBook
|
||||
keyBook*: KeyBook
|
||||
books: Table[string, BasePeerBook]
|
||||
capacity*: int
|
||||
toClean*: seq[PeerId]
|
||||
|
||||
agentBook*: PeerBook[string]
|
||||
protoVersionBook*: PeerBook[string]
|
||||
|
||||
signedPeerRecordBook*: PeerBook[Envelope]
|
||||
|
||||
## Constructs a new PeerStore with metadata of type M
|
||||
proc new*(T: type PeerStore): PeerStore =
|
||||
var p: PeerStore
|
||||
new(p)
|
||||
return p
|
||||
proc new*(T: type PeerStore, capacity = 1000): PeerStore =
|
||||
T(capacity: capacity)
|
||||
|
||||
#########################
|
||||
# Generic Peer Book API #
|
||||
#########################
|
||||
|
||||
proc get*[T](peerBook: PeerBook[T],
|
||||
proc `[]`*[T](peerBook: PeerBook[T],
|
||||
peerId: PeerId): T =
|
||||
## Get all the known metadata of a provided peer.
|
||||
|
||||
peerBook.book.getOrDefault(peerId)
|
||||
|
||||
proc set*[T](peerBook: var PeerBook[T],
|
||||
proc `[]=`*[T](peerBook: PeerBook[T],
|
||||
peerId: PeerId,
|
||||
entry: T) =
|
||||
## Set metadata for a given peerId. This will replace any
|
||||
|
@ -83,86 +77,90 @@ proc set*[T](peerBook: var PeerBook[T],
|
|||
|
||||
# Notify clients
|
||||
for handler in peerBook.changeHandlers:
|
||||
handler(peerId, peerBook.get(peerId))
|
||||
handler(peerId)
|
||||
|
||||
proc delete*[T](peerBook: var PeerBook[T],
|
||||
proc del*[T](peerBook: PeerBook[T],
|
||||
peerId: PeerId): bool =
|
||||
## Delete the provided peer from the book.
|
||||
|
||||
if not peerBook.book.hasKey(peerId):
|
||||
if peerId notin peerBook.book:
|
||||
return false
|
||||
else:
|
||||
peerBook.book.del(peerId)
|
||||
# Notify clients
|
||||
for handler in peerBook.changeHandlers:
|
||||
handler(peerId)
|
||||
return true
|
||||
|
||||
proc contains*[T](peerBook: PeerBook[T], peerId: PeerId): bool =
|
||||
peerId in peerBook.book
|
||||
|
||||
################
|
||||
# Set Book API #
|
||||
################
|
||||
|
||||
proc add*[T](
|
||||
peerBook: var SetPeerBook[T],
|
||||
peerId: PeerId,
|
||||
entry: T) =
|
||||
## Add entry to a given peer. If the peer is not known,
|
||||
## it will be set with the provided entry.
|
||||
|
||||
peerBook.book.mgetOrPut(peerId,
|
||||
initHashSet[T]()).incl(entry)
|
||||
|
||||
# Notify clients
|
||||
for handler in peerBook.changeHandlers:
|
||||
handler(peerId, peerBook.get(peerId))
|
||||
|
||||
# Helper for seq
|
||||
proc set*[T](
|
||||
peerBook: var SetPeerBook[T],
|
||||
peerId: PeerId,
|
||||
entry: seq[T]) =
|
||||
## Add entry to a given peer. If the peer is not known,
|
||||
## it will be set with the provided entry.
|
||||
peerBook.set(peerId, entry.toHashSet())
|
||||
proc addHandler*[T](peerBook: PeerBook[T], handler: PeerBookChangeHandler) =
|
||||
peerBook.changeHandlers.add(handler)
|
||||
|
||||
proc len*[T](peerBook: PeerBook[T]): int = peerBook.book.len
|
||||
|
||||
##################
|
||||
# Peer Store API #
|
||||
##################
|
||||
macro getTypeName(t: type): untyped =
|
||||
# Generate unique name in form of Module.Type
|
||||
let typ = getTypeImpl(t)[1]
|
||||
newLit(repr(typ.owner()) & "." & repr(typ))
|
||||
|
||||
proc addHandlers*(peerStore: PeerStore,
|
||||
addrChangeHandler: AddrChangeHandler,
|
||||
protoChangeHandler: ProtoChangeHandler,
|
||||
keyChangeHandler: KeyChangeHandler) =
|
||||
## Register event handlers to notify clients of changes in the peer store
|
||||
proc `[]`*[T](p: PeerStore, typ: type[T]): T =
|
||||
let name = getTypeName(T)
|
||||
result = T(p.books.getOrDefault(name))
|
||||
if result.isNil:
|
||||
result = T.new()
|
||||
result.deletor = proc(pid: PeerId) =
|
||||
# Manual method because generic method
|
||||
# don't work
|
||||
discard T(p.books.getOrDefault(name)).del(pid)
|
||||
p.books[name] = result
|
||||
return result
|
||||
|
||||
peerStore.addressBook.changeHandlers.add(addrChangeHandler)
|
||||
peerStore.protoBook.changeHandlers.add(protoChangeHandler)
|
||||
peerStore.keyBook.changeHandlers.add(keyChangeHandler)
|
||||
|
||||
proc delete*(peerStore: PeerStore,
|
||||
peerId: PeerId): bool =
|
||||
proc del*(peerStore: PeerStore,
|
||||
peerId: PeerId) =
|
||||
## Delete the provided peer from every book.
|
||||
|
||||
peerStore.addressBook.delete(peerId) and
|
||||
peerStore.protoBook.delete(peerId) and
|
||||
peerStore.keyBook.delete(peerId)
|
||||
for _, book in peerStore.books:
|
||||
book.deletor(peerId)
|
||||
|
||||
proc updatePeerInfo*(
|
||||
peerStore: PeerStore,
|
||||
info: IdentifyInfo) =
|
||||
|
||||
if info.addrs.len > 0:
|
||||
peerStore.addressBook.set(info.peerId, info.addrs)
|
||||
peerStore[AddressBook][info.peerId] = info.addrs
|
||||
|
||||
if info.agentVersion.isSome:
|
||||
peerStore.agentBook.set(info.peerId, info.agentVersion.get().string)
|
||||
peerStore[AgentBook][info.peerId] = info.agentVersion.get().string
|
||||
|
||||
if info.protoVersion.isSome:
|
||||
peerStore.protoVersionBook.set(info.peerId, info.protoVersion.get().string)
|
||||
peerStore[ProtoVersionBook][info.peerId] = info.protoVersion.get().string
|
||||
|
||||
if info.protos.len > 0:
|
||||
peerStore.protoBook.set(info.peerId, info.protos)
|
||||
peerStore[ProtoBook][info.peerId] = info.protos
|
||||
|
||||
if info.signedPeerRecord.isSome:
|
||||
peerStore.signedPeerRecordBook.set(info.peerId, info.signedPeerRecord.get())
|
||||
peerStore[SPRBook][info.peerId] = info.signedPeerRecord.get()
|
||||
|
||||
let cleanupPos = peerStore.toClean.find(info.peerId)
|
||||
if cleanupPos >= 0:
|
||||
peerStore.toClean.delete(cleanupPos)
|
||||
|
||||
proc cleanup*(
|
||||
peerStore: PeerStore,
|
||||
peerId: PeerId) =
|
||||
|
||||
if peerStore.capacity == 0:
|
||||
peerStore.del(peerId)
|
||||
return
|
||||
elif peerStore.capacity < 0:
|
||||
#infinite capacity
|
||||
return
|
||||
|
||||
peerStore.toClean.add(peerId)
|
||||
while peerStore.toClean.len > peerStore.capacity:
|
||||
peerStore.del(peerStore.toClean[0])
|
||||
peerStore.toClean.delete(0)
|
||||
|
|
|
@ -86,13 +86,13 @@ proc peerExchangeList*(g: GossipSub, topic: string): seq[PeerInfoMsg] {.raises:
|
|||
x.score >= 0.0
|
||||
# by spec, larger then Dhi, but let's put some hard caps
|
||||
peers.setLen(min(peers.len, g.parameters.dHigh * 2))
|
||||
let sprBook = g.switch.peerStore.signedPeerRecordBook
|
||||
let sprBook = g.switch.peerStore[SPRBook]
|
||||
peers.map do (x: PubSubPeer) -> PeerInfoMsg:
|
||||
PeerInfoMsg(
|
||||
peerId: x.peerId,
|
||||
signedPeerRecord:
|
||||
if x.peerId in sprBook:
|
||||
sprBook.get(x.peerId).encode().get(default(seq[byte]))
|
||||
sprBook[x.peerId].encode().get(default(seq[byte]))
|
||||
else:
|
||||
default(seq[byte])
|
||||
)
|
||||
|
|
|
@ -281,7 +281,8 @@ proc newSwitch*(peerInfo: PeerInfo,
|
|||
secureManagers: openArray[Secure] = [],
|
||||
connManager: ConnManager,
|
||||
ms: MultistreamSelect,
|
||||
nameResolver: NameResolver = nil): Switch
|
||||
nameResolver: NameResolver = nil,
|
||||
peerStore = PeerStore.new()): Switch
|
||||
{.raises: [Defect, LPError].} =
|
||||
if secureManagers.len == 0:
|
||||
raise newException(LPError, "Provide at least one secure manager")
|
||||
|
@ -291,10 +292,10 @@ proc newSwitch*(peerInfo: PeerInfo,
|
|||
ms: ms,
|
||||
transports: transports,
|
||||
connManager: connManager,
|
||||
peerStore: PeerStore.new(),
|
||||
peerStore: peerStore,
|
||||
dialer: Dialer.new(peerInfo.peerId, connManager, transports, ms, nameResolver),
|
||||
nameResolver: nameResolver)
|
||||
|
||||
switch.connManager.peerStore = switch.peerStore
|
||||
switch.connManager.peerStore = peerStore
|
||||
switch.mount(identity)
|
||||
return switch
|
||||
|
|
|
@ -177,11 +177,11 @@ suite "Identify":
|
|||
IdentifyPushCodec)
|
||||
|
||||
check:
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet()
|
||||
switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] == switch2.peerInfo.addrs
|
||||
switch2.peerStore[AddressBook][switch1.peerInfo.peerId] == switch1.peerInfo.addrs
|
||||
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet()
|
||||
switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] == switch2.peerInfo.addrs
|
||||
switch2.peerStore[AddressBook][switch1.peerInfo.peerId] == switch1.peerInfo.addrs
|
||||
|
||||
#switch1.peerStore.signedPeerRecordBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.signedPeerRecord.get()
|
||||
#switch2.peerStore.signedPeerRecordBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.signedPeerRecord.get()
|
||||
|
@ -198,20 +198,20 @@ suite "Identify":
|
|||
switch2.peerInfo.addrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
|
||||
|
||||
check:
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) != switch2.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) != switch2.peerInfo.protocols.toHashSet()
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] != switch2.peerInfo.addrs
|
||||
switch1.peerStore[ProtoBook][switch2.peerInfo.peerId] != switch2.peerInfo.protocols
|
||||
|
||||
await identifyPush2.push(switch2.peerInfo, conn)
|
||||
|
||||
check await checkExpiring(switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.protocols.toHashSet())
|
||||
check await checkExpiring(switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet())
|
||||
check await checkExpiring(switch1.peerStore[ProtoBook][switch2.peerInfo.peerId] == switch2.peerInfo.protocols)
|
||||
check await checkExpiring(switch1.peerStore[AddressBook][switch2.peerInfo.peerId] == switch2.peerInfo.addrs)
|
||||
|
||||
await closeAll()
|
||||
|
||||
# Wait the very end to be sure that the push has been processed
|
||||
check:
|
||||
switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.protocols.toHashSet()
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore[ProtoBook][switch2.peerInfo.peerId] == switch2.peerInfo.protocols
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] == switch2.peerInfo.addrs
|
||||
|
||||
|
||||
asyncTest "wrong peer id push identify":
|
||||
|
@ -219,8 +219,8 @@ suite "Identify":
|
|||
switch2.peerInfo.addrs.add(MultiAddress.init("/ip4/127.0.0.1/tcp/5555").tryGet())
|
||||
|
||||
check:
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) != switch2.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) != switch2.peerInfo.protocols.toHashSet()
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] != switch2.peerInfo.addrs
|
||||
switch1.peerStore[ProtoBook][switch2.peerInfo.peerId] != switch2.peerInfo.protocols
|
||||
|
||||
let oldPeerId = switch2.peerInfo.peerId
|
||||
switch2.peerInfo = PeerInfo.new(PrivateKey.random(newRng()[]).get())
|
||||
|
@ -237,5 +237,5 @@ suite "Identify":
|
|||
|
||||
# Wait the very end to be sure that the push has been processed
|
||||
check:
|
||||
switch1.peerStore.protoBook.get(oldPeerId) != switch2.peerInfo.protocols.toHashSet()
|
||||
switch1.peerStore.addressBook.get(oldPeerId) != switch2.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore[ProtoBook][oldPeerId] != switch2.peerInfo.protocols
|
||||
switch1.peerStore[AddressBook][oldPeerId] != switch2.peerInfo.addrs
|
||||
|
|
|
@ -28,170 +28,107 @@ suite "PeerStore":
|
|||
var
|
||||
peerStore = PeerStore.new()
|
||||
|
||||
peerStore.addressBook.add(peerId1, multiaddr1)
|
||||
peerStore.addressBook.add(peerId2, multiaddr2)
|
||||
peerStore.protoBook.add(peerId1, testcodec1)
|
||||
peerStore.protoBook.add(peerId2, testcodec2)
|
||||
peerStore.keyBook.set(peerId1, keyPair1.pubkey)
|
||||
peerStore.keyBook.set(peerId2, keyPair2.pubkey)
|
||||
peerStore[AddressBook][peerId1] = @[multiaddr1]
|
||||
peerStore[AddressBook][peerId2] = @[multiaddr2]
|
||||
peerStore[ProtoBook][peerId1] = @[testcodec1]
|
||||
peerStore[ProtoBook][peerId2] = @[testcodec2]
|
||||
peerStore[KeyBook][peerId1] = keyPair1.pubkey
|
||||
peerStore[KeyBook][peerId2] = keyPair2.pubkey
|
||||
|
||||
# Test PeerStore::delete
|
||||
check:
|
||||
# Test PeerStore::del
|
||||
# Delete existing peerId
|
||||
peerStore.delete(peerId1) == true
|
||||
peerId1 notin peerStore.addressBook
|
||||
peerStore.del(peerId1)
|
||||
check peerId1 notin peerStore[AddressBook]
|
||||
# Now try and del it again
|
||||
peerStore.del(peerId1)
|
||||
|
||||
# Now try and delete it again
|
||||
peerStore.delete(peerId1) == false
|
||||
|
||||
test "PeerStore listeners":
|
||||
# Set up peer store with listener
|
||||
var
|
||||
peerStore = PeerStore.new()
|
||||
addrChanged = false
|
||||
protoChanged = false
|
||||
keyChanged = false
|
||||
|
||||
proc addrChange(peerId: PeerId, addrs: HashSet[MultiAddress]) =
|
||||
proc addrChange(peerId: PeerId) {.gcsafe.} =
|
||||
addrChanged = true
|
||||
|
||||
proc protoChange(peerId: PeerId, protos: HashSet[string]) =
|
||||
protoChanged = true
|
||||
|
||||
proc keyChange(peerId: PeerId, publicKey: PublicKey) =
|
||||
keyChanged = true
|
||||
|
||||
peerStore.addHandlers(addrChangeHandler = addrChange,
|
||||
protoChangeHandler = protoChange,
|
||||
keyChangeHandler = keyChange)
|
||||
peerStore[AddressBook].addHandler(addrChange)
|
||||
|
||||
# Test listener triggered on adding multiaddr
|
||||
peerStore.addressBook.add(peerId1, multiaddr1)
|
||||
check:
|
||||
addrChanged == true
|
||||
peerStore[AddressBook][peerId1] = @[multiaddr1]
|
||||
check: addrChanged == true
|
||||
|
||||
# Test listener triggered on setting addresses
|
||||
addrChanged = false
|
||||
peerStore.addressBook.set(peerId2,
|
||||
toHashSet([multiaddr1, multiaddr2]))
|
||||
check:
|
||||
peerStore[AddressBook].del(peerId1) == true
|
||||
addrChanged == true
|
||||
|
||||
# Test listener triggered on adding proto
|
||||
peerStore.protoBook.add(peerId1, testcodec1)
|
||||
check:
|
||||
protoChanged == true
|
||||
|
||||
# Test listener triggered on setting protos
|
||||
protoChanged = false
|
||||
peerStore.protoBook.set(peerId2,
|
||||
toHashSet([testcodec1, testcodec2]))
|
||||
check:
|
||||
protoChanged == true
|
||||
|
||||
# Test listener triggered on setting public key
|
||||
peerStore.keyBook.set(peerId1,
|
||||
keyPair1.pubkey)
|
||||
check:
|
||||
keyChanged == true
|
||||
|
||||
# Test listener triggered on changing public key
|
||||
keyChanged = false
|
||||
peerStore.keyBook.set(peerId1,
|
||||
keyPair2.pubkey)
|
||||
check:
|
||||
keyChanged == true
|
||||
|
||||
test "AddressBook API":
|
||||
test "PeerBook API":
|
||||
# Set up address book
|
||||
var
|
||||
addressBook = PeerStore.new().addressBook
|
||||
var addressBook = PeerStore.new()[AddressBook]
|
||||
|
||||
# Test AddressBook::add
|
||||
addressBook.add(peerId1, multiaddr1)
|
||||
addressBook[peerId1] = @[multiaddr1]
|
||||
|
||||
check:
|
||||
toSeq(keys(addressBook.book))[0] == peerId1
|
||||
toSeq(values(addressBook.book))[0] == toHashSet([multiaddr1])
|
||||
toSeq(values(addressBook.book))[0] == @[multiaddr1]
|
||||
|
||||
# Test AddressBook::get
|
||||
check:
|
||||
addressBook.get(peerId1) == toHashSet([multiaddr1])
|
||||
addressBook[peerId1] == @[multiaddr1]
|
||||
|
||||
# Test AddressBook::delete
|
||||
# Test AddressBook::del
|
||||
check:
|
||||
# Try to delete peerId that doesn't exist
|
||||
addressBook.delete(peerId2) == false
|
||||
# Try to del peerId that doesn't exist
|
||||
addressBook.del(peerId2) == false
|
||||
|
||||
# Delete existing peerId
|
||||
addressBook.book.len == 1 # sanity
|
||||
addressBook.delete(peerId1) == true
|
||||
addressBook.del(peerId1) == true
|
||||
addressBook.book.len == 0
|
||||
|
||||
# Test AddressBook::set
|
||||
# Set peerId2 with multiple multiaddrs
|
||||
addressBook.set(peerId2,
|
||||
toHashSet([multiaddr1, multiaddr2]))
|
||||
addressBook[peerId2] = @[multiaddr1, multiaddr2]
|
||||
check:
|
||||
toSeq(keys(addressBook.book))[0] == peerId2
|
||||
toSeq(values(addressBook.book))[0] == toHashSet([multiaddr1, multiaddr2])
|
||||
toSeq(values(addressBook.book))[0] == @[multiaddr1, multiaddr2]
|
||||
|
||||
test "ProtoBook API":
|
||||
# Set up protocol book
|
||||
var
|
||||
protoBook = PeerStore.new().protoBook
|
||||
test "Pruner - no capacity":
|
||||
let peerStore = PeerStore.new(capacity = 0)
|
||||
peerStore[AgentBook][peerId1] = "gds"
|
||||
|
||||
# Test ProtoBook::add
|
||||
protoBook.add(peerId1, testcodec1)
|
||||
peerStore.cleanup(peerId1)
|
||||
|
||||
check peerId1 notin peerStore[AgentBook]
|
||||
|
||||
test "Pruner - FIFO":
|
||||
let peerStore = PeerStore.new(capacity = 1)
|
||||
peerStore[AgentBook][peerId1] = "gds"
|
||||
peerStore[AgentBook][peerId2] = "gds"
|
||||
peerStore.cleanup(peerId2)
|
||||
peerStore.cleanup(peerId1)
|
||||
check:
|
||||
toSeq(keys(protoBook.book))[0] == peerId1
|
||||
toSeq(values(protoBook.book))[0] == toHashSet([testcodec1])
|
||||
peerId1 in peerStore[AgentBook]
|
||||
peerId2 notin peerStore[AgentBook]
|
||||
|
||||
# Test ProtoBook::get
|
||||
check:
|
||||
protoBook.get(peerId1) == toHashSet([testcodec1])
|
||||
test "Pruner - regular capacity":
|
||||
var peerStore = PeerStore.new(capacity = 20)
|
||||
|
||||
# Test ProtoBook::delete
|
||||
check:
|
||||
# Try to delete peerId that doesn't exist
|
||||
protoBook.delete(peerId2) == false
|
||||
for i in 0..<30:
|
||||
let randomPeerId = PeerId.init(KeyPair.random(ECDSA, rng[]).get().pubkey).get()
|
||||
peerStore[AgentBook][randomPeerId] = "gds"
|
||||
peerStore.cleanup(randomPeerId)
|
||||
|
||||
# Delete existing peerId
|
||||
protoBook.book.len == 1 # sanity
|
||||
protoBook.delete(peerId1) == true
|
||||
protoBook.book.len == 0
|
||||
check peerStore[AgentBook].len == 20
|
||||
|
||||
# Test ProtoBook::set
|
||||
# Set peerId2 with multiple protocols
|
||||
protoBook.set(peerId2,
|
||||
toHashSet([testcodec1, testcodec2]))
|
||||
check:
|
||||
toSeq(keys(protoBook.book))[0] == peerId2
|
||||
toSeq(values(protoBook.book))[0] == toHashSet([testcodec1, testcodec2])
|
||||
test "Pruner - infinite capacity":
|
||||
var peerStore = PeerStore.new(capacity = -1)
|
||||
|
||||
test "KeyBook API":
|
||||
# Set up key book
|
||||
var
|
||||
keyBook = PeerStore.new().keyBook
|
||||
for i in 0..<30:
|
||||
let randomPeerId = PeerId.init(KeyPair.random(ECDSA, rng[]).get().pubkey).get()
|
||||
peerStore[AgentBook][randomPeerId] = "gds"
|
||||
peerStore.cleanup(randomPeerId)
|
||||
|
||||
# Test KeyBook::set
|
||||
keyBook.set(peerId1,
|
||||
keyPair1.pubkey)
|
||||
check:
|
||||
toSeq(keys(keyBook.book))[0] == peerId1
|
||||
toSeq(values(keyBook.book))[0] == keyPair1.pubkey
|
||||
|
||||
# Test KeyBook::get
|
||||
check:
|
||||
keyBook.get(peerId1) == keyPair1.pubkey
|
||||
|
||||
# Test KeyBook::delete
|
||||
check:
|
||||
# Try to delete peerId that doesn't exist
|
||||
keyBook.delete(peerId2) == false
|
||||
|
||||
# Delete existing peerId
|
||||
keyBook.book.len == 1 # sanity
|
||||
keyBook.delete(peerId1) == true
|
||||
keyBook.book.len == 0
|
||||
check peerStore[AgentBook].len == 30
|
||||
|
|
|
@ -811,7 +811,7 @@ suite "Switch":
|
|||
let switch1 = newStandardSwitch()
|
||||
switch1.mount(testProto)
|
||||
|
||||
let switch2 = newStandardSwitch()
|
||||
let switch2 = newStandardSwitch(peerStoreCapacity = 0)
|
||||
await switch1.start()
|
||||
await switch2.start()
|
||||
|
||||
|
@ -834,11 +834,11 @@ suite "Switch":
|
|||
check not switch2.isConnected(switch1.peerInfo.peerId)
|
||||
|
||||
check:
|
||||
switch1.peerStore.addressBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.addrs.toHashSet()
|
||||
switch2.peerStore.addressBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.addrs.toHashSet()
|
||||
switch1.peerStore[AddressBook][switch2.peerInfo.peerId] == switch2.peerInfo.addrs
|
||||
switch1.peerStore[ProtoBook][switch2.peerInfo.peerId] == switch2.peerInfo.protocols
|
||||
|
||||
switch1.peerStore.protoBook.get(switch2.peerInfo.peerId) == switch2.peerInfo.protocols.toHashSet()
|
||||
switch2.peerStore.protoBook.get(switch1.peerInfo.peerId) == switch1.peerInfo.protocols.toHashSet()
|
||||
switch1.peerInfo.peerId notin switch2.peerStore[AddressBook]
|
||||
switch1.peerInfo.peerId notin switch2.peerStore[ProtoBook]
|
||||
|
||||
asyncTest "e2e should allow multiple local addresses":
|
||||
when defined(windows):
|
||||
|
|
Loading…
Reference in New Issue