ipns.embedPublicKey(publicKey, record, (err, embedPublicKeyRecord) => { if (err) { return callback(err) } let keys try { keys = ipns.getIdKeys(peerId.toBytes()) } catch (err) { log.error(err) return callback(err) } series([ (cb) => this._publishEntry(keys.routingKey, embedPublicKeyRecord || record, peerId, cb), // Publish the public key to support old go-ipfs nodes that are looking for it in the routing // We will be able to deprecate this part in the future, since the public keys will be only // in IPNS record and the peerId. (cb) => this._publishPublicKey(keys.routingPubKey, publicKey, peerId, cb) ], (err) => { if (err) { log.error(err) return callback(err) } callback(null, embedPublicKeyRecord || record) }) })
this._datastore.get(ipns.getLocalKey(peerId.id), (err, dsVal) => { if (err) { if (err.code !== 'ERR_NOT_FOUND') { const errMsg = `unexpected error getting the ipns record ${peerId.id} from datastore` log.error(errMsg) return callback(errcode(new Error(errMsg), 'ERR_UNEXPECTED_DATASTORE_RESPONSE')) } if (!checkRouting) { return callback((errcode(err))) } // Try to get from routing let keys try { keys = ipns.getIdKeys(peerId.toBytes()) } catch (err) { log.error(err) return callback(err) } this._routing.get(keys.routingKey.toBuffer(), (err, res) => { if (err) { return callback(err) } // unmarshal data this._unmarshalData(res, callback) }) } else { // unmarshal data this._unmarshalData(dsVal, callback) } })
// resolve ipns entries from the provided routing _resolveName (name, callback) { let peerId try { peerId = PeerId.createFromB58String(name) } catch (err) { return callback(err) } const { routingKey } = ipns.getIdKeys(peerId.toBytes()) // TODO DHT - get public key from routing? // https://github.com/ipfs/go-ipfs/blob/master/namesys/routing.go#L70 // https://github.com/libp2p/go-libp2p-routing/blob/master/routing.go#L99 this._routing.get(routingKey.toBuffer(), (err, res) => { if (err) { if (err.code !== 'ERR_NOT_FOUND') { const errMsg = `unexpected error getting the ipns record ${peerId.id}` log.error(errMsg) return callback(errcode(new Error(errMsg), 'ERR_UNEXPECTED_ERROR_GETTING_RECORD')) } const errMsg = `record requested was not found for ${name} (${routingKey}) in the network` log.error(errMsg) return callback(errcode(new Error(errMsg), 'ERR_NO_RECORD_FOUND')) } let ipnsEntry try { const record = Record.deserialize(res) ipnsEntry = ipns.unmarshal(record.value) } catch (err) { const errMsg = `found ipns record that we couldn't convert to a value` log.error(errMsg) return callback(errcode(new Error(errMsg), 'ERR_INVALID_RECORD_RECEIVED')) } ipns.extractPublicKey(peerId, ipnsEntry, (err, pubKey) => { if (err) { return callback(err) } // IPNS entry validation ipns.validate(pubKey, ipnsEntry, (err) => { if (err) { return callback(err) } callback(null, ipnsEntry.value.toString()) }) }) }) }
it('should publish and then resolve correctly', function (done) { this.timeout(80 * 1000) let subscribed = false function checkMessage (msg) { subscribed = true } const alreadySubscribed = (cb) => { return cb(null, subscribed === true) } // Wait until a peer subscribes a topic const waitForPeerToSubscribe = (node, topic, callback) => { retry({ times: 5, interval: 2000 }, (next) => { node.pubsub.peers(topic, (error, res) => { if (error) { return next(error) } if (!res || !res.length) { return next(new Error('Could not find subscription')) } return next(null, res) }) }, callback) } const keys = ipns.getIdKeys(fromB58String(idA.id)) const topic = `${namespace}${base64url.encode(keys.routingKey.toBuffer())}` nodeB.name.resolve(idA.id, (err) => { expect(err).to.exist() series([ (cb) => waitForPeerToSubscribe(nodeA, topic, cb), (cb) => nodeB.pubsub.subscribe(topic, checkMessage, cb), (cb) => nodeA.name.publish(ipfsRef, { resolve: false }, cb), (cb) => waitFor((callback) => alreadySubscribed(callback), cb), (cb) => setTimeout(() => cb(), 1000), // guarantee record is written (cb) => nodeB.name.resolve(idA.id, cb) ], (err, res) => { expect(err).to.not.exist() expect(res).to.exist() expect(res[5]).to.exist() expect(res[5].path).to.equal(ipfsRef) done() }) }) })