Add more error constructors
MODIFY
lib/errors.js
lib/errors.js
@@ -32,6 +32,18 @@ module.exports = class HypercoreError extends Error {
return new HypercoreError(msg, 'INVALID_CAPABILITY', HypercoreError.INVALID_CAPABILITY)
}
+ static INVALID_CHECKSUM (msg = 'Invalid checksum') {
+ return new HypercoreError(msg, 'INVALID_CHECKSUM', HypercoreError.INVALID_CHECKSUM)
+ }
+
+ static INVALID_OPERATION (msg) {
+ return new HypercoreError(msg, 'INVALID_OPERATION', HypercoreError.INVALID_OPERATION)
+ }
+
+ static INVALID_PROOF (msg = 'Proof not verifiable') {
+ return new HypercoreError(msg, 'INVALID_PROOF', HypercoreError.INVALID_PROOF)
+ }
+
static SNAPSHOT_NOT_AVAILABLE (msg = 'Snapshot is not available') {
return new HypercoreError(msg, 'SNAPSHOT_NOT_AVAILABLE', HypercoreError.SNAPSHOT_NOT_AVAILABLE)
}
@@ -47,4 +59,12 @@ module.exports = class HypercoreError extends Error {
static SESSION_CLOSED (msg = 'Session is closed') {
return new HypercoreError(msg, 'SESSION_CLOSED', HypercoreError.SESSION_CLOSED)
}
+
+ static OPLOG_CORRUPT (msg = 'Oplog file appears corrupt or out of date') {
+ return new HypercoreError(msg, 'OPLOG_CORRUPT', HypercoreError.OPLOG_CORRUPT)
+ }
+
+ static INVALID_OPLOG_VERSION (msg = 'Invalid header version') {
+ return new HypercoreError(msg, 'INVALID_OPLOG_VERSION', HypercoreError.INVALID_OPLOG_VERSION)
+ }
}

