wip
This commit is contained in:
parent
4b5c35534d
commit
512a736c79
|
@ -56,9 +56,19 @@ type
|
||||||
discoveryLoopSleep: Duration # Discovery loop sleep
|
discoveryLoopSleep: Duration # Discovery loop sleep
|
||||||
inFlightDiscReqs*: Table[Cid, Future[seq[SignedPeerRecord]]] # Inflight discovery requests
|
inFlightDiscReqs*: Table[Cid, Future[seq[SignedPeerRecord]]] # Inflight discovery requests
|
||||||
|
|
||||||
|
proc getCid(address: BlockAddress): Cid =
|
||||||
|
# We advertise and discover only the CID part of a block address.
|
||||||
|
# Indices are ignored. This means that multiple blocks of the same tree will
|
||||||
|
# have a single DHT entry.
|
||||||
|
if address.leaf:
|
||||||
|
address.treeCid
|
||||||
|
else:
|
||||||
|
address.cid
|
||||||
|
|
||||||
proc discoveryQueueLoop(b: DiscoveryEngine) {.async: (raises: []).} =
|
proc discoveryQueueLoop(b: DiscoveryEngine) {.async: (raises: []).} =
|
||||||
while b.discEngineRunning:
|
while b.discEngineRunning:
|
||||||
for cid in toSeq(b.pendingBlocks.wantListBlockCids):
|
for address in toSeq(b.pendingBlocks.wantList):
|
||||||
|
let cid = address.getCid()
|
||||||
try:
|
try:
|
||||||
await b.discoveryQueue.put(cid)
|
await b.discoveryQueue.put(cid)
|
||||||
except CancelledError:
|
except CancelledError:
|
||||||
|
@ -88,10 +98,7 @@ proc discoveryTaskLoop(b: DiscoveryEngine) {.async: (raises: []).} =
|
||||||
trace "Discovery request already in progress", cid
|
trace "Discovery request already in progress", cid
|
||||||
continue
|
continue
|
||||||
|
|
||||||
let
|
if b.peers.countPeersWhoHave(cid) < b.minPeersPerBlock:
|
||||||
haves = b.peers.peersHave(cid)
|
|
||||||
|
|
||||||
if haves.len < b.minPeersPerBlock:
|
|
||||||
try:
|
try:
|
||||||
let
|
let
|
||||||
request = b.discovery
|
request = b.discovery
|
||||||
|
@ -127,8 +134,9 @@ proc discoveryTaskLoop(b: DiscoveryEngine) {.async: (raises: []).} =
|
||||||
|
|
||||||
info "Exiting discovery task runner"
|
info "Exiting discovery task runner"
|
||||||
|
|
||||||
proc queueFindBlocksReq*(b: DiscoveryEngine, cids: seq[Cid]) {.inline.} =
|
proc queueFindBlocksReq*(b: DiscoveryEngine, addresses: seq[BlockAddress]) {.inline.} =
|
||||||
for cid in cids:
|
for address in addresses:
|
||||||
|
let cid = address.getCid()
|
||||||
if cid notin b.discoveryQueue:
|
if cid notin b.discoveryQueue:
|
||||||
try:
|
try:
|
||||||
b.discoveryQueue.putNoWait(cid)
|
b.discoveryQueue.putNoWait(cid)
|
||||||
|
|
|
@ -172,7 +172,7 @@ proc monitorBlockHandle(
|
||||||
|
|
||||||
# drop unresponsive peer
|
# drop unresponsive peer
|
||||||
await b.network.switch.disconnect(peerId)
|
await b.network.switch.disconnect(peerId)
|
||||||
b.discovery.queueFindBlocksReq(@[address.cidOrTreeCid])
|
b.discovery.queueFindBlocksReq(@[address])
|
||||||
|
|
||||||
proc pickPseudoRandom(address: BlockAddress, peers: seq[BlockExcPeerCtx]): BlockExcPeerCtx =
|
proc pickPseudoRandom(address: BlockAddress, peers: seq[BlockExcPeerCtx]): BlockExcPeerCtx =
|
||||||
return peers[hash(address) mod peers.len]
|
return peers[hash(address) mod peers.len]
|
||||||
|
@ -187,7 +187,7 @@ proc requestBlock*(
|
||||||
let peers = b.peers.getPeersForBlock(address)
|
let peers = b.peers.getPeersForBlock(address)
|
||||||
|
|
||||||
if peers.with.len == 0:
|
if peers.with.len == 0:
|
||||||
b.discovery.queueFindBlocksReq(@[address.cidOrTreeCid])
|
b.discovery.queueFindBlocksReq(@[address])
|
||||||
else:
|
else:
|
||||||
let selected = pickPseudoRandom(address, peers.with)
|
let selected = pickPseudoRandom(address, peers.with)
|
||||||
asyncSpawn b.monitorBlockHandle(blockFuture, address, selected.id)
|
asyncSpawn b.monitorBlockHandle(blockFuture, address, selected.id)
|
||||||
|
@ -245,21 +245,24 @@ proc blockPresenceHandler*(
|
||||||
# if none of the connected peers report our wants in their have list,
|
# if none of the connected peers report our wants in their have list,
|
||||||
# fire up discovery
|
# fire up discovery
|
||||||
b.discovery.queueFindBlocksReq(
|
b.discovery.queueFindBlocksReq(
|
||||||
toSeq(b.pendingBlocks.wantListCids)
|
toSeq(b.pendingBlocks.wantList).filterIt(b.peers.peersHave(it).len == 0)
|
||||||
.filter do(cid: Cid) -> bool:
|
)
|
||||||
not b.peers.anyIt( cid in it.peerHaveCids ))
|
|
||||||
|
|
||||||
proc scheduleTasks(b: BlockExcEngine, blocksDelivery: seq[BlockDelivery]) {.async.} =
|
proc scheduleTasks(b: BlockExcEngine, blocksDelivery: seq[BlockDelivery]) {.async.} =
|
||||||
let
|
let
|
||||||
cids = blocksDelivery.mapIt( it.blk.cid )
|
addresses = blocksDelivery.mapIt( it.address )
|
||||||
|
|
||||||
|
# TODO: This code assumes p.peerWants are of type wantBlock, and will schedule
|
||||||
|
# the block-sending task. But, want might be wantHave. In this case,
|
||||||
|
# we should send a presence update. Peer is scheduled but task handler
|
||||||
|
# can only send blocks.
|
||||||
|
|
||||||
# schedule any new peers to provide blocks to
|
# schedule any new peers to provide blocks to
|
||||||
for p in b.peers:
|
for p in b.peers:
|
||||||
for c in cids: # for each cid
|
for address in addresses:
|
||||||
# schedule a peer if it wants at least one cid
|
# schedule a peer if it wants at least one
|
||||||
# and we have it in our local store
|
if address in p.peerWants:
|
||||||
if c in p.peerWantsCids:
|
if await (address in b.localStore):
|
||||||
if await (c in b.localStore):
|
|
||||||
if b.scheduleTask(p):
|
if b.scheduleTask(p):
|
||||||
trace "Task scheduled for peer", peer = p.id
|
trace "Task scheduled for peer", peer = p.id
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -130,19 +130,6 @@ iterator wantList*(p: PendingBlocksManager): BlockAddress =
|
||||||
for a in p.blocks.keys:
|
for a in p.blocks.keys:
|
||||||
yield a
|
yield a
|
||||||
|
|
||||||
iterator wantListBlockCids*(p: PendingBlocksManager): Cid =
|
|
||||||
for a in p.blocks.keys:
|
|
||||||
if not a.leaf:
|
|
||||||
yield a.cid
|
|
||||||
|
|
||||||
iterator wantListCids*(p: PendingBlocksManager): Cid =
|
|
||||||
var yieldedCids = initHashSet[Cid]()
|
|
||||||
for a in p.blocks.keys:
|
|
||||||
let cid = a.cidOrTreeCid
|
|
||||||
if cid notin yieldedCids:
|
|
||||||
yieldedCids.incl(cid)
|
|
||||||
yield cid
|
|
||||||
|
|
||||||
iterator wantHandles*(p: PendingBlocksManager): Future[Block] =
|
iterator wantHandles*(p: PendingBlocksManager): Future[Block] =
|
||||||
for v in p.blocks.values:
|
for v in p.blocks.values:
|
||||||
yield v.handle
|
yield v.handle
|
||||||
|
|
|
@ -38,12 +38,6 @@ type
|
||||||
proc peerHave*(self: BlockExcPeerCtx): seq[BlockAddress] =
|
proc peerHave*(self: BlockExcPeerCtx): seq[BlockAddress] =
|
||||||
toSeq(self.blocks.keys)
|
toSeq(self.blocks.keys)
|
||||||
|
|
||||||
proc peerHaveCids*(self: BlockExcPeerCtx): HashSet[Cid] =
|
|
||||||
self.blocks.keys.toSeq.mapIt(it.cidOrTreeCid).toHashSet
|
|
||||||
|
|
||||||
proc peerWantsCids*(self: BlockExcPeerCtx): HashSet[Cid] =
|
|
||||||
self.peerWants.mapIt(it.address.cidOrTreeCid).toHashSet
|
|
||||||
|
|
||||||
proc contains*(self: BlockExcPeerCtx, address: BlockAddress): bool =
|
proc contains*(self: BlockExcPeerCtx, address: BlockAddress): bool =
|
||||||
address in self.blocks
|
address in self.blocks
|
||||||
|
|
||||||
|
|
|
@ -64,15 +64,17 @@ func len*(self: PeerCtxStore): int =
|
||||||
func peersHave*(self: PeerCtxStore, address: BlockAddress): seq[BlockExcPeerCtx] =
|
func peersHave*(self: PeerCtxStore, address: BlockAddress): seq[BlockExcPeerCtx] =
|
||||||
toSeq(self.peers.values).filterIt( it.peerHave.anyIt( it == address ) )
|
toSeq(self.peers.values).filterIt( it.peerHave.anyIt( it == address ) )
|
||||||
|
|
||||||
func peersHave*(self: PeerCtxStore, cid: Cid): seq[BlockExcPeerCtx] =
|
func countPeersWhoHave*(self: PeerCtxStore, cid: Cid): int =
|
||||||
toSeq(self.peers.values).filterIt( it.peerHave.anyIt( it.cidOrTreeCid == cid ) )
|
proc getCid(address: BlockAddress): Cid =
|
||||||
|
if address.leaf:
|
||||||
|
address.treeCid
|
||||||
|
else:
|
||||||
|
address.cid
|
||||||
|
self.peers.values.countIt(it.peerHave.anyIt( it.getCid() == cid ) )
|
||||||
|
|
||||||
func peersWant*(self: PeerCtxStore, address: BlockAddress): seq[BlockExcPeerCtx] =
|
func peersWant*(self: PeerCtxStore, address: BlockAddress): seq[BlockExcPeerCtx] =
|
||||||
toSeq(self.peers.values).filterIt( it.peerWants.anyIt( it == address ) )
|
toSeq(self.peers.values).filterIt( it.peerWants.anyIt( it == address ) )
|
||||||
|
|
||||||
func peersWant*(self: PeerCtxStore, cid: Cid): seq[BlockExcPeerCtx] =
|
|
||||||
toSeq(self.peers.values).filterIt( it.peerWants.anyIt( it.address.cidOrTreeCid == cid ) )
|
|
||||||
|
|
||||||
proc getPeersForBlock*(self: PeerCtxStore, address: BlockAddress): PeersForBlock =
|
proc getPeersForBlock*(self: PeerCtxStore, address: BlockAddress): PeersForBlock =
|
||||||
var res = PeersForBlock()
|
var res = PeersForBlock()
|
||||||
for peer in self:
|
for peer in self:
|
||||||
|
|
|
@ -66,12 +66,6 @@ proc `$`*(a: BlockAddress): string =
|
||||||
else:
|
else:
|
||||||
"cid: " & $a.cid
|
"cid: " & $a.cid
|
||||||
|
|
||||||
proc cidOrTreeCid*(a: BlockAddress): Cid =
|
|
||||||
if a.leaf:
|
|
||||||
a.treeCid
|
|
||||||
else:
|
|
||||||
a.cid
|
|
||||||
|
|
||||||
proc address*(b: Block): BlockAddress =
|
proc address*(b: Block): BlockAddress =
|
||||||
BlockAddress(leaf: false, cid: b.cid)
|
BlockAddress(leaf: false, cid: b.cid)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue