parent
06bb21bfc7
commit
8d61391073
|
@ -122,9 +122,9 @@ proc stop*(b: BlockExcEngine) {.async.} =
|
||||||
|
|
||||||
|
|
||||||
proc sendWantHave(
|
proc sendWantHave(
|
||||||
b: BlockExcEngine,
|
b: BlockExcEngine,
|
||||||
address: BlockAddress,
|
address: BlockAddress,
|
||||||
selectedPeer: BlockExcPeerCtx,
|
selectedPeer: BlockExcPeerCtx,
|
||||||
peers: seq[BlockExcPeerCtx]): Future[void] {.async.} =
|
peers: seq[BlockExcPeerCtx]): Future[void] {.async.} =
|
||||||
trace "Sending wantHave request to peers", address
|
trace "Sending wantHave request to peers", address
|
||||||
for p in peers:
|
for p in peers:
|
||||||
|
@ -137,8 +137,8 @@ proc sendWantHave(
|
||||||
wantType = WantType.WantHave) # we only want to know if the peer has the block
|
wantType = WantType.WantHave) # we only want to know if the peer has the block
|
||||||
|
|
||||||
proc sendWantBlock(
|
proc sendWantBlock(
|
||||||
b: BlockExcEngine,
|
b: BlockExcEngine,
|
||||||
address: BlockAddress,
|
address: BlockAddress,
|
||||||
blockPeer: BlockExcPeerCtx): Future[void] {.async.} =
|
blockPeer: BlockExcPeerCtx): Future[void] {.async.} =
|
||||||
trace "Sending wantBlock request to", peer = blockPeer.id, address
|
trace "Sending wantBlock request to", peer = blockPeer.id, address
|
||||||
await b.network.request.sendWantList(
|
await b.network.request.sendWantList(
|
||||||
|
@ -189,14 +189,14 @@ proc requestBlock*(
|
||||||
if peers.len == 0:
|
if peers.len == 0:
|
||||||
b.discovery.queueFindBlocksReq(@[address.cidOrTreeCid])
|
b.discovery.queueFindBlocksReq(@[address.cidOrTreeCid])
|
||||||
|
|
||||||
let maybePeer =
|
let maybePeer =
|
||||||
if peers.len > 0:
|
if peers.len > 0:
|
||||||
peers[hash(address) mod peers.len].some
|
peers[hash(address) mod peers.len].some
|
||||||
elif b.peers.len > 0:
|
elif b.peers.len > 0:
|
||||||
toSeq(b.peers)[hash(address) mod b.peers.len].some
|
toSeq(b.peers)[hash(address) mod b.peers.len].some
|
||||||
else:
|
else:
|
||||||
BlockExcPeerCtx.none
|
BlockExcPeerCtx.none
|
||||||
|
|
||||||
if peer =? maybePeer:
|
if peer =? maybePeer:
|
||||||
asyncSpawn b.monitorBlockHandle(blockFuture, address, peer.id)
|
asyncSpawn b.monitorBlockHandle(blockFuture, address, peer.id)
|
||||||
b.pendingBlocks.setInFlight(address)
|
b.pendingBlocks.setInFlight(address)
|
||||||
|
@ -204,7 +204,7 @@ proc requestBlock*(
|
||||||
codex_block_exchange_want_block_lists_sent.inc()
|
codex_block_exchange_want_block_lists_sent.inc()
|
||||||
await b.sendWantHave(address, peer, toSeq(b.peers))
|
await b.sendWantHave(address, peer, toSeq(b.peers))
|
||||||
codex_block_exchange_want_have_lists_sent.inc()
|
codex_block_exchange_want_have_lists_sent.inc()
|
||||||
|
|
||||||
return await blockFuture
|
return await blockFuture
|
||||||
|
|
||||||
proc requestBlock*(
|
proc requestBlock*(
|
||||||
|
@ -320,7 +320,7 @@ proc validateBlockDelivery(
|
||||||
if bd.address.leaf:
|
if bd.address.leaf:
|
||||||
without proof =? bd.proof:
|
without proof =? bd.proof:
|
||||||
return failure("Missing proof")
|
return failure("Missing proof")
|
||||||
|
|
||||||
if proof.index != bd.address.index:
|
if proof.index != bd.address.index:
|
||||||
return failure("Proof index " & $proof.index & " doesn't match leaf index " & $bd.address.index)
|
return failure("Proof index " & $proof.index & " doesn't match leaf index " & $bd.address.index)
|
||||||
|
|
||||||
|
@ -539,7 +539,7 @@ proc taskHandler*(b: BlockExcEngine, task: BlockExcPeerCtx) {.gcsafe, async.} =
|
||||||
trace "Handling lookup for entry", address = e.address
|
trace "Handling lookup for entry", address = e.address
|
||||||
if e.address.leaf:
|
if e.address.leaf:
|
||||||
(await b.localStore.getBlockAndProof(e.address.treeCid, e.address.index)).map(
|
(await b.localStore.getBlockAndProof(e.address.treeCid, e.address.index)).map(
|
||||||
(blkAndProof: (Block, MerkleProof)) =>
|
(blkAndProof: (Block, MerkleProof)) =>
|
||||||
BlockDelivery(address: e.address, blk: blkAndProof[0], proof: blkAndProof[1].some)
|
BlockDelivery(address: e.address, blk: blkAndProof[0], proof: blkAndProof[1].some)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -102,7 +102,7 @@ proc resolve*(
|
||||||
retrievalDurationUs = (stopTime - startTime) div 1000
|
retrievalDurationUs = (stopTime - startTime) div 1000
|
||||||
|
|
||||||
blockReq.handle.complete(bd.blk)
|
blockReq.handle.complete(bd.blk)
|
||||||
|
|
||||||
codex_block_exchange_retrieval_time_us.set(retrievalDurationUs)
|
codex_block_exchange_retrieval_time_us.set(retrievalDurationUs)
|
||||||
trace "Block retrieval time", retrievalDurationUs, address = bd.address
|
trace "Block retrieval time", retrievalDurationUs, address = bd.address
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -96,7 +96,7 @@ func new*(
|
||||||
codec = multiCodec("raw")
|
codec = multiCodec("raw")
|
||||||
): ?!Block =
|
): ?!Block =
|
||||||
## creates a new block for both storage and network IO
|
## creates a new block for both storage and network IO
|
||||||
##
|
##
|
||||||
|
|
||||||
let
|
let
|
||||||
hash = ? MultiHash.digest($mcodec, data).mapFailure
|
hash = ? MultiHash.digest($mcodec, data).mapFailure
|
||||||
|
@ -132,7 +132,7 @@ func new*(
|
||||||
|
|
||||||
proc emptyCid*(version: CidVersion, hcodec: MultiCodec, dcodec: MultiCodec): ?!Cid =
|
proc emptyCid*(version: CidVersion, hcodec: MultiCodec, dcodec: MultiCodec): ?!Cid =
|
||||||
## Returns cid representing empty content, given cid version, hash codec and data codec
|
## Returns cid representing empty content, given cid version, hash codec and data codec
|
||||||
##
|
##
|
||||||
|
|
||||||
const
|
const
|
||||||
Sha256 = multiCodec("sha2-256")
|
Sha256 = multiCodec("sha2-256")
|
||||||
|
@ -161,11 +161,11 @@ proc emptyBlock*(version: CidVersion, hcodec: MultiCodec): ?!Block =
|
||||||
.flatMap((cid: Cid) => Block.new(cid = cid, data = @[]))
|
.flatMap((cid: Cid) => Block.new(cid = cid, data = @[]))
|
||||||
|
|
||||||
proc emptyBlock*(cid: Cid): ?!Block =
|
proc emptyBlock*(cid: Cid): ?!Block =
|
||||||
cid.mhash.mapFailure.flatMap((mhash: MultiHash) =>
|
cid.mhash.mapFailure.flatMap((mhash: MultiHash) =>
|
||||||
emptyBlock(cid.cidver, mhash.mcodec))
|
emptyBlock(cid.cidver, mhash.mcodec))
|
||||||
|
|
||||||
proc isEmpty*(cid: Cid): bool =
|
proc isEmpty*(cid: Cid): bool =
|
||||||
success(cid) == cid.mhash.mapFailure.flatMap((mhash: MultiHash) =>
|
success(cid) == cid.mhash.mapFailure.flatMap((mhash: MultiHash) =>
|
||||||
emptyCid(cid.cidver, mhash.mcodec, cid.mcodec))
|
emptyCid(cid.cidver, mhash.mcodec, cid.mcodec))
|
||||||
|
|
||||||
proc isEmpty*(blk: Block): bool =
|
proc isEmpty*(blk: Block): bool =
|
||||||
|
|
|
@ -102,7 +102,7 @@ proc getPendingBlocks(
|
||||||
|
|
||||||
proc isFinished(): bool = pendingBlocks.len == 0
|
proc isFinished(): bool = pendingBlocks.len == 0
|
||||||
|
|
||||||
proc genNext(): Future[(?!bt.Block, int)] {.async.} =
|
proc genNext(): Future[(?!bt.Block, int)] {.async.} =
|
||||||
let completedFut = await one(pendingBlocks)
|
let completedFut = await one(pendingBlocks)
|
||||||
if (let i = pendingBlocks.find(completedFut); i >= 0):
|
if (let i = pendingBlocks.find(completedFut); i >= 0):
|
||||||
pendingBlocks.del(i)
|
pendingBlocks.del(i)
|
||||||
|
@ -112,7 +112,7 @@ proc getPendingBlocks(
|
||||||
raise newException(CatchableError, "Future for block id not found, tree cid: " & $manifest.treeCid & ", index: " & $index)
|
raise newException(CatchableError, "Future for block id not found, tree cid: " & $manifest.treeCid & ", index: " & $index)
|
||||||
|
|
||||||
Iter.new(genNext, isFinished)
|
Iter.new(genNext, isFinished)
|
||||||
|
|
||||||
proc prepareEncodingData(
|
proc prepareEncodingData(
|
||||||
self: Erasure,
|
self: Erasure,
|
||||||
manifest: Manifest,
|
manifest: Manifest,
|
||||||
|
@ -134,7 +134,7 @@ proc prepareEncodingData(
|
||||||
without blk =? blkOrErr, err:
|
without blk =? blkOrErr, err:
|
||||||
warn "Failed retreiving a block", treeCid = manifest.treeCid, idx, msg = err.msg
|
warn "Failed retreiving a block", treeCid = manifest.treeCid, idx, msg = err.msg
|
||||||
continue
|
continue
|
||||||
|
|
||||||
let pos = indexToPos(params.steps, idx, step)
|
let pos = indexToPos(params.steps, idx, step)
|
||||||
shallowCopy(data[pos], if blk.isEmpty: emptyBlock else: blk.data)
|
shallowCopy(data[pos], if blk.isEmpty: emptyBlock else: blk.data)
|
||||||
cids[idx] = blk.cid
|
cids[idx] = blk.cid
|
||||||
|
@ -168,7 +168,7 @@ proc prepareDecodingData(
|
||||||
## `emptyBlock` - the empty block to be used for padding
|
## `emptyBlock` - the empty block to be used for padding
|
||||||
##
|
##
|
||||||
|
|
||||||
let
|
let
|
||||||
indicies = toSeq(countup(step, encoded.blocksCount - 1, encoded.steps))
|
indicies = toSeq(countup(step, encoded.blocksCount - 1, encoded.steps))
|
||||||
pendingBlocksIter = self.getPendingBlocks(encoded, indicies)
|
pendingBlocksIter = self.getPendingBlocks(encoded, indicies)
|
||||||
|
|
||||||
|
|
|
@ -30,17 +30,17 @@ export types
|
||||||
|
|
||||||
type
|
type
|
||||||
Manifest* = ref object of RootObj
|
Manifest* = ref object of RootObj
|
||||||
treeCid {.serialize.}: Cid # Root of the merkle tree
|
treeCid {.serialize.}: Cid # Root of the merkle tree
|
||||||
datasetSize {.serialize.}: NBytes # Total size of all blocks
|
datasetSize {.serialize.}: NBytes # Total size of all blocks
|
||||||
blockSize {.serialize.}: NBytes # Size of each contained block (might not be needed if blocks are len-prefixed)
|
blockSize {.serialize.}: NBytes # Size of each contained block (might not be needed if blocks are len-prefixed)
|
||||||
version: CidVersion # Cid version
|
version: CidVersion # Cid version
|
||||||
hcodec: MultiCodec # Multihash codec
|
hcodec: MultiCodec # Multihash codec
|
||||||
codec: MultiCodec # Data set codec
|
codec: MultiCodec # Data set codec
|
||||||
case protected {.serialize.}: bool # Protected datasets have erasure coded info
|
case protected {.serialize.}: bool # Protected datasets have erasure coded info
|
||||||
of true:
|
of true:
|
||||||
ecK: int # Number of blocks to encode
|
ecK: int # Number of blocks to encode
|
||||||
ecM: int # Number of resulting parity blocks
|
ecM: int # Number of resulting parity blocks
|
||||||
originalTreeCid: Cid # The original root of the dataset being erasure coded
|
originalTreeCid: Cid # The original root of the dataset being erasure coded
|
||||||
originalDatasetSize: NBytes
|
originalDatasetSize: NBytes
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
|
@ -46,7 +46,7 @@ type
|
||||||
###########################################################
|
###########################################################
|
||||||
|
|
||||||
func computeTreeHeight(leavesCount: int): int =
|
func computeTreeHeight(leavesCount: int): int =
|
||||||
if isPowerOfTwo(leavesCount):
|
if isPowerOfTwo(leavesCount):
|
||||||
fastLog2(leavesCount) + 1
|
fastLog2(leavesCount) + 1
|
||||||
else:
|
else:
|
||||||
fastLog2(leavesCount) + 2
|
fastLog2(leavesCount) + 2
|
||||||
|
@ -84,16 +84,16 @@ proc init*(
|
||||||
|
|
||||||
proc addDataBlock*(self: var MerkleTreeBuilder, dataBlock: openArray[byte]): ?!void =
|
proc addDataBlock*(self: var MerkleTreeBuilder, dataBlock: openArray[byte]): ?!void =
|
||||||
## Hashes the data block and adds the result of hashing to a buffer
|
## Hashes the data block and adds the result of hashing to a buffer
|
||||||
##
|
##
|
||||||
let oldLen = self.buffer.len
|
let oldLen = self.buffer.len
|
||||||
self.buffer.setLen(oldLen + self.digestSize)
|
self.buffer.setLen(oldLen + self.digestSize)
|
||||||
digestFn(self.mcodec, self.buffer, oldLen, dataBlock)
|
digestFn(self.mcodec, self.buffer, oldLen, dataBlock)
|
||||||
|
|
||||||
proc addLeaf*(self: var MerkleTreeBuilder, leaf: MultiHash): ?!void =
|
proc addLeaf*(self: var MerkleTreeBuilder, leaf: MultiHash): ?!void =
|
||||||
if leaf.mcodec != self.mcodec or leaf.size != self.digestSize:
|
if leaf.mcodec != self.mcodec or leaf.size != self.digestSize:
|
||||||
return failure("Expected mcodec to be " & $self.mcodec & " and digest size to be " &
|
return failure("Expected mcodec to be " & $self.mcodec & " and digest size to be " &
|
||||||
$self.digestSize & " but was " & $leaf.mcodec & " and " & $leaf.size)
|
$self.digestSize & " but was " & $leaf.mcodec & " and " & $leaf.size)
|
||||||
|
|
||||||
let oldLen = self.buffer.len
|
let oldLen = self.buffer.len
|
||||||
self.buffer.setLen(oldLen + self.digestSize)
|
self.buffer.setLen(oldLen + self.digestSize)
|
||||||
self.buffer[oldLen..<oldLen + self.digestSize] = leaf.data.buffer[leaf.dpos..<leaf.dpos + self.digestSize]
|
self.buffer[oldLen..<oldLen + self.digestSize] = leaf.data.buffer[leaf.dpos..<leaf.dpos + self.digestSize]
|
||||||
|
@ -101,7 +101,7 @@ proc addLeaf*(self: var MerkleTreeBuilder, leaf: MultiHash): ?!void =
|
||||||
|
|
||||||
proc build*(self: MerkleTreeBuilder): ?!MerkleTree =
|
proc build*(self: MerkleTreeBuilder): ?!MerkleTree =
|
||||||
## Builds a tree from previously added data blocks
|
## Builds a tree from previously added data blocks
|
||||||
##
|
##
|
||||||
## Tree built from data blocks A, B and C is
|
## Tree built from data blocks A, B and C is
|
||||||
## H5=H(H3 & H4)
|
## H5=H(H3 & H4)
|
||||||
## / \
|
## / \
|
||||||
|
@ -114,7 +114,7 @@ proc build*(self: MerkleTreeBuilder): ?!MerkleTree =
|
||||||
## Memory layout is [H0, H1, H2, H3, H4, H5]
|
## Memory layout is [H0, H1, H2, H3, H4, H5]
|
||||||
##
|
##
|
||||||
let
|
let
|
||||||
mcodec = self.mcodec
|
mcodec = self.mcodec
|
||||||
digestSize = self.digestSize
|
digestSize = self.digestSize
|
||||||
leavesCount = self.buffer.len div self.digestSize
|
leavesCount = self.buffer.len div self.digestSize
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ proc build*(self: MerkleTreeBuilder): ?!MerkleTree =
|
||||||
|
|
||||||
let levels = computeLevels(leavesCount)
|
let levels = computeLevels(leavesCount)
|
||||||
let totalNodes = levels[^1].offset + 1
|
let totalNodes = levels[^1].offset + 1
|
||||||
|
|
||||||
var tree = MerkleTree(mcodec: mcodec, digestSize: digestSize, leavesCount: leavesCount, nodesBuffer: newSeq[byte](totalNodes * digestSize))
|
var tree = MerkleTree(mcodec: mcodec, digestSize: digestSize, leavesCount: leavesCount, nodesBuffer: newSeq[byte](totalNodes * digestSize))
|
||||||
|
|
||||||
# copy leaves
|
# copy leaves
|
||||||
|
@ -134,7 +134,7 @@ proc build*(self: MerkleTreeBuilder): ?!MerkleTree =
|
||||||
var one = newSeq[byte](digestSize)
|
var one = newSeq[byte](digestSize)
|
||||||
one[^1] = 0x01
|
one[^1] = 0x01
|
||||||
|
|
||||||
var
|
var
|
||||||
concatBuf = newSeq[byte](2 * digestSize)
|
concatBuf = newSeq[byte](2 * digestSize)
|
||||||
prevLevel = levels[0]
|
prevLevel = levels[0]
|
||||||
for level in levels[1..^1]:
|
for level in levels[1..^1]:
|
||||||
|
@ -180,7 +180,7 @@ proc nodes*(self: (MerkleTree | MerkleProof)): seq[MultiHash] {.noSideEffect.} =
|
||||||
proc mcodec*(self: (MerkleTree | MerkleProof)): MultiCodec =
|
proc mcodec*(self: (MerkleTree | MerkleProof)): MultiCodec =
|
||||||
self.mcodec
|
self.mcodec
|
||||||
|
|
||||||
proc digestSize*(self: (MerkleTree | MerkleProof)): Natural =
|
proc digestSize*(self: (MerkleTree | MerkleProof)): Natural =
|
||||||
self.digestSize
|
self.digestSize
|
||||||
|
|
||||||
proc root*(self: MerkleTree): MultiHash =
|
proc root*(self: MerkleTree): MultiHash =
|
||||||
|
@ -204,7 +204,7 @@ proc leavesCount*(self: MerkleTree): Natural =
|
||||||
proc getLeaf*(self: MerkleTree, index: Natural): ?!MultiHash =
|
proc getLeaf*(self: MerkleTree, index: Natural): ?!MultiHash =
|
||||||
if index >= self.leavesCount:
|
if index >= self.leavesCount:
|
||||||
return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" )
|
return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" )
|
||||||
|
|
||||||
success(self.nodeBufferToMultiHash(index))
|
success(self.nodeBufferToMultiHash(index))
|
||||||
|
|
||||||
proc getLeafCid*(self: MerkleTree, index: Natural, version = CIDv1, dataCodec = multiCodec("raw")): ?!Cid =
|
proc getLeafCid*(self: MerkleTree, index: Natural, version = CIDv1, dataCodec = multiCodec("raw")): ?!Cid =
|
||||||
|
@ -216,7 +216,7 @@ proc height*(self: MerkleTree): Natural =
|
||||||
|
|
||||||
proc getProof*(self: MerkleTree, index: Natural): ?!MerkleProof =
|
proc getProof*(self: MerkleTree, index: Natural): ?!MerkleProof =
|
||||||
## Extracts proof from a tree for a given index
|
## Extracts proof from a tree for a given index
|
||||||
##
|
##
|
||||||
## Given a tree built from data blocks A, B and C
|
## Given a tree built from data blocks A, B and C
|
||||||
## H5
|
## H5
|
||||||
## / \
|
## / \
|
||||||
|
@ -230,7 +230,7 @@ proc getProof*(self: MerkleTree, index: Natural): ?!MerkleProof =
|
||||||
## - 0,[H1, H4] for data block A
|
## - 0,[H1, H4] for data block A
|
||||||
## - 1,[H0, H4] for data block B
|
## - 1,[H0, H4] for data block B
|
||||||
## - 2,[0x00, H3] for data block C
|
## - 2,[0x00, H3] for data block C
|
||||||
##
|
##
|
||||||
if index >= self.leavesCount:
|
if index >= self.leavesCount:
|
||||||
return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" )
|
return failure("Index " & $index & " out of range [0.." & $(self.leavesCount - 1) & "]" )
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ proc getProof*(self: MerkleTree, index: Natural): ?!MerkleProof =
|
||||||
var dummyValue = if level.index == 0: zero else: one
|
var dummyValue = if level.index == 0: zero else: one
|
||||||
|
|
||||||
if siblingIndex < level.offset + level.width:
|
if siblingIndex < level.offset + level.width:
|
||||||
proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] =
|
proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] =
|
||||||
self.nodesBuffer[siblingIndex * self.digestSize..<(siblingIndex + 1) * self.digestSize]
|
self.nodesBuffer[siblingIndex * self.digestSize..<(siblingIndex + 1) * self.digestSize]
|
||||||
else:
|
else:
|
||||||
proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] = dummyValue
|
proofNodesBuffer[level.index * self.digestSize..<(level.index + 1) * self.digestSize] = dummyValue
|
||||||
|
@ -281,9 +281,9 @@ proc init*(
|
||||||
if totalNodes * digestSize == nodesBuffer.len:
|
if totalNodes * digestSize == nodesBuffer.len:
|
||||||
success(
|
success(
|
||||||
MerkleTree(
|
MerkleTree(
|
||||||
mcodec: mcodec,
|
mcodec: mcodec,
|
||||||
digestSize: digestSize,
|
digestSize: digestSize,
|
||||||
leavesCount: leavesCount,
|
leavesCount: leavesCount,
|
||||||
nodesBuffer: nodesBuffer
|
nodesBuffer: nodesBuffer
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -296,14 +296,14 @@ proc init*(
|
||||||
): ?!MerkleTree =
|
): ?!MerkleTree =
|
||||||
without leaf =? leaves.?[0]:
|
without leaf =? leaves.?[0]:
|
||||||
return failure("At least one leaf is required")
|
return failure("At least one leaf is required")
|
||||||
|
|
||||||
var builder = ? MerkleTreeBuilder.init(mcodec = leaf.mcodec)
|
var builder = ? MerkleTreeBuilder.init(mcodec = leaf.mcodec)
|
||||||
|
|
||||||
for l in leaves:
|
for l in leaves:
|
||||||
let res = builder.addLeaf(l)
|
let res = builder.addLeaf(l)
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
return failure(res.error)
|
return failure(res.error)
|
||||||
|
|
||||||
builder.build()
|
builder.build()
|
||||||
|
|
||||||
proc init*(
|
proc init*(
|
||||||
|
@ -311,7 +311,7 @@ proc init*(
|
||||||
cids: openArray[Cid]
|
cids: openArray[Cid]
|
||||||
): ?!MerkleTree =
|
): ?!MerkleTree =
|
||||||
var leaves = newSeq[MultiHash]()
|
var leaves = newSeq[MultiHash]()
|
||||||
|
|
||||||
for cid in cids:
|
for cid in cids:
|
||||||
let res = cid.mhash.mapFailure
|
let res = cid.mhash.mapFailure
|
||||||
if res.isErr:
|
if res.isErr:
|
||||||
|
@ -345,7 +345,7 @@ proc verifyLeaf*(self: MerkleProof, leaf: MultiHash, treeRoot: MultiHash): ?!boo
|
||||||
else:
|
else:
|
||||||
concatBuf[0..^1] = self.nodesBuffer[offset..<(offset + self.digestSize)] & digestBuf
|
concatBuf[0..^1] = self.nodesBuffer[offset..<(offset + self.digestSize)] & digestBuf
|
||||||
? digestFn(self.mcodec, digestBuf, 0, concatBuf)
|
? digestFn(self.mcodec, digestBuf, 0, concatBuf)
|
||||||
|
|
||||||
let computedRoot = ? MultiHash.init(self.mcodec, digestBuf).mapFailure
|
let computedRoot = ? MultiHash.init(self.mcodec, digestBuf).mapFailure
|
||||||
|
|
||||||
success(computedRoot == treeRoot)
|
success(computedRoot == treeRoot)
|
||||||
|
@ -369,8 +369,8 @@ proc `$`*(self: MerkleProof): string =
|
||||||
", nodes: " & $self.nodes
|
", nodes: " & $self.nodes
|
||||||
|
|
||||||
func `==`*(a, b: MerkleProof): bool =
|
func `==`*(a, b: MerkleProof): bool =
|
||||||
(a.index == b.index) and
|
(a.index == b.index) and
|
||||||
(a.mcodec == b.mcodec) and
|
(a.mcodec == b.mcodec) and
|
||||||
(a.digestSize == b.digestSize) and
|
(a.digestSize == b.digestSize) and
|
||||||
(a.nodesBuffer == b.nodesBuffer)
|
(a.nodesBuffer == b.nodesBuffer)
|
||||||
|
|
||||||
|
@ -385,11 +385,11 @@ proc init*(
|
||||||
let
|
let
|
||||||
mcodec = nodes[0].mcodec
|
mcodec = nodes[0].mcodec
|
||||||
digestSize = nodes[0].size
|
digestSize = nodes[0].size
|
||||||
|
|
||||||
var nodesBuffer = newSeq[byte](nodes.len * digestSize)
|
var nodesBuffer = newSeq[byte](nodes.len * digestSize)
|
||||||
for nodeIndex, node in nodes:
|
for nodeIndex, node in nodes:
|
||||||
nodesBuffer[nodeIndex * digestSize..<(nodeIndex + 1) * digestSize] = node.data.buffer[node.dpos..<node.dpos + digestSize]
|
nodesBuffer[nodeIndex * digestSize..<(nodeIndex + 1) * digestSize] = node.data.buffer[node.dpos..<node.dpos + digestSize]
|
||||||
|
|
||||||
success(MerkleProof(mcodec: mcodec, digestSize: digestSize, index: index, nodesBuffer: nodesBuffer))
|
success(MerkleProof(mcodec: mcodec, digestSize: digestSize, index: index, nodesBuffer: nodesBuffer))
|
||||||
|
|
||||||
func init*(
|
func init*(
|
||||||
|
|
|
@ -111,7 +111,7 @@ proc fetchBatched*(
|
||||||
onBatch: BatchProc = nil): Future[?!void] {.async, gcsafe.} =
|
onBatch: BatchProc = nil): Future[?!void] {.async, gcsafe.} =
|
||||||
## Fetch manifest in batches of `batchSize`
|
## Fetch manifest in batches of `batchSize`
|
||||||
##
|
##
|
||||||
|
|
||||||
let batchCount = divUp(manifest.blocksCount, batchSize)
|
let batchCount = divUp(manifest.blocksCount, batchSize)
|
||||||
|
|
||||||
trace "Fetching blocks in batches of", size = batchSize
|
trace "Fetching blocks in batches of", size = batchSize
|
||||||
|
@ -209,7 +209,7 @@ proc store*(
|
||||||
|
|
||||||
without blk =? bt.Block.new(cid, chunk, verify = false):
|
without blk =? bt.Block.new(cid, chunk, verify = false):
|
||||||
return failure("Unable to init block from chunk!")
|
return failure("Unable to init block from chunk!")
|
||||||
|
|
||||||
cids.add(cid)
|
cids.add(cid)
|
||||||
|
|
||||||
if err =? (await self.blockStore.putBlock(blk)).errorOption:
|
if err =? (await self.blockStore.putBlock(blk)).errorOption:
|
||||||
|
@ -228,7 +228,7 @@ proc store*(
|
||||||
|
|
||||||
without treeCid =? tree.rootCid(CIDv1, dataCodec), err:
|
without treeCid =? tree.rootCid(CIDv1, dataCodec), err:
|
||||||
return failure(err)
|
return failure(err)
|
||||||
|
|
||||||
for index, cid in cids:
|
for index, cid in cids:
|
||||||
without proof =? tree.getProof(index), err:
|
without proof =? tree.getProof(index), err:
|
||||||
return failure(err)
|
return failure(err)
|
||||||
|
|
|
@ -51,8 +51,8 @@ method getBlock*(self: BlockStore, address: BlockAddress): Future[?!Block] {.bas
|
||||||
|
|
||||||
method getBlockAndProof*(self: BlockStore, treeCid: Cid, index: Natural): Future[?!(Block, MerkleProof)] {.base.} =
|
method getBlockAndProof*(self: BlockStore, treeCid: Cid, index: Natural): Future[?!(Block, MerkleProof)] {.base.} =
|
||||||
## Get a block and associated inclusion proof by Cid of a merkle tree and an index of a leaf in a tree
|
## Get a block and associated inclusion proof by Cid of a merkle tree and an index of a leaf in a tree
|
||||||
##
|
##
|
||||||
|
|
||||||
raiseAssert("getBlockAndProof not implemented!")
|
raiseAssert("getBlockAndProof not implemented!")
|
||||||
|
|
||||||
method putBlock*(
|
method putBlock*(
|
||||||
|
|
|
@ -250,7 +250,7 @@ method delBlock*(self: CacheStore, treeCid: Cid, index: Natural): Future[?!void]
|
||||||
|
|
||||||
if removed =? maybeRemoved:
|
if removed =? maybeRemoved:
|
||||||
return await self.delBlock(removed[0])
|
return await self.delBlock(removed[0])
|
||||||
|
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
method close*(self: CacheStore): Future[void] {.async.} =
|
method close*(self: CacheStore): Future[void] {.async.} =
|
||||||
|
|
|
@ -62,7 +62,7 @@ type
|
||||||
BlockExpiration* = object
|
BlockExpiration* = object
|
||||||
cid*: Cid
|
cid*: Cid
|
||||||
expiration*: SecondsSince1970
|
expiration*: SecondsSince1970
|
||||||
|
|
||||||
proc updateMetrics(self: RepoStore) =
|
proc updateMetrics(self: RepoStore) =
|
||||||
codex_repostore_blocks.set(self.totalBlocks.int64)
|
codex_repostore_blocks.set(self.totalBlocks.int64)
|
||||||
codex_repostore_bytes_used.set(self.quotaUsedBytes.int64)
|
codex_repostore_bytes_used.set(self.quotaUsedBytes.int64)
|
||||||
|
@ -81,10 +81,10 @@ proc encode(cidAndProof: (Cid, MerkleProof)): seq[byte] =
|
||||||
## Encodes a tuple of cid and merkle proof in a following format:
|
## Encodes a tuple of cid and merkle proof in a following format:
|
||||||
## | 8-bytes | n-bytes | remaining bytes |
|
## | 8-bytes | n-bytes | remaining bytes |
|
||||||
## | n | cid | proof |
|
## | n | cid | proof |
|
||||||
##
|
##
|
||||||
## where n is a size of cid
|
## where n is a size of cid
|
||||||
##
|
##
|
||||||
let
|
let
|
||||||
(cid, proof) = cidAndProof
|
(cid, proof) = cidAndProof
|
||||||
cidBytes = cid.data.buffer
|
cidBytes = cid.data.buffer
|
||||||
proofBytes = proof.encode
|
proofBytes = proof.encode
|
||||||
|
@ -96,7 +96,6 @@ proc encode(cidAndProof: (Cid, MerkleProof)): seq[byte] =
|
||||||
proc decode(_: type (Cid, MerkleProof), data: seq[byte]): ?!(Cid, MerkleProof) =
|
proc decode(_: type (Cid, MerkleProof), data: seq[byte]): ?!(Cid, MerkleProof) =
|
||||||
let
|
let
|
||||||
n = uint64.fromBytesBE(data[0..<sizeof(uint64)]).int
|
n = uint64.fromBytesBE(data[0..<sizeof(uint64)]).int
|
||||||
let
|
|
||||||
cid = ? Cid.init(data[sizeof(uint64)..<sizeof(uint64) + n]).mapFailure
|
cid = ? Cid.init(data[sizeof(uint64)..<sizeof(uint64) + n]).mapFailure
|
||||||
proof = ? MerkleProof.decode(data[sizeof(uint64) + n..^1])
|
proof = ? MerkleProof.decode(data[sizeof(uint64) + n..^1])
|
||||||
success((cid, proof))
|
success((cid, proof))
|
||||||
|
|
|
@ -54,14 +54,14 @@ proc new*[T](_: type Iter, genNext: GenNext[T], isFinished: IsFinished, finishOn
|
||||||
|
|
||||||
if isFinished():
|
if isFinished():
|
||||||
iter.finish
|
iter.finish
|
||||||
|
|
||||||
iter.next = next
|
iter.next = next
|
||||||
return iter
|
return iter
|
||||||
|
|
||||||
proc fromItems*[T](_: type Iter, items: seq[T]): Iter[T] =
|
proc fromItems*[T](_: type Iter, items: seq[T]): Iter[T] =
|
||||||
## Create new iterator from items
|
## Create new iterator from items
|
||||||
##
|
##
|
||||||
|
|
||||||
Iter.fromSlice(0..<items.len)
|
Iter.fromSlice(0..<items.len)
|
||||||
.map((i: int) => items[i])
|
.map((i: int) => items[i])
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ proc fromRange*[U, V, S: Ordinal](_: type Iter, a: U, b: V, step: S = 1): Iter[U
|
||||||
let u = i
|
let u = i
|
||||||
inc(i, step)
|
inc(i, step)
|
||||||
u
|
u
|
||||||
|
|
||||||
proc isFinished(): bool =
|
proc isFinished(): bool =
|
||||||
(step > 0 and i > b) or
|
(step > 0 and i > b) or
|
||||||
(step < 0 and i < b)
|
(step < 0 and i < b)
|
||||||
|
|
Loading…
Reference in New Issue