Skip to content
This repository was archived by the owner on Feb 12, 2024. It is now read-only.

feat: Add support for specifying hash algorithms in files.add #1308

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion src/cli/commands/files/add.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ const zip = require('pull-zip')
const getFolderSize = require('get-folder-size')
const byteman = require('byteman')
const waterfall = require('async/waterfall')
const mh = require('multihashes')
const utils = require('../../utils')
const print = require('../../utils').print
const createProgressBar = require('../../utils').createProgressBar
Expand Down Expand Up @@ -162,6 +163,11 @@ module.exports = {
type: 'integer',
describe: 'Cid version. Non-zero value will change default of \'raw-leaves\' to true. (experimental)'
},
hash: {
type: 'string',
choices: Object.keys(mh.names),
describe: 'Hash function to use. Will set Cid version to 1 if used. (experimental)'
},
quiet: {
alias: 'q',
type: 'boolean',
Expand Down Expand Up @@ -191,7 +197,8 @@ module.exports = {
: Infinity,
cidVersion: argv.cidVersion,
rawLeaves: argv.rawLeaves,
onlyHash: argv.onlyHash
onlyHash: argv.onlyHash,
hashAlg: argv.hash
}

// Temporary restriction on raw-leaves:
Expand All @@ -206,6 +213,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 (options.hash && options.rawLeaves !== false) {
throw new Error('Implied argument raw-leaves must be passed and set to false when hash argument is specified')
}

if (options.rawLeaves) {
throw new Error('Not implemented: raw-leaves')
}
Expand Down
25 changes: 17 additions & 8 deletions src/core/components/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,15 @@ function noop () {}
function prepareFile (self, opts, file, callback) {
opts = opts || {}

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

if (opts['cid-version'] === 1) {
cid = cid.toV1()
}
if (opts.cidVersion === 1) {
cid = cid.toV1()
}

waterfall([
(cb) => opts.onlyHash ? cb(null, file) : self.object.get(file.multihash, opts, cb),
(node, cb) => {
const b58Hash = cid.toBaseEncodedString()

cb(null, {
Expand Down Expand Up @@ -110,6 +110,10 @@ module.exports = function files (self) {
: Infinity
}, options)

if (opts.hashAlg && opts.cidVersion !== 1) {
opts.cidVersion = 1
}

let total = 0
let prog = opts.progress || (() => {})
const progress = (bytes) => {
Expand Down Expand Up @@ -182,7 +186,7 @@ module.exports = function files (self) {
}

return {
add: promisify((data, options, callback) => {
add: promisify((data, options = {}, callback) => {
if (typeof options === 'function') {
callback = options
options = {}
Expand All @@ -200,6 +204,11 @@ module.exports = function files (self) {
return callback(new Error('first arg must be a buffer, readable stream, an object or array of objects'))
}

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

pull(
pull.values([data]),
_addPullStream(options),
Expand Down
7 changes: 6 additions & 1 deletion src/core/components/object.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,11 @@ module.exports = function object (self) {
} catch (err) {
return callback(err)
}
const cid = new CID(mh)
let cid = new CID(mh)

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

self._ipld.get(cid, (err, result) => {
if (err) {
Expand All @@ -214,6 +218,7 @@ module.exports = function object (self) {
if (err) {
return callback(err)
}

callback(null, node.data)
})
}),
Expand Down
3 changes: 2 additions & 1 deletion src/http/api/resources/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,8 @@ exports.add = {
cidVersion: request.query['cid-version'],
rawLeaves: request.query['raw-leaves'],
progress: request.query.progress ? progressHandler : null,
onlyHash: request.query['only-hash']
onlyHash: request.query['only-hash'],
hashAlg: request.query['hash']
}

const aborter = abortable()
Expand Down
27 changes: 27 additions & 0 deletions test/cli/files.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,22 @@ const expect = require('chai').expect
const path = require('path')
const compareDir = require('dir-compare').compareSync
const rimraf = require('rimraf').sync
const CID = require('cids')
const mh = require('multihashes')
const runOnAndOff = require('../utils/on-and-off')

// TODO: Test against all algorithms Object.keys(mh.names)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need :)

// 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'
]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vasco-santos good enough :)


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

HASH_ALGS.forEach((name) => {
it(`add with hash=${name} and raw-leaves=false`, function () {
this.timeout(30 * 1000)

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)
expect(mh.decode(cid.multihash).name).to.equal(name)
})
})
})

it('cat', function () {
this.timeout(30 * 1000)

Expand Down