Skip to content

Commit 44b7ff6

Browse files
committed
Include discovery key in error messages
1 parent 758098d commit 44b7ff6

File tree

5 files changed

+56
-38
lines changed

5 files changed

+56
-38
lines changed

index.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ class Hypercore extends EventEmitter {
178178
noiseStream = new NoiseSecretStream(isInitiator, null, opts)
179179
outerStream = noiseStream.rawStream
180180
}
181-
if (!noiseStream) throw BAD_ARGUMENT('Invalid stream')
181+
if (!noiseStream) throw BAD_ARGUMENT('Invalid stream', this.discoveryKey)
182182

183183
if (!noiseStream.userData) {
184184
const protocol = Protomux.from(noiseStream)
@@ -211,10 +211,10 @@ class Hypercore extends EventEmitter {
211211
if (this.closing) {
212212
// This makes the closing logic a lot easier. If this turns out to be a problem
213213
// in practice, open an issue and we'll try to make a solution for it.
214-
throw SESSION_CLOSED('Cannot make sessions on a closing core')
214+
throw SESSION_CLOSED('Cannot make sessions on a closing core', this.discoveryKey)
215215
}
216216
if (opts.checkout !== undefined && !opts.name && !opts.atom) {
217-
throw ASSERTION('Checkouts are only supported on atoms or named sessions')
217+
throw ASSERTION('Checkouts are only supported on atoms or named sessions', this.discoveryKey)
218218
}
219219

220220
const wait = opts.wait === false ? false : this.wait
@@ -253,7 +253,7 @@ class Hypercore extends EventEmitter {
253253
}
254254

255255
if (!isEncryptionProvider(encryption)) {
256-
throw ASSERTION('Provider does not satisfy HypercoreEncryption interface')
256+
throw ASSERTION('Provider does not satisfy HypercoreEncryption interface', this.discoveryKey)
257257
}
258258

259259
this.encryption = encryption
@@ -383,10 +383,10 @@ class Hypercore extends EventEmitter {
383383
}
384384

385385
if (this.state && checkout !== -1) {
386-
if (!opts.name && !opts.atom) throw ASSERTION('Checkouts must be named or atomized')
387-
if (checkout > this.state.length) throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', length is ' + this.state.length)
386+
if (!opts.name && !opts.atom) throw ASSERTION('Checkouts must be named or atomized', this.discoveryKey)
387+
if (checkout > this.state.length) throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', length is ' + this.state.length, this.discoveryKey)
388388
if (this.state.prologue && checkout < this.state.prologue.length) {
389-
throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', prologue length is ' + this.state.prologue.length)
389+
throw ASSERTION('Invalid checkout ' + checkout + ' for ' + opts.name + ', prologue length is ' + this.state.prologue.length, this.discoveryKey)
390390
}
391391
if (checkout < this.state.length) await this.state.truncate(checkout, this.fork)
392392
}
@@ -637,7 +637,7 @@ class Hypercore extends EventEmitter {
637637

638638
this.core = core
639639

640-
old.replicator.clearRequests(this.activeRequests, SESSION_MOVED())
640+
old.replicator.clearRequests(this.activeRequests, SESSION_MOVED(undefined, this.discoveryKey))
641641

642642
this.emit('migrate', this.key)
643643
}
@@ -697,7 +697,7 @@ class Hypercore extends EventEmitter {
697697

698698
async seek (bytes, opts) {
699699
if (this.opened === false) await this.opening
700-
if (!isValidIndex(bytes)) throw ASSERTION('seek is invalid')
700+
if (!isValidIndex(bytes)) throw ASSERTION('seek is invalid', this.discoveryKey)
701701

702702
const activeRequests = (opts && opts.activeRequests) || this.activeRequests
703703

@@ -716,7 +716,7 @@ class Hypercore extends EventEmitter {
716716
const offset = await s.update()
717717
if (offset) return offset
718718

719-
if (this.closing !== null) throw SESSION_CLOSED()
719+
if (this.closing !== null) throw SESSION_CLOSED(undefined, this.discoveryKey)
720720

721721
if (!this._shouldWait(opts, this.wait)) return null
722722

@@ -735,7 +735,7 @@ class Hypercore extends EventEmitter {
735735

736736
async has (start, end = start + 1) {
737737
if (this.opened === false) await this.opening
738-
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('has range is invalid')
738+
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('has range is invalid', this.discoveryKey)
739739

740740
if (this.state.isDefault()) {
741741
if (end === start + 1) return this.core.bitfield.get(start)
@@ -765,9 +765,9 @@ class Hypercore extends EventEmitter {
765765

766766
async get (index, opts) {
767767
if (this.opened === false) await this.opening
768-
if (!isValidIndex(index)) throw ASSERTION('block index is invalid')
768+
if (!isValidIndex(index)) throw ASSERTION('block index is invalid', this.discoveryKey)
769769

770-
if (this.closing !== null) throw SESSION_CLOSED()
770+
if (this.closing !== null) throw SESSION_CLOSED(undefined, this.discoveryKey)
771771

772772
const encoding = (opts && opts.valueEncoding && c.from(opts.valueEncoding)) || this.valueEncoding
773773

@@ -792,14 +792,14 @@ class Hypercore extends EventEmitter {
792792

793793
async clear (start, end = start + 1, opts) {
794794
if (this.opened === false) await this.opening
795-
if (this.closing !== null) throw SESSION_CLOSED()
795+
if (this.closing !== null) throw SESSION_CLOSED(undefined, this.discoveryKey)
796796

797797
if (typeof end === 'object') {
798798
opts = end
799799
end = start + 1
800800
}
801801

802-
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('clear range is invalid')
802+
if (!isValidIndex(start) || !isValidIndex(end)) throw ASSERTION('clear range is invalid', this.discoveryKey)
803803

804804
const cleared = (opts && opts.diff) ? { blocks: 0 } : null
805805

@@ -821,7 +821,7 @@ class Hypercore extends EventEmitter {
821821

822822
if (block !== null) return block
823823

824-
if (this.closing !== null) throw SESSION_CLOSED()
824+
if (this.closing !== null) throw SESSION_CLOSED(undefined, this.discoveryKey)
825825

826826
// snapshot should check if core has block
827827
if (this._snapshot !== null) {
@@ -911,7 +911,7 @@ class Hypercore extends EventEmitter {
911911

912912
const isDefault = this.state === this.core.state
913913
const writable = !this._readonly && !!(signature || (keyPair && keyPair.secretKey))
914-
if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork)) throw SESSION_NOT_WRITABLE()
914+
if (isDefault && writable === false && (newLength > 0 || fork !== this.state.fork)) throw SESSION_NOT_WRITABLE(undefined, this.discoveryKey)
915915

916916
await this.state.truncate(newLength, fork, { keyPair, signature })
917917

@@ -928,7 +928,7 @@ class Hypercore extends EventEmitter {
928928
const { keyPair = defaultKeyPair, signature = null, maxLength } = opts
929929
const writable = !isDefault || !!signature || !!(keyPair && keyPair.secretKey) || opts.writable === true
930930

931-
if (this._readonly || writable === false) throw SESSION_NOT_WRITABLE()
931+
if (this._readonly || writable === false) throw SESSION_NOT_WRITABLE(undefined, this.discoveryKey)
932932

933933
blocks = Array.isArray(blocks) ? blocks : [blocks]
934934

@@ -943,7 +943,7 @@ class Hypercore extends EventEmitter {
943943
}
944944
for (const b of buffers) {
945945
if (b.byteLength > MAX_SUGGESTED_BLOCK_SIZE) {
946-
throw BAD_ARGUMENT('Appended block exceeds the maximum suggested block size')
946+
throw BAD_ARGUMENT('Appended block exceeds the maximum suggested block size', this.discoveryKey)
947947
}
948948
}
949949

@@ -1056,7 +1056,7 @@ class Hypercore extends EventEmitter {
10561056
try {
10571057
if (enc) return c.decode(enc, block)
10581058
} catch {
1059-
throw DECODING_ERROR()
1059+
throw DECODING_ERROR(undefined, this.discoveryKey)
10601060
}
10611061
return block
10621062
}
@@ -1097,7 +1097,7 @@ function maybeUnslab (block) {
10971097
}
10981098

10991099
function checkSnapshot (snapshot, index) {
1100-
if (index >= snapshot.state.snapshotCompatLength) throw SNAPSHOT_NOT_AVAILABLE()
1100+
if (index >= snapshot.state.snapshotCompatLength) throw SNAPSHOT_NOT_AVAILABLE(undefined, this.discoveryKey)
11011101
}
11021102

11031103
function readBlock (rx, index) {

lib/core.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,17 @@ module.exports = class Core {
146146
}
147147

148148
if (!header && (opts.discoveryKey && !(opts.key || opts.manifest))) {
149-
throw STORAGE_EMPTY('No Hypercore is stored here')
149+
throw STORAGE_EMPTY('No Hypercore is stored here', this.discoveryKey)
150150
}
151151

152152
if (!header || overwrite) {
153153
if (!createIfMissing) {
154-
throw STORAGE_EMPTY('No Hypercore is stored here')
154+
throw STORAGE_EMPTY('No Hypercore is stored here', this.discoveryKey)
155155
}
156156

157157
if (compat) {
158158
if (opts.key && opts.keyPair && !b4a.equals(opts.key, opts.keyPair.publicKey)) {
159-
throw BAD_ARGUMENT('Key must match publicKey when in compat mode')
159+
throw BAD_ARGUMENT('Key must match publicKey when in compat mode', this.discoveryKey)
160160
}
161161
}
162162

@@ -216,14 +216,14 @@ module.exports = class Core {
216216
if (opts.manifest) {
217217
// if we provide a manifest and no key, verify that the stored key is the same
218218
if (!opts.key && !Verifier.isValidManifest(header.key, Verifier.createManifest(opts.manifest))) {
219-
throw STORAGE_CONFLICT('Manifest does not hash to provided key')
219+
throw STORAGE_CONFLICT('Manifest does not hash to provided key', this.discoveryKey)
220220
}
221221

222222
if (!header.manifest) header.manifest = opts.manifest
223223
}
224224

225225
if (opts.key && !b4a.equals(header.key, opts.key)) {
226-
throw STORAGE_CONFLICT('Another Hypercore is stored here')
226+
throw STORAGE_CONFLICT('Another Hypercore is stored here', this.discoveryKey)
227227
}
228228

229229
// if we signalled compat, but already now this core isn't disable it
@@ -298,7 +298,7 @@ module.exports = class Core {
298298

299299
try {
300300
if (manifest && this.header.manifest === null) {
301-
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match')
301+
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match', this.discoveryKey)
302302

303303
const tx = this.state.createWriteBatch()
304304
this._setManifest(tx, Verifier.createManifest(manifest), null)
@@ -385,13 +385,13 @@ module.exports = class Core {
385385
if (!manifest) manifest = Verifier.defaultSignerManifest(this.header.key)
386386

387387
if (!manifest || !(Verifier.isValidManifest(this.header.key, manifest) || Verifier.isCompat(this.header.key, manifest))) {
388-
throw INVALID_SIGNATURE('Proof contains an invalid manifest') // TODO: proper error type
388+
throw INVALID_SIGNATURE('Proof contains an invalid manifest', this.discoveryKey) // TODO: proper error type
389389
}
390390
}
391391

392392
const verifier = this.verifier || new Verifier(this.header.key, Verifier.createManifest(manifest), { legacy: this._legacy })
393393
if (!verifier.verify(batch, batch.signature)) {
394-
throw INVALID_SIGNATURE('Proof contains an invalid signature')
394+
throw INVALID_SIGNATURE('Proof contains an invalid signature', this.discoveryKey)
395395
}
396396

397397
return manifest
@@ -451,7 +451,7 @@ module.exports = class Core {
451451

452452
// if we got a manifest AND its strictly a non compat one, lets store it
453453
if (manifest && this.header.manifest === null) {
454-
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match')
454+
if (!Verifier.isValidManifest(this.header.key, manifest)) throw INVALID_CHECKSUM('Manifest hash does not match', this.discoveryKey)
455455
this._setManifest(tx, manifest, null)
456456
}
457457

lib/session-state.js

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -373,10 +373,10 @@ module.exports = class SessionState {
373373

374374
try {
375375
if (this.prologue && length < this.prologue.length) {
376-
throw INVALID_OPERATION('Truncation breaks prologue')
376+
throw INVALID_OPERATION('Truncation breaks prologue', this.core.discoveryKey)
377377
}
378378
if (length > this.length) {
379-
throw INVALID_OPERATION('Not a truncation, ' + length + ' must be less or equal to ' + this.length)
379+
throw INVALID_OPERATION('Not a truncation, ' + length + ' must be less or equal to ' + this.length, this.core.discoveryKey)
380380
}
381381

382382
const batch = this.createTreeBatch()
@@ -531,7 +531,7 @@ module.exports = class SessionState {
531531

532532
// only multisig can have prologue so signature is always present
533533
if (this.prologue && batch.length < this.prologue.length) {
534-
throw INVALID_OPERATION('Append is not consistent with prologue')
534+
throw INVALID_OPERATION('Append is not consistent with prologue', this.core.discoveryKey)
535535
}
536536

537537
if (!signature && keyPair) signature = this.core.verifier.sign(batch, keyPair)
@@ -611,14 +611,15 @@ module.exports = class SessionState {
611611

612612
_updateBitfield (bitfield, flushed) {
613613
if (!bitfield) return
614+
console.log(this.core.discoveryKey)
614615

615616
const p = this._pendingBitfield
616617
const b = bitfield
617618

618619
if (b.drop) {
619620
// truncation must be from end
620621
if (p && (b.start + b.length !== p.start + p.appends)) {
621-
throw INVALID_OPERATION('Atomic truncations must be contiguous')
622+
throw INVALID_OPERATION('Atomic truncations must be contiguous', this.core.discoveryKey)
622623
}
623624

624625
// actual truncation
@@ -642,7 +643,7 @@ module.exports = class SessionState {
642643
}
643644

644645
if (b.start !== p.start + p.appends) {
645-
throw INVALID_OPERATION('Atomic operations must be contiguous')
646+
throw INVALID_OPERATION('Atomic operations must be contiguous', this.core.discoveryKey)
646647
}
647648

648649
p.appends += b.length
@@ -679,7 +680,7 @@ module.exports = class SessionState {
679680
const truncating = sharedLength < origLength
680681

681682
for (const node of roots) {
682-
if (node === null) throw INVALID_OPERATION('Invalid catchup length, tree nodes not available')
683+
if (node === null) throw INVALID_OPERATION('Invalid catchup length, tree nodes not available', this.core.discoveryKey)
683684
}
684685

685686
const fork = truncating ? this.fork + 1 : this.fork
@@ -755,7 +756,7 @@ module.exports = class SessionState {
755756
batch.length = length
756757

757758
if (!this.core.verifier.verify(batch, signature)) {
758-
throw INVALID_SIGNATURE('Signature is not valid over committed tree')
759+
throw INVALID_SIGNATURE('Signature is not valid over committed tree', this.core.discoveryKey)
759760
}
760761
}
761762

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
"fast-fifo": "^1.3.0",
5151
"flat-tree": "^1.9.0",
5252
"hypercore-crypto": "^3.2.1",
53-
"hypercore-errors": "^1.2.0",
53+
"hypercore-errors": "holepunchto/hypercore-errors#opt-disckey",
5454
"hypercore-id-encoding": "^1.2.0",
5555
"hypercore-storage": "^1.0.0",
5656
"is-options": "^1.0.1",

test/sessions.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const test = require('brittle')
33
const crypto = require('hypercore-crypto')
44
const c = require('compact-encoding')
55
const b4a = require('b4a')
6+
const IdEnc = require('hypercore-id-encoding')
67
const { create, createStorage } = require('./helpers')
78

89
const Hypercore = require('../')
@@ -119,6 +120,22 @@ test('sessions - cannot set checkout if name not set', async function (t) {
119120
await core.close()
120121
})
121122

123+
test('sessions - error includes discovery key', async function (t) {
124+
const storage = await createStorage(t)
125+
const core = new Hypercore(storage)
126+
await core.append('Block0')
127+
128+
const discKey = IdEnc.normalize(core.discoveryKey)
129+
try {
130+
await core.session({ checkout: 0 })
131+
t.fail('Should throw')
132+
} catch (e) {
133+
t.is(e.message.includes(discKey), true)
134+
}
135+
136+
await core.close()
137+
})
138+
122139
test('sessions - checkout breaks prologue', async function (t) {
123140
const storage = await createStorage(t)
124141
const storage2 = await createStorage(t)

0 commit comments

Comments
 (0)