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

Commit b9ed2f0

Browse files
committed
wip
1 parent b584324 commit b9ed2f0

File tree

17 files changed

+419
-299
lines changed

17 files changed

+419
-299
lines changed

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
},
8989
"dependencies": {
9090
"async": "^2.6.0",
91+
"base32-encode": "^1.0.0",
9192
"big.js": "^5.0.3",
9293
"binary-querystring": "~0.1.2",
9394
"bl": "^1.2.2",
@@ -164,7 +165,6 @@
164165
"pull-stream": "^3.6.7",
165166
"pull-stream-to-stream": "^1.3.4",
166167
"pull-zip": "^2.0.1",
167-
"quick-lru": "^1.1.0",
168168
"read-pkg-up": "^3.0.0",
169169
"readable-stream": "2.3.6",
170170
"stream-to-pull-stream": "^1.7.2",

src/cli/commands/name/publish.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ module.exports = {
1919
throw err
2020
}
2121

22-
print(`Published to ${result.value}: /ipfs/${result.name}`)
22+
print(`Published to ${result.name}: ${result.value}`)
2323
})
2424
}
2525
}

src/core/components/name.js

+42-72
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
'use strict'
22

33
const promisify = require('promisify-es6')
4-
const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR
4+
const series = require('async/series')
55
const human = require('human-to-milliseconds')
6+
const path = require('../ipns/path')
7+
8+
const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR
69

710
const keyLookup = (ipfsNode, kname, cb) => {
811
if (kname === 'self') {
@@ -18,29 +21,6 @@ const keyLookup = (ipfsNode, kname, cb) => {
1821
})
1922
}
2023

