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

Commit a0642ed

Browse files
vasco-santosAlan Shaw
authored and
Alan Shaw
committed
refactor: ipns routing logic moved to instantiation (#1701)
1 parent eacd580 commit a0642ed

File tree

15 files changed

+551
-200
lines changed

15 files changed

+551
-200
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
"ncp": "^2.0.0",
7575
"qs": "^6.5.2",
7676
"rimraf": "^2.6.2",
77+
"sinon": "^7.1.1",
7778
"stream-to-promise": "^2.2.0"
7879
},
7980
"dependencies": {
@@ -87,6 +88,7 @@
8788
"byteman": "^1.3.5",
8889
"cid-tool": "~0.1.0",
8990
"cids": "~0.5.5",
91+
"datastore-core": "~0.6.0",
9092
"debug": "^4.1.0",
9193
"deep-extend": "~0.6.0",
9294
"err-code": "^1.1.2",

src/core/components/init.js

+11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ const defaultsDeep = require('@nodeutils/defaults-deep')
88
const defaultConfig = require('../runtime/config-nodejs.js')
99
const Keychain = require('libp2p-keychain')
1010

11+
const IPNS = require('../ipns')
12+
const OfflineDatastore = require('../ipns/routing/offline-datastore')
13+
1114
const addDefaultAssets = require('./init-assets')
1215

1316
module.exports = function init (self) {
@@ -105,6 +108,14 @@ module.exports = function init (self) {
105108
cb(null, true)
106109
}
107110
},
111+
// Setup the offline routing for IPNS.
112+
// This is primarily used for offline ipns modifications, such as the initializeKeyspace feature.
113+
(_, cb) => {
114+
const offlineDatastore = new OfflineDatastore(self._repo)
115+
116+
self._ipns = new IPNS(offlineDatastore, self._repo, self._peerInfo, self._keychain, self._options)
117+
cb(null, true)
118+
},
108119
// add empty unixfs dir object (go-ipfs assumes this exists)
109120
(_, cb) => {
110121
if (opts.emptyRepo) {

src/core/components/name.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ module.exports = function name (self) {
128128
const nocache = options.nocache && options.nocache.toString() === 'true'
129129
const recursive = options.recursive && options.recursive.toString() === 'true'
130130

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

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

158158
const resolveOptions = {
159159
nocache,
160-
recursive,
161-
local
160+
recursive
162161
}
163162

164-
self._ipns.resolve(name, self._peerInfo.id, resolveOptions, callback)
163+
self._ipns.resolve(name, resolveOptions, callback)
165164
})
166165
}
167166
}

src/core/components/start.js

+18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ const series = require('async/series')
44
const Bitswap = require('ipfs-bitswap')
55
const setImmediate = require('async/setImmediate')
66
const promisify = require('promisify-es6')
7+
const { TieredDatastore } = require('datastore-core')
8+
9+
const IPNS = require('../ipns')
10+
const OfflineDatastore = require('../ipns/routing/offline-datastore')
711