MODIFY
lib/merkle-tree.js
lib/merkle-tree.js
@@ -4,6 +4,7 @@ const c = require('compact-encoding')
const Xache = require('xache')
const b4a = require('b4a')
const caps = require('./caps')
+const { INVALID_PROOF, INVALID_CHECKSUM, INVALID_OPERATION, BAD_ARGUMENT } = require('./errors')
const BLANK_HASH = b4a.alloc(32)
const OLD_TREE = b4a.from([5, 2, 87, 2, 0, 0, 40, 7, 66, 76, 65, 75, 69, 50, 98])
@@ -26,12 +27,12 @@ class NodeQueue {
}
if (this.i >= this.nodes.length) {
- throw new Error('Expected node ' + index + ', got (nil)')
+ throw INVALID_OPERATION('Expected node ' + index + ', got (nil)')
}
const node = this.nodes[this.i++]
if (node.index !== index) {
- throw new Error('Expected node ' + index + ', got node ' + node.index)
+ throw INVALID_OPERATION('Expected node ' + index + ', got node ' + node.index)
}
this.length--
@@ -109,7 +110,7 @@ class MerkleTreeBatch {
}
commit () {
- if (!this.commitable()) throw new Error('Tree was modified during batch, refusing to commit')
+ if (!this.commitable()) throw INVALID_OPERATION('Tree was modified during batch, refusing to commit')
if (this.upgraded) this._commitUpgrade()
@@ -423,7 +424,7 @@ module.exports = class MerkleTree {
if (node !== undefined) {
if (node.hash === BLANK_HASH) {
- if (error) throw new Error('Could not load node: ' + index)
+ if (error) throw INVALID_OPERATION('Could not load node: ' + index)
return Promise.resolve(null)
}
return Promise.resolve(node)
@@ -560,7 +561,7 @@ module.exports = class MerkleTree {
}
if (!verifyUpgrade(proof, unverified, batch)) {
- throw new Error('Fork proof not verifiable')
+ throw INVALID_PROOF('Fork proof not verifiable')
}
for (const root of batch.roots) {
@@ -594,7 +595,7 @@ module.exports = class MerkleTree {
if (unverified) {
const verified = await this.get(unverified.index)
if (!b4a.equals(verified.hash, unverified.hash)) {
- throw new Error('Invalid checksum at node ' + unverified.index)
+ throw INVALID_CHECKSUM('Invalid checksum at node ' + unverified.index)
}
}
@@ -613,10 +614,10 @@ module.exports = class MerkleTree {
const node = normalizeIndexed(block, hash)
if (from >= to || to > head) {
- throw new Error('Invalid upgrade')
+ throw INVALID_OPERATION('Invalid upgrade')
}
if (seek && upgrade && node !== null && node.index >= from) {
- throw new Error('Cannot both do a seek and block/hash request when upgrading')
+ throw INVALID_OPERATION('Cannot both do a seek and block/hash request when upgrading')
}
let subTree = head
@@ -713,7 +714,7 @@ module.exports = class MerkleTree {
async byteRange (index) {
const head = 2 * this.length
if (((index & 1) === 0 ? index : flat.rightSpan(index)) >= head) {
- throw new Error('Index is out of bounds')
+ throw BAD_ARGUMENT('Index is out of bounds')
}
return [await this.byteOffset(index), (await this.get(index)).size]
}
@@ -862,7 +863,7 @@ function verifyUpgrade ({ fork, upgrade }, blockRoot, batch) {
const node = extra[i++]
while (node.index !== ite.index) {
- if (ite.factor === 2) throw new Error('Unexpected node: ' + node.index)
+ if (ite.factor === 2) throw INVALID_OPERATION('Unexpected node: ' + node.index)
ite.leftChild()
}
@@ -923,14 +924,14 @@ async function seekTrustedTree (tree, root, bytes) {
async function seekUntrustedTree (tree, root, bytes) {
const offset = await tree.byteOffset(root)
- if (offset > bytes) throw new Error('Invalid seek')
+ if (offset > bytes) throw INVALID_OPERATION('Invalid seek')
if (offset === bytes) return root
bytes -= offset
const node = await tree.get(root)
- if (node.size <= bytes) throw new Error('Invalid seek')
+ if (node.size <= bytes) throw INVALID_OPERATION('Invalid seek')
return seekTrustedTree(tree, root, bytes)
}
@@ -1061,7 +1062,7 @@ function nodesToRoot (index, nodes, head) {
for (let i = 0; i < nodes; i++) {
ite.parent()
- if (ite.contains(head)) throw new Error('Nodes is out of bounds')
+ if (ite.contains(head)) throw BAD_ARGUMENT('Nodes is out of bounds')
}
return ite.index

MODIFY
lib/messages.js
lib/messages.js
const c = require('compact-encoding')
const b4a = require('b4a')
+const { INVALID_OPLOG_VERSION } = require('./errors')
const EMPTY = b4a.alloc(0)
@@ -637,7 +638,7 @@ oplog.header = {
const version = c.uint.decode(state)
if (version !== 0) {
- throw new Error('Invalid header version. Expected 0, got ' + version)
+ throw INVALID_OPLOG_VERSION('Invalid header version. Expected 0, got ' + version)
}
return {

MODIFY
lib/oplog.js
lib/oplog.js
const cenc = require('compact-encoding')
const b4a = require('b4a')
const { crc32 } = require('crc-universal')
+const { OPLOG_CORRUPT } = require('./errors')
module.exports = class Oplog {
constructor (storage, { pageSize = 4096, headerEncoding = cenc.raw, entryEncoding = cenc.raw } = {}) {
@@ -77,7 +78,7 @@ module.exports = class Oplog {
this._headers[1] = 0
if (buffer.byteLength >= this._entryOffset) {
- throw new Error('Oplog file appears corrupt or out of date')
+ throw OPLOG_CORRUPT()
}
return result
}

Add more error constructors (#336)