Skip to content

Commit

Permalink
fix: make error codes consistent (#1054)
Browse files Browse the repository at this point in the history
Sometimes they are `NOT_FOUND`, sometimes `ERR_NOT_FOUND`, etc.

Move all error codes into `errors.js` and reference them from there.
  • Loading branch information
achingbrain authored Dec 7, 2021
1 parent cbaa5a2 commit b25e0fe
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 48 deletions.
3 changes: 2 additions & 1 deletion src/dialer/dial-request.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
26 changes: 25 additions & 1 deletion src/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -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'
}
13 changes: 7 additions & 6 deletions src/keychain/cms.js
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -123,15 +124,15 @@ 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
})
}

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)
Expand Down
49 changes: 25 additions & 24 deletions src/keychain/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -297,15 +298,15 @@ 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)
try {
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))
}
}

Expand All @@ -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)
Expand All @@ -339,18 +340,18 @@ 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)
const oldInfoName = DsInfoName(oldName)
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)
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -495,15 +496,15 @@ 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 {
const dsname = DsName(name)
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))
}
}

Expand All @@ -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
Expand Down
9 changes: 5 additions & 4 deletions src/peer-routing.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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(
Expand All @@ -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)
}

/**
Expand All @@ -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) {
Expand Down
11 changes: 4 additions & 7 deletions src/peer-store/book.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
}

/**
Expand Down Expand Up @@ -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())
Expand All @@ -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())) {
Expand Down
4 changes: 2 additions & 2 deletions src/ping/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion src/upgrader.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading

0 comments on commit b25e0fe

Please sign in to comment.