812
module.exports = (self) => {
913
return promisify((callback) => {
@@ -34,6 +38,20 @@ module.exports = (self) => {
3438
},
3539
(cb) => self.libp2p.start(cb),
3640
(cb) => {
41+
// Setup online routing for IPNS with a tiered routing composed by a DHT and a Pubsub router (if properly enabled)
42+
const ipnsStores = []
43+
44+
// TODO Add IPNS pubsub if enabled
45+
46+
// NOTE: IPNS routing is being replaced by the local repo datastore while the IPNS over DHT is not ready
47+
// When DHT is added, if local option enabled, should receive offlineDatastore as well
48+
const offlineDatastore = new OfflineDatastore(self._repo)
49+
ipnsStores.push(offlineDatastore)
50+
51+
// Create ipns routing with a set of datastores
52+
const routing = new TieredDatastore(ipnsStores)
53+
self._ipns = new IPNS(routing, self._repo, self._peerInfo, self._keychain, self._options)
54+
3755
self._bitswap = new Bitswap(
3856
self._libp2pNode,
3957
self._repo.blocks,

src/core/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const EventEmitter = require('events')
1818
const config = require('./config')
1919
const boot = require('./boot')
2020
const components = require('./components')
21-
const IPNS = require('./ipns')
21+
2222
// replaced by repo-browser when running in the browser
2323
const defaultRepo = require('./runtime/repo-nodejs')
2424
const preload = require('./preload')
@@ -126,7 +126,7 @@ class IPFS extends EventEmitter {
126126
})
127127
this._preload = preload(this)
128128
this._mfsPreload = mfsPreload(this)
129-
this._ipns = new IPNS(null, this)
129+
this._ipns = undefined
130130

131131
// IPFS Core exposed components
132132
// - for booting up a node

src/core/ipns/index.js

+22-6
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ const { createFromPrivKey } = require('peer-id')
44
const series = require('async/series')
55
const Receptacle = require('receptacle')
66

7+
const errcode = require('err-code')
78
const debug = require('debug')
89
const log = debug('jsipfs:ipns')
910
log.error = debug('jsipfs:ipns:error')
@@ -16,11 +17,12 @@ const path = require('./path')
1617
const defaultRecordTtl = 60 * 1000
1718

1819
class IPNS {
19-
constructor (routing, ipfs) {
20-
this.publisher = new IpnsPublisher(routing, ipfs._repo)
21-
this.republisher = new IpnsRepublisher(this.publisher, ipfs)
22-
this.resolver = new IpnsResolver(routing, ipfs._repo)
20+
constructor (routing, repo, peerInfo, keychain, options) {
21+
this.publisher = new IpnsPublisher(routing, repo)
22+
this.republisher = new IpnsRepublisher(this.publisher, repo, peerInfo, keychain, options)
23+
this.resolver = new IpnsResolver(routing)
2324
this.cache = new Receptacle({ max: 1000 }) // Create an LRU cache with max 1000 items
25+
this.routing = routing
2426
}
2527

2628
// Publish
@@ -53,7 +55,21 @@ class IPNS {
5355
}
5456

5557
// Resolve
56-
resolve (name, peerId, options, callback) {
58+
resolve (name, options, callback) {
59+
if (typeof name !== 'string') {
60+
const errMsg = `name received is not valid`
61+
62+
log.error(errMsg)
63+
return callback(errcode(new Error(errMsg), 'ERR_INVALID_NAME'))
64+
}
65+
66+
if (typeof options === 'function') {
67+
callback = options
68+
options = {}
69+
}
70+
71+
options = options || {}
72+
5773
// If recursive, we should not try to get the cached value
5874
if (!options.nocache && !options.recursive) {
5975
// Try to get the record from cache
@@ -67,7 +83,7 @@ class IPNS {
6783
}
6884
}
6985

70-
this.resolver.resolve(name, peerId, options, (err, result) => {
86+
this.resolver.resolve(name, options, (err, result) => {
7187
if (err) {
7288
log.error(err)
7389
return callback(err)

src/core/ipns/path.js

+1-7
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,7 @@ const resolvePath = (ipfsNode, name, callback) => {
1313
if (isIPFS.ipnsPath(name)) {
1414
log(`resolve ipns path ${name}`)
1515

16-
const local = true // TODO ROUTING - use self._options.local
17-
18-
const options = {
19-
local: local
20-
}
21-
22-
return ipfsNode._ipns.resolve(name, ipfsNode._peerInfo.id, options, callback)
16+
return ipfsNode._ipns.resolve(name, callback)
2317
}
2418

2519
// ipfs path

src/core/ipns/publisher.js

+10-10
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class IpnsPublisher {
3232

3333
PeerId.createFromPrivKey(privKey.bytes, (err, peerId) => {
3434
if (err) {
35-
callback(err)
35+
return callback(err)
3636
}
3737

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

6868
let keys
6969
try {
70-
keys = ipns.getIdKeys(peerId.id)
70+
keys = ipns.getIdKeys(peerId.toBytes())
7171
} catch (err) {
7272
log.error(err)
7373
return callback(err)
7474
}
7575

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

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

116116
log.error(errMsg)
117-
return callback(errcode(new Error(errMsg), 'ERR_STORING_IN_DATASTORE'))
117+
return callback(errcode(new Error(errMsg), 'ERR_PUTTING_TO_ROUTING'))
118118
}
119119

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

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

154154
log.error(errMsg)
155-
return callback(errcode(new Error(errMsg), 'ERR_STORING_IN_DATASTORE'))
155+
return callback(errcode(new Error(errMsg), 'ERR_PUTTING_TO_ROUTING'))
156156
}
157157

158158
log(`public key for ${key.toString()} was stored in the routing`)

src/core/ipns/republisher.js

+10-8
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ const defaultBroadcastInterval = 4 * hour
1818
const defaultRecordLifetime = 24 * hour
1919

2020
class IpnsRepublisher {
21-
constructor (publisher, ipfs) {
21+
constructor (publisher, repo, peerInfo, keychain, options) {
2222
this._publisher = publisher
23-
this._ipfs = ipfs
24-
this._repo = ipfs._repo
23+
this._repo = repo
24+
this._peerInfo = peerInfo
25+
this._keychain = keychain
26+
this._options = options
2527
this._republishHandle = null
2628
}
2729

@@ -62,8 +64,8 @@ class IpnsRepublisher {
6264
}
6365
}
6466

65-
const { privKey } = this._ipfs._peerInfo.id
66-
const { pass } = this._ipfs._options
67+
const { privKey } = this._peerInfo.id
68+
const { pass } = this._options
6769

6870
republishHandle.runPeriodically((done) => {
6971
this._republishEntries(privKey, pass, () => done(defaultBroadcastInterval))
@@ -98,16 +100,16 @@ class IpnsRepublisher {
98100
}
99101

100102
// keychain needs pass to get the cryptographic keys
101-
if (this._ipfs._keychain && Boolean(pass)) {
102-
this._ipfs._keychain.listKeys((err, list) => {
103+
if (pass) {
104+
this._keychain.listKeys((err, list) => {
103105
if (err) {
104106
log.error(err)
105107
return
106108
}
107109

108110
each(list, (key, cb) => {
109111
waterfall([
110-
(cb) => this._ipfs._keychain.exportKey(key.name, pass, cb),
112+
(cb) => this._keychain.exportKey(key.name, pass, cb),
111113
(pem, cb) => crypto.keys.import(pem, pass, cb)
112114
], (err, privKey) => {
113115
if (err) {

0 commit comments

Comments
 (0)