diff --git a/index.js b/index.js index 72a7693..5085c49 100644 --- a/index.js +++ b/index.js @@ -32,7 +32,8 @@ const TL = { LOCAL_SEED: 1, DKEYS: 2, CORE: 3, - DATA: 4 + DATA: 4, + DEFAULT_KEY: 5 } // core prefixes @@ -276,6 +277,7 @@ class HypercoreStorage { constructor (db, mutex, discoveryKey) { this.db = db this.mutex = mutex + this.discoveryKey = discoveryKey // pointers @@ -284,15 +286,22 @@ class HypercoreStorage { } async open () { + if (!this.discoveryKey) { + const discoveryKey = await getDefaultKey(this.db) + if (!discoveryKey) throw new Error('No discovery key was provided') + + this.discoveryKey = discoveryKey + } + const val = await this.db.get(encodeDiscoveryKey(this.discoveryKey)) - if (val === null) return false + if (val === null) return null const { core, data } = c.decode(m.CorePointer, val) this.corePointer = core this.dataPointer = data - return true + return this.getCoreInfo() } async create ({ key, manifest, keyPair, encryptionKey }) { @@ -306,8 +315,16 @@ class HypercoreStorage { return false } + if (!key) throw new Error('No key was provided') + + let info = await getStorageInfo(this.db) + const write = this.db.write() - const info = (await getStorageInfo(this.db)) || { free: 0, total: 0 } + + if (!info) { + write.tryPut(Buffer.from([TL.DEFAULT_KEY]), this.discoveryKey) + info = { free: 0, total: 0 } + } const core = info.total++ const data = info.free++ @@ -430,6 +447,24 @@ class HypercoreStorage { return p } + async getCoreInfo () { + const r = this.createReadBatch() + + const auth = r.getCoreAuth() + const localKeyPair = r.getLocalKeyPair() + const encryptionKey = r.getEncryptionKey() + const head = r.getCoreHead() + + await r.flush() + + return { + auth: await auth, + localKeyPair: await localKeyPair, + encryptionKey: await encryptionKey, + head: await head + } + } + getBitfieldPage (index) { const b = this.createReadBatch() const p = b.getBitfieldPage(index) @@ -486,6 +521,10 @@ function mapOnlyDiscoveryKey (data) { return data.key.subarray(1) } +async function getDefaultKey (db) { + return db.get(Buffer.from([TL.DEFAULT_KEY])) +} + async function getStorageInfo (db) { const value = await db.get(Buffer.from([TL.STORAGE_INFO])) if (value === null) return null diff --git a/test/basic.js b/test/basic.js index 226db6b..c5a7fbd 100644 --- a/test/basic.js +++ b/test/basic.js @@ -596,6 +596,38 @@ test('user data', async function (t) { t.alike(await c.getUserData('hej'), Buffer.from('verden')) }) +test('reopen default core', async function (t) { + const dir = await tmp(t) + + const manifest = Buffer.from('manifest') + const keyPair = { + publicKey: Buffer.alloc(32, 2), + secretKey: Buffer.alloc(32, 3) + } + const encryptionKey = Buffer.alloc(32, 4) + + const s1 = await getStorage(t, dir) + const c1 = s1.get(DK_0) + if (!(await c1.open())) await c1.create({ key: DK_1, manifest, keyPair, encryptionKey }) + + await s1.close() + + const s2 = await getStorage(t, dir) + const c2 = s2.get() + + t.alike(await c2.open(), { + auth: { + key: DK_1, + manifest + }, + localKeyPair: keyPair, + encryptionKey, + head: null + }) + + t.alike(c2.discoveryKey, DK_0) +}) + async function getStorage (t, dir) { if (!dir) dir = await tmp(t) const s = new CoreStorage(dir) @@ -609,7 +641,7 @@ async function getCore (t) { const s = await getStorage(t) const c = s.get(DK_0) - t.is(await c.open(), false) + t.is(await c.open(), null) await c.create({ key: DK_0 }) return c