Skip to content

Commit

Permalink
fix: identity blockstore should wrap child (#303)
Browse files Browse the repository at this point in the history
Allow passing a child blockstore to an identity blockstore.
  • Loading branch information
achingbrain committed Apr 9, 2024
1 parent c536e25 commit 3d84dd0
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 11 deletions.
1 change: 1 addition & 0 deletions packages/blockstore-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@
"devDependencies": {
"aegir": "^42.2.3",
"interface-blockstore-tests": "^6.0.0",
"it-all": "^3.0.4",
"uint8arrays": "^5.0.2"
}
}
60 changes: 49 additions & 11 deletions packages/blockstore-core/src/identity.ts
Original file line number Diff line number Diff line change
@@ -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<CID> {
if (key.multihash.code === IDENTITY_CODEC) {
return key
}

if (this.child == null) {
return key
}

return this.child.put(key, block)
}

get (key: CID): Await<Uint8Array> {
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<boolean> {
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<void> {
if (key.code === IDENTITY_CODEC) {
return
}

if (this.child != null) {
return this.child.delete(key)
}
}

* getAll (): AwaitIterable<Pair> {
getAll (options?: AbortOptions): AwaitIterable<Pair> {
if (this.child != null) {
return this.child.getAll(options)
}

return []
}
}
70 changes: 70 additions & 0 deletions packages/blockstore-core/test/identity.spec.ts
Original file line number Diff line number Diff line change
@@ -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', () => {
Expand Down Expand Up @@ -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())
})
})

0 comments on commit 3d84dd0

Please sign in to comment.