From 3d84dd0ab164fb5749c34487a217c763d1d09ccb Mon Sep 17 00:00:00 2001 From: Alex Potsides Date: Tue, 9 Apr 2024 19:33:45 +0100 Subject: [PATCH] fix: identity blockstore should wrap child (#303) Allow passing a child blockstore to an identity blockstore. --- packages/blockstore-core/package.json | 1 + packages/blockstore-core/src/identity.ts | 60 +++++++++++++--- .../blockstore-core/test/identity.spec.ts | 70 +++++++++++++++++++ 3 files changed, 120 insertions(+), 11 deletions(-) diff --git a/packages/blockstore-core/package.json b/packages/blockstore-core/package.json index abc4fe5d..1d56b240 100644 --- a/packages/blockstore-core/package.json +++ b/packages/blockstore-core/package.json @@ -110,6 +110,7 @@ "devDependencies": { "aegir": "^42.2.3", "interface-blockstore-tests": "^6.0.0", + "it-all": "^3.0.4", "uint8arrays": "^5.0.2" } } diff --git a/packages/blockstore-core/src/identity.ts b/packages/blockstore-core/src/identity.ts index 059902df..fdebafe4 100644 --- a/packages/blockstore-core/src/identity.ts +++ b/packages/blockstore-core/src/identity.ts @@ -1,34 +1,72 @@ import { BaseBlockstore } from './base.js' -import * as Errors from './errors.js' -import type { Pair } from 'interface-blockstore' -import type { Await, AwaitIterable } from 'interface-store' +import { Errors } from './index.js' +import type { Blockstore, Pair } from 'interface-blockstore' +import type { AbortOptions, Await, AwaitIterable } from 'interface-store' import type { CID } from 'multiformats/cid' // https://github.com/multiformats/multicodec/blob/d06fc6194710e8909bac64273c43f16b56ca4c34/table.csv#L2 const IDENTITY_CODEC = 0x00 export class IdentityBlockstore extends BaseBlockstore { - put (key: CID): CID { - return key + private readonly child?: Blockstore + + constructor (child?: Blockstore) { + super() + + this.child = child + } + + put (key: CID, block: Uint8Array): Await { + if (key.multihash.code === IDENTITY_CODEC) { + return key + } + + if (this.child == null) { + return key + } + + return this.child.put(key, block) } get (key: CID): Await { - if (key.code === IDENTITY_CODEC) { + if (key.multihash.code === IDENTITY_CODEC) { return key.multihash.digest } - throw Errors.notFoundError() + if (this.child == null) { + throw Errors.notFoundError() + } + + return this.child.get(key) } - has (key: CID): boolean { - return key.code === IDENTITY_CODEC + has (key: CID): Await { + if (key.multihash.code === IDENTITY_CODEC) { + return true + } + + if (this.child == null) { + return false + } + + return this.child.has(key) } - delete (): void { + delete (key: CID): Await { + if (key.code === IDENTITY_CODEC) { + return + } + if (this.child != null) { + return this.child.delete(key) + } } - * getAll (): AwaitIterable { + getAll (options?: AbortOptions): AwaitIterable { + if (this.child != null) { + return this.child.getAll(options) + } + return [] } } diff --git a/packages/blockstore-core/test/identity.spec.ts b/packages/blockstore-core/test/identity.spec.ts index e0bfcdfc..9d64cb0a 100644 --- a/packages/blockstore-core/test/identity.spec.ts +++ b/packages/blockstore-core/test/identity.spec.ts @@ -1,19 +1,23 @@ /* eslint-env mocha */ import { expect } from 'aegir/chai' +import all from 'it-all' import drain from 'it-drain' import { CID } from 'multiformats/cid' import * as raw from 'multiformats/codecs/raw' import { identity } from 'multiformats/hashes/identity' import { sha256 } from 'multiformats/hashes/sha2' import { IdentityBlockstore } from '../src/identity.js' +import { MemoryBlockstore } from '../src/memory.js' import type { Blockstore } from 'interface-blockstore' describe('identity', () => { let blockstore: Blockstore + let child: Blockstore beforeEach(() => { blockstore = new IdentityBlockstore() + child = new MemoryBlockstore() }) it('has an identity CID', () => { @@ -56,4 +60,70 @@ describe('identity', () => { expect(blockstore.has(cid)).to.be.true() }) + + it('puts CIDs to child', async () => { + const block = Uint8Array.from([0, 1, 2, 3, 4]) + const multihash = await sha256.digest(block) + const cid = CID.createV1(raw.code, multihash) + + blockstore = new IdentityBlockstore(child) + + await blockstore.put(cid, block) + expect(child.has(cid)).to.be.true() + expect(child.get(cid)).to.equalBytes(block) + }) + + it('gets CIDs from child', async () => { + const block = Uint8Array.from([0, 1, 2, 3, 4]) + const multihash = await sha256.digest(block) + const cid = CID.createV1(raw.code, multihash) + + await child.put(cid, block) + + blockstore = new IdentityBlockstore(child) + expect(blockstore.has(cid)).to.be.true() + expect(blockstore.get(cid)).to.equalBytes(block) + }) + + it('has CIDs from child', async () => { + const block = Uint8Array.from([0, 1, 2, 3, 4]) + const multihash = await sha256.digest(block) + const cid = CID.createV1(raw.code, multihash) + + await child.put(cid, block) + + blockstore = new IdentityBlockstore(child) + expect(blockstore.has(cid)).to.be.true() + }) + + it('deletes CIDs from child', async () => { + const block = Uint8Array.from([0, 1, 2, 3, 4]) + const multihash = await sha256.digest(block) + const cid = CID.createV1(raw.code, multihash) + + await child.put(cid, block) + + blockstore = new IdentityBlockstore(child) + expect(blockstore.has(cid)).to.be.true() + + await blockstore.delete(cid) + + expect(blockstore.has(cid)).to.be.false() + }) + + it('gets all pairs from child', async () => { + const block = Uint8Array.from([0, 1, 2, 3, 4]) + const multihash = await sha256.digest(block) + const cid = CID.createV1(raw.code, multihash) + + await child.put(cid, block) + + blockstore = new IdentityBlockstore(child) + expect(blockstore.has(cid)).to.be.true() + + const result = await all(blockstore.getAll()) + + expect(result).to.have.lengthOf(1) + expect(result[0].cid.toString()).to.equal(cid.toString()) + }) })