mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-02 13:33:10 +00:00
169 lines
5.1 KiB
Nim
169 lines
5.1 KiB
Nim
import std/sequtils
|
|
import std/sets
|
|
|
|
import pkg/chronos
|
|
import pkg/libp2p
|
|
import pkg/libp2p/errors
|
|
|
|
import pkg/codex/discovery
|
|
import pkg/codex/stores
|
|
import pkg/codex/blocktype as bt
|
|
import pkg/codex/blockexchange
|
|
import pkg/codex/merkletree
|
|
import pkg/codex/manifest
|
|
import pkg/codex/utils/safeasynciter
|
|
|
|
import ./datasetutils
|
|
import ./mockdiscovery
|
|
import ../examples
|
|
import ../../helpers
|
|
|
|
type NodesComponents* =
|
|
tuple[
|
|
switch: Switch,
|
|
blockDiscovery: Discovery,
|
|
wallet: WalletRef,
|
|
network: BlockExcNetwork,
|
|
localStore: BlockStore,
|
|
peerStore: PeerCtxStore,
|
|
pendingBlocks: PendingBlocksManager,
|
|
discovery: DiscoveryEngine,
|
|
engine: BlockExcEngine,
|
|
networkStore: NetworkStore,
|
|
]
|
|
|
|
proc assignBlocks*(
|
|
node: NodesComponents,
|
|
dataset: TestDataset,
|
|
indices: seq[int],
|
|
putMerkleProofs = true,
|
|
): Future[void] {.async: (raises: [CatchableError]).} =
|
|
let rootCid = dataset.tree.rootCid.tryGet()
|
|
|
|
for i in indices:
|
|
assert (await node.networkStore.putBlock(dataset.blocks[i])).isOk
|
|
if putMerkleProofs:
|
|
assert (
|
|
await node.networkStore.putCidAndProof(
|
|
rootCid, i, dataset.blocks[i].cid, dataset.tree.getProof(i).tryGet()
|
|
)
|
|
).isOk
|
|
|
|
proc assignBlocks*(
|
|
node: NodesComponents,
|
|
dataset: TestDataset,
|
|
indices: HSlice[int, int],
|
|
putMerkleProofs = true,
|
|
): Future[void] {.async: (raises: [CatchableError]).} =
|
|
await assignBlocks(node, dataset, indices.toSeq, putMerkleProofs)
|
|
|
|
proc assignBlocks*(
|
|
node: NodesComponents, dataset: TestDataset, putMerkleProofs = true
|
|
): Future[void] {.async: (raises: [CatchableError]).} =
|
|
await assignBlocks(node, dataset, 0 ..< dataset.blocks.len, putMerkleProofs)
|
|
|
|
proc generateNodes*(
|
|
num: Natural, blocks: openArray[bt.Block] = [], enableDiscovery = true
|
|
): seq[NodesComponents] =
|
|
for i in 0 ..< num:
|
|
let
|
|
switch = newStandardSwitch(transportFlags = {ServerFlags.ReuseAddr})
|
|
discovery =
|
|
if enableDiscovery:
|
|
Discovery.new(
|
|
switch.peerInfo.privateKey,
|
|
announceAddrs =
|
|
@[
|
|
MultiAddress.init("/ip4/127.0.0.1/tcp/0").expect(
|
|
"Should return multiaddress"
|
|
)
|
|
],
|
|
)
|
|
else:
|
|
nullDiscovery()
|
|
|
|
let
|
|
wallet = WalletRef.example
|
|
network = BlockExcNetwork.new(switch)
|
|
localStore = CacheStore.new(blocks)
|
|
peerStore = PeerCtxStore.new()
|
|
pendingBlocks = PendingBlocksManager.new()
|
|
advertiser = Advertiser.new(localStore, discovery)
|
|
blockDiscovery =
|
|
DiscoveryEngine.new(localStore, peerStore, network, discovery, pendingBlocks)
|
|
engine = BlockExcEngine.new(
|
|
localStore, wallet, network, blockDiscovery, advertiser, peerStore,
|
|
pendingBlocks,
|
|
)
|
|
networkStore = NetworkStore.new(engine, localStore)
|
|
|
|
switch.mount(network)
|
|
|
|
let nc: NodesComponents = (
|
|
switch, discovery, wallet, network, localStore, peerStore, pendingBlocks,
|
|
blockDiscovery, engine, networkStore,
|
|
)
|
|
|
|
result.add(nc)
|
|
|
|
proc start*(nodes: NodesComponents) {.async: (raises: [CatchableError]).} =
|
|
await allFuturesThrowing(
|
|
nodes.switch.start(),
|
|
#nodes.blockDiscovery.start(),
|
|
nodes.engine.start(),
|
|
)
|
|
|
|
proc stop*(nodes: NodesComponents) {.async: (raises: [CatchableError]).} =
|
|
await allFuturesThrowing(
|
|
nodes.switch.stop(),
|
|
# nodes.blockDiscovery.stop(),
|
|
nodes.engine.stop(),
|
|
)
|
|
|
|
proc start*(nodes: seq[NodesComponents]) {.async: (raises: [CatchableError]).} =
|
|
await allFuturesThrowing(nodes.mapIt(it.start()).toSeq)
|
|
|
|
proc stop*(nodes: seq[NodesComponents]) {.async: (raises: [CatchableError]).} =
|
|
await allFuturesThrowing(nodes.mapIt(it.stop()).toSeq)
|
|
|
|
proc connectNodes*(nodes: seq[Switch]) {.async.} =
|
|
for dialer in nodes:
|
|
for node in nodes:
|
|
if dialer.peerInfo.peerId != node.peerInfo.peerId:
|
|
await dialer.connect(node.peerInfo.peerId, node.peerInfo.addrs)
|
|
|
|
proc connectNodes*(nodes: seq[NodesComponents]) {.async.} =
|
|
await connectNodes(nodes.mapIt(it.switch))
|
|
|
|
proc connectNodes(nodes: varargs[NodesComponents]): Future[void] =
|
|
# varargs can't be captured on closures, and async procs are closures,
|
|
# so we have to do this mess
|
|
let copy = nodes.toSeq
|
|
(
|
|
proc() {.async.} =
|
|
await connectNodes(copy.mapIt(it.switch))
|
|
)()
|
|
|
|
proc linearTopology*(nodes: seq[NodesComponents]) {.async.} =
|
|
for i in 0 .. nodes.len - 2:
|
|
await connectNodes(nodes[i], nodes[i + 1])
|
|
|
|
proc downloadDataset*(
|
|
node: NodesComponents, dataset: TestDataset
|
|
): Future[void] {.async.} =
|
|
# This is the same as fetchBatched, but we don't construct CodexNodes so I can't use
|
|
# it here.
|
|
let requestAddresses = collect:
|
|
for i in 0 ..< dataset.manifest.blocksCount:
|
|
BlockAddress.init(dataset.manifest.treeCid, i)
|
|
|
|
let blockCids = dataset.blocks.mapIt(it.cid).toHashSet()
|
|
|
|
var count = 0
|
|
for blockFut in (await node.networkStore.getBlocks(requestAddresses)):
|
|
let blk = (await blockFut).tryGet()
|
|
assert blk.cid in blockCids, "Unknown block CID: " & $blk.cid
|
|
count += 1
|
|
|
|
assert count == dataset.blocks.len, "Incorrect number of blocks downloaded"
|