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

refactor: ipns routing logic moved to instantiation #1701

Merged
merged 4 commits into from
Nov 19, 2018
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
"ncp": "^2.0.0",
"qs": "^6.5.2",
"rimraf": "^2.6.2",
"sinon": "^7.1.1",
"stream-to-promise": "^2.2.0"
},
"dependencies": {
Expand All @@ -87,6 +88,7 @@
"byteman": "^1.3.5",
"cid-tool": "~0.1.0",
"cids": "~0.5.5",
"datastore-core": "~0.6.0",
"debug": "^4.1.0",
"deep-extend": "~0.6.0",
"err-code": "^1.1.2",
Expand Down
11 changes: 11 additions & 0 deletions src/core/components/init.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ const defaultsDeep = require('@nodeutils/defaults-deep')
const defaultConfig = require('../runtime/config-nodejs.js')
const Keychain = require('libp2p-keychain')

const IPNS = require('../ipns')
const OfflineDatastore = require('../ipns/routing/offline-datastore')

const addDefaultAssets = require('./init-assets')

module.exports = function init (self) {
Expand Down Expand Up @@ -105,6 +108,14 @@ module.exports = function init (self) {
cb(null, true)
}
},
// Setup the offline routing for IPNS.
// This is primarily used for offline ipns modifications, such as the initializeKeyspace feature.
(_, cb) => {
const offlineDatastore = new OfflineDatastore(self._repo)

self._ipns = new IPNS(offlineDatastore, self._repo, self._peerInfo, self._keychain, self._options)
cb(null, true)
},
// add empty unixfs dir object (go-ipfs assumes this exists)
(_, cb) => {
if (opts.emptyRepo) {
Expand Down
7 changes: 3 additions & 4 deletions src/core/components/name.js
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ module.exports = function name (self) {
const nocache = options.nocache && options.nocache.toString() === 'true'
const recursive = options.recursive && options.recursive.toString() === 'true'

const local = true // TODO ROUTING - use self._options.local
const local = self._options.local

if (!self.isOnline() && !local) {
const errMsg = utils.OFFLINE_ERROR
Expand Down Expand Up @@ -157,11 +157,10 @@ module.exports = function name (self) {

const resolveOptions = {
nocache,
recursive,
local
recursive
}

self._ipns.resolve(name, self._peerInfo.id, resolveOptions, callback)
self._ipns.resolve(name, resolveOptions, callback)
})
}
}
18 changes: 18 additions & 0 deletions src/core/components/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ const series = require('async/series')
const Bitswap = require('ipfs-bitswap')
const setImmediate = require('async/setImmediate')
const promisify = require('promisify-es6')
const { TieredDatastore } = require('datastore-core')

const IPNS = require('../ipns')
const OfflineDatastore = require('../ipns/routing/offline-datastore')

module.exports = (self) => {
return promisify((callback) => {
Expand Down Expand Up @@ -34,6 +38,20 @@ module.exports = (self) => {
},
(cb) => self.libp2p.start(cb),
(cb) => {
// Setup online routing for IPNS with a tiered routing composed by a DHT and a Pubsub router (if properly enabled)
const ipnsStores = []

// TODO Add IPNS pubsub if enabled

// NOTE: IPNS routing is being replaced by the local repo datastore while the IPNS over DHT is not ready
// When DHT is added, if local option enabled, should receive offlineDatastore as well
const offlineDatastore = new OfflineDatastore(self._repo)
ipnsStores.push(offlineDatastore)

// Create ipns routing with a set of datastores
const routing = new TieredDatastore(ipnsStores)
self._ipns = new IPNS(routing, self._repo, self._peerInfo, self._keychain, self._options)

self._bitswap = new Bitswap(
self._libp2pNode,
self._repo.blocks,
Expand Down
4 changes: 2 additions & 2 deletions src/core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const EventEmitter = require('events')
const config = require('./config')
const boot = require('./boot')
const components = require('./components')
const IPNS = require('./ipns')

// replaced by repo-browser when running in the browser
const defaultRepo = require('./runtime/repo-nodejs')
const preload = require('./preload')
Expand Down Expand Up @@ -126,7 +126,7 @@ class IPFS extends EventEmitter {
})
this._preload = preload(this)
this._mfsPreload = mfsPreload(this)
this._ipns = new IPNS(null, this)
this._ipns = undefined

// IPFS Core exposed components
// - for booting up a node
Expand Down
28 changes: 22 additions & 6 deletions src/core/ipns/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const { createFromPrivKey } = require('peer-id')
const series = require('async/series')
const Receptacle = require('receptacle')

const errcode = require('err-code')
const debug = require('debug')
const log = debug('jsipfs:ipns')
log.error = debug('jsipfs:ipns:error')
Expand All @@ -16,11 +17,12 @@ const path = require('./path')
const defaultRecordTtl = 60 * 1000

class IPNS {
constructor (routing, ipfs) {
this.publisher = new IpnsPublisher(routing, ipfs._repo)
this.republisher = new IpnsRepublisher(this.publisher, ipfs)
this.resolver = new IpnsResolver(routing, ipfs._repo)
constructor (routing, repo, peerInfo, keychain, options) {
this.publisher = new IpnsPublisher(routing, repo)
this.republisher = new IpnsRepublisher(this.publisher, repo, peerInfo, keychain, options)
this.resolver = new IpnsResolver(routing)
this.cache = new Receptacle({ max: 1000 }) // Create an LRU cache with max 1000 items
this.routing = routing
}

// Publish
Expand Down Expand Up @@ -53,7 +55,21 @@ class IPNS {
}

// Resolve
resolve (name, peerId, options, callback) {
resolve (name, options, callback) {
if (typeof name !== 'string') {
const errMsg = `name received is not valid`

log.error(errMsg)
return callback(errcode(new Error(errMsg), 'ERR_INVALID_NAME'))
}

if (typeof options === 'function') {
callback = options
options = {}
}

options = options || {}

// If recursive, we should not try to get the cached value
if (!options.nocache && !options.recursive) {
// Try to get the record from cache
Expand All @@ -67,7 +83,7 @@ class IPNS {
}
}

this.resolver.resolve(name, peerId, options, (err, result) => {
this.resolver.resolve(name, options, (err, result) => {
if (err) {
log.error(err)
return callback(err)
Expand Down
8 changes: 1 addition & 7 deletions src/core/ipns/path.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,7 @@ const resolvePath = (ipfsNode, name, callback) => {
if (isIPFS.ipnsPath(name)) {
log(`resolve ipns path ${name}`)

const local = true // TODO ROUTING - use self._options.local

const options = {
local: local
}

return ipfsNode._ipns.resolve(name, ipfsNode._peerInfo.id, options, callback)
return ipfsNode._ipns.resolve(name, callback)
}

// ipfs path
Expand Down
20 changes: 10 additions & 10 deletions src/core/ipns/publisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class IpnsPublisher {

PeerId.createFromPrivKey(privKey.bytes, (err, peerId) => {
if (err) {
callback(err)
return callback(err)
}

this._updateOrCreateRecord(privKey, value, lifetime, peerId, (err, record) => {
Expand Down Expand Up @@ -67,17 +67,17 @@ class IpnsPublisher {

let keys
try {
keys = ipns.getIdKeys(peerId.id)
keys = ipns.getIdKeys(peerId.toBytes())
} catch (err) {
log.error(err)
return callback(err)
}

series([
(cb) => this._publishEntry(keys.ipnsKey, embedPublicKeyRecord || record, peerId, cb),
(cb) => this._publishEntry(keys.routingKey, embedPublicKeyRecord || record, peerId, cb),
// Publish the public key if a public key cannot be extracted from the ID
// We will be able to deprecate this part in the future, since the public keys will be only in the peerId
(cb) => embedPublicKeyRecord ? this._publishPublicKey(keys.pkKey, publicKey, peerId, cb) : cb()
(cb) => embedPublicKeyRecord ? this._publishPublicKey(keys.routingPubKey, publicKey, peerId, cb) : cb()
], (err) => {
if (err) {
log.error(err)
Expand Down Expand Up @@ -108,13 +108,13 @@ class IpnsPublisher {
return callback(err)
}

// TODO Routing - this should be replaced by a put to the DHT
this._repo.datastore.put(key, rec.serialize(), (err, res) => {
// Add record to routing (buffer key)
this._routing.put(key.toBuffer(), rec.serialize(), (err, res) => {
if (err) {
const errMsg = `ipns record for ${key.toString()} could not be stored in the routing`

log.error(errMsg)
return callback(errcode(new Error(errMsg), 'ERR_STORING_IN_DATASTORE'))
return callback(errcode(new Error(errMsg), 'ERR_PUTTING_TO_ROUTING'))
}

log(`ipns record for ${key.toString()} was stored in the routing`)
Expand Down Expand Up @@ -146,13 +146,13 @@ class IpnsPublisher {
return callback(err)
}

// TODO Routing - this should be replaced by a put to the DHT
this._repo.datastore.put(key, rec.serialize(), (err, res) => {
// Add public key to routing (buffer key)
this._routing.put(key.toBuffer(), rec.serialize(), (err, res) => {
if (err) {
const errMsg = `public key for ${key.toString()} could not be stored in the routing`

log.error(errMsg)
return callback(errcode(new Error(errMsg), 'ERR_STORING_IN_DATASTORE'))
return callback(errcode(new Error(errMsg), 'ERR_PUTTING_TO_ROUTING'))
}

log(`public key for ${key.toString()} was stored in the routing`)
Expand Down
18 changes: 10 additions & 8 deletions src/core/ipns/republisher.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ const defaultBroadcastInterval = 4 * hour
const defaultRecordLifetime = 24 * hour

class IpnsRepublisher {
constructor (publisher, ipfs) {
constructor (publisher, repo, peerInfo, keychain, options) {
this._publisher = publisher
this._ipfs = ipfs
this._repo = ipfs._repo
this._repo = repo
this._peerInfo = peerInfo
this._keychain = keychain
this._options = options
this._republishHandle = null
}

Expand Down Expand Up @@ -62,8 +64,8 @@ class IpnsRepublisher {
}
}

const { privKey } = this._ipfs._peerInfo.id
const { pass } = this._ipfs._options
const { privKey } = this._peerInfo.id
const { pass } = this._options

republishHandle.runPeriodically((done) => {
this._republishEntries(privKey, pass, () => done(defaultBroadcastInterval))
Expand Down Expand Up @@ -98,16 +100,16 @@ class IpnsRepublisher {
}

// keychain needs pass to get the cryptographic keys
if (this._ipfs._keychain && Boolean(pass)) {
this._ipfs._keychain.listKeys((err, list) => {
if (pass) {
this._keychain.listKeys((err, list) => {
if (err) {
log.error(err)
return
}

each(list, (key, cb) => {
waterfall([
(cb) => this._ipfs._keychain.exportKey(key.name, pass, cb),
(cb) => this._keychain.exportKey(key.name, pass, cb),
(pem, cb) => crypto.keys.import(pem, pass, cb)
], (err, privKey) => {
if (err) {
Expand Down
Loading