From 632bd3dfbeb93f059990f8cb3227d1774275cd68 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 13:36:13 +0000 Subject: [PATCH 01/10] test: Test replication of keyvalue db. --- .../db/replication/keyvalue-persisted.test.js | 217 ++++++++++++++++++ test/db/replication/keyvalue.test.js | 14 +- 2 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 test/db/replication/keyvalue-persisted.test.js diff --git a/test/db/replication/keyvalue-persisted.test.js b/test/db/replication/keyvalue-persisted.test.js new file mode 100644 index 0000000..59406a6 --- /dev/null +++ b/test/db/replication/keyvalue-persisted.test.js @@ -0,0 +1,217 @@ +import { deepStrictEqual } from 'assert' +import rmrf from 'rimraf' +import { copy } from 'fs-extra' +import * as IPFS from 'ipfs' +import { Log, Entry, Database, KeyStore, Identities } from '../../../src/index.js' +import { KeyValue, KeyValuePersisted } from '../../../src/db/index.js' +import config from '../../config.js' +import testKeysPath from '../../fixtures/test-keys-path.js ' +import connectPeers from '../../utils/connect-nodes.js' +import waitFor from '../../utils/wait-for.js' + +const OpLog = { Log, Entry } +const keysPath = './testkeys' + +describe('KeyValue Database Replication', function () { + this.timeout(30000) + + let ipfs1, ipfs2 + let keystore + let identities + let testIdentity1, testIdentity2 + let kv1, kv2 + + const databaseId = 'kv-AAA' + + const accessController = { + canAppend: async (entry) => { + const identity = await identities.getIdentity(entry.identity) + return identity.id === testIdentity1.id + } + } + + before(async () => { + ipfs1 = await IPFS.create({ ...config.daemon1, repo: './ipfs1' }) + ipfs2 = await IPFS.create({ ...config.daemon2, repo: './ipfs2' }) + await connectPeers(ipfs1, ipfs2) + + await copy(testKeysPath, keysPath) + keystore = await KeyStore({ path: keysPath }) + identities = await Identities({ keystore }) + testIdentity1 = await identities.createIdentity({ id: 'userA' }) + testIdentity2 = await identities.createIdentity({ id: 'userB' }) + }) + + after(async () => { + if (ipfs1) { + await ipfs1.stop() + } + + if (ipfs2) { + await ipfs2.stop() + } + + if (keystore) { + await keystore.close() + } + + await rmrf(keysPath) + await rmrf('./orbitdb1') + await rmrf('./orbitdb2') + await rmrf('./ipfs1') + await rmrf('./ipfs2') + }) + + afterEach(async () => { + if (kv1) { + await kv1.drop() + await kv1.close() + } + if (kv2) { + await kv2.drop() + await kv2.close() + } + }) + + it('replicates a database', async () => { + let connected = false + let updateCount = 0 + + const onConnected = async (peerId) => { + connected = true + } + + const onUpdate = (entry) => { + ++updateCount + } + + const onError = (err) => { + console.error(err) + } + + kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + + kv2.events.on('join', onConnected) + kv1.events.on('join', onConnected) + kv2.events.on('update', onUpdate) + kv2.events.on('error', onError) + kv1.events.on('error', onError) + + await kv1.set('init', true) + await kv1.set('hello', 'friend') + await kv1.del('hello') + await kv1.set('hello', 'friend2') + await kv1.del('hello') + await kv1.set('empty', '') + await kv1.del('empty') + await kv1.set('hello', 'friend3') + + await waitFor(() => connected, () => true) + await waitFor(() => updateCount > 0, () => true) + + const value0 = await kv2.get('init') + deepStrictEqual(value0, true) + + const value2 = await kv2.get('hello') + deepStrictEqual(value2, 'friend3') + + const value1 = await kv1.get('hello') + deepStrictEqual(value1, 'friend3') + + const value9 = await kv1.get('empty') + deepStrictEqual(value9, undefined) + + const all2 = [] + for await (const keyValue of kv2.iterator()) { + all2.push(keyValue) + } + deepStrictEqual(all2, [ + { key: 'hello', value: 'friend3' }, + { key: 'init', value: true } + ]) + + const all1 = [] + for await (const keyValue of kv1.iterator()) { + all1.push(keyValue) + } + deepStrictEqual(all1, [ + { key: 'hello', value: 'friend3' }, + { key: 'init', value: true } + ]) + }) + + it('loads the database after replication', async () => { + let updateCount = 0 + let connected = false + + const onConnected = async (peerId) => { + connected = true + } + + const onUpdate = (entry) => { + ++updateCount + } + + const onError = (err) => { + console.error(err) + } + + kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + + kv2.events.on('join', onConnected) + kv1.events.on('join', onConnected) + kv2.events.on('update', onUpdate) + kv2.events.on('error', onError) + kv1.events.on('error', onError) + + await kv1.set('init', true) + await kv1.set('hello', 'friend') + await kv1.del('hello') + await kv1.set('hello', 'friend2') + await kv1.del('hello') + await kv1.set('empty', '') + await kv1.del('empty') + await kv1.set('hello', 'friend3') + + await waitFor(() => connected, () => true) + await waitFor(() => updateCount > 0, () => true) + + await kv1.close() + await kv2.close() + + kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + + const value0 = await kv2.get('init') + deepStrictEqual(value0, true) + + const value2 = await kv2.get('hello') + deepStrictEqual(value2, 'friend3') + + const value1 = await kv1.get('hello') + deepStrictEqual(value1, 'friend3') + + const value9 = await kv1.get('empty') + deepStrictEqual(value9, undefined) + + const all2 = [] + for await (const keyValue of kv2.iterator()) { + all2.push(keyValue) + } + deepStrictEqual(all2, [ + { key: 'hello', value: 'friend3' }, + { key: 'init', value: true } + ]) + + const all1 = [] + for await (const keyValue of kv1.iterator()) { + all1.push(keyValue) + } + deepStrictEqual(all1, [ + { key: 'hello', value: 'friend3' }, + { key: 'init', value: true } + ]) + }) +}) diff --git a/test/db/replication/keyvalue.test.js b/test/db/replication/keyvalue.test.js index 59406a6..0120878 100644 --- a/test/db/replication/keyvalue.test.js +++ b/test/db/replication/keyvalue.test.js @@ -3,7 +3,7 @@ import rmrf from 'rimraf' import { copy } from 'fs-extra' import * as IPFS from 'ipfs' import { Log, Entry, Database, KeyStore, Identities } from '../../../src/index.js' -import { KeyValue, KeyValuePersisted } from '../../../src/db/index.js' +import { KeyValue } from '../../../src/db/index.js' import config from '../../config.js' import testKeysPath from '../../fixtures/test-keys-path.js ' import connectPeers from '../../utils/connect-nodes.js' @@ -89,8 +89,8 @@ describe('KeyValue Database Replication', function () { console.error(err) } - kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) - kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + kv1 = await KeyValue({ OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValue({ OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) kv2.events.on('join', onConnected) kv1.events.on('join', onConnected) @@ -157,8 +157,8 @@ describe('KeyValue Database Replication', function () { console.error(err) } - kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) - kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + kv1 = await KeyValue({ OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValue({ OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) kv2.events.on('join', onConnected) kv1.events.on('join', onConnected) @@ -181,8 +181,8 @@ describe('KeyValue Database Replication', function () { await kv1.close() await kv2.close() - kv1 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) - kv2 = await KeyValuePersisted({ KeyValue, OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) + kv1 = await KeyValue({ OpLog, Database, ipfs: ipfs1, identity: testIdentity1, address: databaseId, accessController, directory: './orbitdb1' }) + kv2 = await KeyValue({ OpLog, Database, ipfs: ipfs2, identity: testIdentity2, address: databaseId, accessController, directory: './orbitdb2' }) const value0 = await kv2.get('init') deepStrictEqual(value0, true) From 53369de51c1bd3f8445b3b7ed6a7cef962dc49a7 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 16:34:51 +0000 Subject: [PATCH 02/10] test: default and custom options. --- src/key-store.js | 14 ++++++-- test/key-store.test.js | 73 ++++++++++++++++++++++++++++++++++++++---- 2 files changed, 79 insertions(+), 8 deletions(-) diff --git a/src/key-store.js b/src/key-store.js index cc4ced1..651df52 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -74,8 +74,16 @@ const verifyMessage = async (signature, publicKey, data) => { return res } +/** + * Creates an instance of KeyStore. + * @param {Object} options Various options to use when instantiating KeyStore. + * @param {Object} options.storage An instance of a storage class. Can be one of ComposedStorage, IPFSBlockStorage, LevelStorage, etc. Defaults to ComposedStorage. + * @param {string} options.path The path to a valid storage. Defaults to ./keystore. + * @return {KeyStore} An instance of KeyStore. + */ const KeyStore = async ({ storage, path } = {}) => { - storage = storage || await ComposedStorage(await LevelStorage({ path: path || './keystore' }), await LRUStorage({ size: 1000 })) + const defaultPath = './keystore' + storage = storage || await ComposedStorage(await LevelStorage({ path: path || defaultPath }), await LRUStorage({ size: 1000 })) const close = async () => { await storage.close() @@ -168,7 +176,9 @@ const KeyStore = async ({ storage, path } = {}) => { addKey, createKey, getKey, - getPublic + getPublic, + defaultPath, + storage } } diff --git a/test/key-store.test.js b/test/key-store.test.js index a2e6bd8..383c016 100644 --- a/test/key-store.test.js +++ b/test/key-store.test.js @@ -1,7 +1,8 @@ import { strictEqual, deepStrictEqual } from 'assert' import rmrf from 'rimraf' -import { copy } from 'fs-extra' +import { copy, pathExists } from 'fs-extra' import KeyStore, { signMessage, verifyMessage } from '../src/key-store.js' +import LevelStorage from '../src/storage/level.js' import testKeysPath from './fixtures/test-keys-path.js ' const keysPath = './testkeys' @@ -10,21 +11,23 @@ describe('KeyStore', () => { let keystore describe('Creating and retrieving keys', () => { + let id + beforeEach(async () => { - await copy(testKeysPath, keysPath) - keystore = await KeyStore({ path: keysPath }) + keystore = await KeyStore() + + id = 'key1' + await keystore.createKey(id) }) afterEach(async () => { if (keystore) { await keystore.close() + await rmrf(keystore.defaultPath) } - await rmrf(keysPath) }) it('creates a key', async () => { - const id = 'key1' - await keystore.createKey(id) const hasKey = await keystore.hasKey(id) strictEqual(hasKey, true) }) @@ -123,6 +126,64 @@ describe('KeyStore', () => { }) }) + describe('Options', () => { + describe('Using default options', () => { + beforeEach(async () => { + keystore = await KeyStore() + }) + + afterEach(async () => { + if (keystore) { + await keystore.close() + await rmrf(keystore.defaultPath) + } + }) + + it('loads default storage using default path', async () => { + strictEqual(await pathExists(keystore.defaultPath), true) + }) + }) + + describe('Setting options.storage', () => { + const path = './custom-level-key-store' + + beforeEach(async () => { + const storage = await LevelStorage({ path }) + keystore = await KeyStore({ storage }) + }) + + afterEach(async () => { + if (keystore) { + await keystore.close() + await rmrf(path) + } + }) + + it('loads custom storage', async () => { + strictEqual(await pathExists(path), true) + }) + }) + + describe('Setting options.path', () => { + beforeEach(async () => { + await copy(testKeysPath, keysPath) + keystore = await KeyStore({ path: keysPath }) + }) + + afterEach(async () => { + if (keystore) { + await keystore.close() + } + + await rmrf(keysPath) + }) + + it('loads default storage using custom path', async () => { + strictEqual(await pathExists(keysPath), true) + }) + }) + }) + describe('Using keys for signing and verifying', () => { beforeEach(async () => { await copy(testKeysPath, keysPath) From 7396a4ac6465f27c7fc0d3eed4a44967e0393e7f Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 16:36:25 +0000 Subject: [PATCH 03/10] fix: Linting. --- src/key-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key-store.js b/src/key-store.js index 651df52..5d94930 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -82,7 +82,7 @@ const verifyMessage = async (signature, publicKey, data) => { * @return {KeyStore} An instance of KeyStore. */ const KeyStore = async ({ storage, path } = {}) => { - const defaultPath = './keystore' + const defaultPath = './keystore' storage = storage || await ComposedStorage(await LevelStorage({ path: path || defaultPath }), await LRUStorage({ size: 1000 })) const close = async () => { From 1fb02ea4cb1667e8fa60107f8c8eba83e96cbcdb Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 17:56:38 +0000 Subject: [PATCH 04/10] refactor: Throw any storage errors when adding a key. --- src/key-store.js | 8 ++------ test/key-store.test.js | 12 ++++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/key-store.js b/src/key-store.js index 5d94930..31e7ab0 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -111,12 +111,8 @@ const KeyStore = async ({ storage, path } = {}) => { } const addKey = async (id, key) => { - try { - await storage.put('public_' + id, key.publicKey) - await storage.put('private_' + id, key.privateKey) - } catch (e) { - console.log(e) - } + await storage.put('public_' + id, key.publicKey) + await storage.put('private_' + id, key.privateKey) } const createKey = async (id, { entropy } = {}) => { diff --git a/test/key-store.test.js b/test/key-store.test.js index 383c016..c4309e9 100644 --- a/test/key-store.test.js +++ b/test/key-store.test.js @@ -124,6 +124,18 @@ describe('KeyStore', () => { strictEqual(actual, expected) }) + + it('creates a key when storage is closed', async () => { + let err + await keystore.close() + try { + await keystore.createKey(id) + } catch (e) { + err = e.toString() + } + + strictEqual(err, 'Error: Database is not open') + }) }) describe('Options', () => { From 885fc5f02cf28c06e3243ba5347e34beabd07e71 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 22:21:17 +0000 Subject: [PATCH 05/10] test: Load keys into storage and retrieve from keystore. --- src/key-store.js | 7 +++---- test/key-store.test.js | 41 +++++++++++++++++++++++++++++++++++------ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/key-store.js b/src/key-store.js index 31e7ab0..b4d77da 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -74,6 +74,8 @@ const verifyMessage = async (signature, publicKey, data) => { return res } +const defaultPath = './keystore' + /** * Creates an instance of KeyStore. * @param {Object} options Various options to use when instantiating KeyStore. @@ -82,7 +84,6 @@ const verifyMessage = async (signature, publicKey, data) => { * @return {KeyStore} An instance of KeyStore. */ const KeyStore = async ({ storage, path } = {}) => { - const defaultPath = './keystore' storage = storage || await ComposedStorage(await LevelStorage({ path: path || defaultPath }), await LRUStorage({ size: 1000 })) const close = async () => { @@ -172,9 +173,7 @@ const KeyStore = async ({ storage, path } = {}) => { addKey, createKey, getKey, - getPublic, - defaultPath, - storage + getPublic } } diff --git a/test/key-store.test.js b/test/key-store.test.js index c4309e9..a50f21e 100644 --- a/test/key-store.test.js +++ b/test/key-store.test.js @@ -1,10 +1,13 @@ import { strictEqual, deepStrictEqual } from 'assert' +import * as crypto from '@libp2p/crypto' +import { Buffer } from 'safe-buffer' import rmrf from 'rimraf' -import { copy, pathExists } from 'fs-extra' +import { copy } from 'fs-extra' import KeyStore, { signMessage, verifyMessage } from '../src/key-store.js' import LevelStorage from '../src/storage/level.js' import testKeysPath from './fixtures/test-keys-path.js ' +const defaultPath = './keystore' const keysPath = './testkeys' describe('KeyStore', () => { @@ -23,7 +26,7 @@ describe('KeyStore', () => { afterEach(async () => { if (keystore) { await keystore.close() - await rmrf(keystore.defaultPath) + await rmrf(defaultPath) } }) @@ -83,6 +86,7 @@ describe('KeyStore', () => { it('gets a key', async () => { const id = 'key1' const keys = await keystore.createKey(id) + deepStrictEqual(await keystore.getKey(id), keys) }) @@ -139,20 +143,36 @@ describe('KeyStore', () => { }) describe('Options', () => { + const unmarshal = crypto.keys.supportedKeys.secp256k1.unmarshalSecp256k1PrivateKey + const privateKey = '198594a8de39fd97017d11996d619b3746211605a9d290964badf58bc79bdb33' + const publicKey = '0260baeaffa1de1e4135e5b395e0380563a622b9599d1b8e012a0f7603f516bdaa' + let privateKeyBuffer, publicKeyBuffer, unmarshalledPrivateKey + + before(async () => { + privateKeyBuffer = Buffer.from(privateKey, 'hex') + publicKeyBuffer = Buffer.from(publicKey, 'hex') + unmarshalledPrivateKey = await unmarshal(privateKeyBuffer) + }) + describe('Using default options', () => { beforeEach(async () => { + const storage = await LevelStorage({ path: defaultPath }) + await storage.put('private_key1', privateKeyBuffer) + await storage.put('public_key1', publicKeyBuffer) + await storage.close() + keystore = await KeyStore() }) afterEach(async () => { if (keystore) { await keystore.close() - await rmrf(keystore.defaultPath) + await rmrf(defaultPath) } }) it('loads default storage using default path', async () => { - strictEqual(await pathExists(keystore.defaultPath), true) + deepStrictEqual(await keystore.getKey('key1'), unmarshalledPrivateKey) }) }) @@ -161,6 +181,9 @@ describe('KeyStore', () => { beforeEach(async () => { const storage = await LevelStorage({ path }) + await storage.put('private_key2', privateKeyBuffer) + await storage.put('public_key2', publicKeyBuffer) + keystore = await KeyStore({ storage }) }) @@ -172,13 +195,19 @@ describe('KeyStore', () => { }) it('loads custom storage', async () => { - strictEqual(await pathExists(path), true) + deepStrictEqual(await keystore.getKey('key2'), unmarshalledPrivateKey) }) }) describe('Setting options.path', () => { beforeEach(async () => { await copy(testKeysPath, keysPath) + + const storage = await LevelStorage({ path: keysPath }) + await storage.put('private_key3', privateKeyBuffer) + await storage.put('public_key3', publicKeyBuffer) + await storage.close() + keystore = await KeyStore({ path: keysPath }) }) @@ -191,7 +220,7 @@ describe('KeyStore', () => { }) it('loads default storage using custom path', async () => { - strictEqual(await pathExists(keysPath), true) + deepStrictEqual(await keystore.getKey('key3'), unmarshalledPrivateKey) }) }) }) From 9b2dd487b85e5deef714e2768507bdd3dd15983d Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Mon, 6 Mar 2023 22:23:51 +0000 Subject: [PATCH 06/10] fix: Linting. --- test/key-store.test.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/key-store.test.js b/test/key-store.test.js index a50f21e..462aa90 100644 --- a/test/key-store.test.js +++ b/test/key-store.test.js @@ -202,7 +202,7 @@ describe('KeyStore', () => { describe('Setting options.path', () => { beforeEach(async () => { await copy(testKeysPath, keysPath) - + const storage = await LevelStorage({ path: keysPath }) await storage.put('private_key3', privateKeyBuffer) await storage.put('public_key3', publicKeyBuffer) From 528ce9818619458ee7adaf05cc971ead7613dfdc Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Tue, 7 Mar 2023 00:03:13 +0000 Subject: [PATCH 07/10] test: Remove custom keystore. Merged with keystore tests. --- test/custom-keystore.test.js | 78 ------------------------------------ 1 file changed, 78 deletions(-) delete mode 100644 test/custom-keystore.test.js diff --git a/test/custom-keystore.test.js b/test/custom-keystore.test.js deleted file mode 100644 index 5df81aa..0000000 --- a/test/custom-keystore.test.js +++ /dev/null @@ -1,78 +0,0 @@ -// import assert from 'assert' -// import rmrf from 'rimraf' -// import path from 'path' -// import OrbitDB from '../src/OrbitDB.js' -// import Identities from 'orbit-db-identity-provider' -// // Include test utilities -// import { -// config, -// startIpfs, -// stopIpfs, -// testAPIs, -// } from 'orbit-db-test-utils' - -// import { -// CustomTestKeystore, -// databases, -// } from './utils/index.js' - -// Identities.addIdentityProvider(CustomTestKeystore().identityProvider) - -// const dbPath = './orbitdb/tests/customKeystore' - -// Object.keys(testAPIs).forEach(API => { -// describe(`orbit-db - Use a Custom Keystore (${API})`, function() { -// this.timeout(20000) - -// let ipfsd, ipfs, orbitdb1 - -// before(async () => { -// rmrf.sync(dbPath) -// ipfsd = await startIpfs(API, config.daemon1) -// ipfs = ipfsd.api -// const identity = await Identities.createIdentity({ type: 'custom', keystore: CustomTestKeystore().create() }) -// orbitdb1 = await OrbitDB.createInstance(ipfs, { -// directory: path.join(dbPath, '1'), -// identity -// }) -// }) - -// after(async () => { -// await orbitdb1.stop() -// await stopIpfs(ipfsd) -// }) - -// describe('allows orbit to use a custom keystore with different store types', function() { -// databases.forEach(async (database) => { -// it(database.type + ' allows custom keystore', async () => { -// const db1 = await database.create(orbitdb1, 'custom-keystore') -// await database.tryInsert(db1) - -// assert.deepEqual(database.getTestValue(db1), database.expectedValue) - -// await db1.close() -// }) -// }) -// }) - -// describe('allows a custom keystore to be used with different store and write permissions', function() { -// databases.forEach(async (database) => { -// it(database.type + ' allows custom keystore', async () => { -// const options = { -// accessController: { -// // Set write access for both clients -// write: [orbitdb1.identity.id] -// } -// } - -// const db1 = await database.create(orbitdb1, 'custom-keystore', options) -// await database.tryInsert(db1) - -// assert.deepEqual(database.getTestValue(db1), database.expectedValue) - -// await db1.close() -// }) -// }) -// }) -// }) -// }) From 93366f0b8c4bd010807ce94cc0fa8949fbee11d0 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Tue, 7 Mar 2023 01:41:41 +0000 Subject: [PATCH 08/10] test: Remove redundant counter tests. --- test/counterdb.test.js | 176 ----------------------------------------- 1 file changed, 176 deletions(-) delete mode 100644 test/counterdb.test.js diff --git a/test/counterdb.test.js b/test/counterdb.test.js deleted file mode 100644 index 3591dc6..0000000 --- a/test/counterdb.test.js +++ /dev/null @@ -1,176 +0,0 @@ -// import assert from 'assert' -// import mapSeries from 'p-each-series' -// import rmrf from 'rimraf' -// import OrbitDB from '../src/OrbitDB.js' -// // Include test utilities -// import { -// config, -// startIpfs, -// stopIpfs, -// testAPIs, -// connectPeers, -// waitForPeers -// } from 'orbit-db-test-utils' - -// const orbitdbPath1 = './orbitdb/tests/counters/1' -// const orbitdbPath2 = './orbitdb/tests/counters/2' -// const dbPath1 = './orbitdb/tests/counters/db1' -// const dbPath2 = './orbitdb/tests/counters/db2' - -// Object.keys(testAPIs).forEach(API => { -// describe(`orbit-db - Counters (${API})`, function () { -// this.timeout(config.timeout) - -// let orbitdb1, orbitdb2 -// let ipfsd1, ipfsd2, ipfs1, ipfs2 - -// before(async () => { -// rmrf.sync(dbPath1) -// rmrf.sync(dbPath2) -// rmrf.sync(orbitdbPath1) -// rmrf.sync(orbitdbPath2) -// ipfsd1 = await startIpfs(API, config.daemon1) -// ipfsd2 = await startIpfs(API, config.daemon2) -// ipfs1 = ipfsd1.api -// ipfs2 = ipfsd2.api -// // Connect the peers manually to speed up test times -// const isLocalhostAddress = (addr) => addr.toString().includes('127.0.0.1') -// await connectPeers(ipfs1, ipfs2, { filter: isLocalhostAddress }) -// }) - -// after(async () => { -// if (orbitdb1) -// await orbitdb1.stop() - -// if (orbitdb2) -// await orbitdb2.stop() - -// if (ipfsd1) -// await stopIpfs(ipfsd1) - -// if (ipfsd2) -// await stopIpfs(ipfsd2) -// }) - -// beforeEach(async () => { -// orbitdb1 = await OrbitDB.createInstance(ipfs1, { directory: './orbitdb/1' }) -// orbitdb2 = await OrbitDB.createInstance(ipfs2, { directory: './orbitdb/2' }) -// }) - -// afterEach(async () => { -// if (orbitdb1) -// await orbitdb1.stop() - -// if (orbitdb2) -// await orbitdb2.stop() -// }) - -// describe('counters', function() { -// let address - -// it('creates and opens a database', async () => { -// const db = await orbitdb1.counter('counter database') -// assert.notEqual(db, null) -// assert.equal(db.type, 'counter') -// assert.equal(db.dbname, 'counter database') -// }) - -// it('value is zero when it\'s a fresh database', async () => { -// const db = await orbitdb1.counter('counter database') -// assert.equal(db.value, 0) -// await db.close() -// }) - -// it('increases a counter value', async () => { -// const counter = await orbitdb1.counter('counter test', { path: dbPath1 }) -// address = counter.address.toString() -// await mapSeries([13, 1], (f) => counter.inc(f)) -// assert.equal(counter.value, 14) -// await counter.close() -// }) - -// it('opens a saved counter', async () => { -// const counter = await orbitdb1.counter(address, { path: dbPath1 }) -// await counter.load() -// assert.equal(counter.value, 14) -// await counter.drop() -// }) - -// it('syncs counters', async () => { -// console.log("Sync counters") - -// let options = { -// accessController: { -// // Set write access for both clients -// write: [ -// orbitdb1.identity.id, -// orbitdb2.identity.id -// ] -// } -// } - -// const dbName = new Date().getTime().toString() - -// const numbers = [[13, 10], [2, 5]] -// const increaseCounter = (counterDB, i) => mapSeries(numbers[i], n => counterDB.inc(n)) - -// // Create a new counter database in the first client -// options = Object.assign({}, options, { path: dbPath1 }) -// const counter1 = await orbitdb1.counter(dbName, options) - -// // Open the database in the second client -// options = Object.assign({}, options, { path: dbPath2 }) -// const counter2 = await orbitdb2.counter(dbName, options) - -// // Make sure database addresses match since they're built deterministically -// assert.equal(counter1.address.toString(), counter2.address.toString()) - -// // Wait for peers to connect -// console.log("Waiting for peers to connect") -// await waitForPeers(ipfs1, [orbitdb2.id], counter1.address.toString()) -// await waitForPeers(ipfs2, [orbitdb1.id], counter1.address.toString()) - -// let finished1 = counter1.value === 30 -// let finished2 = counter2.value === 30 - -// counter1.events.on('replicated', () => { -// finished1 = (counter1.value === 30) -// finished2 = (counter2.value === 30) -// }) -// counter2.events.on('replicated', () => { -// finished1 = (counter1.value === 30) -// finished2 = (counter2.value === 30) -// }) -// counter1.events.on('write', () => { -// finished1 = (counter1.value === 30) -// finished2 = (counter2.value === 30) -// }) -// counter2.events.on('write', () => { -// finished1 = (counter1.value === 30) -// finished2 = (counter2.value === 30) -// }) - -// // Increase the counters sequentially -// await mapSeries([counter1, counter2], increaseCounter) -// console.log("Waiting for replication to finish") - -// return new Promise((resolve, reject) => { -// let timer = setInterval(async () => { -// if (finished1 && finished2) { -// try { -// clearInterval(timer) -// assert.equal(counter1.value, 30) -// assert.equal(counter2.value, 30) -// await counter1.close() -// await counter2.close() -// resolve() -// } catch (e) { -// reject(e) -// } -// } -// }, 100) -// }) -// }) -// }) -// }) -// }) From 113d954b4205e07f4e54eb7ca6433071bb9ecd62 Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Tue, 7 Mar 2023 11:38:34 +0000 Subject: [PATCH 09/10] refactor: Load LRU first. --- src/key-store.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/key-store.js b/src/key-store.js index b4d77da..04c6e3a 100644 --- a/src/key-store.js +++ b/src/key-store.js @@ -84,7 +84,7 @@ const defaultPath = './keystore' * @return {KeyStore} An instance of KeyStore. */ const KeyStore = async ({ storage, path } = {}) => { - storage = storage || await ComposedStorage(await LevelStorage({ path: path || defaultPath }), await LRUStorage({ size: 1000 })) + storage = storage || await ComposedStorage(await LRUStorage({ size: 1000 }), await LevelStorage({ path: path || defaultPath })) const close = async () => { await storage.close() From 796e84af10e1830373bb78a9a04cdcc1898c381f Mon Sep 17 00:00:00 2001 From: Hayden Young Date: Tue, 7 Mar 2023 11:42:07 +0000 Subject: [PATCH 10/10] test: Rename tests to better reflect what is being tested. --- test/key-store.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/key-store.test.js b/test/key-store.test.js index 462aa90..5ff4b0f 100644 --- a/test/key-store.test.js +++ b/test/key-store.test.js @@ -129,7 +129,7 @@ describe('KeyStore', () => { strictEqual(actual, expected) }) - it('creates a key when storage is closed', async () => { + it('doesn\'t create a key when keystore is closed', async () => { let err await keystore.close() try { @@ -171,7 +171,7 @@ describe('KeyStore', () => { } }) - it('loads default storage using default path', async () => { + it('uses default storage and default path to retrieve a key', async () => { deepStrictEqual(await keystore.getKey('key1'), unmarshalledPrivateKey) }) }) @@ -194,7 +194,7 @@ describe('KeyStore', () => { } }) - it('loads custom storage', async () => { + it('uses the given storage to retrieve a key', async () => { deepStrictEqual(await keystore.getKey('key2'), unmarshalledPrivateKey) }) }) @@ -219,7 +219,7 @@ describe('KeyStore', () => { await rmrf(keysPath) }) - it('loads default storage using custom path', async () => { + it('uses default storage using given path to retrieve a key', async () => { deepStrictEqual(await keystore.getKey('key3'), unmarshalledPrivateKey) }) })