Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add public key support #4

Merged
merged 5 commits into from
Aug 9, 2018
Merged

Conversation

vasco-santos
Copy link
Member

Adding public key methods for allowing full interop with go-ipfs

@ghost ghost assigned vasco-santos Aug 6, 2018
@ghost ghost added the status/in-progress In progress label Aug 6, 2018
src/errors.js Outdated
@@ -5,3 +5,5 @@ exports.ERR_UNRECOGNIZED_VALIDITY = 'ERR_UNRECOGNIZED_VALIDITY'
exports.ERR_SIGNATURE_CREATION = 'ERR_SIGNATURE_CREATION'
exports.ERR_SIGNATURE_VERIFICATION = 'ERR_SIGNATURE_VERIFICATION'
exports.ERR_UNRECOGNIZED_FORMAT = 'ERR_UNRECOGNIZED_FORMAT'
exports.ERR_PEER_ID_FROM_PUBLIC_KEY = 'ERR_PEER_ID_FROM_PUBLIC_KEY'
exports.ERR_PUBLICK_KEY_FROM_ID = 'ERR_PUBLICK_KEY_FROM_ID'
Copy link
Member

Choose a reason for hiding this comment

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

typo: "PUBLICK"

src/index.js Outdated
@@ -4,6 +4,9 @@ const base32Encode = require('base32-encode')
const Big = require('big.js')
const NanoDate = require('nano-date').default
const { Key } = require('interface-datastore')
const crypto = require('libp2p-crypto')
const peerId = require('peer-id')
Copy link
Member

Choose a reason for hiding this comment

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

I would import this as PeerId - it is a class and saves you having to use peerIdResult to differentiate between this and a peer ID instance.

src/index.js Outdated
@@ -13,6 +16,7 @@ const ipnsEntryProto = require('./pb/ipns.proto')
const { parseRFC3339 } = require('./utils')
const ERRORS = require('./errors')

const ID_MULTIHASH_CODE = 0
Copy link
Member

Choose a reason for hiding this comment

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

Can this be imported from multihashes? If not then it needs a comment to explain what it is.

Copy link
Member Author

Choose a reason for hiding this comment

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

Just created a PR multiformats/js-multihash#57 for that 🙂

src/index.js Outdated
if (err) {
const error = 'cannot create peer id from the public key'

log.error(error)
Copy link
Member

Choose a reason for hiding this comment

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

Much more useful to log err than the message

src/index.js Outdated
const error = 'cannot create peer id from the public key'

log.error(error)
return callback(Object.assign(new Error(error), { code: ERRORS.ERR_PEER_ID_FROM_PUBLIC_KEY }))
Copy link
Member

Choose a reason for hiding this comment

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

Either assign the code to err or use a module like explain-error to retain the stack.

src/index.js Outdated

// If we vailed to extract the public key from the peer ID, embed it in the record.
entry.pubKey = crypto.keys.marshalPublicKey(publicKey)
return callback(null, entry)
Copy link
Member

Choose a reason for hiding this comment

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

Minor, no need to return a call to callback when it's the last statement of the function.

src/index.js Outdated
return callback(null, pubKey)
} else {
return callback(null, peerId.pubKey)
}
Copy link
Member

Choose a reason for hiding this comment

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

Minor, use if with a single return or if & else with no returns.

