Skip to content

Commit

Permalink
Allow hash algorithm to be passed, allow object get/data via CID
Browse files Browse the repository at this point in the history
  • Loading branch information
alanshaw committed Sep 8, 2017
1 parent 53aeea2 commit 3f64347
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 44 deletions.
12 changes: 12 additions & 0 deletions src/cli/commands/files/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,18 @@ module.exports = {
throw new Error('Implied argument raw-leaves must be passed and set to false when cid-version is > 0')
}

// Temporary restriction on raw-leaves:
// When hash != undefined then raw-leaves MUST be present and false.
//
// This is because raw-leaves is not yet implemented in js-ipfs,
// and go-ipfs changes the value of raw-leaves to true when
// hash != undefined unless explicitly set to false.
//
// This retains feature parity without having to implement raw-leaves.
if (argv.hash && argv.rawLeaves !== false) {
throw new Error('Implied argument raw-leaves must be passed and set to false when hash argument is specified')
}

if (argv.rawLeaves) {
throw new Error('Not implemented: raw-leaves')
}
Expand Down
21 changes: 11 additions & 10 deletions src/core/components/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ module.exports = function files (self) {
shardSplitThreshold: self._options.EXPERIMENTAL.sharding ? 1000 : Infinity
}, options)

// CID v0 is for multihashes encoded with sha2-256
if (opts.hashAlg && opts.hashAlg !== 'sha2-256' && opts.cidVersion !== 1) {
if (opts.hashAlg && opts.cidVersion !== 1) {
opts.cidVersion = 1
}

Expand Down Expand Up @@ -70,8 +69,10 @@ module.exports = function files (self) {
return callback(new Error('Invalid arguments, data must be an object, Buffer or readable stream'))
}

options = options || {}

// CID v0 is for multihashes encoded with sha2-256
if (options && options.hashAlg && options.hashAlg !== 'sha2-256' && options.cidVersion !== 1) {
if (options.hashAlg && options.cidVersion !== 1) {
options.cidVersion = 1
}

Expand Down Expand Up @@ -127,15 +128,15 @@ module.exports = function files (self) {
function prepareFile (self, opts, file, callback) {
opts = opts || {}

waterfall([
(cb) => self.object.get(file.multihash, cb),
(node, cb) => {
let cid = new CID(file.multihash)
let cid = new CID(file.multihash)

if (opts.cidVersion === 1) {
cid = cid.toV1()
}
if (opts.cidVersion === 1) {
cid = cid.toV1()
}

waterfall([
(cb) => self.object.get(cid, cb),
(node, cb) => {
const b58Hash = cid.toBaseEncodedString()

cb(null, {
Expand Down
33 changes: 13 additions & 20 deletions src/core/components/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ const mh = require('multihashes')
const Unixfs = require('ipfs-unixfs')
const assert = require('assert')

function normalizeMultihash (multihash, enc) {
if (typeof multihash === 'string') {
if (enc === 'base58' || !enc) {
return multihash
}

return new Buffer(multihash, enc)
} else if (Buffer.isBuffer(multihash)) {
return multihash
} else {
throw new Error('unsupported multihash')
}
}

function parseBuffer (buf, encoding, callback) {
switch (encoding) {
case 'json':
Expand Down Expand Up @@ -178,20 +164,19 @@ module.exports = function object (self) {
}
}),

get: promisify((multihash, options, callback) => {
get: promisify((hash, options, callback) => {
if (typeof options === 'function') {
callback = options
options = {}
}

let mh
let cid

try {
mh = normalizeMultihash(multihash, options.enc)
cid = new CID(hash)
} catch (err) {
return callback(err)
}
const cid = new CID(mh)

self._ipldResolver.get(cid, (err, result) => {
if (err) {
Expand All @@ -204,13 +189,21 @@ module.exports = function object (self) {
})
}),

data: promisify((multihash, options, callback) => {
data: promisify((hash, options, callback) => {
if (typeof options === 'function') {
callback = options
options = {}
}

self.object.get(multihash, options, (err, node) => {
let cid

try {
cid = new CID(hash)
} catch (err) {
return callback(err)
}

self.object.get(cid, options, (err, node) => {
if (err) {
return callback(err)
}
Expand Down
15 changes: 7 additions & 8 deletions src/http-api/resources/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -145,20 +145,19 @@ exports.add = {
query: Joi.object()
.keys({
'cid-version': Joi.number().integer().min(0).max(1),
hash: Joi.string().valid(Object.keys(mh.names)),
// Temporary restriction on raw-leaves:
// When cid-version=1 then raw-leaves MUST be present and false.
// When cid-version > 0 or hash != undefined then raw-leaves MUST be
// present and false.
//
// This is because raw-leaves is not yet implemented in js-ipfs,
// and go-ipfs changes the value of raw-leaves to true when
// cid-version > 0 unless explicitly set to false.
// cid-version > 0 or hash != undefined unless explicitly set to false.
//
// This retains feature parity without having to implement raw-leaves.
'raw-leaves': Joi.any().when('cid-version', {
is: 1,
then: Joi.boolean().valid(false).required(),
otherwise: Joi.boolean().valid(false)
}),
hash: Joi.string().valid(Object.keys(mh.names))
'raw-leaves': Joi.boolean().valid(false)
.when('cid-version', { is: 1, then: Joi.required() })
.when('hash', { is: Joi.string(), then: Joi.required() })
})
// TODO: Necessary until validate "recursive", "stream-channels" etc.
.options({ allowUnknown: true })
Expand Down
5 changes: 2 additions & 3 deletions src/http-api/resources/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const DAGLink = dagPB.DAGLink
const DAGNode = dagPB.DAGNode
const waterfall = require('async/waterfall')
const series = require('async/series')
const CID = require('cids')
const debug = require('debug')
const log = debug('jsipfs:http-api:object')
log.error = debug('jsipfs:http-api:object:error')
Expand All @@ -20,9 +21,7 @@ exports.parseKey = (request, reply) => {
}

try {
return reply({
key: mh.fromB58String(request.query.arg)
})
return reply({ key: new CID(request.query.arg) })
} catch (err) {
log.error(err)
return reply({
Expand Down
18 changes: 15 additions & 3 deletions test/cli/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,18 @@ const CID = require('cids')
const mh = require('multihashes')
const runOnAndOff = require('../utils/on-and-off')

// TODO: Test against all algorithms Object.keys(mh.names)
// This subset is known to work with both go-ipfs and js-ipfs as of 2017-09-05
const HASH_ALGS = [
'sha1',
'sha2-256',
'sha2-512',
'keccak-224',
'keccak-256',
'keccak-384',
'keccak-512'
]

describe('files', () => runOnAndOff((thing) => {
let ipfs
const readme = fs.readFileSync(path.join(process.cwd(), '/src/init-files/init-docs/readme'))
Expand Down Expand Up @@ -224,9 +236,9 @@ describe('files', () => runOnAndOff((thing) => {
})
})

Object.keys(mh.names).forEach((name) => {
it('add with hash=' + name, () => {
return ipfs('add src/init-files/init-docs/readme --hash=' + name)
HASH_ALGS.forEach((name) => {
it(`add with hash=${name} and raw-leaves=false`, () => {
return ipfs(`add src/init-files/init-docs/readme --hash=${name} --raw-leaves=false`)
.then((out) => {
const hash = out.split(' ')[1]
const cid = new CID(hash)
Expand Down

0 comments on commit 3f64347

Please sign in to comment.