21-
const publish = (ipfsNode, privateKey, ipfsPath, publishOptions, callback) => {
22-
// Should verify if exists ?
23-
if (publishOptions.verifyIfExists) {
24-
// TODO resolve
25-
// https://github.com/ipfs/go-ipfs/blob/master/core/commands/publish.go#L172
26-
}
27-
28-
// Add pubValidTime
29-
30-
// Publish
31-
const eol = new Date(Date.now())
32-
33-
ipfsNode._namesys.publishWithEOL(privateKey, ipfsPath, eol, (err, res) => {
34-
if (err) {
35-
callback(err)
36-
}
37-
38-
// TODO HERE HERE HERE
39-
40-
callback(null, res)
41-
})
42-
}
43-
4424
module.exports = function name (self) {
4525
return {
4626
/**
@@ -51,64 +31,55 @@ module.exports = function name (self) {
5131
*
5232
* Examples: TODO such as in go
5333
*
54-
* @param {String} ipfsPath
55-
* @param {Object} options
34+
* @param {String} value ipfs path of the object to be published.
35+
* @param {boolean} resolve resolve given path before publishing.
36+
* @param {String} lifetime time duration that the record will be valid for.
37+
This accepts durations such as "300s", "1.5h" or "2h45m". Valid time units are
38+
"ns", "us" (or "µs"), "ms", "s", "m", "h".
39+
* @param {String} ttl time duration this record should be cached for (caution: experimental).
40+
* @param {String} key name of the key to be used or a valid PeerID, as listed by 'ipfs key list -l'.
5641
* @param {function(Error)} [callback]
5742
* @returns {Promise|void}
5843
*/
59-
publish: promisify((ipfsPath, callback) => {
60-
// https://github.com/ipfs/go-ipfs/blob/master/core/commands/publish.go
44+
publish: promisify((value, resolve = true, lifetime = '24h', ttl, key = 'self', callback) => {
6145
if (!self.isOnline()) {
6246
return callback(new Error(OFFLINE_ERROR))
6347
}
6448

65-
// TODO Validate Mounts IPNS - cannot manually publish while IPNS is mounted
66-
67-
// TODO Validate Node identity not validated
68-
69-
// TODO Parse options and create object
70-
const options = {
71-
resolve: true,
72-
d: '24h',
73-
ttl: undefined,
74-
key: 'self'
49+
// Parse ipfs path value
50+
try {
51+
value = path.parsePath(value)
52+
} catch (err) {
53+
return callback(err)
7554
}
7655

77-
// TODO Create waterfall
78-
/* waterfall([
79-
(cb) => human(options.d || '1s', cb),
80-
], callback) */
81-
82-
human(options.d || '1s', (err, value) => {
56+
series([
57+
(cb) => human(lifetime || '1s', cb),
58+
// (cb) => ttl ? human(ttl, cb) : cb(),
59+
(cb) => keyLookup(self, key, cb),
60+
(cb) => resolve ? path.resolvePath(self, value, cb) : cb() // if not resolved, and error will stop the execution
61+
], (err, results) => {
8362
if (err) {
84-
return callback(new Error('Error parsing lifetime option'))
63+
return callback(err)
8564
}
8665

87-
const publishOptions = {
88-
verifyIfExists: options.resolve,
89-
pubValidTime: value
90-
}
66+
const pubValidTime = results[0]
67+
const privateKey = results[1]
9168

92-
// TODO Date.now() + value
69+
// TODO IMPROVEMENT - Handle ttl for cache
70+
// const ttl = results[1]
71+
// const privateKey = results[2]
9372

94-
// TODO TTL integration
73+
// Calculate eol
74+
const eol = new Date(Date.now() + pubValidTime)
9575

96-
// Get Key
97-
keyLookup(self, options.key, (err, key) => {
76+
// Start publishing process
77+
self._ipns.publish(privateKey, value, eol, (err, res) => {
9878
if (err) {
99-
return callback(err)
79+
callback(err)
10080
}
10181

102-
// TODO ParsePath
103-
// https://github.com/ipfs/go-ipfs/blob/master/path/path.go
104-
105-
publish(self, key, ipfsPath, publishOptions, (err, result) => {
106-
if (err) {
107-
callback(err)
108-
}
109-
110-
return callback(null, result)
111-
})
82+
callback(null, res)
11283
})
11384
})
11485
}),
@@ -125,17 +96,10 @@ module.exports = function name (self) {
12596
resolve: promisify((name, nocache, recursive, callback) => {
12697
const local = true
12798

128-
if (typeof name === 'function') {
129-
callback = name
130-
name = undefined
131-
}
132-
13399
if (!self.isOnline()) {
134100
return callback(new Error(OFFLINE_ERROR))
135101
}
136102

137-
// let resolver = self._namesys.ipnsResolver
138-
139103
if (local && nocache) {
140104
return callback(new Error('Cannot specify both local and nocache'))
141105
}
@@ -149,9 +113,15 @@ module.exports = function name (self) {
149113
name = `/ipns/${name}`
150114
}
151115

116+
// TODO local public key?
152117
const pubKey = self._peerInfo.id.pubKey
118+
const options = {
119+
local: local,
120+
nocache: nocache,
121+
recursive: recursive
122+
}
153123

154-
self._namesys.resolve(name, pubKey, (err, result) => {
124+
self._ipns.resolve(name, pubKey, options, (err, result) => {
155125
if (err) {
156126
return callback(err)
157127
}

src/core/index.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ const EventEmitter = require('events')
2020
const config = require('./config')
2121
const boot = require('./boot')
2222
const components = require('./components')
23-
const Namesys = require('./namesys')
23+
const IPNS = require('./ipns')
2424
// replaced by repo-browser when running in the browser
2525
const defaultRepo = require('./runtime/repo-nodejs')
2626

@@ -80,7 +80,7 @@ class IPFS extends EventEmitter {
8080
this._blockService = new BlockService(this._repo)
8181
this._ipld = new Ipld(this._blockService)
8282
this._pubsub = undefined
83-
this._namesys = new Namesys(null, this._repo)
83+
this._ipns = new IPNS(null, this._repo)
8484

8585
// IPFS Core exposed components
8686
// - for booting up a node

src/core/namesys/index.js src/core/ipns/index.js

+10-14
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
const peerId = require('peer-id')
44
const series = require('async/series')
55
// const QuickLRU = require('quick-lru');
6+
// Consider using https://github.com/dominictarr/hashlru
67

78
const IpnsPublisher = require('./publisher')
89
const IpnsResolver = require('./resolver')
10+
const path = require('./path')
911

1012
// const defaultRecordTtl = 60 * 1000
1113

12-
class Namesys {
14+
class IPNS {
1315
constructor (routing, repo, peerInfo) {
1416
this.ipnsPublisher = new IpnsPublisher(routing, repo)
1517
this.ipnsResolver = new IpnsResolver(repo)
1618
// this.cache = new QuickLRU({maxSize: 1000});
1719
}
1820

1921
// Resolve
20-
resolve (name, pubKey, callback) {
21-
// this.ipnsResolver.resolve()
22-
23-
this.ipnsResolver.resolve(name, pubKey, (err, result) => {
22+
resolve (name, pubKey, options, callback) {
23+
this.ipnsResolver.resolve(name, pubKey, options, (err, result) => {
2424
if (err) {
2525
return callback(err)
2626
}
@@ -29,13 +29,8 @@ class Namesys {
2929
})
3030
}
3131

32-
// publish (value = ipfsPath)
33-
publish (privKey, value) {
34-
// TODO https://github.com/ipfs/go-ipfs/blob/master/namesys/namesys.go#L111
35-
}
36-
37-
// publish with EOL (value = ipfsPath)
38-
publishWithEOL (privKey, value, eol, callback) {
32+
// Publish
33+
publish (privKey, value, eol, callback) {
3934
series([
4035
(cb) => peerId.createFromPrivKey(privKey.bytes.toString('base64'), cb),
4136
(cb) => this.ipnsPublisher.publishWithEOL(privKey, value, eol, cb)
@@ -44,7 +39,7 @@ class Namesys {
4439
return callback(err)
4540
}
4641

47-
// TODO Add to cache
42+
// TODO IMPROVEMENT - Add to cache
4843
// this.cache.set(id.toB58String(), {
4944
// val: value,
5045
// eol: Date.now() + ttl
@@ -55,4 +50,5 @@ class Namesys {
5550
}
5651
}
5752

58-
exports = module.exports = Namesys
53+
exports = module.exports = IPNS
54+
exports.path = path

src/core/ipns/path.js

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
'use strict'
2+
3+
const CID = require('cids')
4+
5+
const BAD_PATH_ERROR = new Error('invalid \'ipfs ref\' path')
6+
const NO_COMPONENTS_ERROR = new Error('path must contain at least one component')
7+
8+
// Should verify if the value exists before publishing it
9+
const resolvePath = (ipfsNode, value, callback) => {
10+
if (value.startsWith('/ipns/')) {
11+
// TODO resolve local?
12+
// TODO Resolve from DHT
13+
return callback(new Error('not implemented yet'))
14+
}
15+
16+
ipfsNode.dag.get(value.substring('/ipfs/'.length), (err, value) => {
17+
if (err) {
18+
return callback(err)
19+
}
20+
21+
return callback(null, value)
22+
})
23+
}
24+
25+
// parsePath returns a well-formed ipfs Path.
26+
// The returned path will always be prefixed with /ipfs/ or /ipns/.
27+
// If the received string is not a valid ipfs path, an error will be returned
28+
const parsePath = (pathStr) => {
29+
const parts = pathStr.split('/')
30+
31+
if (parts.length === 1) {
32+
return parseCidToPath(pathStr)
33+
}
34+
35+
// if the path does not begin with a slash, we expect this to start with a hash and be an ipfs path
36+
if (parts[0] !== '') {
37+
if (parseCidToPath(parts[0])) {
38+
return `/ipfs/${pathStr}`
39+
}
40+
}
41+
42+
if (parts.length < 3) {
43+
throw BAD_PATH_ERROR
44+
}
45+
46+
if (parts[1] === 'ipfs') {
47+
if (!parseCidToPath(parts[2])) {
48+
throw BAD_PATH_ERROR
49+
}
50+
} else if (parts[1] !== 'ipns') {
51+
throw BAD_PATH_ERROR
52+
}
53+
return pathStr
54+
}
55+
56+
// parseCidToPath takes a CID in string form and returns a valid ipfs Path.
57+
const parseCidToPath = (value) => {
58+
if (value === '') {
59+
throw NO_COMPONENTS_ERROR
60+
}
61+
62+
const cid = new CID(value)
63+
CID.validateCID(cid)
64+
65+
return `/ipfs/${value}`
66+
}
67+
68+
module.exports = {
69+
resolvePath,
70+
parsePath
71+
}
File renamed without changes.

src/core/namesys/pb/ipnsEntry.js src/core/ipns/pb/ipnsEntry.js

+13-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module.exports = {
1010
validityType = ipnsEntryProto.ValidityType.EOL
1111
}
1212

13-
return {
13+
const entry = {
1414
value: value,
1515
signature: signature,
1616
validityType: validityType,
@@ -19,6 +19,16 @@ module.exports = {
1919
ttl: ttl,
2020
pubKey: pubKey
2121
}
22+
23+
return Object.keys(entry).reduce((acc, key) => {
24+
const reducedEntry = acc
25+
26+
if (entry[key] !== undefined) {
27+
reducedEntry[key] = entry[key]
28+
}
29+
30+
return reducedEntry
31+
}, {})
2232
},
2333
// Marshal
2434
marshal: (ipnsEntry) => {
@@ -27,5 +37,6 @@ module.exports = {
2737
// Unmarshal
2838
unmarshal: (marsheled) => {
2939
return ipnsEntryProto.decode(marsheled)
30-
}
40+
},
41+
validityType: ipnsEntryProto.ValidityType
3142
}

0 commit comments

Comments
 (0)