Conversation
53e7b95 to
b9ed2f0
Compare
src/core/ipns/pb/ipnsEntry.js
Outdated
| return ipnsEntryProto.decode(marsheled) | ||
| }, | ||
| validityType: ipnsEntryProto.ValidityType | ||
| } |
There was a problem hiding this comment.
module.exports = {
create,
marshal : ipnsEntryProto.encode,
unmarshal : ipnsEntryProto.decode,
validityType: ipnsEntryProto.ValidityType
}
src/core/components/name.js
Outdated
| const human = require('human-to-milliseconds') | ||
| const path = require('../ipns/path') | ||
|
|
||
| const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR |
There was a problem hiding this comment.
const { OFFLINE_ERROR } = require('../utils')
There was a problem hiding this comment.
Actually, I think it's better to:
const ERRORS = require('../utils')so when you use it bellow is more meaningful:
return callback(new Error(ERROR.OFFLINE_ERROR))There was a problem hiding this comment.
It is really strange to me that the errors are in a utils.js file, making those imports really strange. In the future, all errors should be easily accessible from all the project, and we should access them in the same way as @fsdiogo suggested.
src/core/ipns/index.js
Outdated
| @@ -0,0 +1,54 @@ | |||
| 'use strict' | |||
|
|
|||
| const peerId = require('peer-id') | |||
There was a problem hiding this comment.
const { createFromPrivKey } = require('peer-id')
src/core/ipns/validator.js
Outdated
| } | ||
|
|
||
| // Validate EOL | ||
| const validityDate = Date.parse(validity.toString()) |
There was a problem hiding this comment.
FYI, the only valid time format is RFC3339 with nanosecond precision. That is:
2006-01-02T15:04:05.999999999Z07:00
There was a problem hiding this comment.
Note: It's extremely important that you only except strings of this exact form. Not validating this has unfortunate security implications.
This also needs to check the validity type.
There was a problem hiding this comment.
I will support milliseconds precision at first here and I added a task to improve the precision to nanosecond later (in the list above).
Basically, JS does not support nanoseconds precision natively and all the libs that I managed to find don't support summing date times with nanosecond precision.
There was a problem hiding this comment.
When you say that I must validate if the string has this exact form, you say that it should be compliant with RFC3339, right?
src/core/components/name.js
Outdated
| const human = require('human-to-milliseconds') | ||
| const path = require('../ipns/path') | ||
|
|
||
| const OFFLINE_ERROR = require('../utils').OFFLINE_ERROR |
There was a problem hiding this comment.
Actually, I think it's better to:
const ERRORS = require('../utils')so when you use it bellow is more meaningful:
return callback(new Error(ERROR.OFFLINE_ERROR))
src/core/components/name.js
Outdated
|
|
||
| // Parse ipfs path value | ||
| try { | ||
| value = path.parsePath(value) |
There was a problem hiding this comment.
Note: the value can be any arbitrary path.
src/core/ipns/resolver.js
Outdated
| } | ||
|
|
||
| // https://github.com/ipfs/go-ipfs-routing/blob/master/offline/offline.go | ||
| resolveLocal (name, publicKey, callback) { |
There was a problem hiding this comment.
Eventually, this should be pushed into a non-IPNS specific routing layer.
There was a problem hiding this comment.
I had been thinking about the go-ipfs implementation for the resolver.
For one side, I agree with your approach. That is, you decide which router the IPNS resolver should use, and this router is completely transparent for the IPNS resolver. However, as we are fetching from an offline and local source (datastore), it also seems strange to me to have the OfflineRouter.
Anyway, I am not sure about where this code should live on. @diasdavid any opinion here?
There was a problem hiding this comment.
Basically, it means that we can swap out the router at will. However, given the fact that you're only implementing offline routing, it doesn't really make a difference.
There was a problem hiding this comment.
Being a pluggable router is a considerable advantage. But yeah, that's what I thought while putting the resolveLocal in there.
However, when I integrate the routing I will have to understand if it still makes sense to have the resolveLocal inside the IPNS layer.
src/core/ipns/validator.js
Outdated
| } | ||
|
|
||
| // Validate EOL | ||
| const validityDate = Date.parse(validity.toString()) |
There was a problem hiding this comment.
Note: It's extremely important that you only except strings of this exact form. Not validating this has unfortunate security implications.
This also needs to check the validity type.
src/core/ipns/validator.js
Outdated
|
|
||
| // Validate EOL | ||
| const validityDate = Date.parse(validity.toString()) | ||
| if (validityType === IpnsEntry.validityType.EOL) { |
There was a problem hiding this comment.
We should fail by default if we can't validate the record.
src/core/ipns/validator.js
Outdated
| // Validate EOL | ||
| const validityDate = Date.parse(validity.toString()) | ||
| if (validityType === IpnsEntry.validityType.EOL) { | ||
| const validityDate = Date.parse(validity.toString()) |
There was a problem hiding this comment.
So it doesn't get lost in the buried review comments, this needs to explicitly check the date format.
There was a problem hiding this comment.
Once js-ipns initial implementation PR is merged, I will create an issue in there for tackling this with priority. I have been thinking a lot earlier and reading some stuff about bigint for js and I think that I reached a way to add the nanoseconds precision here. I also need to find a way to explicitly check the date format according to the RFC 3339
There was a problem hiding this comment.
I wouldn't feel comfortable merging this until this is fixed. Unfortunately, due to some mistakes in how we make signatures in IPNS, we rely on precisely validating the date for security.
|
@Stebalien why go-ipns and not go-libp2p-ipns? Did I miss any important convo? |
As far as I know, IPNS falls under the umbrella of IPFS, not libp2p. |
I see IPNS as a different piece than IPFS and libp2p. But as we don't have an IPNS umbrella, I don't know which would suit best here. By the way @Stebalien and @diasdavid , if one day we decide to completely move IPNS (publish, resolve) to a new repo, this repo should be called |
|
I know that there is no spec, but IPNS has been libp2p all along -- https://github.com/libp2p/specs/blob/master/4-architecture.md#46-naming Anyway. @vasco-santos, don't forget about the interop tests! You should be able to publish stuff with a go daemon and then read it from the repo with a js-ipfs daemon. |
|
@diasdavid I will change to the Yeah @diasdavid ! I have been testing everything to guarantee the interoperability between both. There are two fields which I am not sure right now, which are the record |
|
@vasco-santos mind doing a drawing of the IPNS architecture first as you see it so that we clearly sync what are the pieces and their respective names? |
That's a bit odd. I guess one could, e.g., make an IPNS record point to a multiaddr but I still don't feel like it fits in libp2p. It really does feel like a separate thing. I can move it, I just don't want to shuffle things back and forth. As for lang-ipns versus lang-ipns-record: ipfs/go-ipns#1 However, I held off on that as IPNS is record-store independent. That is, I'd almost expect:
|
|
@Stebalien I would go with that package naming proposal! |
|
My claim (and others) is that IPNS is just a specialized version of IPRS and that naming is essential piece to Networking and therefore it should be part of libp2p primitives. But you know what, I'll let you paint the bikeshed the color you want as long as we keep making progress here and we having IPNS working locally, over PubSub and DHT as soon as possible :) |
734b4b9 to
77caec1
Compare
alanshaw
left a comment
There was a problem hiding this comment.
All green apart from commitlint! 💚

A working version of IPNS working locally is here! 🚀 😎 💪
Steps:
Some notes, regarding the previous steps:
ttl, since it is still experimental, we can add it in a separate PR.Finally, thanks @Stebalien for your help and time answering all my questions regarding the IPNS implementation in GO.
Moreover, since there are no specs, and not that much documentation, I have been writing a document with all the IPNS workflow. It is a WIP by now, but it is currently available here.
Related PRs:
interface-ipfs-coretests for IPNS injs-ipfs