feat: add block knowledge request mechanism, implement tests

This commit is contained in:
gmega 2025-07-08 15:23:54 -03:00
parent d7c403edfe
commit 2ada4b5eb3
No known key found for this signature in database
GPG Key ID: 6290D34EAD824B18
16 changed files with 255 additions and 92 deletions

View File

@ -121,7 +121,6 @@ proc blockexcTaskRunner(self: BlockExcEngine) {.async: (raises: []).}
proc start*(self: BlockExcEngine) {.async: (raises: []).} = proc start*(self: BlockExcEngine) {.async: (raises: []).} =
## Start the blockexc task ## Start the blockexc task
## ##
await self.discovery.start() await self.discovery.start()
await self.advertiser.start() await self.advertiser.start()
@ -200,11 +199,14 @@ proc refreshBlockKnowledge(self: BlockExcEngine) {.async: (raises: [CancelledErr
# In dynamic swarms, staleness will dominate latency. # In dynamic swarms, staleness will dominate latency.
if peer.lastRefresh < self.pendingBlocks.lastInclusion or peer.isKnowledgeStale: if peer.lastRefresh < self.pendingBlocks.lastInclusion or peer.isKnowledgeStale:
trace "Refreshing block knowledge for peer", peer = peer.id
peer.refreshRequested() peer.refreshRequested()
# TODO: optimize this by keeping track of what was sent and sending deltas. # TODO: optimize this by keeping track of what was sent and sending deltas.
# This should allow us to run much more frequent refreshes, and be way more # This should allow us to run much more frequent refreshes, and be way more
# efficient about it. # efficient about it.
await self.refreshBlockKnowledge(peer) await self.refreshBlockKnowledge(peer)
else:
trace "Not refreshing: peer is up to date", peer = peer.id
proc searchForNewPeers(self: BlockExcEngine, cid: Cid) = proc searchForNewPeers(self: BlockExcEngine, cid: Cid) =
if self.lastDiscRequest + DiscoveryRateLimit < Moment.now(): if self.lastDiscRequest + DiscoveryRateLimit < Moment.now():
@ -336,10 +338,11 @@ proc requestBlocks*(
for address in addresses: for address in addresses:
self.trackedFutures.track(self.downloadInternal(address)) self.trackedFutures.track(self.downloadInternal(address))
var completed: int = 0 let totalHandles = handles.len
var completed = 0
proc isFinished(): bool = proc isFinished(): bool =
completed == handles.len completed == totalHandles
proc genNext(): Future[?!Block] {.async: (raises: [CancelledError]).} = proc genNext(): Future[?!Block] {.async: (raises: [CancelledError]).} =
# Be it success or failure, we're completing this future. # Be it success or failure, we're completing this future.

View File

@ -34,7 +34,7 @@ declareGauge(
const const
DefaultBlockRetries* = 3000 DefaultBlockRetries* = 3000
DefaultRetryInterval* = 5.seconds DefaultRetryInterval* = 1.seconds
type type
RetriesExhaustedError* = object of CatchableError RetriesExhaustedError* = object of CatchableError

View File

@ -341,7 +341,7 @@ proc handlePeerDeparted*(
if not self.handlers.onPeerDeparted.isNil: if not self.handlers.onPeerDeparted.isNil:
await self.handlers.onPeerDeparted(peer) await self.handlers.onPeerDeparted(peer)
method init*(self: BlockExcNetwork) = method init*(self: BlockExcNetwork) {.raises: [].} =
## Perform protocol initialization ## Perform protocol initialization
## ##

View File

@ -26,7 +26,7 @@ import ../../logutils
export payments, nitro export payments, nitro
const const
MinRefreshInterval = 5.seconds MinRefreshInterval = 1.seconds
MaxRefreshBackoff = 36 # 3 minutes MaxRefreshBackoff = 36 # 3 minutes
type BlockExcPeerCtx* = ref object of RootObj type BlockExcPeerCtx* = ref object of RootObj

View File

@ -66,6 +66,21 @@ method getBlock*(
trace "Error requesting block from cache", cid, error = exc.msg trace "Error requesting block from cache", cid, error = exc.msg
return failure exc return failure exc
method getBlocks*(
self: CacheStore, addresses: seq[BlockAddress]
): Future[SafeAsyncIter[Block]] {.async: (raises: [CancelledError]).} =
var i = 0
proc isFinished(): bool =
i == addresses.len
proc genNext(): Future[?!Block] {.async: (raises: [CancelledError]).} =
let value = await self.getBlock(addresses[i])
inc(i)
return value
return SafeAsyncIter[Block].new(genNext, isFinished)
method getCidAndProof*( method getCidAndProof*(
self: CacheStore, treeCid: Cid, index: Natural self: CacheStore, treeCid: Cid, index: Natural
): Future[?!(Cid, CodexProof)] {.async: (raises: [CancelledError]).} = ): Future[?!(Cid, CodexProof)] {.async: (raises: [CancelledError]).} =

View File

@ -54,7 +54,7 @@ asyncchecksuite "Block Advertising and Discovery":
peerStore = PeerCtxStore.new() peerStore = PeerCtxStore.new()
pendingBlocks = PendingBlocksManager.new() pendingBlocks = PendingBlocksManager.new()
(manifest, tree) = makeManifestAndTree(blocks).tryGet() (_, tree, manifest) = makeDataset(blocks).tryGet()
manifestBlock = manifestBlock =
bt.Block.new(manifest.encode().tryGet(), codec = ManifestCodec).tryGet() bt.Block.new(manifest.encode().tryGet(), codec = ManifestCodec).tryGet()
@ -172,7 +172,7 @@ asyncchecksuite "E2E - Multiple Nodes Discovery":
break break
blocks.add(bt.Block.new(chunk).tryGet()) blocks.add(bt.Block.new(chunk).tryGet())
let (manifest, tree) = makeManifestAndTree(blocks).tryGet() let (_, tree, manifest) = makeDataset(blocks).tryGet()
manifests.add(manifest) manifests.add(manifest)
mBlocks.add(manifest.asBlock()) mBlocks.add(manifest.asBlock())
trees.add(tree) trees.add(tree)

View File

@ -43,7 +43,7 @@ asyncchecksuite "Test Discovery Engine":
blocks.add(bt.Block.new(chunk).tryGet()) blocks.add(bt.Block.new(chunk).tryGet())
(manifest, tree) = makeManifestAndTree(blocks).tryGet() (_, tree, manifest) = makeDataset(blocks).tryGet()
manifestBlock = manifest.asBlock() manifestBlock = manifest.asBlock()
blocks.add(manifestBlock) blocks.add(manifestBlock)

View File

@ -24,19 +24,12 @@ asyncchecksuite "NetworkStore engine - 2 nodes":
pendingBlocks1, pendingBlocks2: seq[BlockHandle] pendingBlocks1, pendingBlocks2: seq[BlockHandle]
setup: setup:
blocks1 = await makeRandomBlocks(datasetSize = 2048, blockSize = 256'nb) blocks1 = makeRandomBlocks(nBlocks = 8, blockSize = 256'nb)
blocks2 = await makeRandomBlocks(datasetSize = 2048, blockSize = 256'nb) blocks2 = makeRandomBlocks(nBlocks = 8, blockSize = 256'nb)
nodeCmps1 = generateNodes(1, blocks1)[0] nodeCmps1 = generateNodes(1, blocks1)[0]
nodeCmps2 = generateNodes(1, blocks2)[0] nodeCmps2 = generateNodes(1, blocks2)[0]
await allFuturesThrowing( await allFuturesThrowing(nodeCmps1.start(), nodeCmps2.start())
nodeCmps1.switch.start(),
nodeCmps1.blockDiscovery.start(),
nodeCmps1.engine.start(),
nodeCmps2.switch.start(),
nodeCmps2.blockDiscovery.start(),
nodeCmps2.engine.start(),
)
# initialize our want lists # initialize our want lists
pendingBlocks1 = pendingBlocks1 =
@ -65,14 +58,7 @@ asyncchecksuite "NetworkStore engine - 2 nodes":
check isNil(peerCtx2).not check isNil(peerCtx2).not
teardown: teardown:
await allFuturesThrowing( await allFuturesThrowing(nodeCmps1.stop(), nodeCmps2.stop())
nodeCmps1.blockDiscovery.stop(),
nodeCmps1.engine.stop(),
nodeCmps1.switch.stop(),
nodeCmps2.blockDiscovery.stop(),
nodeCmps2.engine.stop(),
nodeCmps2.switch.stop(),
)
test "Should exchange blocks on connect": test "Should exchange blocks on connect":
await allFuturesThrowing(allFinished(pendingBlocks1)).wait(10.seconds) await allFuturesThrowing(allFinished(pendingBlocks1)).wait(10.seconds)
@ -145,7 +131,7 @@ asyncchecksuite "NetworkStore - multiple nodes":
blocks: seq[bt.Block] blocks: seq[bt.Block]
setup: setup:
blocks = await makeRandomBlocks(datasetSize = 4096, blockSize = 256'nb) blocks = makeRandomBlocks(nBlocks = 16, blockSize = 256'nb)
nodes = generateNodes(5) nodes = generateNodes(5)
for e in nodes: for e in nodes:
await e.engine.start() await e.engine.start()
@ -203,3 +189,28 @@ asyncchecksuite "NetworkStore - multiple nodes":
check pendingBlocks1.mapIt(it.read) == blocks[0 .. 3] check pendingBlocks1.mapIt(it.read) == blocks[0 .. 3]
check pendingBlocks2.mapIt(it.read) == blocks[12 .. 15] check pendingBlocks2.mapIt(it.read) == blocks[12 .. 15]
asyncchecksuite "NetworkStore - dissemination":
var nodes: seq[NodesComponents]
teardown:
if nodes.len > 0:
await nodes.stop()
test "Should disseminate blocks across large diameter swarm":
let dataset = makeRandomDataset(nBlocks = 60, blockSize = 256'nb).tryGet()
nodes = generateNodes(6, enableDiscovery = false)
await assignBlocks(nodes[0], dataset, 0 .. 9)
await assignBlocks(nodes[1], dataset, 10 .. 19)
await assignBlocks(nodes[2], dataset, 20 .. 29)
await assignBlocks(nodes[3], dataset, 30 .. 39)
await assignBlocks(nodes[4], dataset, 40 .. 49)
await assignBlocks(nodes[5], dataset, 50 .. 59)
await nodes.start()
await nodes.linearTopology()
let downloads = nodes.mapIt(downloadDataset(it, dataset))
await allFuturesThrowing(downloads).wait(20.seconds)

View File

@ -12,13 +12,16 @@ import pkg/codex/rng
import pkg/codex/utils import pkg/codex/utils
import ./helpers/nodeutils import ./helpers/nodeutils
import ./helpers/datasetutils
import ./helpers/randomchunker import ./helpers/randomchunker
import ./helpers/mockchunker import ./helpers/mockchunker
import ./helpers/mockdiscovery import ./helpers/mockdiscovery
import ./helpers/always import ./helpers/always
import ../checktest import ../checktest
export randomchunker, nodeutils, mockdiscovery, mockchunker, always, checktest, manifest export
randomchunker, nodeutils, datasetutils, mockdiscovery, mockchunker, always, checktest,
manifest
export libp2p except setup, eventually export libp2p except setup, eventually
@ -46,23 +49,6 @@ proc lenPrefix*(msg: openArray[byte]): seq[byte] =
return buf return buf
proc makeManifestAndTree*(blocks: seq[Block]): ?!(Manifest, CodexTree) =
if blocks.len == 0:
return failure("Blocks list was empty")
let
datasetSize = blocks.mapIt(it.data.len).foldl(a + b)
blockSize = blocks.mapIt(it.data.len).foldl(max(a, b))
tree = ?CodexTree.init(blocks.mapIt(it.cid))
treeCid = ?tree.rootCid
manifest = Manifest.new(
treeCid = treeCid,
blockSize = NBytes(blockSize),
datasetSize = NBytes(datasetSize),
)
return success((manifest, tree))
proc makeWantList*( proc makeWantList*(
cids: seq[Cid], cids: seq[Cid],
priority: int = 0, priority: int = 0,
@ -91,7 +77,7 @@ proc storeDataGetManifest*(
(await store.putBlock(blk)).tryGet() (await store.putBlock(blk)).tryGet()
let let
(manifest, tree) = makeManifestAndTree(blocks).tryGet() (_, tree, manifest) = makeDataset(blocks).tryGet()
treeCid = tree.rootCid.tryGet() treeCid = tree.rootCid.tryGet()
for i in 0 ..< tree.leavesCount: for i in 0 ..< tree.leavesCount:
@ -110,19 +96,6 @@ proc storeDataGetManifest*(
return await storeDataGetManifest(store, blocks) return await storeDataGetManifest(store, blocks)
proc makeRandomBlocks*(
datasetSize: int, blockSize: NBytes
): Future[seq[Block]] {.async.} =
var chunker =
RandomChunker.new(Rng.instance(), size = datasetSize, chunkSize = blockSize)
while true:
let chunk = await chunker.getBytes()
if chunk.len <= 0:
break
result.add(Block.new(chunk).tryGet())
proc corruptBlocks*( proc corruptBlocks*(
store: BlockStore, manifest: Manifest, blks, bytes: int store: BlockStore, manifest: Manifest, blks, bytes: int
): Future[seq[int]] {.async.} = ): Future[seq[int]] {.async.} =
@ -147,4 +120,5 @@ proc corruptBlocks*(
bytePos.add(ii) bytePos.add(ii)
blk.data[ii] = byte 0 blk.data[ii] = byte 0
return pos return pos

View File

@ -0,0 +1,35 @@
import std/random
import pkg/codex/blocktype as bt
import pkg/codex/merkletree
import pkg/codex/manifest
type TestDataset* = tuple[blocks: seq[Block], tree: CodexTree, manifest: Manifest]
proc makeRandomBlock*(size: NBytes): Block =
let bytes = newSeqWith(size.int, rand(uint8))
Block.new(bytes).tryGet()
proc makeRandomBlocks*(nBlocks: int, blockSize: NBytes): seq[Block] =
for i in 0 ..< nBlocks:
result.add(makeRandomBlock(blockSize))
proc makeDataset*(blocks: seq[Block]): ?!TestDataset =
if blocks.len == 0:
return failure("Blocks list was empty")
let
datasetSize = blocks.mapIt(it.data.len).foldl(a + b)
blockSize = blocks.mapIt(it.data.len).foldl(max(a, b))
tree = ?CodexTree.init(blocks.mapIt(it.cid))
treeCid = ?tree.rootCid
manifest = Manifest.new(
treeCid = treeCid,
blockSize = NBytes(blockSize),
datasetSize = NBytes(datasetSize),
)
return success((blocks, tree, manifest))
proc makeRandomDataset*(nBlocks: int, blockSize: NBytes): ?!TestDataset =
makeDataset(makeRandomBlocks(nBlocks, blockSize))

View File

@ -70,3 +70,31 @@ method provide*(
return return
await d.publishHostProvideHandler(d, host) await d.publishHostProvideHandler(d, host)
proc nullDiscovery*(): MockDiscovery =
proc findBlockProvidersHandler(
d: MockDiscovery, cid: Cid
): Future[seq[SignedPeerRecord]] {.async: (raises: [CancelledError]).} =
return @[]
proc publishBlockProvideHandler(
d: MockDiscovery, cid: Cid
): Future[void] {.async: (raises: [CancelledError]).} =
return
proc findHostProvidersHandler(
d: MockDiscovery, host: ca.Address
): Future[seq[SignedPeerRecord]] {.async: (raises: [CancelledError]).} =
return @[]
proc publishHostProvideHandler(
d: MockDiscovery, host: ca.Address
): Future[void] {.async: (raises: [CancelledError]).} =
return
return MockDiscovery(
findBlockProvidersHandler: findBlockProvidersHandler,
publishBlockProvideHandler: publishBlockProvideHandler,
findHostProvidersHandler: findHostProvidersHandler,
publishHostProvideHandler: publishHostProvideHandler,
)

View File

@ -1,4 +1,5 @@
import std/sequtils import std/sequtils
import std/sets
import pkg/chronos import pkg/chronos
import pkg/libp2p import pkg/libp2p
@ -8,8 +9,14 @@ import pkg/codex/discovery
import pkg/codex/stores import pkg/codex/stores
import pkg/codex/blocktype as bt import pkg/codex/blocktype as bt
import pkg/codex/blockexchange import pkg/codex/blockexchange
import pkg/codex/merkletree
import pkg/codex/manifest
import pkg/codex/utils/safeasynciter
import ./datasetutils
import ./mockdiscovery
import ../examples import ../examples
import ../../helpers
type NodesComponents* = type NodesComponents* =
tuple[ tuple[
@ -25,24 +32,60 @@ type NodesComponents* =
networkStore: NetworkStore, 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*( proc generateNodes*(
num: Natural, blocks: openArray[bt.Block] = [] num: Natural, blocks: openArray[bt.Block] = [], enableDiscovery = true
): seq[NodesComponents] = ): seq[NodesComponents] =
for i in 0 ..< num: for i in 0 ..< num:
let let
switch = newStandardSwitch(transportFlags = {ServerFlags.ReuseAddr}) switch = newStandardSwitch(transportFlags = {ServerFlags.ReuseAddr})
discovery = Discovery.new( discovery =
switch.peerInfo.privateKey, if enableDiscovery:
announceAddrs = Discovery.new(
@[ switch.peerInfo.privateKey,
MultiAddress.init("/ip4/127.0.0.1/tcp/0").expect( announceAddrs =
"Should return multiaddress" @[
) MultiAddress.init("/ip4/127.0.0.1/tcp/0").expect(
], "Should return multiaddress"
) )
],
)
else:
nullDiscovery()
let
wallet = WalletRef.example wallet = WalletRef.example
network = BlockExcNetwork.new(switch) network = BlockExcNetwork.new(switch)
localStore = CacheStore.new(blocks.mapIt(it)) localStore = CacheStore.new(blocks)
peerStore = PeerCtxStore.new() peerStore = PeerCtxStore.new()
pendingBlocks = PendingBlocksManager.new() pendingBlocks = PendingBlocksManager.new()
advertiser = Advertiser.new(localStore, discovery) advertiser = Advertiser.new(localStore, discovery)
@ -63,6 +106,26 @@ proc generateNodes*(
result.add(nc) 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.} = proc connectNodes*(nodes: seq[Switch]) {.async.} =
for dialer in nodes: for dialer in nodes:
for node in nodes: for node in nodes:
@ -71,3 +134,35 @@ proc connectNodes*(nodes: seq[Switch]) {.async.} =
proc connectNodes*(nodes: seq[NodesComponents]) {.async.} = proc connectNodes*(nodes: seq[NodesComponents]) {.async.} =
await connectNodes(nodes.mapIt(it.switch)) 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"

View File

@ -82,7 +82,7 @@ asyncchecksuite "Test Node - Basic":
).tryGet() ).tryGet()
test "Block Batching with corrupted blocks": test "Block Batching with corrupted blocks":
let blocks = await makeRandomBlocks(datasetSize = 64.KiBs.int, blockSize = 64.KiBs) let blocks = makeRandomBlocks(nBlocks = 1, blockSize = 64.KiBs)
assert blocks.len == 1 assert blocks.len == 1
let blk = blocks[0] let blk = blocks[0]
@ -215,7 +215,7 @@ asyncchecksuite "Test Node - Basic":
test "Should delete an entire dataset": test "Should delete an entire dataset":
let let
blocks = await makeRandomBlocks(datasetSize = 2048, blockSize = 256'nb) blocks = makeRandomBlocks(nBlocks = 8, blockSize = 256'nb)
manifest = await storeDataGetManifest(localStore, blocks) manifest = await storeDataGetManifest(localStore, blocks)
manifestBlock = (await store.storeManifest(manifest)).tryGet() manifestBlock = (await store.storeManifest(manifest)).tryGet()
manifestCid = manifestBlock.cid manifestCid = manifestBlock.cid

View File

@ -38,8 +38,8 @@ proc commonBlockStoreTests*(
newBlock2 = Block.new("2".repeat(100).toBytes()).tryGet() newBlock2 = Block.new("2".repeat(100).toBytes()).tryGet()
newBlock3 = Block.new("3".repeat(100).toBytes()).tryGet() newBlock3 = Block.new("3".repeat(100).toBytes()).tryGet()
(manifest, tree) = (_, tree, manifest) =
makeManifestAndTree(@[newBlock, newBlock1, newBlock2, newBlock3]).tryGet() makeDataset(@[newBlock, newBlock1, newBlock2, newBlock3]).tryGet()
if not isNil(before): if not isNil(before):
await before() await before()

View File

@ -364,9 +364,9 @@ asyncchecksuite "RepoStore":
let let
repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =
1000'nb) 1000'nb)
dataset = await makeRandomBlocks(datasetSize = 512, blockSize = 256'nb) (blocks, tree, manifest) =
blk = dataset[0] makeRandomDataset(nBlocks = 2, blockSize = 256'nb).tryGet()
(manifest, tree) = makeManifestAndTree(dataset).tryGet() blk = blocks[0]
treeCid = tree.rootCid.tryGet() treeCid = tree.rootCid.tryGet()
proof = tree.getProof(0).tryGet() proof = tree.getProof(0).tryGet()
@ -381,9 +381,9 @@ asyncchecksuite "RepoStore":
let let
repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =
1000'nb) 1000'nb)
dataset = await makeRandomBlocks(datasetSize = 512, blockSize = 256'nb) (blocks, tree, manifest) =
blk = dataset[0] makeRandomDataset(nBlocks = 2, blockSize = 256'nb).tryGet()
(manifest, tree) = makeManifestAndTree(dataset).tryGet() blk = blocks[0]
treeCid = tree.rootCid.tryGet() treeCid = tree.rootCid.tryGet()
proof = tree.getProof(0).tryGet() proof = tree.getProof(0).tryGet()
@ -397,7 +397,7 @@ asyncchecksuite "RepoStore":
let let
repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =
1000'nb) 1000'nb)
blockPool = await makeRandomBlocks(datasetSize = 768, blockSize = 256'nb) blockPool = makeRandomBlocks(nBlocks = 3, blockSize = 256'nb)
let let
dataset1 = @[blockPool[0], blockPool[1]] dataset1 = @[blockPool[0], blockPool[1]]
@ -406,9 +406,9 @@ asyncchecksuite "RepoStore":
let sharedBlock = blockPool[1] let sharedBlock = blockPool[1]
let let
(manifest1, tree1) = makeManifestAndTree(dataset1).tryGet() (_, tree1, manifest1) = makeDataset(dataset1).tryGet()
treeCid1 = tree1.rootCid.tryGet() treeCid1 = tree1.rootCid.tryGet()
(manifest2, tree2) = makeManifestAndTree(dataset2).tryGet() (_, tree2, manifest2) = makeDataset(dataset2).tryGet()
treeCid2 = tree2.rootCid.tryGet() treeCid2 = tree2.rootCid.tryGet()
(await repo.putBlock(sharedBlock)).tryGet() (await repo.putBlock(sharedBlock)).tryGet()
@ -435,9 +435,9 @@ asyncchecksuite "RepoStore":
let let
repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =
1000'nb) 1000'nb)
dataset = await makeRandomBlocks(datasetSize = 512, blockSize = 256'nb) blocks = makeRandomBlocks(nBlocks = 2, blockSize = 256'nb)
blk = dataset[0] blk = blocks[0]
(manifest, tree) = makeManifestAndTree(dataset).tryGet() (_, tree, manifest) = makeDataset(blocks).tryGet()
treeCid = tree.rootCid.tryGet() treeCid = tree.rootCid.tryGet()
proof = tree.getProof(1).tryGet() proof = tree.getProof(1).tryGet()
@ -455,9 +455,9 @@ asyncchecksuite "RepoStore":
let let
repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =
1000'nb) 1000'nb)
dataset = await makeRandomBlocks(datasetSize = 512, blockSize = 256'nb) blocks = makeRandomBlocks(nBlocks = 2, blockSize = 256'nb)
blk = dataset[0] blk = blocks[0]
(manifest, tree) = makeManifestAndTree(dataset).tryGet() (_, tree, manifest) = makeDataset(blocks).tryGet()
treeCid = tree.rootCid.tryGet() treeCid = tree.rootCid.tryGet()
proof = tree.getProof(1).tryGet() proof = tree.getProof(1).tryGet()

View File

@ -7,12 +7,11 @@ import std/sequtils, chronos
export multisetup, trackers, templeveldb export multisetup, trackers, templeveldb
### taken from libp2p errorhelpers.nim ### taken from libp2p errorhelpers.nim
proc allFuturesThrowing*(args: varargs[FutureBase]): Future[void] = proc allFuturesThrowing(futs: seq[FutureBase]): Future[void] =
# This proc is only meant for use in tests / not suitable for general use. # This proc is only meant for use in tests / not suitable for general use.
# - Swallowing errors arbitrarily instead of aggregating them is bad design # - Swallowing errors arbitrarily instead of aggregating them is bad design
# - It raises `CatchableError` instead of the union of the `futs` errors, # - It raises `CatchableError` instead of the union of the `futs` errors,
# inflating the caller's `raises` list unnecessarily. `macro` could fix it # inflating the caller's `raises` list unnecessarily. `macro` could fix it
let futs = @args
( (
proc() {.async: (raises: [CatchableError]).} = proc() {.async: (raises: [CatchableError]).} =
await allFutures(futs) await allFutures(futs)
@ -28,6 +27,9 @@ proc allFuturesThrowing*(args: varargs[FutureBase]): Future[void] =
raise firstErr raise firstErr
)() )()
proc allFuturesThrowing*(args: varargs[FutureBase]): Future[void] =
allFuturesThrowing(@args)
proc allFuturesThrowing*[T](futs: varargs[Future[T]]): Future[void] = proc allFuturesThrowing*[T](futs: varargs[Future[T]]): Future[void] =
allFuturesThrowing(futs.mapIt(FutureBase(it))) allFuturesThrowing(futs.mapIt(FutureBase(it)))