src/index.js Outdated
@@ -120,7 +157,13 @@ const embedPublicKey = (publicKey, entry, callback) => {
* @return {Void}
*/
const extractPublicKey = (peerId, entry, callback) => {
callback(new Error('not implemented yet'))
if (entry.pubKey) {
const pubKey = crypto.keys.unmarshalPublicKey(entry.pubKey)
Copy link
Member

Choose a reason for hiding this comment

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

Needs a try/catch around this?

src/index.js Outdated
if (validityType.toString() === '0') {
return 'EOL'
} else {
log.error('unrecognized validity type')
Copy link
Member

Choose a reason for hiding this comment

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

Put the validityType in the log message for better debugging

src/index.js Outdated
@@ -139,16 +182,16 @@ const getLocalKey = (key) => new Key(`/ipns/${rawStdEncoding(key)}`)
* Get key for sharing the record in the routing mechanism.
* Format: ${base32(/ipns/<HASH>)}, ${base32(/pk/<HASH>)}
*
* @param {Buffer} key peer identifier object.
* @param {Buffer} pid peer identifier object.
Copy link
Member

Choose a reason for hiding this comment

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

Not specifically an object, a buffer. Does this need an explanation of how you might extract this from a PeerId instance?

Copy link
Member

@alanshaw alanshaw left a comment

Choose a reason for hiding this comment

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

Nice! Just a few small issues to clean up and this will be gtg.

src/index.js Outdated
try {
const pubKey = crypto.keys.unmarshalPublicKey(entry.pubKey)

return callback(null, pubKey)
Copy link
Member

Choose a reason for hiding this comment

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

Avoid callback in a try block - if the callback throws, it'll be caught and the callback will be called again - very hard to debug!

Copy link
Member Author

Choose a reason for hiding this comment

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

true!

*
* @param {Object} publicKey public key for validating the record.
* @param {Object} publicKey public key to embed.
* @param {Object} entry ipns entry record.
* @param {function(Error)} [callback]
* @return {Void}
*/
const embedPublicKey = (publicKey, entry, callback) => {
Copy link
Member

Choose a reason for hiding this comment

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

Check publicKey, publicKey.bytes and entry exist?

src/index.js Outdated
}

// If we failed to extract the public key from the peer ID, embed it in the record.
entry.pubKey = crypto.keys.marshalPublicKey(publicKey)
Copy link
Member

Choose a reason for hiding this comment

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

try/catch around this?

@@ -120,7 +153,17 @@ const embedPublicKey = (publicKey, entry, callback) => {
* @return {Void}
*/
const extractPublicKey = (peerId, entry, callback) => {
Copy link
Member

Choose a reason for hiding this comment

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

Check peerId and entry exist

package.json Outdated
@@ -49,8 +51,7 @@
"dirty-chai": "^2.0.1",
"ipfs": "^0.29.3",
"ipfsd-ctl": "^0.36.0",
"libp2p-crypto": "^0.13.0",
"multihashes": "^0.4.13"
"libp2p-crypto": "^0.13.0"
Copy link
Member

Choose a reason for hiding this comment

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

This needs to move to dependencies

@vasco-santos vasco-santos merged commit e743632 into master Aug 9, 2018
@ghost ghost removed the status/in-progress In progress label Aug 9, 2018
@vasco-santos vasco-santos deleted the feat/add-public-key-support branch August 9, 2018 11:33
alanshaw pushed a commit to ipfs/js-ipfs that referenced this pull request Aug 29, 2018
A working version of **IPNS working locally** is here!  🚀 😎 💪 

Steps:

- [x] Create a new repo (**js-ipns**) like it was made with go in the last week ([go-ipns](https://github.com/ipfs/go-ipns)) and port the related code from this PR to there
- [x] Resolve IPNS names in publish, in order to verify if they exist (as it is being done for regular files) before being published
- [x] Handle remaining parameters in publish and resolve (except ttl). 
- [x] Test interface core spec [interface-ipfs-core#327](ipfs-inactive/interface-js-ipfs-core#327)
- [x] Test interoperability with go. [interop#26](ipfs/interop#26)
- [x] Integrate logging
- [x] Write unit tests
- [x] Add support for the lifetime with nanoseconds precision
- [x] Add Cache
- [x] Add initializeKeyspace
- [x] Republish

Some notes, regarding the previous steps: 

- There is an optional parameter not implemented in this PR, which is `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](ipfs/specs#184).

Related PRs:

- [x] [js-ipns#4](ipfs/js-ipns#4)
- [x] [js-ipfs-repo#173](ipfs/js-ipfs-repo#173)
- [x] [js-ipfs#1496](#1496)
- [x] [interface-ipfs-core#327](ipfs-inactive/interface-js-ipfs-core#327)
- [x] enable `interface-ipfs-core` tests for IPNS in `js-ipfs`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants