diff --git a/storage/conf.nim b/storage/conf.nim index db9dbc27..062eec0b 100644 --- a/storage/conf.nim +++ b/storage/conf.nim @@ -136,8 +136,7 @@ type .}: OutDir listenIp* {. - desc: - "IP address to listen on for remote peer connections, can be ipv4 or ipv6", + desc: "IP address to listen on for remote peer connections, can be ipv4 or ipv6", defaultValue: "0.0.0.0".parseIpAddress, defaultValueDesc: "Listens on all addresses.", abbr: "i", diff --git a/storage/stores/repostore/operations.nim b/storage/stores/repostore/operations.nim index f2e67094..d83c46b4 100644 --- a/storage/stores/repostore/operations.nim +++ b/storage/stores/repostore/operations.nim @@ -94,9 +94,9 @@ proc updateTotalBlocksCount*( proc(maybeCurrCount: ?Natural): Future[?Natural] {.async.} = let count: Natural = if currCount =? maybeCurrCount: - currCount + plusCount - minusCount + max(0, currCount + plusCount - minusCount) else: - plusCount - minusCount + max(0, plusCount - minusCount) self.totalBlocks = count storage_repostore_blocks.set(count.int64) @@ -157,7 +157,7 @@ proc updateBlockMetadata*( BlockMetadata( size: currBlockMd.size, expiry: max(currBlockMd.expiry, minExpiry), - refCount: currBlockMd.refCount + plusRefCount - minusRefCount, + refCount: max(0, currBlockMd.refCount + plusRefCount - minusRefCount), ).some else: raise newException( diff --git a/storage/stores/repostore/store.nim b/storage/stores/repostore/store.nim index feec3807..f4cfa9e3 100644 --- a/storage/stores/repostore/store.nim +++ b/storage/stores/repostore/store.nim @@ -272,7 +272,8 @@ method delBlock*( error "Failed to delete leaf metadata, block will remain on disk.", err = err.msg return failure(err) - if err =? + if leafMd.blkCid.mcodec == BlockCodec and + err =? (await self.updateBlockMetadata(leafMd.blkCid, minusRefCount = 1)).errorOption: if not (err of BlockNotFoundError): return failure(err) diff --git a/tests/storage/stores/testrepostore.nim b/tests/storage/stores/testrepostore.nim index 0af4e742..30617c08 100644 --- a/tests/storage/stores/testrepostore.nim +++ b/tests/storage/stores/testrepostore.nim @@ -435,6 +435,25 @@ asyncchecksuite "RepoStore": (await repo.delBlock(treeCid2, 0.Natural)).tryGet() check not (await sharedBlock.cid in repo) + test "should not panic (underflow) when deleting a manifest as a leaf": + let + repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes = + 1000'nb) + (_, tree, manifest) = makeDataset( + await makeRandomBlocks(datasetSize = 2 * 256, blockSize = 256'nb) + ).tryGet() + treeCid = tree.rootCid.tryGet() + proof = tree.getProof(1).tryGet() + + let encodedVerifiable = manifest.encode().tryGet + let blk = bt.Block.new(data = encodedVerifiable, codec = ManifestCodec).tryGet + + (await repo.putCidAndProof(treeCid, 0.Natural, blk.cid, proof)).tryGet() + + (await repo.delBlock(treeCid, 0.Natural)).tryGet + + check not (await blk.cid in repo) + test "should clear leaf metadata when block is deleted from dataset": let repo = RepoStore.new(repoDs, metaDs, clock = mockClock, quotaMaxBytes =