@dxos/echo-db 2.33.9-dev.7d11f506 → 2.33.9-dev.9bbef4e2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.d.ts.map +1 -1
- package/dist/src/api/index.js +1 -0
- package/dist/src/api/index.js.map +1 -1
- package/dist/src/api/result-set.js +4 -4
- package/dist/src/api/result-set.js.map +1 -1
- package/dist/src/api/subscription.d.ts +5 -0
- package/dist/src/api/subscription.d.ts.map +1 -0
- package/dist/src/api/subscription.js +25 -0
- package/dist/src/api/subscription.js.map +1 -0
- package/dist/src/echo-api.test.d.ts +2 -0
- package/dist/src/echo-api.test.d.ts.map +1 -0
- package/dist/src/echo-api.test.js +117 -0
- package/dist/src/echo-api.test.js.map +1 -0
- package/dist/src/echo.d.ts +3 -4
- package/dist/src/echo.d.ts.map +1 -1
- package/dist/src/echo.js +6 -8
- package/dist/src/echo.js.map +1 -1
- package/dist/src/echo.test.js +3 -3
- package/dist/src/echo.test.js.map +1 -1
- package/dist/src/halo/halo-factory.js +8 -8
- package/dist/src/halo/halo-factory.js.map +1 -1
- package/dist/src/halo/halo-party.d.ts +2 -2
- package/dist/src/halo/halo-party.d.ts.map +1 -1
- package/dist/src/halo/halo-party.js +3 -3
- package/dist/src/halo/halo-party.js.map +1 -1
- package/dist/src/halo/halo.js +9 -9
- package/dist/src/halo/halo.js.map +1 -1
- package/dist/src/halo/halo.test.js.map +1 -1
- package/dist/src/halo/identity-manager.d.ts.map +1 -1
- package/dist/src/halo/identity-manager.js +7 -10
- package/dist/src/halo/identity-manager.js.map +1 -1
- package/dist/src/halo/identity.d.ts +1 -1
- package/dist/src/halo/identity.d.ts.map +1 -1
- package/dist/src/halo/identity.js +4 -2
- package/dist/src/halo/identity.js.map +1 -1
- package/dist/src/halo/preferences.d.ts.map +1 -1
- package/dist/src/halo/preferences.js +6 -6
- package/dist/src/halo/preferences.js.map +1 -1
- package/dist/src/invitations/greeting-initiator.js +6 -6
- package/dist/src/invitations/greeting-initiator.js.map +1 -1
- package/dist/src/invitations/greeting-responder.js +5 -5
- package/dist/src/invitations/greeting-responder.js.map +1 -1
- package/dist/src/invitations/halo-recovery-initiator.js +6 -6
- package/dist/src/invitations/halo-recovery-initiator.js.map +1 -1
- package/dist/src/invitations/invitation-descriptor.js +9 -9
- package/dist/src/invitations/invitation-descriptor.js.map +1 -1
- package/dist/src/invitations/invitation-factory.js +3 -3
- package/dist/src/invitations/invitation-factory.js.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.js +7 -7
- package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
- package/dist/src/packlets/database/data-mirror.js +8 -8
- package/dist/src/packlets/database/data-mirror.js.map +1 -1
- package/dist/src/packlets/database/data-service-host.js +3 -3
- package/dist/src/packlets/database/data-service-host.js.map +1 -1
- package/dist/src/packlets/database/data-service-router.js +5 -5
- package/dist/src/packlets/database/data-service-router.js.map +1 -1
- package/dist/src/packlets/database/database-backend.js +3 -3
- package/dist/src/packlets/database/database-backend.js.map +1 -1
- package/dist/src/packlets/database/database.js +2 -2
- package/dist/src/packlets/database/database.js.map +1 -1
- package/dist/src/packlets/database/item-demuxer.js +14 -14
- package/dist/src/packlets/database/item-demuxer.js.map +1 -1
- package/dist/src/packlets/database/item-manager.d.ts.map +1 -1
- package/dist/src/packlets/database/item-manager.js +18 -18
- package/dist/src/packlets/database/item-manager.js.map +1 -1
- package/dist/src/packlets/database/link.js +3 -3
- package/dist/src/packlets/database/link.js.map +1 -1
- package/dist/src/packlets/database/selection/result.js +2 -2
- package/dist/src/packlets/database/selection/result.js.map +1 -1
- package/dist/src/parties/data-party.d.ts.map +1 -1
- package/dist/src/parties/data-party.js +11 -11
- package/dist/src/parties/data-party.js.map +1 -1
- package/dist/src/parties/data-party.test.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts +3 -2
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +4 -4
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts +3 -3
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +6 -11
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/parties/party-manager.test.js +6 -6
- package/dist/src/parties/party-manager.test.js.map +1 -1
- package/dist/src/parties/party-preferences.d.ts +1 -1
- package/dist/src/parties/party-preferences.d.ts.map +1 -1
- package/dist/src/parties/party-preferences.js +5 -5
- package/dist/src/parties/party-preferences.js.map +1 -1
- package/dist/src/pipeline/feed-muxer.js +3 -3
- package/dist/src/pipeline/feed-muxer.js.map +1 -1
- package/dist/src/pipeline/feed-muxer.test.js +4 -2
- package/dist/src/pipeline/feed-muxer.test.js.map +1 -1
- package/dist/src/pipeline/message-selector.js +2 -2
- package/dist/src/pipeline/message-selector.js.map +1 -1
- package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
- package/dist/src/pipeline/metadata-store.js +35 -32
- package/dist/src/pipeline/metadata-store.js.map +1 -1
- package/dist/src/pipeline/party-feed-provider.js +3 -3
- package/dist/src/pipeline/party-feed-provider.js.map +1 -1
- package/dist/src/pipeline/party-pipeline.d.ts +3 -1
- package/dist/src/pipeline/party-pipeline.d.ts.map +1 -1
- package/dist/src/pipeline/party-pipeline.js +20 -18
- package/dist/src/pipeline/party-pipeline.js.map +1 -1
- package/dist/src/pipeline/party-pipeline.test.js +10 -9
- package/dist/src/pipeline/party-pipeline.test.js.map +1 -1
- package/dist/src/pipeline/party-processor.js +3 -3
- package/dist/src/pipeline/party-processor.js.map +1 -1
- package/dist/src/protocol/authenticator.test.js +53 -12
- package/dist/src/protocol/authenticator.test.js.map +1 -1
- package/dist/src/protocol/identity-credentials.d.ts +0 -1
- package/dist/src/protocol/identity-credentials.d.ts.map +1 -1
- package/dist/src/protocol/identity-credentials.js.map +1 -1
- package/dist/src/protocol/index.d.ts +1 -0
- package/dist/src/protocol/index.d.ts.map +1 -1
- package/dist/src/protocol/index.js +1 -0
- package/dist/src/protocol/index.js.map +1 -1
- package/dist/src/protocol/party-protocol-factory.d.ts +1 -1
- package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
- package/dist/src/snapshots/snapshot-store.js +2 -2
- package/dist/src/snapshots/snapshot-store.js.map +1 -1
- package/dist/src/snapshots/snapshot-store.test.js +5 -1
- package/dist/src/snapshots/snapshot-store.test.js.map +1 -1
- package/dist/src/testing/testing-factories.js +2 -2
- package/dist/src/testing/testing-factories.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +21 -17
- package/src/api/index.ts +1 -0
- package/src/api/result-set.ts +1 -1
- package/src/api/subscription.ts +24 -0
- package/src/echo-api.test.ts +162 -0
- package/src/echo.test.ts +3 -3
- package/src/echo.ts +12 -11
- package/src/halo/halo-factory.ts +1 -1
- package/src/halo/halo-party.ts +4 -4
- package/src/halo/halo.test.ts +1 -3
- package/src/halo/halo.ts +1 -1
- package/src/halo/identity-manager.ts +2 -7
- package/src/halo/identity.ts +3 -3
- package/src/halo/preferences.ts +2 -1
- package/src/invitations/greeting-initiator.ts +1 -1
- package/src/invitations/greeting-responder.ts +1 -1
- package/src/invitations/halo-recovery-initiator.ts +1 -1
- package/src/invitations/invitation-descriptor.ts +1 -1
- package/src/invitations/invitation-factory.ts +1 -1
- package/src/invitations/offline-invitation-claimer.ts +1 -1
- package/src/packlets/database/data-mirror.ts +1 -1
- package/src/packlets/database/data-service-host.ts +1 -1
- package/src/packlets/database/data-service-router.ts +1 -1
- package/src/packlets/database/database-backend.ts +1 -1
- package/src/packlets/database/database.ts +1 -1
- package/src/packlets/database/item-demuxer.ts +1 -1
- package/src/packlets/database/item-manager.ts +6 -6
- package/src/packlets/database/link.ts +1 -1
- package/src/packlets/database/selection/result.ts +1 -1
- package/src/parties/data-party.test.ts +3 -1
- package/src/parties/data-party.ts +3 -3
- package/src/parties/party-factory.ts +4 -4
- package/src/parties/party-manager.test.ts +1 -1
- package/src/parties/party-manager.ts +7 -14
- package/src/parties/party-preferences.ts +4 -4
- package/src/pipeline/feed-muxer.test.ts +4 -2
- package/src/pipeline/feed-muxer.ts +1 -1
- package/src/pipeline/message-selector.ts +1 -1
- package/src/pipeline/metadata-store.ts +38 -29
- package/src/pipeline/party-feed-provider.ts +1 -1
- package/src/pipeline/party-pipeline.test.ts +3 -2
- package/src/pipeline/party-pipeline.ts +10 -7
- package/src/pipeline/party-processor.ts +1 -1
- package/src/protocol/authenticator.test.ts +102 -17
- package/src/protocol/identity-credentials.ts +0 -2
- package/src/protocol/index.ts +1 -0
- package/src/protocol/party-protocol-factory.ts +1 -1
- package/src/snapshots/snapshot-store.test.ts +5 -1
- package/src/snapshots/snapshot-store.ts +1 -1
- package/src/testing/testing-factories.ts +1 -1
|
@@ -5,7 +5,9 @@
|
|
|
5
5
|
import expect from 'expect';
|
|
6
6
|
import { it as test } from 'mocha';
|
|
7
7
|
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
createKeyAdmitMessage, createPartyGenesisMessage, defaultSecretProvider, Keyring, KeyType, codec as haloCodec
|
|
10
|
+
} from '@dxos/credentials';
|
|
9
11
|
import { codec } from '@dxos/echo-protocol';
|
|
10
12
|
import { FeedStore } from '@dxos/feed-store';
|
|
11
13
|
import { ModelFactory } from '@dxos/model-factory';
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
5
|
+
import assert from 'node:assert';
|
|
6
6
|
|
|
7
7
|
import { synchronized, Event } from '@dxos/async';
|
|
8
8
|
import { timed } from '@dxos/debug';
|
|
@@ -30,7 +30,7 @@ export const PARTY_TITLE_PROPERTY = 'title'; // TODO(burdon): Remove (should not
|
|
|
30
30
|
|
|
31
31
|
// TODO(burdon): Factor out public API.
|
|
32
32
|
export interface PartyMember {
|
|
33
|
-
publicKey: PublicKey
|
|
33
|
+
publicKey: PublicKey
|
|
34
34
|
displayName?: string
|
|
35
35
|
}
|
|
36
36
|
|
|
@@ -142,7 +142,7 @@ export class DataParty {
|
|
|
142
142
|
await this._preferences?.setLastKnownTitle(title);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
-
get genesisFeedKey () {
|
|
145
|
+
get genesisFeedKey (): PublicKey {
|
|
146
146
|
assert(this._genesisFeedKey);
|
|
147
147
|
return this._genesisFeedKey;
|
|
148
148
|
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
import debug from 'debug';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
7
|
|
|
8
8
|
import {
|
|
9
9
|
createEnvelopeMessage,
|
|
@@ -19,7 +19,7 @@ import { ModelFactory } from '@dxos/model-factory';
|
|
|
19
19
|
import { NetworkManager } from '@dxos/network-manager';
|
|
20
20
|
import { ObjectModel } from '@dxos/object-model';
|
|
21
21
|
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
22
|
-
import { humanize } from '@dxos/util';
|
|
22
|
+
import { humanize, Provider } from '@dxos/util';
|
|
23
23
|
|
|
24
24
|
import {
|
|
25
25
|
createDataPartyAdmissionMessages,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
} from '../invitations';
|
|
28
28
|
import { IdentityNotInitializedError } from '../packlets/errors';
|
|
29
29
|
import { MetadataStore, PartyFeedProvider, PipelineOptions } from '../pipeline';
|
|
30
|
-
import {
|
|
30
|
+
import { IdentityCredentials } from '../protocol/identity-credentials';
|
|
31
31
|
import { SnapshotStore } from '../snapshots';
|
|
32
32
|
import { DataParty, PARTY_ITEM_TYPE } from './data-party';
|
|
33
33
|
|
|
@@ -38,7 +38,7 @@ const log = debug('dxos:echo-db:party-factory');
|
|
|
38
38
|
*/
|
|
39
39
|
export class PartyFactory {
|
|
40
40
|
constructor (
|
|
41
|
-
private readonly _identityProvider:
|
|
41
|
+
private readonly _identityProvider: Provider<IdentityCredentials | undefined>,
|
|
42
42
|
private readonly _networkManager: NetworkManager,
|
|
43
43
|
private readonly _modelFactory: ModelFactory,
|
|
44
44
|
private readonly _snapshotStore: SnapshotStore,
|
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
/* eslint-disable jest/no-conditional-expect */
|
|
6
6
|
|
|
7
|
-
import assert from 'assert';
|
|
8
7
|
import debug from 'debug';
|
|
9
8
|
import expect from 'expect';
|
|
10
9
|
import { it as test } from 'mocha';
|
|
10
|
+
import assert from 'node:assert';
|
|
11
11
|
|
|
12
12
|
import { latch } from '@dxos/async';
|
|
13
13
|
import {
|
|
@@ -2,20 +2,20 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
import debug from 'debug';
|
|
7
6
|
import unionWith from 'lodash.unionwith';
|
|
7
|
+
import assert from 'node:assert';
|
|
8
8
|
|
|
9
9
|
import { Event, synchronized } from '@dxos/async';
|
|
10
10
|
import { SecretProvider } from '@dxos/credentials';
|
|
11
11
|
import { failUndefined, timed } from '@dxos/debug';
|
|
12
12
|
import { PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
13
13
|
import { PublicKey } from '@dxos/protocols';
|
|
14
|
-
import { ComplexMap, boolGuard } from '@dxos/util';
|
|
14
|
+
import { ComplexMap, boolGuard, Provider } from '@dxos/util';
|
|
15
15
|
|
|
16
16
|
import { InvitationDescriptor } from '../invitations';
|
|
17
17
|
import { MetadataStore } from '../pipeline';
|
|
18
|
-
import {
|
|
18
|
+
import { IdentityCredentials } from '../protocol/identity-credentials';
|
|
19
19
|
import { SnapshotStore } from '../snapshots';
|
|
20
20
|
import { DataParty, PARTY_ITEM_TYPE, PARTY_TITLE_PROPERTY } from './data-party';
|
|
21
21
|
import { PartyFactory } from './party-factory';
|
|
@@ -25,9 +25,9 @@ export const CONTACT_DEBOUNCE_INTERVAL = 500;
|
|
|
25
25
|
const log = debug('dxos:echo-db:party-manager');
|
|
26
26
|
|
|
27
27
|
export interface OpenProgress {
|
|
28
|
-
haloOpened: boolean
|
|
29
|
-
partiesOpened?: number
|
|
30
|
-
totalParties?: number
|
|
28
|
+
haloOpened: boolean
|
|
29
|
+
partiesOpened?: number
|
|
30
|
+
totalParties?: number
|
|
31
31
|
}
|
|
32
32
|
|
|
33
33
|
/**
|
|
@@ -42,16 +42,12 @@ export class PartyManager {
|
|
|
42
42
|
// Map of parties by party key.
|
|
43
43
|
private readonly _parties = new ComplexMap<PublicKey, DataParty>(key => key.toHex());
|
|
44
44
|
|
|
45
|
-
// Unsubscribe handlers.
|
|
46
|
-
// TODO(burdon): Never used.
|
|
47
|
-
private readonly _onCloseHandlers: (() => void)[] = [];
|
|
48
|
-
|
|
49
45
|
private _open = false;
|
|
50
46
|
|
|
51
47
|
constructor (
|
|
52
48
|
private readonly _metadataStore: MetadataStore,
|
|
53
49
|
private readonly _snapshotStore: SnapshotStore,
|
|
54
|
-
private readonly _identityProvider:
|
|
50
|
+
private readonly _identityProvider: Provider<IdentityCredentials | undefined>,
|
|
55
51
|
private readonly _partyFactory: PartyFactory
|
|
56
52
|
) {}
|
|
57
53
|
|
|
@@ -129,9 +125,6 @@ export class PartyManager {
|
|
|
129
125
|
}
|
|
130
126
|
this._open = false;
|
|
131
127
|
|
|
132
|
-
// Clean-up.
|
|
133
|
-
this._onCloseHandlers.forEach(callback => callback());
|
|
134
|
-
|
|
135
128
|
// Close parties.
|
|
136
129
|
for (const party of this._parties.values()) {
|
|
137
130
|
if (party.isOpen) {
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// Copyright 2020 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
5
|
+
import assert from 'node:assert';
|
|
6
6
|
|
|
7
|
-
import { PARTY_TITLE_PROPERTY, DataParty } from '.';
|
|
8
7
|
import { Preferences } from '../halo/preferences';
|
|
8
|
+
import { PARTY_TITLE_PROPERTY, DataParty } from './data-party';
|
|
9
9
|
|
|
10
10
|
export interface ActivationOptions {
|
|
11
|
-
global?: boolean
|
|
12
|
-
device?: boolean
|
|
11
|
+
global?: boolean
|
|
12
|
+
device?: boolean
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/**
|
|
@@ -128,7 +128,8 @@ describe('FeedMuxer', () => {
|
|
|
128
128
|
await pipeline.outboundEchoStream!.write({
|
|
129
129
|
itemId: '123',
|
|
130
130
|
genesis: {
|
|
131
|
-
itemType: 'foo'
|
|
131
|
+
itemType: 'foo',
|
|
132
|
+
modelType: 'bar'
|
|
132
133
|
}
|
|
133
134
|
});
|
|
134
135
|
|
|
@@ -138,7 +139,8 @@ describe('FeedMuxer', () => {
|
|
|
138
139
|
expect((echoMessages[0] as any).data).toEqual({
|
|
139
140
|
itemId: '123',
|
|
140
141
|
genesis: {
|
|
141
|
-
itemType: 'foo'
|
|
142
|
+
itemType: 'foo',
|
|
143
|
+
modelType: 'bar'
|
|
142
144
|
}
|
|
143
145
|
});
|
|
144
146
|
});
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
6
5
|
import debug from 'debug';
|
|
6
|
+
import assert from 'node:assert';
|
|
7
7
|
|
|
8
8
|
import { synchronized } from '@dxos/async';
|
|
9
9
|
import { failUndefined } from '@dxos/debug';
|
|
@@ -25,13 +25,15 @@ export interface AddPartyOptions {
|
|
|
25
25
|
genesisFeed: PublicKey
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
+
const emptyEchoMetadata = (): EchoMetadata => ({
|
|
29
|
+
version: STORAGE_VERSION,
|
|
30
|
+
parties: [],
|
|
31
|
+
created: new Date(),
|
|
32
|
+
updated: new Date()
|
|
33
|
+
});
|
|
34
|
+
|
|
28
35
|
export class MetadataStore {
|
|
29
|
-
private _metadata: EchoMetadata =
|
|
30
|
-
version: STORAGE_VERSION,
|
|
31
|
-
parties: [],
|
|
32
|
-
created: new Date(),
|
|
33
|
-
updated: new Date()
|
|
34
|
-
};
|
|
36
|
+
private _metadata: EchoMetadata = emptyEchoMetadata();
|
|
35
37
|
|
|
36
38
|
constructor (
|
|
37
39
|
private readonly _directory: Directory
|
|
@@ -56,19 +58,26 @@ export class MetadataStore {
|
|
|
56
58
|
async load (): Promise<void> {
|
|
57
59
|
const file = this._directory.createOrOpen('EchoMetadata');
|
|
58
60
|
try {
|
|
59
|
-
const { size } = await file.stat();
|
|
60
|
-
if (
|
|
61
|
+
const { size: fileLength } = await file.stat();
|
|
62
|
+
if (fileLength < 4) {
|
|
61
63
|
return;
|
|
62
64
|
}
|
|
65
|
+
// Loading file size from first 4 bytes.
|
|
66
|
+
const dataSize = fromBytesInt32(await file.read(0, 4));
|
|
67
|
+
log(`Load: data size ${dataSize}`);
|
|
68
|
+
|
|
69
|
+
// Sanity check.
|
|
70
|
+
{
|
|
71
|
+
if (fileLength < dataSize + 4) {
|
|
72
|
+
throw new Error('Metadata storage is corrupted');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
63
75
|
|
|
64
|
-
const data = await file.read(
|
|
76
|
+
const data = await file.read(4, dataSize);
|
|
65
77
|
this._metadata = schema.getCodecForType('dxos.echo.metadata.EchoMetadata').decode(data);
|
|
66
78
|
} catch (err: any) {
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
} else {
|
|
70
|
-
throw err;
|
|
71
|
-
}
|
|
79
|
+
log(`Error loading metadata: ${err}`);
|
|
80
|
+
this._metadata = emptyEchoMetadata();
|
|
72
81
|
} finally {
|
|
73
82
|
await file.close();
|
|
74
83
|
}
|
|
@@ -87,22 +96,14 @@ export class MetadataStore {
|
|
|
87
96
|
|
|
88
97
|
try {
|
|
89
98
|
const encoded = Buffer.from(schema.getCodecForType('dxos.echo.metadata.EchoMetadata').encode(data));
|
|
90
|
-
await file.write(0, encoded);
|
|
91
99
|
|
|
92
|
-
//
|
|
93
|
-
{
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
100
|
+
// Saving file size at first 4 bytes.
|
|
101
|
+
log(`Save: data size ${encoded.length}`);
|
|
102
|
+
await file.write(0, toBytesInt32(encoded.length));
|
|
103
|
+
|
|
104
|
+
// Saving data.
|
|
105
|
+
await file.write(4, encoded);
|
|
99
106
|
|
|
100
|
-
// Sanity check.
|
|
101
|
-
const { size } = await file.stat();
|
|
102
|
-
if (size !== encoded.length) {
|
|
103
|
-
console.log('SANITY!');
|
|
104
|
-
}
|
|
105
|
-
assert(size === encoded.length);
|
|
106
107
|
} finally {
|
|
107
108
|
await file.close();
|
|
108
109
|
}
|
|
@@ -196,3 +197,11 @@ export class MetadataStore {
|
|
|
196
197
|
await this._save();
|
|
197
198
|
}
|
|
198
199
|
}
|
|
200
|
+
|
|
201
|
+
const toBytesInt32 = (num: number) => {
|
|
202
|
+
const buf = Buffer.alloc(4);
|
|
203
|
+
buf.writeInt32LE(num, 0);
|
|
204
|
+
return buf;
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
const fromBytesInt32 = (buf: Buffer) => buf.readInt32LE(0);
|
|
@@ -18,9 +18,10 @@ import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
|
18
18
|
import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
|
|
19
19
|
import { afterTest } from '@dxos/testutils';
|
|
20
20
|
|
|
21
|
-
import {
|
|
22
|
-
import { createReplicatorPlugin } from '../protocol/replicator-plugin';
|
|
21
|
+
import { createReplicatorPlugin } from '../protocol';
|
|
23
22
|
import { SnapshotStore } from '../snapshots';
|
|
23
|
+
import { MetadataStore } from './metadata-store';
|
|
24
|
+
import { PartyFeedProvider } from './party-feed-provider';
|
|
24
25
|
import { PartyPipeline } from './party-pipeline';
|
|
25
26
|
|
|
26
27
|
describe('PartyPipeline', () => {
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import assert from 'assert';
|
|
5
|
+
import assert from 'node:assert';
|
|
6
6
|
|
|
7
7
|
import { synchronized } from '@dxos/async';
|
|
8
8
|
import { KeyType, Message as HaloMessage } from '@dxos/credentials';
|
|
@@ -14,20 +14,23 @@ import { ModelFactory } from '@dxos/model-factory';
|
|
|
14
14
|
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
15
15
|
import { SubscriptionGroup } from '@dxos/util';
|
|
16
16
|
|
|
17
|
-
import { createMessageSelector, PartyProcessor, PartyFeedProvider, FeedMuxer } from '.';
|
|
18
17
|
import { Database, FeedDatabaseBackend, TimeframeClock } from '../packlets/database';
|
|
19
18
|
import { createAutomaticSnapshots, SnapshotStore } from '../snapshots';
|
|
19
|
+
import { FeedMuxer } from './feed-muxer';
|
|
20
|
+
import { createMessageSelector } from './message-selector';
|
|
21
|
+
import { PartyFeedProvider } from './party-feed-provider';
|
|
22
|
+
import { PartyProcessor } from './party-processor';
|
|
20
23
|
|
|
21
24
|
const DEFAULT_SNAPSHOT_INTERVAL = 100; // Every 100 messages.
|
|
22
25
|
|
|
23
26
|
export interface PipelineOptions {
|
|
24
|
-
readLogger?: (msg: any) => void
|
|
25
|
-
writeLogger?: (msg: any) => void
|
|
26
|
-
readOnly?: boolean
|
|
27
|
+
readLogger?: (msg: any) => void
|
|
28
|
+
writeLogger?: (msg: any) => void
|
|
29
|
+
readOnly?: boolean
|
|
27
30
|
// TODO(burdon): Hierarchical options.
|
|
28
31
|
// snapshots: { enabled: true, interval: 100 } }
|
|
29
|
-
snapshots?: boolean
|
|
30
|
-
snapshotInterval?: number
|
|
32
|
+
snapshots?: boolean
|
|
33
|
+
snapshotInterval?: number
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
export interface OpenOptions {
|
|
@@ -5,21 +5,18 @@
|
|
|
5
5
|
import expect from 'expect';
|
|
6
6
|
import { it as test } from 'mocha';
|
|
7
7
|
|
|
8
|
-
import { createAuthMessage, createKeyAdmitMessage, createPartyGenesisMessage, Keyring, KeyType } from '@dxos/credentials';
|
|
8
|
+
import { createAuthMessage, createEnvelopeMessage, createFeedAdmitMessage, createKeyAdmitMessage, createPartyGenesisMessage, Keyring, KeyType, wrapMessage } from '@dxos/credentials';
|
|
9
9
|
|
|
10
10
|
import { PartyProcessor } from '../pipeline';
|
|
11
11
|
import { createAuthenticator } from './authenticator';
|
|
12
|
-
import {
|
|
12
|
+
import { createTestIdentityCredentials } from './identity-credentials';
|
|
13
13
|
|
|
14
14
|
describe('authenticator', () => {
|
|
15
|
-
|
|
16
|
-
test.skip('authenticates admitted peer', async () => {
|
|
15
|
+
test('authenticates party creator', async () => {
|
|
17
16
|
const keyring = new Keyring();
|
|
17
|
+
const identity = await createTestIdentityCredentials(keyring);
|
|
18
18
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
19
|
-
const
|
|
20
|
-
const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
21
|
-
const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
|
|
22
|
-
const signer = CredentialsSigner.createDirectDeviceSigner(keyring);
|
|
19
|
+
const feedKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
23
20
|
|
|
24
21
|
const partyProcessor = new PartyProcessor(partyKey.publicKey);
|
|
25
22
|
await partyProcessor.processMessage({
|
|
@@ -27,16 +24,106 @@ describe('authenticator', () => {
|
|
|
27
24
|
keyring,
|
|
28
25
|
partyKey,
|
|
29
26
|
feedKey.publicKey,
|
|
30
|
-
|
|
27
|
+
partyKey
|
|
31
28
|
),
|
|
32
29
|
meta: {} as any
|
|
33
30
|
});
|
|
31
|
+
await partyProcessor.processMessage({
|
|
32
|
+
data: createEnvelopeMessage(
|
|
33
|
+
identity.keyring,
|
|
34
|
+
partyKey.publicKey,
|
|
35
|
+
wrapMessage(identity.identityGenesis),
|
|
36
|
+
[partyKey]
|
|
37
|
+
),
|
|
38
|
+
meta: {} as any
|
|
39
|
+
});
|
|
40
|
+
await partyProcessor.processMessage({
|
|
41
|
+
data: createFeedAdmitMessage(
|
|
42
|
+
keyring,
|
|
43
|
+
partyKey.publicKey,
|
|
44
|
+
feedKey.publicKey,
|
|
45
|
+
[identity.deviceKeyChain]
|
|
46
|
+
),
|
|
47
|
+
meta: {} as any
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
const authenticator = createAuthenticator(partyProcessor, identity.createCredentialsSigner(), null as any);
|
|
51
|
+
|
|
52
|
+
//
|
|
53
|
+
// This test follows the same party creation routing as party factory.
|
|
54
|
+
// Oddly, it does not admit the device key to the party.
|
|
55
|
+
// This means that authentication is actually done using the signature created using the feed key.
|
|
56
|
+
//
|
|
57
|
+
|
|
58
|
+
// Does not authenticate without the feed key.
|
|
59
|
+
{
|
|
60
|
+
const credential = createAuthMessage(
|
|
61
|
+
keyring,
|
|
62
|
+
partyKey.publicKey,
|
|
63
|
+
identity.identityKey,
|
|
64
|
+
identity.deviceKey
|
|
65
|
+
);
|
|
66
|
+
expect(await authenticator.authenticate(credential.payload)).toEqual(false);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Does authenticate with the feed key.
|
|
70
|
+
{
|
|
71
|
+
const credential = createAuthMessage(
|
|
72
|
+
keyring,
|
|
73
|
+
partyKey.publicKey,
|
|
74
|
+
identity.identityKey,
|
|
75
|
+
identity.deviceKey,
|
|
76
|
+
feedKey.publicKey
|
|
77
|
+
);
|
|
78
|
+
expect(await authenticator.authenticate(credential.payload)).toEqual(true);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('authenticates another identity', async () => {
|
|
83
|
+
const keyring = new Keyring();
|
|
84
|
+
const identity = await createTestIdentityCredentials(keyring);
|
|
85
|
+
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
86
|
+
const feedKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
87
|
+
|
|
88
|
+
const partyProcessor = new PartyProcessor(partyKey.publicKey);
|
|
89
|
+
await partyProcessor.processMessage({
|
|
90
|
+
data: createPartyGenesisMessage(
|
|
91
|
+
keyring,
|
|
92
|
+
partyKey,
|
|
93
|
+
feedKey.publicKey,
|
|
94
|
+
partyKey
|
|
95
|
+
),
|
|
96
|
+
meta: {} as any
|
|
97
|
+
});
|
|
98
|
+
await partyProcessor.processMessage({
|
|
99
|
+
data: createEnvelopeMessage(
|
|
100
|
+
identity.keyring,
|
|
101
|
+
partyKey.publicKey,
|
|
102
|
+
wrapMessage(identity.identityGenesis),
|
|
103
|
+
[partyKey]
|
|
104
|
+
),
|
|
105
|
+
meta: {} as any
|
|
106
|
+
});
|
|
107
|
+
await partyProcessor.processMessage({
|
|
108
|
+
data: createFeedAdmitMessage(
|
|
109
|
+
keyring,
|
|
110
|
+
partyKey.publicKey,
|
|
111
|
+
feedKey.publicKey,
|
|
112
|
+
[identity.deviceKeyChain]
|
|
113
|
+
),
|
|
114
|
+
meta: {} as any
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const authenticator = createAuthenticator(partyProcessor, identity.createCredentialsSigner(), null as any);
|
|
118
|
+
|
|
119
|
+
const identity2 = await createTestIdentityCredentials(keyring);
|
|
120
|
+
|
|
34
121
|
await partyProcessor.processMessage({
|
|
35
122
|
data: createKeyAdmitMessage(
|
|
36
123
|
keyring,
|
|
37
124
|
partyKey.publicKey,
|
|
38
|
-
identityKey,
|
|
39
|
-
[
|
|
125
|
+
identity2.identityKey,
|
|
126
|
+
[identity.deviceKeyChain]
|
|
40
127
|
),
|
|
41
128
|
meta: {} as any
|
|
42
129
|
});
|
|
@@ -44,20 +131,18 @@ describe('authenticator', () => {
|
|
|
44
131
|
data: createKeyAdmitMessage(
|
|
45
132
|
keyring,
|
|
46
133
|
partyKey.publicKey,
|
|
47
|
-
deviceKey,
|
|
48
|
-
[
|
|
134
|
+
identity2.deviceKey,
|
|
135
|
+
[identity.deviceKeyChain]
|
|
49
136
|
),
|
|
50
137
|
meta: {} as any
|
|
51
138
|
});
|
|
52
139
|
|
|
53
|
-
const authenticator = createAuthenticator(partyProcessor, signer, null as any);
|
|
54
140
|
const credential = createAuthMessage(
|
|
55
141
|
keyring,
|
|
56
142
|
partyKey.publicKey,
|
|
57
|
-
identityKey,
|
|
58
|
-
deviceKey
|
|
143
|
+
identity2.identityKey,
|
|
144
|
+
identity2.deviceKey
|
|
59
145
|
);
|
|
60
|
-
|
|
61
146
|
expect(await authenticator.authenticate(credential.payload)).toEqual(true);
|
|
62
147
|
});
|
|
63
148
|
});
|
|
@@ -27,8 +27,6 @@ export interface IdentityCredentials {
|
|
|
27
27
|
contacts: ContactManager | undefined
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
|
|
31
|
-
|
|
32
30
|
export const createTestIdentityCredentials = async (keyring: Keyring): Promise<IdentityCredentials> => {
|
|
33
31
|
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
34
32
|
const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
|
package/src/protocol/index.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { MMSTTopology, NetworkManager, Plugin } from '@dxos/network-manager';
|
|
|
11
11
|
import { PresencePlugin } from '@dxos/protocol-plugin-presence';
|
|
12
12
|
import { PublicKey } from '@dxos/protocols';
|
|
13
13
|
|
|
14
|
-
import { CredentialsProvider } from '
|
|
14
|
+
import { CredentialsProvider } from './authenticator';
|
|
15
15
|
|
|
16
16
|
const log = debug('dxos:echo-db:party-protocol-factory');
|
|
17
17
|
|
|
@@ -26,10 +26,14 @@ describe('SnapshotStore', () => {
|
|
|
26
26
|
|
|
27
27
|
const snapshot: PartySnapshot = {
|
|
28
28
|
partyKey: key1.asBuffer(),
|
|
29
|
+
halo: {
|
|
30
|
+
messages: []
|
|
31
|
+
},
|
|
29
32
|
database: {
|
|
30
33
|
items: [{
|
|
31
34
|
itemId: createId(),
|
|
32
|
-
itemType: 'example:test'
|
|
35
|
+
itemType: 'example:test',
|
|
36
|
+
modelType: 'example:model'
|
|
33
37
|
}],
|
|
34
38
|
links: []
|
|
35
39
|
}
|