@dxos/echo-db 2.33.2 → 2.33.3-dev.08e106c3
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/echo.js +2 -2
- package/dist/src/echo.js.map +1 -1
- package/dist/src/echo.test.js +10 -10
- package/dist/src/echo.test.js.map +1 -1
- package/dist/src/halo/halo-party.d.ts.map +1 -1
- package/dist/src/halo/halo-party.js +1 -1
- package/dist/src/halo/halo-party.js.map +1 -1
- package/dist/src/halo/halo.d.ts +1 -0
- package/dist/src/halo/halo.d.ts.map +1 -1
- package/dist/src/halo/halo.js +10 -1
- package/dist/src/halo/halo.js.map +1 -1
- package/dist/src/halo/identity-manager.d.ts +0 -1
- package/dist/src/halo/identity-manager.d.ts.map +1 -1
- package/dist/src/halo/identity-manager.js +11 -11
- package/dist/src/halo/identity-manager.js.map +1 -1
- package/dist/src/halo/identity.d.ts +18 -13
- package/dist/src/halo/identity.d.ts.map +1 -1
- package/dist/src/halo/identity.js +24 -27
- package/dist/src/halo/identity.js.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.d.ts +2 -2
- package/dist/src/invitations/offline-invitation-claimer.d.ts.map +1 -1
- package/dist/src/invitations/offline-invitation-claimer.js +2 -4
- package/dist/src/invitations/offline-invitation-claimer.js.map +1 -1
- package/dist/src/parties/data-party.d.ts.map +1 -1
- package/dist/src/parties/data-party.js +1 -1
- package/dist/src/parties/data-party.js.map +1 -1
- package/dist/src/parties/data-party.test.d.ts +2 -0
- package/dist/src/parties/data-party.test.d.ts.map +1 -0
- package/dist/src/parties/data-party.test.js +129 -0
- package/dist/src/parties/data-party.test.js.map +1 -0
- package/dist/src/parties/party-factory.d.ts +2 -2
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +12 -20
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts +2 -2
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +2 -1
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/parties/party-manager.test.js +7 -22
- package/dist/src/parties/party-manager.test.js.map +1 -1
- package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
- package/dist/src/pipeline/metadata-store.js +5 -6
- package/dist/src/pipeline/metadata-store.js.map +1 -1
- package/dist/src/pipeline/party-core.test.js +1 -1
- package/dist/src/pipeline/party-core.test.js.map +1 -1
- package/dist/src/pipeline/party-processor.d.ts +0 -5
- package/dist/src/pipeline/party-processor.d.ts.map +1 -1
- package/dist/src/pipeline/party-processor.js +0 -7
- package/dist/src/pipeline/party-processor.js.map +1 -1
- package/dist/src/protocol/credentials-signer.d.ts +4 -4
- package/dist/src/protocol/credentials-signer.d.ts.map +1 -1
- package/dist/src/protocol/credentials-signer.js +8 -8
- package/dist/src/protocol/credentials-signer.js.map +1 -1
- package/dist/src/protocol/identity-credentials.d.ts +22 -0
- package/dist/src/protocol/identity-credentials.d.ts.map +1 -0
- package/dist/src/protocol/identity-credentials.js +50 -0
- package/dist/src/protocol/identity-credentials.js.map +1 -0
- package/dist/src/protocol/party-protocol-factory.d.ts +3 -4
- package/dist/src/protocol/party-protocol-factory.d.ts.map +1 -1
- package/dist/src/protocol/party-protocol-factory.js +12 -15
- package/dist/src/protocol/party-protocol-factory.js.map +1 -1
- package/dist/src/snapshots/snapshot-store.d.ts.map +1 -1
- package/dist/src/snapshots/snapshot-store.js +5 -6
- package/dist/src/snapshots/snapshot-store.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/echo.test.ts +10 -10
- package/src/echo.ts +1 -1
- package/src/halo/halo-party.ts +1 -2
- package/src/halo/halo.ts +8 -1
- package/src/halo/identity-manager.ts +13 -14
- package/src/halo/identity.ts +39 -41
- package/src/invitations/offline-invitation-claimer.ts +6 -7
- package/src/parties/data-party.test.ts +212 -0
- package/src/parties/data-party.ts +1 -2
- package/src/parties/party-factory.ts +14 -20
- package/src/parties/party-manager.test.ts +8 -42
- package/src/parties/party-manager.ts +4 -3
- package/src/pipeline/metadata-store.ts +5 -6
- package/src/pipeline/party-core.test.ts +2 -4
- package/src/pipeline/party-processor.ts +0 -13
- package/src/protocol/credentials-signer.ts +9 -9
- package/src/protocol/identity-credentials.ts +78 -0
- package/src/protocol/party-protocol-factory.ts +13 -17
- package/src/snapshots/snapshot-store.ts +5 -6
|
@@ -33,9 +33,9 @@ import { createStorage, StorageType } from '@dxos/random-access-multi-storage';
|
|
|
33
33
|
import { afterTest, testTimeout } from '@dxos/testutils';
|
|
34
34
|
|
|
35
35
|
import { Item } from '../api';
|
|
36
|
-
import { HaloFactory, Identity, IdentityManager } from '../halo';
|
|
37
36
|
import { defaultInvitationAuthenticator, OfflineInvitationClaimer } from '../invitations';
|
|
38
37
|
import { MetadataStore, PartyFeedProvider } from '../pipeline';
|
|
38
|
+
import { createTestIdentityCredentials } from '../protocol/identity-credentials';
|
|
39
39
|
import { SnapshotStore } from '../snapshots';
|
|
40
40
|
import { messageLogger } from '../testing';
|
|
41
41
|
import { createRamStorage } from '../util';
|
|
@@ -58,33 +58,12 @@ const setup = async () => {
|
|
|
58
58
|
const keyring = new Keyring();
|
|
59
59
|
const metadataStore = new MetadataStore(createRamStorage());
|
|
60
60
|
const feedStore = new FeedStore(createStorage('', StorageType.RAM), { valueEncoding: codec });
|
|
61
|
-
|
|
62
|
-
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
63
|
-
|
|
64
|
-
assert(keyring.keys.length === 1);
|
|
65
|
-
|
|
66
61
|
const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
|
|
67
62
|
const modelFactory = new ModelFactory().registerModel(ObjectModel);
|
|
68
63
|
const networkManager = new NetworkManager();
|
|
69
64
|
const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
|
|
70
65
|
|
|
71
|
-
const
|
|
72
|
-
networkManager,
|
|
73
|
-
modelFactory,
|
|
74
|
-
snapshotStore,
|
|
75
|
-
feedProviderFactory,
|
|
76
|
-
keyring,
|
|
77
|
-
{
|
|
78
|
-
writeLogger: messageLogger('<<<'),
|
|
79
|
-
readLogger: messageLogger('>>>')
|
|
80
|
-
}
|
|
81
|
-
);
|
|
82
|
-
const haloParty = await haloFactory.createHalo({
|
|
83
|
-
identityDisplayName: identityKey.publicKey.humanize()
|
|
84
|
-
});
|
|
85
|
-
afterTest(() => haloParty.close());
|
|
86
|
-
const identity = new Identity(keyring, haloParty);
|
|
87
|
-
|
|
66
|
+
const identity = await createTestIdentityCredentials(keyring);
|
|
88
67
|
const partyFactory = new PartyFactory(
|
|
89
68
|
() => identity,
|
|
90
69
|
networkManager,
|
|
@@ -171,33 +150,22 @@ describe('Party manager', () => {
|
|
|
171
150
|
test('Create from cold start', async () => {
|
|
172
151
|
const storage = createStorage('', StorageType.RAM);
|
|
173
152
|
const feedStore = new FeedStore(storage, { valueEncoding: codec });
|
|
174
|
-
|
|
175
153
|
const keyring = new Keyring();
|
|
176
154
|
const metadataStore = new MetadataStore(createRamStorage());
|
|
177
|
-
|
|
178
|
-
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
179
|
-
await keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
180
|
-
|
|
181
155
|
const modelFactory = new ModelFactory().registerModel(ObjectModel);
|
|
182
156
|
const snapshotStore = new SnapshotStore(createStorage('', StorageType.RAM));
|
|
183
157
|
const networkManager = new NetworkManager();
|
|
184
158
|
const feedProviderFactory = (partyKey: PublicKey) => new PartyFeedProvider(metadataStore, keyring, feedStore, partyKey);
|
|
159
|
+
|
|
160
|
+
const identity = await createTestIdentityCredentials(keyring);
|
|
185
161
|
const partyFactory = new PartyFactory(
|
|
186
|
-
() =>
|
|
162
|
+
() => identity,
|
|
187
163
|
networkManager,
|
|
188
164
|
modelFactory,
|
|
189
165
|
snapshotStore,
|
|
190
166
|
feedProviderFactory
|
|
191
167
|
);
|
|
192
|
-
const
|
|
193
|
-
networkManager,
|
|
194
|
-
modelFactory,
|
|
195
|
-
snapshotStore,
|
|
196
|
-
feedProviderFactory,
|
|
197
|
-
keyring
|
|
198
|
-
);
|
|
199
|
-
const identityManager = new IdentityManager(keyring, haloFactory, metadataStore);
|
|
200
|
-
const partyManager = new PartyManager(metadataStore, snapshotStore, () => identityManager.identity, partyFactory);
|
|
168
|
+
const partyManager = new PartyManager(metadataStore, snapshotStore, () => identity, partyFactory);
|
|
201
169
|
|
|
202
170
|
/* TODO(telackey): Injecting "raw" Parties into the feeds behind the scenes seems fishy to me, as it writes the
|
|
203
171
|
* Party messages in a slightly different way than the code inside PartyFactory does, and so could easily diverge
|
|
@@ -221,7 +189,7 @@ describe('Party manager', () => {
|
|
|
221
189
|
assert(feedKey);
|
|
222
190
|
|
|
223
191
|
const feedStream = createWritableFeedStream(feed);
|
|
224
|
-
feedStream.write({ halo: createPartyGenesisMessage(keyring, partyKey, feedKey.publicKey, identityKey) });
|
|
192
|
+
feedStream.write({ halo: createPartyGenesisMessage(keyring, partyKey, feedKey.publicKey, identity.identityKey) });
|
|
225
193
|
feedStream.write({
|
|
226
194
|
echo: checkType<EchoEnvelope>({
|
|
227
195
|
itemId: 'foo',
|
|
@@ -235,8 +203,6 @@ describe('Party manager', () => {
|
|
|
235
203
|
}
|
|
236
204
|
|
|
237
205
|
// Open.
|
|
238
|
-
await identityManager.createHalo();
|
|
239
|
-
afterTest(() => identityManager.close());
|
|
240
206
|
await partyManager.open();
|
|
241
207
|
expect(partyManager.parties).toHaveLength(numParties);
|
|
242
208
|
await partyManager.close();
|
|
@@ -450,7 +416,7 @@ describe('Party manager', () => {
|
|
|
450
416
|
// Redeem the invitation on B.
|
|
451
417
|
expect(partyManagerB.parties).toHaveLength(0);
|
|
452
418
|
const partyB = await partyManagerB.joinParty(invitationDescriptor,
|
|
453
|
-
OfflineInvitationClaimer.createSecretProvider(identityB));
|
|
419
|
+
OfflineInvitationClaimer.createSecretProvider(identityB.createCredentialsSigner()));
|
|
454
420
|
expect(partyB).toBeDefined();
|
|
455
421
|
log(`Joined ${partyB.key.toHex()}`);
|
|
456
422
|
|
|
@@ -13,9 +13,9 @@ import { timed } from '@dxos/debug';
|
|
|
13
13
|
import { PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
14
14
|
import { ComplexMap, boolGuard } from '@dxos/util';
|
|
15
15
|
|
|
16
|
-
import { IdentityProvider } from '../halo';
|
|
17
16
|
import { InvitationDescriptor } from '../invitations';
|
|
18
17
|
import { MetadataStore } from '../pipeline';
|
|
18
|
+
import { IdentityCredentialsProvider } 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';
|
|
@@ -51,7 +51,7 @@ export class PartyManager {
|
|
|
51
51
|
constructor (
|
|
52
52
|
private readonly _metadataStore: MetadataStore,
|
|
53
53
|
private readonly _snapshotStore: SnapshotStore,
|
|
54
|
-
private readonly _identityProvider:
|
|
54
|
+
private readonly _identityProvider: IdentityCredentialsProvider,
|
|
55
55
|
private readonly _partyFactory: PartyFactory
|
|
56
56
|
) {}
|
|
57
57
|
|
|
@@ -74,10 +74,11 @@ export class PartyManager {
|
|
|
74
74
|
|
|
75
75
|
let partyKeys = this._metadataStore.parties.map(party => party.key).filter(boolGuard);
|
|
76
76
|
|
|
77
|
+
// Identity may be undefined, for example, on the first start.
|
|
77
78
|
const identity = this._identityProvider();
|
|
78
79
|
|
|
79
80
|
// TODO(telackey): Does it make any sense to load other parties if we don't have an HALO?
|
|
80
|
-
if (identity
|
|
81
|
+
if (identity) {
|
|
81
82
|
partyKeys = partyKeys.filter(partyKey => !partyKey.equals(identity.identityKey!.publicKey));
|
|
82
83
|
}
|
|
83
84
|
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
import debug from 'debug';
|
|
7
|
-
import pify from 'pify';
|
|
8
7
|
|
|
9
8
|
import { PublicKey } from '@dxos/crypto';
|
|
10
9
|
import { failUndefined } from '@dxos/debug';
|
|
@@ -50,12 +49,12 @@ export class MetadataStore {
|
|
|
50
49
|
async load (): Promise<void> {
|
|
51
50
|
const file = this._storage.createOrOpen('EchoMetadata');
|
|
52
51
|
try {
|
|
53
|
-
const { size } = await
|
|
52
|
+
const { size } = await file.stat();
|
|
54
53
|
if (size === 0) {
|
|
55
54
|
return;
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
const data = await
|
|
57
|
+
const data = await file.read(0, size);
|
|
59
58
|
this._metadata = schema.getCodecForType('dxos.echo.metadata.EchoMetadata').decode(data);
|
|
60
59
|
} catch (err: any) {
|
|
61
60
|
if (err.code === 'ENOENT') {
|
|
@@ -64,7 +63,7 @@ export class MetadataStore {
|
|
|
64
63
|
throw err;
|
|
65
64
|
}
|
|
66
65
|
} finally {
|
|
67
|
-
await
|
|
66
|
+
await file.close();
|
|
68
67
|
}
|
|
69
68
|
}
|
|
70
69
|
|
|
@@ -80,9 +79,9 @@ export class MetadataStore {
|
|
|
80
79
|
|
|
81
80
|
try {
|
|
82
81
|
const encoded = Buffer.from(schema.getCodecForType('dxos.echo.metadata.EchoMetadata').encode(data));
|
|
83
|
-
await
|
|
82
|
+
await file.write(0, encoded);
|
|
84
83
|
} finally {
|
|
85
|
-
await
|
|
84
|
+
await file.close();
|
|
86
85
|
}
|
|
87
86
|
}
|
|
88
87
|
|
|
@@ -325,12 +325,10 @@ describe('PartyCore', () => {
|
|
|
325
325
|
|
|
326
326
|
createTestProtocolPair(
|
|
327
327
|
new ReplicatorProtocolPluginFactory(
|
|
328
|
-
peer1.partyFeedProvider
|
|
329
|
-
peer1.party.processor.getActiveFeedSet()
|
|
328
|
+
peer1.partyFeedProvider
|
|
330
329
|
).createPlugins().map(r => r.createExtension()),
|
|
331
330
|
new ReplicatorProtocolPluginFactory(
|
|
332
|
-
partyFeedProvider
|
|
333
|
-
peer1.party.processor.getActiveFeedSet()
|
|
331
|
+
partyFeedProvider
|
|
334
332
|
).createPlugins().map(r => r.createExtension())
|
|
335
333
|
);
|
|
336
334
|
|
|
@@ -20,11 +20,6 @@ import { jsonReplacer } from '@dxos/util';
|
|
|
20
20
|
|
|
21
21
|
const log = debug('dxos:echo-db:party-processor');
|
|
22
22
|
|
|
23
|
-
export interface FeedSetProvider {
|
|
24
|
-
get(): FeedKey[]
|
|
25
|
-
added: Event<FeedKey>
|
|
26
|
-
}
|
|
27
|
-
|
|
28
23
|
/**
|
|
29
24
|
* TODO(burdon): Wrapper/Bridge between HALO APIs.
|
|
30
25
|
*/
|
|
@@ -108,14 +103,6 @@ export class PartyProcessor {
|
|
|
108
103
|
return this._state.getAdmittedBy(feedKey);
|
|
109
104
|
}
|
|
110
105
|
|
|
111
|
-
// TODO(burdon): Rename xxxProvider.
|
|
112
|
-
getActiveFeedSet (): FeedSetProvider {
|
|
113
|
-
return {
|
|
114
|
-
get: () => this.feedKeys,
|
|
115
|
-
added: this.feedAdded
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
106
|
getOfflineInvitation (invitationID: Buffer) {
|
|
120
107
|
return this._state.getInvitation(invitationID);
|
|
121
108
|
}
|
|
@@ -19,17 +19,17 @@ export class CredentialsSigner {
|
|
|
19
19
|
|
|
20
20
|
return new CredentialsSigner(
|
|
21
21
|
keyring,
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
identityKey,
|
|
23
|
+
deviceKey,
|
|
24
|
+
deviceKey
|
|
25
25
|
);
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
constructor (
|
|
29
29
|
private readonly _signer: Signer,
|
|
30
|
-
private readonly
|
|
31
|
-
private readonly
|
|
32
|
-
private readonly
|
|
30
|
+
private readonly _identityKey: KeyRecord,
|
|
31
|
+
private readonly _deviceKey: KeyRecord,
|
|
32
|
+
private readonly _signingKeys: KeyRecord | KeyChain
|
|
33
33
|
) {}
|
|
34
34
|
|
|
35
35
|
get signer (): Signer {
|
|
@@ -37,11 +37,11 @@ export class CredentialsSigner {
|
|
|
37
37
|
}
|
|
38
38
|
|
|
39
39
|
getIdentityKey (): KeyRecord {
|
|
40
|
-
return this.
|
|
40
|
+
return this._identityKey;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
43
|
getDeviceKey (): KeyRecord {
|
|
44
|
-
return this.
|
|
44
|
+
return this._deviceKey;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
47
|
/**
|
|
@@ -55,6 +55,6 @@ export class CredentialsSigner {
|
|
|
55
55
|
* Devices need to sign with their keyChain including the device key admission credential in the signature.
|
|
56
56
|
*/
|
|
57
57
|
getDeviceSigningKeys (): KeyRecord | KeyChain {
|
|
58
|
-
return this.
|
|
58
|
+
return this._signingKeys;
|
|
59
59
|
}
|
|
60
60
|
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2022 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { createIdentityInfoMessage, createKeyAdmitMessage, createPartyGenesisMessage, KeyChain, KeyRecord, Keyring, KeyType, SignedMessage } from '@dxos/credentials';
|
|
6
|
+
|
|
7
|
+
import { ContactManager, Preferences } from '../halo';
|
|
8
|
+
import { CredentialsSigner } from './credentials-signer';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Provides access to identity credentials without revealing the underlying mechanism (HALO party).
|
|
12
|
+
*/
|
|
13
|
+
export interface IdentityCredentials {
|
|
14
|
+
keyring: Keyring
|
|
15
|
+
identityKey: KeyRecord
|
|
16
|
+
deviceKey: KeyRecord
|
|
17
|
+
deviceKeyChain: KeyChain
|
|
18
|
+
identityGenesis: SignedMessage
|
|
19
|
+
identityInfo: SignedMessage | undefined
|
|
20
|
+
displayName: string | undefined
|
|
21
|
+
createCredentialsSigner(): CredentialsSigner
|
|
22
|
+
preferences: Preferences | undefined
|
|
23
|
+
contacts: ContactManager | undefined
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type IdentityCredentialsProvider = () => IdentityCredentials | undefined
|
|
27
|
+
|
|
28
|
+
export async function createTestIdentityCredentials (keyring: Keyring): Promise<IdentityCredentials> {
|
|
29
|
+
const identityKey = await keyring.createKeyRecord({ type: KeyType.IDENTITY });
|
|
30
|
+
const deviceKey = await keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
31
|
+
const feedKey = await keyring.createKeyRecord({ type: KeyType.FEED });
|
|
32
|
+
|
|
33
|
+
const partyGenesis = createPartyGenesisMessage(keyring, identityKey, feedKey.publicKey, deviceKey);
|
|
34
|
+
const keyAdmit = createKeyAdmitMessage(keyring, identityKey.publicKey, identityKey);
|
|
35
|
+
|
|
36
|
+
const messageMap = new Map();
|
|
37
|
+
messageMap.set(identityKey.publicKey.toHex(), keyAdmit);
|
|
38
|
+
messageMap.set(deviceKey.publicKey.toHex(), partyGenesis);
|
|
39
|
+
const deviceKeyChain = Keyring.buildKeyChain(deviceKey.publicKey, messageMap, [feedKey.publicKey]);
|
|
40
|
+
|
|
41
|
+
const displayName = identityKey.publicKey.humanize();
|
|
42
|
+
const identityInfo = createIdentityInfoMessage(keyring, displayName, identityKey);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
keyring,
|
|
46
|
+
identityKey,
|
|
47
|
+
deviceKey,
|
|
48
|
+
deviceKeyChain,
|
|
49
|
+
identityGenesis: keyAdmit.payload as SignedMessage,
|
|
50
|
+
identityInfo: identityInfo.payload as SignedMessage,
|
|
51
|
+
displayName,
|
|
52
|
+
createCredentialsSigner: () => new CredentialsSigner(keyring, identityKey, deviceKey, deviceKeyChain),
|
|
53
|
+
preferences: undefined,
|
|
54
|
+
contacts: undefined
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export async function deriveTestDeviceCredentials (identity: IdentityCredentials): Promise<IdentityCredentials> {
|
|
59
|
+
const deviceKey = await identity.keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
60
|
+
const keyAdmit = createKeyAdmitMessage(identity.keyring, identity.identityKey.publicKey, deviceKey, [identity.identityKey]);
|
|
61
|
+
|
|
62
|
+
const messageMap = new Map();
|
|
63
|
+
messageMap.set(identity.identityKey.publicKey.toHex(), identity.identityGenesis);
|
|
64
|
+
messageMap.set(deviceKey.publicKey.toHex(), keyAdmit);
|
|
65
|
+
const deviceKeyChain = Keyring.buildKeyChain(deviceKey.publicKey, messageMap, []);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
...identity,
|
|
69
|
+
deviceKey,
|
|
70
|
+
deviceKeyChain,
|
|
71
|
+
createCredentialsSigner: () => new CredentialsSigner(
|
|
72
|
+
identity.keyring,
|
|
73
|
+
identity.identityKey,
|
|
74
|
+
deviceKey,
|
|
75
|
+
deviceKeyChain
|
|
76
|
+
)
|
|
77
|
+
};
|
|
78
|
+
}
|
|
@@ -6,7 +6,7 @@ import debug from 'debug';
|
|
|
6
6
|
|
|
7
7
|
import { synchronized } from '@dxos/async';
|
|
8
8
|
import { discoveryKey, keyToString, PublicKey } from '@dxos/crypto';
|
|
9
|
-
import { FeedKey,
|
|
9
|
+
import { FeedKey, PartyKey } from '@dxos/echo-protocol';
|
|
10
10
|
import type { HypercoreFeed } from '@dxos/feed-store';
|
|
11
11
|
import { Protocol } from '@dxos/mesh-protocol';
|
|
12
12
|
import { MMSTTopology, NetworkManager, Plugin } from '@dxos/network-manager';
|
|
@@ -32,12 +32,11 @@ export class PartyProtocolFactory {
|
|
|
32
32
|
private readonly _networkManager: NetworkManager,
|
|
33
33
|
private readonly _feedProvider: PartyFeedProvider,
|
|
34
34
|
private readonly _peerId: PublicKey,
|
|
35
|
-
private readonly _credentials: CredentialsProvider
|
|
36
|
-
activeFeeds: FeedSetProvider
|
|
35
|
+
private readonly _credentials: CredentialsProvider
|
|
37
36
|
) {
|
|
38
37
|
// Replication.
|
|
39
38
|
this._replicatorProtocolPluginFactory =
|
|
40
|
-
new ReplicatorProtocolPluginFactory(this._feedProvider
|
|
39
|
+
new ReplicatorProtocolPluginFactory(this._feedProvider);
|
|
41
40
|
}
|
|
42
41
|
|
|
43
42
|
async start (plugins: Plugin[]) {
|
|
@@ -125,34 +124,31 @@ export class PartyProtocolFactory {
|
|
|
125
124
|
*/
|
|
126
125
|
export class ReplicatorProtocolPluginFactory {
|
|
127
126
|
constructor (
|
|
128
|
-
private readonly _feedProvider: PartyFeedProvider
|
|
129
|
-
private readonly _activeFeeds: FeedSetProvider
|
|
127
|
+
private readonly _feedProvider: PartyFeedProvider
|
|
130
128
|
) {}
|
|
131
129
|
|
|
132
130
|
createPlugins () {
|
|
133
131
|
return [
|
|
134
132
|
new Replicator({
|
|
135
133
|
load: async () => {
|
|
136
|
-
const
|
|
137
|
-
log(`Loading feeds: ${
|
|
138
|
-
return
|
|
139
|
-
return { discoveryKey: feed.discoveryKey };
|
|
140
|
-
});
|
|
134
|
+
const feeds = this._feedProvider.getFeeds();
|
|
135
|
+
log(`Loading feeds: ${feeds.map(feed => keyToString(feed.key))}`);
|
|
136
|
+
return feeds.map((feed) => ({ discoveryKey: feed.feed.discoveryKey }));
|
|
141
137
|
},
|
|
142
138
|
|
|
143
139
|
subscribe: (addFeedToReplicatedSet: (feed: any) => void) => {
|
|
144
|
-
return this.
|
|
145
|
-
log(`Adding feed: ${
|
|
146
|
-
|
|
147
|
-
addFeedToReplicatedSet({ discoveryKey: feed.discoveryKey });
|
|
140
|
+
return this._feedProvider.feedOpened.on(async (feed) => {
|
|
141
|
+
log(`Adding feed: ${feed.key.toHex()}`);
|
|
142
|
+
addFeedToReplicatedSet({ discoveryKey: feed.feed.discoveryKey });
|
|
148
143
|
});
|
|
149
144
|
},
|
|
150
145
|
|
|
151
146
|
replicate: async (remoteFeeds, info) => {
|
|
152
147
|
// We can ignore remoteFeeds entirely, since the set of feeds we want to replicate is dictated by the Party.
|
|
153
148
|
// TODO(telackey): Why are we opening feeds? Necessary or belt/braces thinking, or because open party does it?
|
|
154
|
-
|
|
155
|
-
|
|
149
|
+
const feeds = this._feedProvider.getFeeds();
|
|
150
|
+
log(`Replicating: peerId=${info.session}; feeds=${feeds.map(feed => feed.key.toHex())}`);
|
|
151
|
+
return feeds.map(feed => feed.feed);
|
|
156
152
|
}
|
|
157
153
|
})
|
|
158
154
|
];
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
import debug from 'debug';
|
|
7
|
-
import pify from 'pify';
|
|
8
7
|
|
|
9
8
|
import { keyToString } from '@dxos/crypto';
|
|
10
9
|
import { schema, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
@@ -26,12 +25,12 @@ export class SnapshotStore {
|
|
|
26
25
|
const file = this._storage.createOrOpen(partyKey.toHex());
|
|
27
26
|
|
|
28
27
|
try {
|
|
29
|
-
const { size } = await
|
|
28
|
+
const { size } = await file.stat();
|
|
30
29
|
if (size === 0) {
|
|
31
30
|
return undefined;
|
|
32
31
|
}
|
|
33
32
|
|
|
34
|
-
const data = await
|
|
33
|
+
const data = await file.read(0, size);
|
|
35
34
|
return schema.getCodecForType('dxos.echo.snapshot.PartySnapshot').decode(data);
|
|
36
35
|
} catch (err: any) {
|
|
37
36
|
if (err.code === 'ENOENT') {
|
|
@@ -40,7 +39,7 @@ export class SnapshotStore {
|
|
|
40
39
|
throw err;
|
|
41
40
|
}
|
|
42
41
|
} finally {
|
|
43
|
-
await
|
|
42
|
+
await file.close();
|
|
44
43
|
}
|
|
45
44
|
}
|
|
46
45
|
|
|
@@ -50,9 +49,9 @@ export class SnapshotStore {
|
|
|
50
49
|
|
|
51
50
|
try {
|
|
52
51
|
const data = schema.getCodecForType('dxos.echo.snapshot.PartySnapshot').encode(snapshot);
|
|
53
|
-
await
|
|
52
|
+
await file.write(0, Buffer.from(data));
|
|
54
53
|
} finally {
|
|
55
|
-
await
|
|
54
|
+
await file.close();
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
|