diff --git a/src/dialer/dial-request.js b/src/dialer/dial-request.js index 707f4e2171..397fc784c4 100644 --- a/src/dialer/dial-request.js +++ b/src/dialer/dial-request.js @@ -7,6 +7,7 @@ const FIFO = require('p-fifo') const pAny = require('p-any') // @ts-expect-error setMaxListeners is missing from the types const { setMaxListeners } = require('events') +const { codes } = require('../errors') /** * @typedef {import('libp2p-interfaces/src/connection').Connection} Connection @@ -55,7 +56,7 @@ class DialRequest { const tokens = this.dialer.getTokens(this.addrs.length) // If no tokens are available, throw if (tokens.length < 1) { - throw errCode(new Error('No dial tokens available'), 'ERR_NO_DIAL_TOKENS') + throw errCode(new Error('No dial tokens available'), codes.ERR_NO_DIAL_TOKENS) } const tokenHolder = new FIFO() diff --git a/src/errors.js b/src/errors.js index efaed29c06..a5db3901b1 100644 --- a/src/errors.js +++ b/src/errors.js @@ -36,5 +36,29 @@ exports.codes = { ERR_TRANSPORT_DIAL_FAILED: 'ERR_TRANSPORT_DIAL_FAILED', ERR_UNSUPPORTED_PROTOCOL: 'ERR_UNSUPPORTED_PROTOCOL', ERR_INVALID_MULTIADDR: 'ERR_INVALID_MULTIADDR', - ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID' + ERR_SIGNATURE_NOT_VALID: 'ERR_SIGNATURE_NOT_VALID', + ERR_FIND_SELF: 'ERR_FIND_SELF', + ERR_NO_ROUTERS: 'ERR_NO_ROUTERS', + ERR_CONNECTION_NOT_MULTIPLEXED: 'ERR_CONNECTION_NOT_MULTIPLEXED', + ERR_NO_DIAL_TOKENS: 'ERR_NO_DIAL_TOKENS', + ERR_KEYCHAIN_REQUIRED: 'ERR_KEYCHAIN_REQUIRED', + ERR_INVALID_CMS: 'ERR_INVALID_CMS', + ERR_MISSING_KEYS: 'ERR_MISSING_KEYS', + ERR_NO_KEY: 'ERR_NO_KEY', + ERR_INVALID_KEY_NAME: 'ERR_INVALID_KEY_NAME', + ERR_INVALID_KEY_TYPE: 'ERR_INVALID_KEY_TYPE', + ERR_KEY_ALREADY_EXISTS: 'ERR_KEY_ALREADY_EXISTS', + ERR_INVALID_KEY_SIZE: 'ERR_INVALID_KEY_SIZE', + ERR_KEY_NOT_FOUND: 'ERR_KEY_NOT_FOUND', + ERR_OLD_KEY_NAME_INVALID: 'ERR_OLD_KEY_NAME_INVALID', + ERR_NEW_KEY_NAME_INVALID: 'ERR_NEW_KEY_NAME_INVALID', + ERR_PASSWORD_REQUIRED: 'ERR_PASSWORD_REQUIRED', + ERR_PEM_REQUIRED: 'ERR_PEM_REQUIRED', + ERR_CANNOT_READ_KEY: 'ERR_CANNOT_READ_KEY', + ERR_MISSING_PRIVATE_KEY: 'ERR_MISSING_PRIVATE_KEY', + ERR_INVALID_OLD_PASS_TYPE: 'ERR_INVALID_OLD_PASS_TYPE', + ERR_INVALID_NEW_PASS_TYPE: 'ERR_INVALID_NEW_PASS_TYPE', + ERR_INVALID_PASS_LENGTH: 'ERR_INVALID_PASS_LENGTH', + ERR_NOT_IMPLEMENTED: 'ERR_NOT_IMPLEMENTED', + ERR_WRONG_PING_ACK: 'ERR_WRONG_PING_ACK' } diff --git a/src/keychain/cms.js b/src/keychain/cms.js index e9361882df..f929cb4e71 100644 --- a/src/keychain/cms.js +++ b/src/keychain/cms.js @@ -10,6 +10,7 @@ const { certificateForKey, findAsync } = require('./util') const errcode = require('err-code') const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string') const { toString: uint8ArrayToString } = require('uint8arrays/to-string') +const { codes } = require('../errors') const privates = new WeakMap() @@ -31,7 +32,7 @@ class CMS { */ constructor (keychain, dek) { if (!keychain) { - throw errcode(new Error('keychain is required'), 'ERR_KEYCHAIN_REQUIRED') + throw errcode(new Error('keychain is required'), codes.ERR_KEYCHAIN_REQUIRED) } this.keychain = keychain @@ -49,7 +50,7 @@ class CMS { */ async encrypt (name, plain) { if (!(plain instanceof Uint8Array)) { - throw errcode(new Error('Plain data must be a Uint8Array'), 'ERR_INVALID_PARAMS') + throw errcode(new Error('Plain data must be a Uint8Array'), codes.ERR_INVALID_PARAMETERS) } const key = await this.keychain.findKeyByName(name) @@ -81,7 +82,7 @@ class CMS { */ async decrypt (cmsData) { if (!(cmsData instanceof Uint8Array)) { - throw errcode(new Error('CMS data is required'), 'ERR_INVALID_PARAMS') + throw errcode(new Error('CMS data is required'), codes.ERR_INVALID_PARAMETERS) } let cms @@ -91,7 +92,7 @@ class CMS { // @ts-ignore not defined cms = forge.pkcs7.messageFromAsn1(obj) } catch (/** @type {any} */ err) { - throw errcode(new Error('Invalid CMS: ' + err.message), 'ERR_INVALID_CMS') + throw errcode(new Error('Invalid CMS: ' + err.message), codes.ERR_INVALID_CMS) } // Find a recipient whose key we hold. We only deal with recipient certs @@ -123,7 +124,7 @@ class CMS { if (!r) { // @ts-ignore cms types not defined const missingKeys = recipients.map(r => r.keyId) - throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), 'ERR_MISSING_KEYS', { + throw errcode(new Error('Decryption needs one of the key(s): ' + missingKeys.join(', ')), codes.ERR_MISSING_KEYS, { missingKeys }) } @@ -131,7 +132,7 @@ class CMS { const key = await this.keychain.findKeyById(r.keyId) if (!key) { - throw errcode(new Error('No key available to decrypto'), 'ERR_NO_KEY') + throw errcode(new Error('No key available to decrypto'), codes.ERR_NO_KEY) } const pem = await this.keychain._getPrivateKey(key.name) diff --git a/src/keychain/index.js b/src/keychain/index.js index b25be5a854..f6a17ab62e 100644 --- a/src/keychain/index.js +++ b/src/keychain/index.js @@ -10,6 +10,7 @@ const crypto = require('libp2p-crypto') const { Key } = require('interface-datastore/key') const CMS = require('./cms') const errcode = require('err-code') +const { codes } = require('../errors') const { toString: uint8ArrayToString } = require('uint8arrays/to-string') const { fromString: uint8ArrayFromString } = require('uint8arrays/from-string') @@ -210,21 +211,21 @@ class Keychain { const self = this if (!validateKeyName(name) || name === 'self') { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } if (typeof type !== 'string') { - return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), 'ERR_INVALID_KEY_TYPE')) + return throwDelayed(errcode(new Error(`Invalid key type '${type}'`), codes.ERR_INVALID_KEY_TYPE)) } const dsname = DsName(name) const exists = await self.store.has(dsname) - if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS')) + if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS)) switch (type.toLowerCase()) { case 'rsa': if (!Number.isSafeInteger(size) || size < 2048) { - return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), 'ERR_INVALID_KEY_SIZE')) + return throwDelayed(errcode(new Error(`Invalid RSA key size ${size}`), codes.ERR_INVALID_KEY_SIZE)) } break default: @@ -297,7 +298,7 @@ class Keychain { */ async findKeyByName (name) { if (!validateKeyName(name)) { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } const dsname = DsInfoName(name) @@ -305,7 +306,7 @@ class Keychain { const res = await this.store.get(dsname) return JSON.parse(uint8ArrayToString(res)) } catch (/** @type {any} */ err) { - return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND')) + return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND)) } } @@ -318,7 +319,7 @@ class Keychain { async removeKey (name) { const self = this if (!validateKeyName(name) || name === 'self') { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } const dsname = DsName(name) const keyInfo = await self.findKeyByName(name) @@ -339,10 +340,10 @@ class Keychain { async renameKey (oldName, newName) { const self = this if (!validateKeyName(oldName) || oldName === 'self') { - return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), 'ERR_OLD_KEY_NAME_INVALID')) + return throwDelayed(errcode(new Error(`Invalid old key name '${oldName}'`), codes.ERR_OLD_KEY_NAME_INVALID)) } if (!validateKeyName(newName) || newName === 'self') { - return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), 'ERR_NEW_KEY_NAME_INVALID')) + return throwDelayed(errcode(new Error(`Invalid new key name '${newName}'`), codes.ERR_NEW_KEY_NAME_INVALID)) } const oldDsname = DsName(oldName) const newDsname = DsName(newName) @@ -350,7 +351,7 @@ class Keychain { const newInfoName = DsInfoName(newName) const exists = await self.store.has(newDsname) - if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), 'ERR_KEY_ALREADY_EXISTS')) + if (exists) return throwDelayed(errcode(new Error(`Key '${newName}' already exists`), codes.ERR_KEY_ALREADY_EXISTS)) try { const pem = await self.store.get(oldDsname) @@ -379,10 +380,10 @@ class Keychain { */ async exportKey (name, password) { if (!validateKeyName(name)) { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } if (!password) { - return throwDelayed(errcode(new Error('Password is required'), 'ERR_PASSWORD_REQUIRED')) + return throwDelayed(errcode(new Error('Password is required'), codes.ERR_PASSWORD_REQUIRED)) } const dsname = DsName(name) @@ -409,20 +410,20 @@ class Keychain { async importKey (name, pem, password) { const self = this if (!validateKeyName(name) || name === 'self') { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } if (!pem) { - return throwDelayed(errcode(new Error('PEM encoded key is required'), 'ERR_PEM_REQUIRED')) + return throwDelayed(errcode(new Error('PEM encoded key is required'), codes.ERR_PEM_REQUIRED)) } const dsname = DsName(name) const exists = await self.store.has(dsname) - if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS')) + if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS)) let privateKey try { privateKey = await crypto.keys.import(pem, password) } catch (/** @type {any} */ err) { - return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), 'ERR_CANNOT_READ_KEY')) + return throwDelayed(errcode(new Error('Cannot read the key, most likely the password is wrong'), codes.ERR_CANNOT_READ_KEY)) } let kid @@ -457,16 +458,16 @@ class Keychain { async importPeer (name, peer) { const self = this if (!validateKeyName(name)) { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } if (!peer || !peer.privKey) { - return throwDelayed(errcode(new Error('Peer.privKey is required'), 'ERR_MISSING_PRIVATE_KEY')) + return throwDelayed(errcode(new Error('Peer.privKey is required'), codes.ERR_MISSING_PRIVATE_KEY)) } const privateKey = peer.privKey const dsname = DsName(name) const exists = await self.store.has(dsname) - if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), 'ERR_KEY_ALREADY_EXISTS')) + if (exists) return throwDelayed(errcode(new Error(`Key '${name}' already exists`), codes.ERR_KEY_ALREADY_EXISTS)) try { const kid = await privateKey.id() @@ -495,7 +496,7 @@ class Keychain { */ async _getPrivateKey (name) { if (!validateKeyName(name)) { - return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), 'ERR_INVALID_KEY_NAME')) + return throwDelayed(errcode(new Error(`Invalid key name '${name}'`), codes.ERR_INVALID_KEY_NAME)) } try { @@ -503,7 +504,7 @@ class Keychain { const res = await this.store.get(dsname) return uint8ArrayToString(res) } catch (/** @type {any} */ err) { - return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), 'ERR_KEY_NOT_FOUND')) + return throwDelayed(errcode(new Error(`Key '${name}' does not exist. ${err.message}`), codes.ERR_KEY_NOT_FOUND)) } } @@ -515,13 +516,13 @@ class Keychain { */ async rotateKeychainPass (oldPass, newPass) { if (typeof oldPass !== 'string') { - return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), 'ERR_INVALID_OLD_PASS_TYPE')) + return throwDelayed(errcode(new Error(`Invalid old pass type '${typeof oldPass}'`), codes.ERR_INVALID_OLD_PASS_TYPE)) } if (typeof newPass !== 'string') { - return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), 'ERR_INVALID_NEW_PASS_TYPE')) + return throwDelayed(errcode(new Error(`Invalid new pass type '${typeof newPass}'`), codes.ERR_INVALID_NEW_PASS_TYPE)) } if (newPass.length < 20) { - return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), 'ERR_INVALID_PASS_LENGTH')) + return throwDelayed(errcode(new Error(`Invalid pass length ${newPass.length}`), codes.ERR_INVALID_PASS_LENGTH)) } log('recreating keychain') const oldDek = privates.get(this).dek diff --git a/src/peer-routing.js b/src/peer-routing.js index 2ffa5cfd74..a49e847c1c 100644 --- a/src/peer-routing.js +++ b/src/peer-routing.js @@ -5,6 +5,7 @@ const log = Object.assign(debug('libp2p:peer-routing'), { error: debug('libp2p:peer-routing:err') }) const errCode = require('err-code') +const errors = require('./errors') const { storeAddresses, uniquePeers, @@ -104,11 +105,11 @@ class PeerRouting { */ async findPeer (id, options) { // eslint-disable-line require-await if (!this._routers.length) { - throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE') + throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS) } if (id.toB58String() === this._peerId.toB58String()) { - throw errCode(new Error('Should not try to find self'), 'ERR_FIND_SELF') + throw errCode(new Error('Should not try to find self'), errors.codes.ERR_FIND_SELF) } const output = await pipe( @@ -125,7 +126,7 @@ class PeerRouting { return output } - throw errCode(new Error('not found'), 'NOT_FOUND') + throw errCode(new Error(errors.messages.NOT_FOUND), errors.codes.ERR_NOT_FOUND) } /** @@ -139,7 +140,7 @@ class PeerRouting { */ async * getClosestPeers (key, options = { timeout: 30e3 }) { if (!this._routers.length) { - throw errCode(new Error('No peer routers available'), 'NO_ROUTERS_AVAILABLE') + throw errCode(new Error('No peer routers available'), errors.codes.ERR_NO_ROUTERS) } if (options.timeout) { diff --git a/src/peer-store/book.js b/src/peer-store/book.js index 9b6d561b1e..3de0459486 100644 --- a/src/peer-store/book.js +++ b/src/peer-store/book.js @@ -2,10 +2,7 @@ const errcode = require('err-code') const PeerId = require('peer-id') - -const { - codes: { ERR_INVALID_PARAMETERS } -} = require('../errors') +const { codes } = require('../errors') /** * @param {any} data @@ -48,7 +45,7 @@ class Book { * @param {any[]|any} data */ set (peerId, data) { - throw errcode(new Error('set must be implemented by the subclass'), 'ERR_NOT_IMPLEMENTED') + throw errcode(new Error('set must be implemented by the subclass'), codes.ERR_NOT_IMPLEMENTED) } /** @@ -94,7 +91,7 @@ class Book { */ get (peerId) { if (!PeerId.isPeerId(peerId)) { - throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS) + throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS) } const rec = this.data.get(peerId.toB58String()) @@ -111,7 +108,7 @@ class Book { */ delete (peerId) { if (!PeerId.isPeerId(peerId)) { - throw errcode(new Error('peerId must be an instance of peer-id'), ERR_INVALID_PARAMETERS) + throw errcode(new Error('peerId must be an instance of peer-id'), codes.ERR_INVALID_PARAMETERS) } if (!this.data.delete(peerId.toB58String())) { diff --git a/src/ping/index.js b/src/ping/index.js index 758c0ccabd..15b2692399 100644 --- a/src/ping/index.js +++ b/src/ping/index.js @@ -5,7 +5,7 @@ const log = Object.assign(debug('libp2p:ping'), { error: debug('libp2p:ping:err') }) const errCode = require('err-code') - +const { codes } = require('../errors') const crypto = require('libp2p-crypto') const { pipe } = require('it-pipe') // @ts-ignore it-buffer has no types exported @@ -50,7 +50,7 @@ async function ping (node, peer) { const end = Date.now() if (!equals(data, result)) { - throw errCode(new Error('Received wrong ping ack'), 'ERR_WRONG_PING_ACK') + throw errCode(new Error('Received wrong ping ack'), codes.ERR_WRONG_PING_ACK) } return end - start diff --git a/src/upgrader.js b/src/upgrader.js index 8b07be9731..23f9a338b9 100644 --- a/src/upgrader.js +++ b/src/upgrader.js @@ -297,7 +297,7 @@ class Upgrader { maConn.timeline.upgraded = Date.now() const errConnectionNotMultiplexed = () => { - throw errCode(new Error('connection is not multiplexed'), 'ERR_CONNECTION_NOT_MULTIPLEXED') + throw errCode(new Error('connection is not multiplexed'), codes.ERR_CONNECTION_NOT_MULTIPLEXED) } // Create the connection diff --git a/test/keychain/keychain.spec.js b/test/keychain/keychain.spec.js index 0404ebf03e..070a233da4 100644 --- a/test/keychain/keychain.spec.js +++ b/test/keychain/keychain.spec.js @@ -296,7 +296,7 @@ describe('keychain', () => { it('requires plain data as a Uint8Array', async () => { const err = await ks.cms.encrypt(rsaKeyName, 'plain data').then(fail, err => err) expect(err).to.exist() - expect(err).to.have.property('code', 'ERR_INVALID_PARAMS') + expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS') }) it('encrypts', async () => { @@ -308,7 +308,7 @@ describe('keychain', () => { it('is a PKCS #7 message', async () => { const err = await ks.cms.decrypt('not CMS').then(fail, err => err) expect(err).to.exist() - expect(err).to.have.property('code', 'ERR_INVALID_PARAMS') + expect(err).to.have.property('code', 'ERR_INVALID_PARAMETERS') }) it('is a PKCS #7 binary message', async () => {