Skip to content

Commit f83edae

Browse files
Alan Shawjacobheun
Alan Shaw
authored andcommitted
feat: export blockstore key encode/decode utils (#206)
* 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]>
1 parent 79fb031 commit f83edae

File tree

7 files changed

+64
-31
lines changed

7 files changed

+64
-31
lines changed

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ Arguments:
141141
* `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()`)
142142
* `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`.
143143
* `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`
144-
* `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`.
144+
* `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`.
145145

146146
```js
147147
const repo = new Repo('path/to/repo')

src/blockstore-utils.js

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use strict'
2+
3+
const base32 = require('base32.js')
4+
const { Key } = require('interface-datastore')
5+
const CID = require('cids')
6+
7+
/**
8+
* Transform a cid to the appropriate datastore key.
9+
*
10+
* @param {CID} cid
11+
* @returns {Key}
12+
*/
13+
exports.cidToKey = cid => {
14+
const enc = new base32.Encoder()
15+
return new Key('/' + enc.write(cid.buffer).finalize(), false)
16+
}
17+
18+
/**
19+
* Transform a datastore Key instance to a CID
20+
*
21+
* @param {Key} key
22+
* @returns {CID}
23+
*/
24+
exports.keyToCid = key => {
25+
// Block key is of the form /<base32 encoded string>
26+
const decoder = new base32.Decoder()
27+
const buff = decoder.write(key.toString().slice(1)).finalize()
28+
return new CID(Buffer.from(buff))
29+
}

src/blockstore.js

+8-30
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,10 @@
22

33
const core = require('datastore-core')
44
const ShardingStore = core.ShardingDatastore
5-
const Key = require('interface-datastore').Key
6-
const base32 = require('base32.js')
75
const Block = require('ipfs-block')
86
const CID = require('cids')
97
const errcode = require('err-code')
10-
11-
/**
12-
* Transform a raw buffer to a base32 encoded key.
13-
*
14-
* @param {Buffer} rawKey
15-
* @returns {Key}
16-
*/
17-
const keyFromBuffer = (rawKey) => {
18-
const enc = new base32.Encoder()
19-
return new Key('/' + enc.write(rawKey).finalize(), false)
20-
}
21-
22-
/**
23-
* Transform a cid to the appropriate datastore key.
24-
*
25-
* @param {CID} cid
26-
* @returns {Key}
27-
*/
28-
const cidToDsKey = (cid) => {
29-
return keyFromBuffer(cid.buffer)
30-
}
8+
const { cidToKey } = require('./blockstore-utils')
319

3210
module.exports = async (filestore, options) => {
3311
const store = await maybeWithSharding(filestore, options)
@@ -65,7 +43,7 @@ function createBaseStore (store) {
6543
if (!CID.isCID(cid)) {
6644
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
6745
}
68-
const key = cidToDsKey(cid)
46+
const key = cidToKey(cid)
6947
let blockData
7048
try {
7149
blockData = await store.get(key)
@@ -78,7 +56,7 @@ function createBaseStore (store) {
7856
throw err
7957
}
8058

81-
const otherKey = cidToDsKey(otherCid)
59+
const otherKey = cidToKey(otherCid)
8260
const blockData = await store.get(otherKey)
8361
await store.put(key, blockData)
8462
return new Block(blockData, cid)
@@ -98,7 +76,7 @@ function createBaseStore (store) {
9876
throw new Error('invalid block')
9977
}
10078

101-
const k = cidToDsKey(block.cid)
79+
const k = cidToKey(block.cid)
10280
const exists = await store.has(k)
10381
if (exists) return
10482
return store.put(k, block.data)
@@ -112,7 +90,7 @@ function createBaseStore (store) {
11290
*/
11391
async putMany (blocks) {
11492
const keys = blocks.map((b) => ({
115-
key: cidToDsKey(b.cid),
93+
key: cidToKey(b.cid),
11694
block: b
11795
}))
11896

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

144-
const exists = await store.has(cidToDsKey(cid))
122+
const exists = await store.has(cidToKey(cid))
145123
if (exists) return exists
146124
const otherCid = cidToOtherVersion(cid)
147125
if (!otherCid) return false
148-
return store.has(cidToDsKey(otherCid))
126+
return store.has(cidToKey(otherCid))
149127
},
150128
/**
151129
* Delete a block from the store
@@ -157,7 +135,7 @@ function createBaseStore (store) {
157135
if (!CID.isCID(cid)) {
158136
throw errcode(new Error('Not a valid cid'), 'ERR_INVALID_CID')
159137
}
160-
return store.delete(cidToDsKey(cid))
138+
return store.delete(cidToKey(cid))
161139
},
162140
/**
163141
* Close the store

src/index.js

+1
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ async function getSize (queryFn) {
298298
}
299299

300300
module.exports = IpfsRepo
301+
module.exports.utils = { blockstore: require('./blockstore-utils') }
301302
module.exports.repoVersion = repoVersion
302303
module.exports.errors = ERRORS
303304

test/blockstore-utils-test.js

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/* eslint-env mocha */
2+
'use strict'
3+
4+
const chai = require('chai')
5+
chai.use(require('dirty-chai'))
6+
const { expect } = chai
7+
const { Key } = require('interface-datastore')
8+
const CID = require('cids')
9+
const Repo = require('../src')
10+
11+
module.exports = () => {
12+
describe('blockstore utils', () => {
13+
it('converts a CID to a datastore Key and back', () => {
14+
const originalCid = new CID('Qme6KJdKcp85TYbLxuLV7oQzMiLremD7HMoXLZEmgo6Rnh')
15+
const key = Repo.utils.blockstore.cidToKey(originalCid)
16+
expect(key instanceof Key).to.be.true()
17+
const cid = Repo.utils.blockstore.keyToCid(key)
18+
expect(cid instanceof CID).to.be.true()
19+
expect(originalCid.toString()).to.equal(cid.toString())
20+
})
21+
})
22+
}

test/browser.js

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ describe('IPFS Repo Tests on the Browser', () => {
1919

2020
require('./repo-test')(repo)
2121
require('./blockstore-test')(repo)
22+
require('./blockstore-utils-test')()
2223
require('./datastore-test')(repo)
2324
require('./keystore-test')(repo)
2425
require('./config-test')(repo)

test/node.js

+2
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,6 @@ describe('IPFS Repo Tests onNode.js', () => {
103103
require('./interop-test')(repo)
104104
}
105105
}))
106+
107+
require('./blockstore-utils-test')()
106108
})

0 commit comments

Comments
 (0)