libp2p / js-peer-id

peer-id implementation in JavaScript. Deprecated; use https://github.com/libp2p/js-libp2p-peer-id instead.
https://github.com/libp2p/js-libp2p-peer-id
MIT License
80 stars 44 forks source link

Anyway type of config option to use old `Qm...` style IDs? #99

Closed rmisio closed 5 years ago

rmisio commented 5 years ago

I have data like this:

"peerID": "QmUWYRp3mkQUUVeyGVjcM1fC7kbVxmDieGpGsQzopXivyk",
"pubkey": "CAESILYoTcsl9HZVSyyvDmIIGXAPMtXxv0YHI1etWS1l9Nn1",

and I'd like to be able to validate that the pubkey and peerID match, but using the latest code createFromPubKey will get me a peerID of 12D3KooWN5S1ouS8cNLk5vhdKwQE3VUdxfLm89gW8NW9yS95KFtY.

Is there any type of config option where I could have it generate the old Qm style key so that I could validate old data?

rmisio commented 5 years ago

My second use-case is our JS codebase needs to be compatible with our GO codebase and when I spin up a node using the new peerID format (12D3Koo) I can't dial GO nodes that use the Qm format.

Our GO codebase is not ready to update and I'd rather not be stuck on old JS versions because critical functionality is coming in hopefully soon releases (e.g. DHT).

Ideally... there would be a config option where when we spin up a node we could configure it to use the old Qm... style IDs and then when our GO codebase updates, we just turn that flag back off.

jacobheun commented 5 years ago

What version of go-libp2p is being used? The pubKey you have is an Ed25519 key, but the ID string is rsa, so they're not going to match. How were those generated?

There may be an issue with the ed25519 version that go is using, if it's an old enough version, which could be causing the issues. If this is the case, you might need to use rsa keys in JS until that is upgraded.

rmisio commented 5 years ago

What version of go-libp2p is being used?

(from my GO dev) There's a lot of libp2p packages but the main one is 6.0.39

The pubKey you have is an Ed25519 key, but the ID string is rsa, so they're not going to match. How were those generated?

We're manually generating the Ed25519 pubkey from a mnemonic and then generating the peer ID from the Ed25519 pubkey using GO's equivalent of js-peer-id's createFromPubKey.

you might need to use rsa keys in JS until that is upgraded.

How exactly can I do that? It doesn't look like createFromPubKey offers a way for me to specify the key type. Looks like create does, but then that doesn't allow me to specify my own pubkey.

Also, I not only need to be able to specify the key type to js-peer-id, but I also would need a way to specify that in the ipfsjs node constructor since I'm deterministically creating a node based off of an ed25519 private key and in order for the node to be able to talk to our GO nodes, I'd need it to be created with an RSA peer ID.

rmisio commented 5 years ago

Ok, I found the issue and a not-so-pretty, but works-for-now fix.

Basically, I need this:

const computeDigest = (pubKey) => {
  if (pubKey.bytes.length <= 42) {
     return mh.encode(pubKey.bytes, 'identity')
  } else {
    return pubKey.hash()
 }
}

to become this:

const computeDigest = (pubKey) => {
  // if (pubKey.bytes.length <= 42) {
  //   return mh.encode(pubKey.bytes, 'identity')
  // } else {
    return pubKey.hash()
  // }
}

..which is actually how it worked until recently. Our GO implementation is still using hashed peerIDs (Qm...) and if web uses inline ones (12D3Koo...) then communication between the two fails. Also I can't just sit on an old version of ipfsjs because I need upcoming critical stuff like the DHT. And, our GO implementation probably won't be ready to update to the newer peerId format for weeks or months.

The fix is further complicated because it looks like 13 or so depenedencies have their own dependency on peer-id (and their own copies), so not only do I have to do the replacement in my own peer-id source in node_modules but I also have to do it in any dep which depends on it. Looks like a global search and replace luckily did the trick. Not pretty and it's something each JS dev will have to do after npm installing (unless I automate it somehow), but it works for now.

If this could be made into a config option, it would be awesome, although that would have to be exposed up the chain into any library (like ipfsjs) that creates a peerId. Not sure if others have this pain point, but we definitely do.

jacobheun commented 5 years ago

In theory you could get around this by doing something like the following when you create the PeerIds, although you will probably hit issues marshaling keys from the network.

const PeerId = require('peer-id')
const cryptoKeys = require('libp2p-crypto/src/keys')
const mh = require('multihashes')

async function createPeerId (peerIdString, pubKeyString) {
  const pubKey = await cryptoKeys.unmarshalPublicKey(Buffer.from(pubKeyString, 'base64'))
  const idBuffer = mh.fromB58String(peerIdString)
  return new PeerId(idBuffer, null, pubKey)
}

Because of how pervasive PeerId is in the ecosystem this is a difficult thing to resolve, as whatever logic creates the PeerId has to be updated everywhere. The inline update fixes issues with us not being able to communicate with more recent versions of go-libp2p.

Lock files Another option, instead of replacing code would be to use npm shrinkwrap or package locks depending on your needs, to make sure you're using <= 0.12.2 or 13.0.0. Long term this will probably be annoying to deal with, but it could be a viable option until the go portion of your network is able to update.

rmisio commented 5 years ago

Ok thanks, I have enough info to work around this issue for now. Thanks!