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

feat: allow passing the id of a network peer to ipfs.id #3386

Merged
merged 7 commits into from
May 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/core-api/MISCELLANEOUS.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ An optional object which may have the following keys:
| ---- | ---- | ------- | ----------- |
| timeout | `Number` | `undefined` | A timeout in ms |
| signal | [AbortSignal][] | `undefined` | Can be used to cancel any long running requests started as a result of this call |
| peerId | `string` | `undefined` | Look up the identity for this peer instead of the current node |

### Returns

Expand Down Expand Up @@ -300,4 +301,4 @@ A great source of [examples](https://github.com/ipfs/js-ipfs/blob/master/package
[rs]: https://www.npmjs.com/package/readable-stream
[ps]: https://www.npmjs.com/package/pull-stream
[cid]: https://www.npmjs.com/package/cids
[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
[AbortSignal]: https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal
2 changes: 1 addition & 1 deletion examples/custom-libp2p/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"license": "MIT",
"dependencies": {
"ipfs": "^0.55.1",
"libp2p": "^0.31.0",
"libp2p": "^0.31.5",
"libp2p-bootstrap": "^0.12.3",
"libp2p-kad-dht": "^0.22.0",
"libp2p-mdns": "^0.16.0",
Expand Down
1 change: 1 addition & 0 deletions packages/interface-ipfs-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
"nanoid": "^3.1.12",
"native-abort-controller": "^1.0.3",
"p-map": "^4.0.0",
"p-retry": "^4.5.0",
"peer-id": "^0.14.1",
"readable-stream": "^3.4.0",
"uint8arrays": "^2.1.3"
Expand Down
30 changes: 30 additions & 0 deletions packages/interface-ipfs-core/src/miscellaneous/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { getDescribe, getIt, expect } = require('../utils/mocha')
const { Multiaddr } = require('multiaddr')
const CID = require('cids')
const { isWebWorker } = require('ipfs-utils/src/env')
const retry = require('p-retry')

/** @typedef { import("ipfsd-ctl/src/factory") } Factory */
/**
Expand Down Expand Up @@ -66,5 +67,34 @@ module.exports = (common, options) => {

await expect(ipfs.id()).to.eventually.have.property('addresses').that.is.not.empty()
})

it('should get the id of another node in the swarm', async function () {
if (isWebWorker) {
// TODO: https://github.com/libp2p/js-libp2p-websockets/issues/129
return this.skip()
}

const ipfsB = (await common.spawn()).api
await ipfs.swarm.connect(ipfsB.peerId.addresses[0])

// have to wait for identify to complete before protocols etc are available for remote hosts
await retry(async () => {
const result = await ipfs.id({
peerId: ipfsB.peerId.id
})

expect(result).to.deep.equal(ipfsB.peerId)
}, { retries: 5 })
})

it('should get our own id when passed as an option', async function () {
const res = await ipfs.id()

const result = await ipfs.id({
peerId: res.id
})

expect(result).to.deep.equal(res)
})
})
}
12 changes: 9 additions & 3 deletions packages/ipfs-cli/src/commands/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,15 @@
const { default: parseDuration } = require('parse-duration')

module.exports = {
command: 'id',
command: 'id [peerId]',

describe: 'Shows IPFS Node ID info',

builder: {
peerid: {
type: 'string',
describe: 'Peer.ID of node to look up'
},
format: {
alias: 'f',
type: 'string',
Expand All @@ -24,10 +28,12 @@ module.exports = {
* @param {import('../types').Context} argv.ctx
* @param {string} argv.format
* @param {number} argv.timeout
* @param {string} [argv.peerId]
*/
async handler ({ ctx: { ipfs, print }, format, timeout }) {
async handler ({ ctx: { ipfs, print }, format, timeout, peerId }) {
const id = await ipfs.id({
timeout
timeout,
peerId
})

if (format) {
Expand Down
21 changes: 20 additions & 1 deletion packages/ipfs-cli/test/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
const { expect } = require('aegir/utils/chai')
const cli = require('./utils/cli')
const sinon = require('sinon')
const PeerId = require('peer-id')

const defaultOptions = {
timeout: undefined
timeout: undefined,
peerId: undefined
}

describe('id', () => {
Expand Down Expand Up @@ -54,4 +56,21 @@ describe('id', () => {
expect(res).to.have.property('id', 'id')
expect(res).to.have.property('publicKey', 'publicKey')
})

it('get the id of another peer', async () => {
const peerId = PeerId.createFromB58String('QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D')

ipfs.id.withArgs({
...defaultOptions,
peerId: peerId.toString()
}).resolves({
id: 'id',
publicKey: 'publicKey'
})

const out = await cli(`id ${peerId}`, { ipfs })
const res = JSON.parse(out)
expect(res).to.have.property('id', 'id')
expect(res).to.have.property('publicKey', 'publicKey')
})
})
6 changes: 5 additions & 1 deletion packages/ipfs-core-types/src/root.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export interface API<OptionExtension = {}> {
* console.log(identity)
* ```
*/
id: (options?: AbortOptions & OptionExtension) => Promise<IDResult>
id: (options?: IDOptions & OptionExtension) => Promise<IDResult>

/**
* Returns the implementation version
Expand Down Expand Up @@ -289,6 +289,10 @@ export interface ListOptions extends AbortOptions, PreloadOptions {
includeContent?: boolean
}

export interface IDOptions extends AbortOptions {
peerId?: string
}

export interface IDResult {
id: string
publicKey: string
Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs-core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
"it-map": "^1.0.4",
"it-pipe": "^1.1.0",
"just-safe-set": "^2.2.1",
"libp2p": "^0.31.2",
"libp2p": "^0.31.5",
"libp2p-bootstrap": "^0.12.3",
"libp2p-crypto": "^0.19.3",
"libp2p-floodsub": "^0.25.1",
Expand Down
69 changes: 39 additions & 30 deletions packages/ipfs-core/src/components/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ const pkgversion = require('../../package.json').version
const { Multiaddr } = require('multiaddr')
const withTimeoutOption = require('ipfs-core-utils/src/with-timeout-option')
const uint8ArrayToString = require('uint8arrays/to-string')
const PeerId = require('peer-id')
const { NotStartedError } = require('../errors')

/**
* @param {Object} config
Expand All @@ -14,54 +16,61 @@ module.exports = ({ peerId, network }) => {
/**
* @type {import('ipfs-core-types/src/root').API["id"]}
*/
async function id (_options = {}) { // eslint-disable-line require-await
const id = peerId.toB58String()
/** @type {Multiaddr[]} */
let addresses = []
/** @type {string[]} */
let protocols = []
async function id (options = {}) { // eslint-disable-line require-await
if (options.peerId === peerId.toB58String()) {
delete options.peerId
}

const net = network.try()

if (net) {
const { libp2p } = net
// only available while the node is running
addresses = libp2p.multiaddrs
protocols = Array.from(libp2p.upgrader.protocols.keys())
if (!net) {
if (options.peerId) {
throw new NotStartedError()
}

const idStr = peerId.toB58String()

return {
id: idStr,
publicKey: uint8ArrayToString(peerId.pubKey.bytes, 'base64pad'),
addresses: [],
agentVersion: `js-ipfs/${pkgversion}`,
protocolVersion: '9000',
protocols: []
}
}

const id = options.peerId ? PeerId.createFromB58String(options.peerId.toString()) : peerId
const { libp2p } = net

const publicKey = options.peerId ? libp2p.peerStore.keyBook.get(id) : id.pubKey
const addresses = options.peerId ? libp2p.peerStore.addressBook.getMultiaddrsForPeer(id) : libp2p.multiaddrs
const protocols = options.peerId ? libp2p.peerStore.protoBook.get(id) : Array.from(libp2p.upgrader.protocols.keys())
const agentVersion = uint8ArrayToString(libp2p.peerStore.metadataBook.getValue(id, 'AgentVersion') || new Uint8Array())
const protocolVersion = uint8ArrayToString(libp2p.peerStore.metadataBook.getValue(id, 'ProtocolVersion') || new Uint8Array())
const idStr = id.toB58String()

return {
id,
publicKey: uint8ArrayToString(peerId.pubKey.bytes, 'base64pad'),
addresses: addresses
id: idStr,
publicKey: uint8ArrayToString(publicKey.bytes, 'base64pad'),
addresses: (addresses || [])
.map(ma => {
const str = ma.toString()

// some relay-style transports add our peer id to the ma for us
// so don't double-add
if (str.endsWith(`/p2p/${id}`)) {
if (str.endsWith(`/p2p/${idStr}`)) {
return str
}

return `${str}/p2p/${id}`
return `${str}/p2p/${idStr}`
})
.sort()
.map(ma => new Multiaddr(ma)),
agentVersion: `js-ipfs/${pkgversion}`,
protocolVersion: '9000',
protocols: protocols.sort()
agentVersion,
protocolVersion,
protocols: (protocols || []).sort()
}
}
return withTimeoutOption(id)
}

/**
* @typedef {object} ID
* The Peer identity
* @property {string} id - the Peer ID
* @property {string} publicKey - the public key of the peer as a base64 encoded string
* @property {Multiaddr[]} addresses - A list of multiaddrs this node is listening on
* @property {string} agentVersion - The agent version
* @property {string} protocolVersion - The supported protocol version
* @property {string[]} protocols - The supported protocols
*/
4 changes: 4 additions & 0 deletions packages/ipfs-core/src/components/libp2p.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const get = require('dlv')
const mergeOptions = require('merge-options')
const errCode = require('err-code')
const PubsubRouters = require('../runtime/libp2p-pubsub-routers-nodejs')
const pkgversion = require('../../package.json').version

/**
* @typedef {Object} KeychainConfig
Expand Down Expand Up @@ -134,6 +135,9 @@ function getLibp2pOptions ({ options, config, datastore, keys, keychainConfig, p
keychain: {
datastore: keys,
...keychainConfig
},
host: {
agentVersion: `js-ipfs/${pkgversion}`
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/ipfs-daemon/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"ipfs-http-server": "^0.4.0",
"ipfs-utils": "^7.0.0",
"just-safe-set": "^2.2.1",
"libp2p": "^0.31.2",
"libp2p": "^0.31.5",
"libp2p-delegated-content-routing": "^0.10.0",
"libp2p-delegated-peer-routing": "^0.9.0",
"libp2p-webrtc-star": "^0.22.2",
Expand Down
5 changes: 4 additions & 1 deletion packages/ipfs-http-client/src/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ module.exports = configure(api => {
const res = await api.post('id', {
timeout: options.timeout,
signal: options.signal,
searchParams: toUrlSearchParams(options),
searchParams: toUrlSearchParams({
arg: options.peerId ? options.peerId.toString() : undefined,
...options
}),
headers: options.headers
})
const data = await res.json()
Expand Down
13 changes: 10 additions & 3 deletions packages/ipfs-http-server/src/api/resources/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ module.exports = {
stripUnknown: true
},
query: Joi.object().keys({
timeout: Joi.timeout()
timeout: Joi.timeout(),
peerId: Joi.string()
})
.rename('arg', 'peerId', {
override: true,
ignoreUndefined: true
})
}
},
/**
Expand All @@ -29,13 +34,15 @@ module.exports = {
}
},
query: {
timeout
timeout,
peerId
}
} = request

const id = await ipfs.id({
signal,
timeout
timeout,
peerId
})
return h.response({
ID: id.id,
Expand Down
25 changes: 24 additions & 1 deletion packages/ipfs-http-server/test/inject/id.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ const { AbortSignal } = require('native-abort-controller')

const defaultOptions = {
signal: sinon.match.instanceOf(AbortSignal),
timeout: undefined
timeout: undefined,
peerId: undefined
}

describe('/id', () => {
Expand Down Expand Up @@ -65,4 +66,26 @@ describe('/id', () => {

expect(res).to.have.property('statusCode', 200)
})

it('get the id of another peer', async () => {
const peerId = 'QmSnuWmxptJZdLJpKRarxBMS2Ju2oANVrgbr2xWbie9b2D'

ipfs.id.withArgs({
...defaultOptions,
peerId
}).returns({
id: 'id',
publicKey: 'publicKey',
addresses: 'addresses',
agentVersion: 'agentVersion',
protocolVersion: 'protocolVersion'
})

const res = await http({
method: 'POST',
url: `/api/v0/id?peerId=${peerId}`
}, { ipfs })

expect(res).to.have.property('statusCode', 200)
})
})