Skip to content

Commit

Permalink
feat: export blockstore key encode/decode utils (#206)
Browse files Browse the repository at this point in the history
* feat: export blockstore key encode/decode utils

These have already been duplicated twice in js-ipfs. This exposes utility functions to encode a CID as a blockstore Key and decode a blockstore Key to a CID.

refs https://github.com/ipfs/js-ipfs/pull/2022/files#r303389863

License: MIT
Signed-off-by: Alan Shaw <[email protected]>

* chore: appease linter

License: MIT
Signed-off-by: Alan Shaw <[email protected]>
  • Loading branch information
Alan Shaw authored and jacobheun committed Aug 21, 2019
1 parent 79fb031 commit f83edae
Show file tree
Hide file tree
Showing 7 changed files with 64 additions and 31 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ Arguments:
* `root` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of values at the root (`repo.set()`, `repo.get()`)
* `blocks` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of values at `repo.blocks`.
* `keys` (defaults to [`datastore-fs`](https://github.com/ipfs/js-datastore-fs#readme) in Node.js and [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme) in the browser). Defines the back-end type used for gets and puts of encrypted keys at `repo.keys`
* `datastore` (defaults to [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme)). Defines the back-end type used as the key-valye store used for gets and puts of values at `repo.datastore`.
* `datastore` (defaults to [`datastore-level`](https://github.com/ipfs/js-datastore-level#readme)). Defines the back-end type used as the key-value store used for gets and puts of values at `repo.datastore`.

```js
const repo = new Repo('path/to/repo')
Expand Down
29 changes: 29 additions & 0 deletions src/blockstore-utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
'use strict'

const base32 = require('base32.js')
const { Key } = require('interface-datastore')
const CID = require('cids')

/**
* Transform a cid to the appropriate datastore key.
*
* @param {CID} cid
* @returns {Key}
*/
exports.cidToKey = cid => {
const enc = new base32.Encoder()
return new Key('/' + enc.write(cid.buffer).finalize(), false)
}

/**
* Transform a datastore Key instance to a CID
*
* @param {Key} key
* @returns {CID}
*/
exports.keyToCid = key => {
// Block key is of the form /<base32 encoded string>
const decoder = new base32.Decoder()
const buff = decoder.write(key.toString().slice(1)).finalize()
return new CID(Buffer.from(buff))
}
38 changes: 8 additions & 30 deletions src/blockstore.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,10 @@

const core = require('datastore-core')
const ShardingStore = core.ShardingDatastore
const Key = require('interface-datastore').Key
const base32 = require('base32.js')
const Block = require('ipfs-block')
const CID = require('cids')
const errcode = require('err-code')

/**
* Transform a raw buffer to a base32 encoded key.
*
* @param {Buffer} rawKey
* @returns {Key}
*/
const keyFromBuffer = (rawKey) => {
const enc = new base32.Encoder()
return new Key('/' + enc.write(rawKey).finalize(), false)
}

/**
* Transform a cid to the appropriate datastore key.
*
* @param {CID} cid
* @returns {Key}
*/
const cidToDsKey = (cid) => {
return keyFromBuffer(cid.buffer)
}
const { cidToKey } = require('./blockstore-utils')

module.exports = async (filestore, options) => {
const store = await maybeWithSharding(filestore, options)
Expand Down Expand Up @@ -65,7 +43,7 @@ function createBaseStore (store) {
if (!CID.isCID(cid)) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
}
const key = cidToDsKey(cid)
const key = cidToKey(cid)
let blockData
try {
blockData = await store.get(key)
Expand All @@ -78,7 +56,7 @@ function createBaseStore (store) {
throw err
}

const otherKey = cidToDsKey(otherCid)
const otherKey = cidToKey(otherCid)
const blockData = await store.get(otherKey)
await store.put(key, blockData)
return new Block(blockData, cid)
Expand All @@ -98,7 +76,7 @@ function createBaseStore (store) {
throw new Error('invalid block')
}

const k = cidToDsKey(block.cid)
const k = cidToKey(block.cid)
const exists = await store.has(k)
if (exists) return
return store.put(k, block.data)
Expand All @@ -112,7 +90,7 @@ function createBaseStore (store) {
*/
async putMany (blocks) {
const keys = blocks.map((b) => ({
key: cidToDsKey(b.cid),
key: cidToKey(b.cid),
block: b
}))

Expand Down Expand Up @@ -141,11 +119,11 @@ function createBaseStore (store) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
}

const exists = await store.has(cidToDsKey(cid))
const exists = await store.has(cidToKey(cid))
if (exists) return exists
const otherCid = cidToOtherVersion(cid)
if (!otherCid) return false
return store.has(cidToDsKey(otherCid))
return store.has(cidToKey(otherCid))
},
/**
* Delete a block from the store
Expand All @@ -157,7 +135,7 @@ function createBaseStore (store) {
if (!CID.isCID(cid)) {
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
}
return store.delete(cidToDsKey(cid))
return store.delete(cidToKey(cid))
},
/**
* Close the store
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ async function getSize (queryFn) {
}

module.exports = IpfsRepo
module.exports.utils = { blockstore: require('./blockstore-utils') }
module.exports.repoVersion = repoVersion
module.exports.errors = ERRORS

Expand Down
22 changes: 22 additions & 0 deletions test/blockstore-utils-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/* eslint-env mocha */
'use strict'

const chai = require('chai')
chai.use(require('dirty-chai'))
const { expect } = chai
const { Key } = require('interface-datastore')
const CID = require('cids')
const Repo = require('../src')

module.exports = () => {
describe('blockstore utils', () => {
it('converts a CID to a datastore Key and back', () => {
const originalCid = new CID('Qme6KJdKcp85TYbLxuLV7oQzMiLremD7HMoXLZEmgo6Rnh')
const key = Repo.utils.blockstore.cidToKey(originalCid)
expect(key instanceof Key).to.be.true()
const cid = Repo.utils.blockstore.keyToCid(key)
expect(cid instanceof CID).to.be.true()
expect(originalCid.toString()).to.equal(cid.toString())
})
})
}
1 change: 1 addition & 0 deletions test/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ describe('IPFS Repo Tests on the Browser', () => {

require('./repo-test')(repo)
require('./blockstore-test')(repo)
require('./blockstore-utils-test')()
require('./datastore-test')(repo)
require('./keystore-test')(repo)
require('./config-test')(repo)
Expand Down
2 changes: 2 additions & 0 deletions test/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,4 +103,6 @@ describe('IPFS Repo Tests onNode.js', () => {
require('./interop-test')(repo)
}
}))

require('./blockstore-utils-test')()
})

0 comments on commit f83edae

Please sign in to comment.