@dxos/echo-db 2.33.8 → 2.33.9-dev.d70ac9ee
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/halo/halo-factory.d.ts +1 -1
- package/dist/src/halo/halo-factory.d.ts.map +1 -1
- package/dist/src/halo/halo-factory.js +7 -6
- package/dist/src/halo/halo-factory.js.map +1 -1
- package/dist/src/halo/halo-party.d.ts +4 -6
- package/dist/src/halo/halo-party.d.ts.map +1 -1
- package/dist/src/halo/halo-party.js +10 -4
- package/dist/src/halo/halo-party.js.map +1 -1
- package/dist/src/halo/identity-manager.d.ts.map +1 -1
- package/dist/src/halo/identity-manager.js +8 -2
- package/dist/src/halo/identity-manager.js.map +1 -1
- package/dist/src/halo/party-opener.d.ts.map +1 -1
- package/dist/src/halo/party-opener.js +2 -4
- package/dist/src/halo/party-opener.js.map +1 -1
- package/dist/src/halo/preferences.d.ts.map +1 -1
- package/dist/src/halo/preferences.js +3 -6
- package/dist/src/halo/preferences.js.map +1 -1
- package/dist/src/invitations/greeting-initiator.d.ts +5 -4
- package/dist/src/invitations/greeting-initiator.d.ts.map +1 -1
- package/dist/src/invitations/greeting-initiator.js +2 -2
- package/dist/src/invitations/greeting-initiator.js.map +1 -1
- package/dist/src/invitations/greeting-responder.d.ts +4 -7
- package/dist/src/invitations/greeting-responder.d.ts.map +1 -1
- package/dist/src/invitations/greeting-responder.js +4 -18
- package/dist/src/invitations/greeting-responder.js.map +1 -1
- package/dist/src/invitations/invitation-factory.d.ts +2 -1
- package/dist/src/invitations/invitation-factory.d.ts.map +1 -1
- package/dist/src/invitations/invitation-factory.js +3 -5
- package/dist/src/invitations/invitation-factory.js.map +1 -1
- package/dist/src/packlets/database/data-mirror.test.js +1 -1
- package/dist/src/packlets/database/data-mirror.test.js.map +1 -1
- package/dist/src/packlets/database/item-demuxer.test.js +1 -1
- package/dist/src/packlets/database/item-demuxer.test.js.map +1 -1
- package/dist/src/packlets/database/testing.js +1 -1
- package/dist/src/packlets/database/testing.js.map +1 -1
- package/dist/src/packlets/database/timeframe-clock.d.ts +2 -1
- package/dist/src/packlets/database/timeframe-clock.d.ts.map +1 -1
- package/dist/src/packlets/database/timeframe-clock.js +15 -5
- package/dist/src/packlets/database/timeframe-clock.js.map +1 -1
- package/dist/src/parties/data-party.d.ts +4 -3
- package/dist/src/parties/data-party.d.ts.map +1 -1
- package/dist/src/parties/data-party.js +9 -5
- package/dist/src/parties/data-party.js.map +1 -1
- package/dist/src/parties/data-party.test.js +12 -12
- package/dist/src/parties/data-party.test.js.map +1 -1
- package/dist/src/parties/party-factory.d.ts +2 -4
- package/dist/src/parties/party-factory.d.ts.map +1 -1
- package/dist/src/parties/party-factory.js +11 -8
- package/dist/src/parties/party-factory.js.map +1 -1
- package/dist/src/parties/party-manager.d.ts +1 -1
- package/dist/src/parties/party-manager.d.ts.map +1 -1
- package/dist/src/parties/party-manager.js +13 -13
- package/dist/src/parties/party-manager.js.map +1 -1
- package/dist/src/parties/party-manager.test.js +9 -6
- package/dist/src/parties/party-manager.test.js.map +1 -1
- package/dist/src/pipeline/feed-muxer.js +1 -1
- package/dist/src/pipeline/feed-muxer.js.map +1 -1
- package/dist/src/pipeline/feed-muxer.test.js +2 -2
- package/dist/src/pipeline/feed-muxer.test.js.map +1 -1
- package/dist/src/pipeline/message-selector.d.ts +1 -2
- package/dist/src/pipeline/message-selector.d.ts.map +1 -1
- package/dist/src/pipeline/message-selector.js +4 -31
- package/dist/src/pipeline/message-selector.js.map +1 -1
- package/dist/src/pipeline/metadata-store.d.ts +7 -2
- package/dist/src/pipeline/metadata-store.d.ts.map +1 -1
- package/dist/src/pipeline/metadata-store.js +9 -0
- package/dist/src/pipeline/metadata-store.js.map +1 -1
- package/dist/src/pipeline/party-feed-provider.d.ts +2 -2
- package/dist/src/pipeline/party-feed-provider.d.ts.map +1 -1
- package/dist/src/pipeline/party-feed-provider.js +2 -1
- package/dist/src/pipeline/party-feed-provider.js.map +1 -1
- package/dist/src/pipeline/party-pipeline.d.ts +5 -5
- package/dist/src/pipeline/party-pipeline.d.ts.map +1 -1
- package/dist/src/pipeline/party-pipeline.js +6 -7
- package/dist/src/pipeline/party-pipeline.js.map +1 -1
- package/dist/src/pipeline/party-pipeline.test.js +13 -18
- package/dist/src/pipeline/party-pipeline.test.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/halo/halo-factory.ts +6 -6
- package/src/halo/halo-party.ts +14 -6
- package/src/halo/identity-manager.ts +11 -2
- package/src/halo/party-opener.ts +2 -4
- package/src/halo/preferences.ts +4 -8
- package/src/invitations/greeting-initiator.ts +8 -2
- package/src/invitations/greeting-responder.ts +7 -26
- package/src/invitations/invitation-factory.ts +2 -2
- package/src/packlets/database/data-mirror.test.ts +2 -2
- package/src/packlets/database/item-demuxer.test.ts +2 -2
- package/src/packlets/database/testing.ts +2 -2
- package/src/packlets/database/timeframe-clock.ts +4 -1
- package/src/parties/data-party.test.ts +12 -12
- package/src/parties/data-party.ts +14 -6
- package/src/parties/party-factory.ts +17 -9
- package/src/parties/party-manager.test.ts +9 -6
- package/src/parties/party-manager.ts +14 -12
- package/src/pipeline/feed-muxer.test.ts +2 -2
- package/src/pipeline/feed-muxer.ts +2 -2
- package/src/pipeline/message-selector.ts +4 -35
- package/src/pipeline/metadata-store.ts +15 -2
- package/src/pipeline/party-feed-provider.ts +2 -2
- package/src/pipeline/party-pipeline.test.ts +13 -19
- package/src/pipeline/party-pipeline.ts +13 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/echo-db",
|
|
3
|
-
"version": "2.33.
|
|
3
|
+
"version": "2.33.9-dev.d70ac9ee",
|
|
4
4
|
"description": "ECHO database.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -10,22 +10,22 @@
|
|
|
10
10
|
"src"
|
|
11
11
|
],
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"@dxos/async": "2.33.
|
|
14
|
-
"@dxos/codec-protobuf": "2.33.
|
|
15
|
-
"@dxos/credentials": "2.33.
|
|
16
|
-
"@dxos/crypto": "2.33.
|
|
17
|
-
"@dxos/debug": "2.33.
|
|
18
|
-
"@dxos/echo-protocol": "2.33.
|
|
19
|
-
"@dxos/feed-store": "2.33.
|
|
20
|
-
"@dxos/mesh-protocol": "2.33.
|
|
21
|
-
"@dxos/model-factory": "2.33.
|
|
22
|
-
"@dxos/network-manager": "2.33.
|
|
23
|
-
"@dxos/object-model": "2.33.
|
|
24
|
-
"@dxos/protocol-plugin-presence": "2.33.
|
|
25
|
-
"@dxos/protocol-plugin-replicator": "2.33.
|
|
26
|
-
"@dxos/protocols": "2.33.
|
|
27
|
-
"@dxos/random-access-multi-storage": "2.33.
|
|
28
|
-
"@dxos/util": "2.33.
|
|
13
|
+
"@dxos/async": "2.33.9-dev.d70ac9ee",
|
|
14
|
+
"@dxos/codec-protobuf": "2.33.9-dev.d70ac9ee",
|
|
15
|
+
"@dxos/credentials": "2.33.9-dev.d70ac9ee",
|
|
16
|
+
"@dxos/crypto": "2.33.9-dev.d70ac9ee",
|
|
17
|
+
"@dxos/debug": "2.33.9-dev.d70ac9ee",
|
|
18
|
+
"@dxos/echo-protocol": "2.33.9-dev.d70ac9ee",
|
|
19
|
+
"@dxos/feed-store": "2.33.9-dev.d70ac9ee",
|
|
20
|
+
"@dxos/mesh-protocol": "2.33.9-dev.d70ac9ee",
|
|
21
|
+
"@dxos/model-factory": "2.33.9-dev.d70ac9ee",
|
|
22
|
+
"@dxos/network-manager": "2.33.9-dev.d70ac9ee",
|
|
23
|
+
"@dxos/object-model": "2.33.9-dev.d70ac9ee",
|
|
24
|
+
"@dxos/protocol-plugin-presence": "2.33.9-dev.d70ac9ee",
|
|
25
|
+
"@dxos/protocol-plugin-replicator": "2.33.9-dev.d70ac9ee",
|
|
26
|
+
"@dxos/protocols": "2.33.9-dev.d70ac9ee",
|
|
27
|
+
"@dxos/random-access-multi-storage": "2.33.9-dev.d70ac9ee",
|
|
28
|
+
"@dxos/util": "2.33.9-dev.d70ac9ee",
|
|
29
29
|
"base-x": "~3.0.9",
|
|
30
30
|
"buffer-json-encoding": "^1.0.2",
|
|
31
31
|
"debug": "^4.3.3",
|
package/src/halo/halo-factory.ts
CHANGED
|
@@ -54,17 +54,15 @@ export class HaloFactory {
|
|
|
54
54
|
private readonly _options: PipelineOptions = {}
|
|
55
55
|
) {}
|
|
56
56
|
|
|
57
|
-
async constructParty (
|
|
57
|
+
async constructParty (): Promise<HaloParty> {
|
|
58
58
|
const credentialsSigner = CredentialsSigner.createDirectDeviceSigner(this._keyring);
|
|
59
59
|
const feedProvider = this._feedProviderFactory(credentialsSigner.getIdentityKey().publicKey);
|
|
60
|
-
const writableFeed = await feedProvider.createOrOpenWritableFeed();
|
|
61
60
|
const halo = new HaloParty(
|
|
62
61
|
this._modelFactory,
|
|
63
62
|
this._snapshotStore,
|
|
64
63
|
feedProvider,
|
|
65
64
|
credentialsSigner,
|
|
66
65
|
this._networkManager,
|
|
67
|
-
[...feedHints, writableFeed.key],
|
|
68
66
|
undefined,
|
|
69
67
|
this._options
|
|
70
68
|
);
|
|
@@ -81,10 +79,11 @@ export class HaloFactory {
|
|
|
81
79
|
await this._keyring.createKeyRecord({ type: KeyType.DEVICE });
|
|
82
80
|
|
|
83
81
|
// 1. Create a feed for the HALO.
|
|
84
|
-
const halo = await this.constructParty(
|
|
82
|
+
const halo = await this.constructParty();
|
|
85
83
|
const feedKey = await halo.getWriteFeedKey();
|
|
86
84
|
const feedKeyPair = this._keyring.getKey(feedKey);
|
|
87
85
|
assert(feedKeyPair);
|
|
86
|
+
halo._setGenesisFeedKey(feedKey);
|
|
88
87
|
|
|
89
88
|
// Connect the pipeline.
|
|
90
89
|
await halo.open();
|
|
@@ -193,9 +192,10 @@ export class HaloFactory {
|
|
|
193
192
|
);
|
|
194
193
|
|
|
195
194
|
await initiator.connect();
|
|
196
|
-
const {
|
|
195
|
+
const { genesisFeedKey } = await initiator.redeemInvitation(secretProvider);
|
|
197
196
|
|
|
198
|
-
const halo = await this.constructParty(
|
|
197
|
+
const halo = await this.constructParty();
|
|
198
|
+
halo._setGenesisFeedKey(genesisFeedKey);
|
|
199
199
|
await halo.open();
|
|
200
200
|
|
|
201
201
|
await initiator.destroy();
|
package/src/halo/halo-party.ts
CHANGED
|
@@ -5,12 +5,10 @@
|
|
|
5
5
|
import assert from 'assert';
|
|
6
6
|
|
|
7
7
|
import { Event, synchronized } from '@dxos/async';
|
|
8
|
-
import { KeyHint } from '@dxos/credentials';
|
|
9
8
|
import { timed } from '@dxos/debug';
|
|
10
|
-
import { Timeframe } from '@dxos/echo-protocol';
|
|
11
9
|
import { ModelFactory } from '@dxos/model-factory';
|
|
12
10
|
import { NetworkManager } from '@dxos/network-manager';
|
|
13
|
-
import { PublicKey } from '@dxos/protocols';
|
|
11
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
14
12
|
|
|
15
13
|
import { InvitationAuthenticator, InvitationDescriptor, InvitationFactory, InvitationOptions } from '../invitations';
|
|
16
14
|
import { PARTY_ITEM_TYPE } from '../parties';
|
|
@@ -32,7 +30,7 @@ export const HALO_PARTY_DEVICE_PREFERENCES_TYPE = 'dxos:item/halo/device/prefere
|
|
|
32
30
|
*/
|
|
33
31
|
export interface JoinedParty {
|
|
34
32
|
partyKey: PublicKey,
|
|
35
|
-
|
|
33
|
+
genesisFeed: PublicKey,
|
|
36
34
|
}
|
|
37
35
|
|
|
38
36
|
/**
|
|
@@ -48,13 +46,14 @@ export class HaloParty {
|
|
|
48
46
|
private readonly _contactManager: ContactManager;
|
|
49
47
|
private readonly _preferences: Preferences;
|
|
50
48
|
|
|
49
|
+
private _genesisFeedKey?: PublicKey | undefined;
|
|
50
|
+
|
|
51
51
|
constructor (
|
|
52
52
|
modelFactory: ModelFactory,
|
|
53
53
|
snapshotStore: SnapshotStore,
|
|
54
54
|
private readonly _feedProvider: PartyFeedProvider,
|
|
55
55
|
private readonly _credentialsSigner: CredentialsSigner,
|
|
56
56
|
private readonly _networkManager: NetworkManager,
|
|
57
|
-
private readonly _feedHints: PublicKey[] = [],
|
|
58
57
|
private readonly _initialTimeframe: Timeframe | undefined,
|
|
59
58
|
_options: PipelineOptions
|
|
60
59
|
) {
|
|
@@ -134,6 +133,13 @@ export class HaloParty {
|
|
|
134
133
|
return this._partyCore.processor;
|
|
135
134
|
}
|
|
136
135
|
|
|
136
|
+
/**
|
|
137
|
+
* @internal
|
|
138
|
+
*/
|
|
139
|
+
_setGenesisFeedKey (genesisFeedKey: PublicKey) {
|
|
140
|
+
this._genesisFeedKey = genesisFeedKey;
|
|
141
|
+
}
|
|
142
|
+
|
|
137
143
|
/**
|
|
138
144
|
* Opens the pipeline and connects the streams.
|
|
139
145
|
*/
|
|
@@ -144,13 +150,15 @@ export class HaloParty {
|
|
|
144
150
|
return this;
|
|
145
151
|
}
|
|
146
152
|
|
|
153
|
+
assert(this._genesisFeedKey);
|
|
147
154
|
await this._partyCore.open({
|
|
148
|
-
|
|
155
|
+
genesisFeedKey: this._genesisFeedKey,
|
|
149
156
|
initialTimeframe: this._initialTimeframe
|
|
150
157
|
});
|
|
151
158
|
|
|
152
159
|
this._invitationManager = new InvitationFactory(
|
|
153
160
|
this._partyCore.processor,
|
|
161
|
+
this._genesisFeedKey,
|
|
154
162
|
this._credentialsSigner,
|
|
155
163
|
this._partyCore.credentialsWriter,
|
|
156
164
|
this._networkManager
|
|
@@ -69,9 +69,14 @@ export class IdentityManager {
|
|
|
69
69
|
async loadFromStorage () {
|
|
70
70
|
const identityKey = this.getIdentityKey();
|
|
71
71
|
if (identityKey) {
|
|
72
|
-
|
|
72
|
+
const metadata = this._metadataStore.getParty(identityKey.publicKey);
|
|
73
|
+
if (metadata) {
|
|
73
74
|
// TODO(marik-d): Snapshots for halo party?
|
|
74
|
-
const halo = await this._haloFactory.constructParty(
|
|
75
|
+
const halo = await this._haloFactory.constructParty();
|
|
76
|
+
|
|
77
|
+
assert(metadata.genesisFeedKey);
|
|
78
|
+
halo._setGenesisFeedKey(metadata.genesisFeedKey);
|
|
79
|
+
|
|
75
80
|
// Always open the HALO.
|
|
76
81
|
await halo.open();
|
|
77
82
|
await this._initialize(halo);
|
|
@@ -89,6 +94,10 @@ export class IdentityManager {
|
|
|
89
94
|
assert(!this._identity, 'Identity already initialized.');
|
|
90
95
|
|
|
91
96
|
const halo = await this._haloFactory.createHalo(options);
|
|
97
|
+
|
|
98
|
+
const identityKey = this.getIdentityKey() ?? failUndefined();
|
|
99
|
+
await this._metadataStore.setGenesisFeed(identityKey.publicKey, await halo.getWriteFeedKey());
|
|
100
|
+
|
|
92
101
|
await this._initialize(halo);
|
|
93
102
|
return halo;
|
|
94
103
|
}
|
package/src/halo/party-opener.ts
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import debug from 'debug';
|
|
6
6
|
|
|
7
|
-
import { KeyType } from '@dxos/credentials';
|
|
8
7
|
import { SubscriptionGroup, Unsubscribe } from '@dxos/util';
|
|
9
8
|
|
|
10
9
|
import { PartyManager } from '../parties';
|
|
@@ -25,9 +24,8 @@ export const autoPartyOpener = (preferences: Preferences, partyManager: PartyMan
|
|
|
25
24
|
|
|
26
25
|
for (const partyDesc of values) {
|
|
27
26
|
if (!partyManager.parties.some(x => x.key === partyDesc.partyKey)) {
|
|
28
|
-
log(`Auto-opening new Party from HALO: ${partyDesc.partyKey.toHex()}
|
|
29
|
-
|
|
30
|
-
await partyManager.addParty(partyDesc.partyKey, feedHints);
|
|
27
|
+
log(`Auto-opening new Party from HALO: ${partyDesc.partyKey.toHex()}`);
|
|
28
|
+
await partyManager.addParty(partyDesc.partyKey, partyDesc.genesisFeed);
|
|
31
29
|
}
|
|
32
30
|
}
|
|
33
31
|
}));
|
package/src/halo/preferences.ts
CHANGED
|
@@ -7,7 +7,6 @@ import stableStringify from 'json-stable-stringify';
|
|
|
7
7
|
import defaultsDeep from 'lodash.defaultsdeep';
|
|
8
8
|
|
|
9
9
|
import { Event } from '@dxos/async';
|
|
10
|
-
import { KeyHint } from '@dxos/credentials';
|
|
11
10
|
import { raise } from '@dxos/debug';
|
|
12
11
|
import { ObjectModel } from '@dxos/object-model';
|
|
13
12
|
import { PublicKey } from '@dxos/protocols';
|
|
@@ -151,8 +150,8 @@ export class Preferences {
|
|
|
151
150
|
type: HALO_PARTY_DESCRIPTOR_TYPE,
|
|
152
151
|
props: {
|
|
153
152
|
publicKey: joinedParty.partyKey.asBuffer(),
|
|
154
|
-
|
|
155
|
-
|
|
153
|
+
genesisFeed: joinedParty.genesisFeed.toHex(),
|
|
154
|
+
subscribed: true
|
|
156
155
|
}
|
|
157
156
|
});
|
|
158
157
|
}
|
|
@@ -160,12 +159,9 @@ export class Preferences {
|
|
|
160
159
|
subscribeToJoinedPartyList (callback: (parties: JoinedParty[]) => void): () => void {
|
|
161
160
|
const database = this._getDatabase() ?? raise(new IdentityNotInitializedError());
|
|
162
161
|
|
|
163
|
-
const converter = (partyDesc: Item<any>) => ({
|
|
162
|
+
const converter = (partyDesc: Item<any>): JoinedParty => ({
|
|
164
163
|
partyKey: PublicKey.from(partyDesc.model.get('publicKey')),
|
|
165
|
-
|
|
166
|
-
...hint,
|
|
167
|
-
publicKey: PublicKey.from(hint.publicKey)
|
|
168
|
-
} as KeyHint))
|
|
164
|
+
genesisFeed: PublicKey.from(partyDesc.model.get('genesisFeed'))
|
|
169
165
|
});
|
|
170
166
|
|
|
171
167
|
const result = database.select({ type: HALO_PARTY_DESCRIPTOR_TYPE }).exec();
|
|
@@ -35,6 +35,11 @@ const log = debug('dxos:echo-db:greeting-initiator');
|
|
|
35
35
|
|
|
36
36
|
const DEFAULT_TIMEOUT = 30_000;
|
|
37
37
|
|
|
38
|
+
export interface InvitationResult {
|
|
39
|
+
partyKey: PublicKey;
|
|
40
|
+
genesisFeedKey: PublicKey
|
|
41
|
+
}
|
|
42
|
+
|
|
38
43
|
/**
|
|
39
44
|
* Attempts to connect to a greeting responder to 'redeem' an invitation, potentially with some out-of-band
|
|
40
45
|
* authentication check, in order to be admitted to a Party.
|
|
@@ -112,7 +117,7 @@ export class GreetingInitiator {
|
|
|
112
117
|
/**
|
|
113
118
|
* Called after connecting to initiate greeting protocol exchange.
|
|
114
119
|
*/
|
|
115
|
-
async redeemInvitation (secretProvider: SecretProvider): Promise<
|
|
120
|
+
async redeemInvitation (secretProvider: SecretProvider): Promise<InvitationResult> {
|
|
116
121
|
assert(this._state === GreetingState.CONNECTED);
|
|
117
122
|
const { swarmKey } = this._invitationDescriptor;
|
|
118
123
|
|
|
@@ -170,9 +175,10 @@ export class GreetingInitiator {
|
|
|
170
175
|
await this.disconnect();
|
|
171
176
|
|
|
172
177
|
this._state = GreetingState.SUCCEEDED;
|
|
178
|
+
assert(notarizeResponse.genesisFeed);
|
|
173
179
|
return {
|
|
174
180
|
partyKey,
|
|
175
|
-
|
|
181
|
+
genesisFeedKey: notarizeResponse.genesisFeed
|
|
176
182
|
};
|
|
177
183
|
}
|
|
178
184
|
|
|
@@ -9,12 +9,11 @@ import { Event, waitForCondition } from '@dxos/async';
|
|
|
9
9
|
import {
|
|
10
10
|
admitsKeys,
|
|
11
11
|
createEnvelopeMessage, Greeter,
|
|
12
|
-
GreetingCommandPlugin,
|
|
12
|
+
GreetingCommandPlugin,
|
|
13
13
|
Keyring,
|
|
14
|
-
KeyType,
|
|
15
14
|
SecretProvider,
|
|
16
|
-
SecretValidator
|
|
17
|
-
|
|
15
|
+
SecretValidator,
|
|
16
|
+
Message as HaloMessage
|
|
18
17
|
} from '@dxos/credentials';
|
|
19
18
|
import { randomBytes } from '@dxos/crypto';
|
|
20
19
|
import { FeedWriter, SwarmKey } from '@dxos/echo-protocol';
|
|
@@ -60,13 +59,14 @@ export class GreetingResponder {
|
|
|
60
59
|
constructor (
|
|
61
60
|
private readonly _networkManager: NetworkManager,
|
|
62
61
|
private readonly _partyProcessor: PartyStateProvider,
|
|
62
|
+
private readonly _genesisFeedKey: PublicKey,
|
|
63
63
|
private readonly _credentialsSigner: CredentialsSigner,
|
|
64
64
|
private readonly _credentialsWriter: FeedWriter<HaloMessage>
|
|
65
65
|
) {
|
|
66
66
|
this._greeter = new Greeter(
|
|
67
67
|
this._partyProcessor.partyKey,
|
|
68
|
-
|
|
69
|
-
async () => this.
|
|
68
|
+
this._genesisFeedKey,
|
|
69
|
+
async (messages: any) => this._writeCredentialsToParty(messages)
|
|
70
70
|
);
|
|
71
71
|
|
|
72
72
|
this._greeterPlugin = new GreetingCommandPlugin(Buffer.from(this._swarmKey), this._greeter.createMessageHandler());
|
|
@@ -210,6 +210,7 @@ export class GreetingResponder {
|
|
|
210
210
|
// Place the self-signed messages inside an Envelope, sign then write the signed Envelope to the Party.
|
|
211
211
|
const envelopes = [];
|
|
212
212
|
for (const message of messages) {
|
|
213
|
+
// TODO(dmaretskyi): Refactor to pass in a callback: `await admitKeys(messages)`.
|
|
213
214
|
const admittedKeys = admitsKeys(message);
|
|
214
215
|
|
|
215
216
|
// TODO(telackey): Add hasKey/isMember to PartyProcessor?
|
|
@@ -238,24 +239,4 @@ export class GreetingResponder {
|
|
|
238
239
|
// Return the signed messages to the caller because copies are sent back to the invitee.
|
|
239
240
|
return envelopes;
|
|
240
241
|
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Callback to gather member key and feed "hints" for the Invitee.
|
|
244
|
-
* @private
|
|
245
|
-
*/
|
|
246
|
-
_gatherHints (): KeyHint[] {
|
|
247
|
-
assert(this._state === GreetingState.SUCCEEDED);
|
|
248
|
-
|
|
249
|
-
const memberKeys = this._partyProcessor.memberKeys.map((publicKey) => ({
|
|
250
|
-
publicKey,
|
|
251
|
-
type: KeyType.UNKNOWN
|
|
252
|
-
}));
|
|
253
|
-
|
|
254
|
-
const memberFeeds = this._partyProcessor.feedKeys.map((publicKey) => ({
|
|
255
|
-
publicKey,
|
|
256
|
-
type: KeyType.FEED
|
|
257
|
-
}));
|
|
258
|
-
|
|
259
|
-
return [...memberKeys, ...memberFeeds];
|
|
260
|
-
}
|
|
261
242
|
}
|
|
@@ -21,8 +21,7 @@ import { InvitationDescriptor, InvitationDescriptorType } from './invitation-des
|
|
|
21
21
|
export class InvitationFactory {
|
|
22
22
|
constructor (
|
|
23
23
|
private readonly _partyProcessor: PartyStateProvider,
|
|
24
|
-
|
|
25
|
-
// Then the identity would be changed after this is instantiated.
|
|
24
|
+
private readonly _genesisFeedKey: PublicKey,
|
|
26
25
|
private readonly _credentialsSigner: CredentialsSigner,
|
|
27
26
|
private readonly _credentialsWriter: FeedWriter<HaloMessage>,
|
|
28
27
|
private readonly _networkManager: NetworkManager
|
|
@@ -62,6 +61,7 @@ export class InvitationFactory {
|
|
|
62
61
|
const responder = new GreetingResponder(
|
|
63
62
|
this._networkManager,
|
|
64
63
|
this._partyProcessor,
|
|
64
|
+
this._genesisFeedKey,
|
|
65
65
|
this._credentialsSigner,
|
|
66
66
|
this._credentialsWriter
|
|
67
67
|
);
|
|
@@ -6,10 +6,10 @@ import expect from 'expect';
|
|
|
6
6
|
import { it as test } from 'mocha';
|
|
7
7
|
|
|
8
8
|
import { promiseTimeout } from '@dxos/async';
|
|
9
|
-
import { EchoEnvelope, MockFeedWriter
|
|
9
|
+
import { EchoEnvelope, MockFeedWriter } from '@dxos/echo-protocol';
|
|
10
10
|
import { ModelFactory } from '@dxos/model-factory';
|
|
11
11
|
import { ObjectModel } from '@dxos/object-model';
|
|
12
|
-
import { PublicKey } from '@dxos/protocols';
|
|
12
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
13
13
|
|
|
14
14
|
import { DataMirror } from './data-mirror';
|
|
15
15
|
import { DataServiceHost } from './data-service-host';
|
|
@@ -9,10 +9,10 @@ import { it as test } from 'mocha';
|
|
|
9
9
|
import { latch } from '@dxos/async';
|
|
10
10
|
import { createId } from '@dxos/crypto';
|
|
11
11
|
import { checkType } from '@dxos/debug';
|
|
12
|
-
import { EchoEnvelope, MockFeedWriter
|
|
12
|
+
import { EchoEnvelope, MockFeedWriter } from '@dxos/echo-protocol';
|
|
13
13
|
import { ModelFactory, TestModel } from '@dxos/model-factory';
|
|
14
14
|
import { ObjectModel } from '@dxos/object-model';
|
|
15
|
-
import { PublicKey } from '@dxos/protocols';
|
|
15
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
16
16
|
|
|
17
17
|
import { Item } from './item';
|
|
18
18
|
import { ItemDemuxer } from './item-demuxer';
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// Copyright 2021 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import { EchoEnvelope, MockFeedWriter
|
|
5
|
+
import { EchoEnvelope, MockFeedWriter } from '@dxos/echo-protocol';
|
|
6
6
|
import { ModelFactory } from '@dxos/model-factory';
|
|
7
|
-
import { PublicKey } from '@dxos/protocols';
|
|
7
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
8
8
|
|
|
9
9
|
import { DataServiceHost } from './data-service-host';
|
|
10
10
|
import { DataServiceRouter } from './data-service-router';
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Event } from '@dxos/async';
|
|
6
|
-
import {
|
|
6
|
+
import { timed } from '@dxos/debug';
|
|
7
|
+
import { FeedKey } from '@dxos/echo-protocol';
|
|
8
|
+
import { Timeframe } from '@dxos/protocols';
|
|
7
9
|
|
|
8
10
|
/**
|
|
9
11
|
* Keeps state of the last timeframe that was processed by ECHO.
|
|
@@ -29,6 +31,7 @@ export class TimeframeClock {
|
|
|
29
31
|
return !gaps.isEmpty();
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
@timed(5_000)
|
|
32
35
|
async waitUntilReached (target: Timeframe) {
|
|
33
36
|
await this.update.waitForCondition(() => Timeframe.dependencies(target, this._timeframe).isEmpty());
|
|
34
37
|
}
|
|
@@ -22,7 +22,7 @@ import { SnapshotStore } from '../snapshots';
|
|
|
22
22
|
import { DataParty } from './data-party';
|
|
23
23
|
|
|
24
24
|
describe('DataParty', () => {
|
|
25
|
-
const createParty = async (identity: IdentityCredentials, partyKey: PublicKey,
|
|
25
|
+
const createParty = async (identity: IdentityCredentials, partyKey: PublicKey, genesisFeedKey?: PublicKey) => {
|
|
26
26
|
|
|
27
27
|
const storage = createStorage('', StorageType.RAM);
|
|
28
28
|
const snapshotStore = new SnapshotStore(storage.directory('snapshots'));
|
|
@@ -43,7 +43,7 @@ describe('DataParty', () => {
|
|
|
43
43
|
identity.preferences,
|
|
44
44
|
networkManager
|
|
45
45
|
);
|
|
46
|
-
party.
|
|
46
|
+
party._setGenesisFeedKey(genesisFeedKey ?? writableFeed.key);
|
|
47
47
|
return party;
|
|
48
48
|
};
|
|
49
49
|
|
|
@@ -51,7 +51,7 @@ describe('DataParty', () => {
|
|
|
51
51
|
const keyring = new Keyring();
|
|
52
52
|
const identity = await createTestIdentityCredentials(keyring);
|
|
53
53
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
54
|
-
const party = await createParty(identity, partyKey.publicKey
|
|
54
|
+
const party = await createParty(identity, partyKey.publicKey);
|
|
55
55
|
|
|
56
56
|
await party.open();
|
|
57
57
|
await party.close();
|
|
@@ -61,7 +61,7 @@ describe('DataParty', () => {
|
|
|
61
61
|
const keyring = new Keyring();
|
|
62
62
|
const identity = await createTestIdentityCredentials(keyring);
|
|
63
63
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
64
|
-
const party = await createParty(identity, partyKey.publicKey
|
|
64
|
+
const party = await createParty(identity, partyKey.publicKey);
|
|
65
65
|
await party.open();
|
|
66
66
|
|
|
67
67
|
const feed = await party.getWriteFeed();
|
|
@@ -81,7 +81,7 @@ describe('DataParty', () => {
|
|
|
81
81
|
const keyring = new Keyring();
|
|
82
82
|
const identity = await createTestIdentityCredentials(keyring);
|
|
83
83
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
84
|
-
const party = await createParty(identity, partyKey.publicKey
|
|
84
|
+
const party = await createParty(identity, partyKey.publicKey);
|
|
85
85
|
await party.open();
|
|
86
86
|
|
|
87
87
|
const feed = await party.getWriteFeed();
|
|
@@ -109,7 +109,7 @@ describe('DataParty', () => {
|
|
|
109
109
|
const identity = await createTestIdentityCredentials(keyring);
|
|
110
110
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
111
111
|
|
|
112
|
-
const party = await createParty(identity, partyKey.publicKey
|
|
112
|
+
const party = await createParty(identity, partyKey.publicKey);
|
|
113
113
|
await party.open();
|
|
114
114
|
const feed = await party.getWriteFeed();
|
|
115
115
|
await party.credentialsWriter.write(createPartyGenesisMessage(
|
|
@@ -134,7 +134,7 @@ describe('DataParty', () => {
|
|
|
134
134
|
const identityA = await createTestIdentityCredentials(keyring);
|
|
135
135
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
136
136
|
|
|
137
|
-
const party = await createParty(identityA, partyKey.publicKey
|
|
137
|
+
const party = await createParty(identityA, partyKey.publicKey);
|
|
138
138
|
await party.open();
|
|
139
139
|
const feed = await party.getWriteFeed();
|
|
140
140
|
await party.credentialsWriter.write(createPartyGenesisMessage(
|
|
@@ -161,7 +161,7 @@ describe('DataParty', () => {
|
|
|
161
161
|
const identityA = await createTestIdentityCredentials(keyring);
|
|
162
162
|
const partyKey = await keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
163
163
|
|
|
164
|
-
const partyA = await createParty(identityA, partyKey.publicKey
|
|
164
|
+
const partyA = await createParty(identityA, partyKey.publicKey);
|
|
165
165
|
await partyA.open();
|
|
166
166
|
const feedA = await partyA.getWriteFeed();
|
|
167
167
|
await partyA.credentialsWriter.write(createPartyGenesisMessage(
|
|
@@ -178,7 +178,7 @@ describe('DataParty', () => {
|
|
|
178
178
|
));
|
|
179
179
|
|
|
180
180
|
const identityB = await deriveTestDeviceCredentials(identityA);
|
|
181
|
-
const partyB = await createParty(identityB, partyKey.publicKey,
|
|
181
|
+
const partyB = await createParty(identityB, partyKey.publicKey, feedA.key);
|
|
182
182
|
await partyB.open();
|
|
183
183
|
|
|
184
184
|
await partyA.database.createItem({ type: 'test:item-a' });
|
|
@@ -195,7 +195,7 @@ describe('DataParty', () => {
|
|
|
195
195
|
const identityA = await createTestIdentityCredentials(new Keyring());
|
|
196
196
|
const partyKeyA = await identityA.keyring.createKeyRecord({ type: KeyType.PARTY });
|
|
197
197
|
|
|
198
|
-
const partyA = await createParty(identityA, partyKeyA.publicKey
|
|
198
|
+
const partyA = await createParty(identityA, partyKeyA.publicKey);
|
|
199
199
|
await partyA.open();
|
|
200
200
|
const feedA = await partyA.getWriteFeed();
|
|
201
201
|
await partyA.credentialsWriter.write(createPartyGenesisMessage(
|
|
@@ -226,9 +226,9 @@ describe('DataParty', () => {
|
|
|
226
226
|
);
|
|
227
227
|
|
|
228
228
|
await initiator.connect();
|
|
229
|
-
const { partyKey: partyKeyB,
|
|
229
|
+
const { partyKey: partyKeyB, genesisFeedKey } = await initiator.redeemInvitation(defaultSecretProvider);
|
|
230
230
|
expect(partyKeyB.equals(partyKeyA.publicKey));
|
|
231
|
-
const partyB = await createParty(identityB, partyKeyB,
|
|
231
|
+
const partyB = await createParty(identityB, partyKeyB, genesisFeedKey);
|
|
232
232
|
await partyB.open();
|
|
233
233
|
await initiator.destroy();
|
|
234
234
|
|
|
@@ -6,12 +6,12 @@ import assert from 'assert';
|
|
|
6
6
|
|
|
7
7
|
import { synchronized, Event } from '@dxos/async';
|
|
8
8
|
import { timed } from '@dxos/debug';
|
|
9
|
-
import { PartyKey, PartySnapshot
|
|
9
|
+
import { PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
10
10
|
import { FeedDescriptor } from '@dxos/feed-store';
|
|
11
11
|
import { ModelFactory } from '@dxos/model-factory';
|
|
12
12
|
import { NetworkManager } from '@dxos/network-manager';
|
|
13
13
|
import { ObjectModel } from '@dxos/object-model';
|
|
14
|
-
import { PublicKey } from '@dxos/protocols';
|
|
14
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
15
15
|
|
|
16
16
|
import { ResultSet } from '../api';
|
|
17
17
|
import { ActivationOptions, PartyPreferences, Preferences } from '../halo';
|
|
@@ -46,7 +46,8 @@ export class DataParty {
|
|
|
46
46
|
private readonly _preferences?: PartyPreferences;
|
|
47
47
|
private _invitationManager?: InvitationFactory;
|
|
48
48
|
private _protocol?: PartyProtocolFactory;
|
|
49
|
-
|
|
49
|
+
|
|
50
|
+
private _genesisFeedKey?: PublicKey | undefined;
|
|
50
51
|
|
|
51
52
|
constructor (
|
|
52
53
|
partyKey: PartyKey,
|
|
@@ -141,11 +142,16 @@ export class DataParty {
|
|
|
141
142
|
await this._preferences?.setLastKnownTitle(title);
|
|
142
143
|
}
|
|
143
144
|
|
|
145
|
+
get genesisFeedKey () {
|
|
146
|
+
assert(this._genesisFeedKey);
|
|
147
|
+
return this._genesisFeedKey;
|
|
148
|
+
}
|
|
149
|
+
|
|
144
150
|
/**
|
|
145
151
|
* @internal
|
|
146
152
|
*/
|
|
147
|
-
|
|
148
|
-
this.
|
|
153
|
+
_setGenesisFeedKey (genesisFeedKey: PublicKey) {
|
|
154
|
+
this._genesisFeedKey = genesisFeedKey;
|
|
149
155
|
}
|
|
150
156
|
|
|
151
157
|
/**
|
|
@@ -161,8 +167,9 @@ export class DataParty {
|
|
|
161
167
|
// TODO(dmaretskyi): May be undefined in some tests.
|
|
162
168
|
const party = this._metadataStore.getParty(this._partyCore.key);
|
|
163
169
|
|
|
170
|
+
assert(this._genesisFeedKey);
|
|
164
171
|
await this._partyCore.open({
|
|
165
|
-
|
|
172
|
+
genesisFeedKey: this._genesisFeedKey,
|
|
166
173
|
initialTimeframe: this._initialTimeframe,
|
|
167
174
|
targetTimeframe: party?.latestTimeframe
|
|
168
175
|
});
|
|
@@ -175,6 +182,7 @@ export class DataParty {
|
|
|
175
182
|
|
|
176
183
|
this._invitationManager = new InvitationFactory(
|
|
177
184
|
this._partyCore.processor,
|
|
185
|
+
this._genesisFeedKey,
|
|
178
186
|
this._credentialsSigner,
|
|
179
187
|
this._partyCore.credentialsWriter,
|
|
180
188
|
this._networkManager
|
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
wrapMessage
|
|
15
15
|
} from '@dxos/credentials';
|
|
16
16
|
import { failUndefined, raise, timed } from '@dxos/debug';
|
|
17
|
-
import { createFeedWriter, FeedMessage, PartyKey, PartySnapshot
|
|
17
|
+
import { createFeedWriter, FeedMessage, PartyKey, PartySnapshot } from '@dxos/echo-protocol';
|
|
18
18
|
import { ModelFactory } from '@dxos/model-factory';
|
|
19
19
|
import { NetworkManager } from '@dxos/network-manager';
|
|
20
20
|
import { ObjectModel } from '@dxos/object-model';
|
|
21
|
-
import { PublicKey } from '@dxos/protocols';
|
|
21
|
+
import { PublicKey, Timeframe } from '@dxos/protocols';
|
|
22
22
|
import { humanize } from '@dxos/util';
|
|
23
23
|
|
|
24
24
|
import {
|
|
@@ -59,8 +59,10 @@ export class PartyFactory {
|
|
|
59
59
|
const party = await this.constructParty(partyKey.publicKey);
|
|
60
60
|
|
|
61
61
|
const writableFeed = await party.getWriteFeed();
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
party._setGenesisFeedKey(writableFeed.key);
|
|
63
|
+
|
|
64
|
+
await this._metadataStore.addParty(partyKey.publicKey);
|
|
65
|
+
await this._metadataStore.setGenesisFeed(partyKey.publicKey, writableFeed.key);
|
|
64
66
|
|
|
65
67
|
// Connect the pipeline.
|
|
66
68
|
await party.open();
|
|
@@ -111,8 +113,6 @@ export class PartyFactory {
|
|
|
111
113
|
|
|
112
114
|
/**
|
|
113
115
|
* Constructs a party object from an existing set of feeds.
|
|
114
|
-
* @param partyKey
|
|
115
|
-
* @param hints
|
|
116
116
|
*/
|
|
117
117
|
async constructParty (partyKey: PartyKey, initialTimeframe?: Timeframe) {
|
|
118
118
|
const identity = this._identityProvider() ?? raise(new IdentityNotInitializedError());
|
|
@@ -172,9 +172,14 @@ export class PartyFactory {
|
|
|
172
172
|
);
|
|
173
173
|
|
|
174
174
|
await initiator.connect();
|
|
175
|
-
const { partyKey,
|
|
175
|
+
const { partyKey, genesisFeedKey } = await initiator.redeemInvitation(secretProvider);
|
|
176
176
|
const party = await this.constructParty(partyKey);
|
|
177
|
-
|
|
177
|
+
|
|
178
|
+
await this._metadataStore.addParty(partyKey);
|
|
179
|
+
await this._metadataStore.setGenesisFeed(partyKey, genesisFeedKey);
|
|
180
|
+
|
|
181
|
+
party._setGenesisFeedKey(genesisFeedKey);
|
|
182
|
+
|
|
178
183
|
await party.open();
|
|
179
184
|
await initiator.destroy();
|
|
180
185
|
|
|
@@ -201,7 +206,10 @@ export class PartyFactory {
|
|
|
201
206
|
|
|
202
207
|
const writableFeed = await party.getWriteFeed();
|
|
203
208
|
// Hint at the newly created writable feed so that we can start replicating from it.
|
|
204
|
-
party.
|
|
209
|
+
party._setGenesisFeedKey(writableFeed.key);
|
|
210
|
+
|
|
211
|
+
await this._metadataStore.addParty(partyKey.publicKey);
|
|
212
|
+
await this._metadataStore.setGenesisFeed(partyKey.publicKey, writableFeed.key);
|
|
205
213
|
|
|
206
214
|
// Connect the pipeline.
|
|
207
215
|
await party.open();
|