@plane31/blind-relay 0.0.0-stage → 0.1.1
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/LICENSE +202 -0
- package/README.md +26 -2
- package/dist/adapters/index.d.ts +18 -0
- package/dist/adapters/index.d.ts.map +1 -0
- package/dist/adapters/index.js +22 -0
- package/dist/adapters/index.js.map +1 -0
- package/dist/audience.d.ts +77 -0
- package/dist/audience.d.ts.map +1 -0
- package/dist/audience.js +76 -0
- package/dist/audience.js.map +1 -0
- package/dist/bytes.d.ts +54 -0
- package/dist/bytes.d.ts.map +1 -0
- package/dist/bytes.js +200 -0
- package/dist/bytes.js.map +1 -0
- package/dist/circle.d.ts +59 -0
- package/dist/circle.d.ts.map +1 -0
- package/dist/circle.js +105 -0
- package/dist/circle.js.map +1 -0
- package/dist/client.d.ts +234 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1365 -0
- package/dist/client.js.map +1 -0
- package/dist/codec.d.ts +189 -0
- package/dist/codec.d.ts.map +1 -0
- package/dist/codec.js +512 -0
- package/dist/codec.js.map +1 -0
- package/dist/crypto/backend.d.ts +39 -0
- package/dist/crypto/backend.d.ts.map +1 -0
- package/dist/crypto/backend.js +8 -0
- package/dist/crypto/backend.js.map +1 -0
- package/dist/crypto/noble.d.ts +3 -0
- package/dist/crypto/noble.d.ts.map +1 -0
- package/dist/crypto/noble.js +107 -0
- package/dist/crypto/noble.js.map +1 -0
- package/dist/crypto/sodium.d.ts +7 -0
- package/dist/crypto/sodium.d.ts.map +1 -0
- package/dist/crypto/sodium.js +39 -0
- package/dist/crypto/sodium.js.map +1 -0
- package/dist/crypto.d.ts +66 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +225 -0
- package/dist/crypto.js.map +1 -0
- package/dist/epoch.d.ts +93 -0
- package/dist/epoch.d.ts.map +1 -0
- package/dist/epoch.js +121 -0
- package/dist/epoch.js.map +1 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +30 -0
- package/dist/errors.js.map +1 -0
- package/dist/historyIndex.d.ts +15 -0
- package/dist/historyIndex.d.ts.map +1 -0
- package/dist/historyIndex.js +57 -0
- package/dist/historyIndex.js.map +1 -0
- package/dist/identity.d.ts +62 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +99 -0
- package/dist/identity.js.map +1 -0
- package/dist/inbox.d.ts +153 -0
- package/dist/inbox.d.ts.map +1 -0
- package/dist/inbox.js +472 -0
- package/dist/inbox.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/outbox.d.ts +96 -0
- package/dist/outbox.d.ts.map +1 -0
- package/dist/outbox.js +339 -0
- package/dist/outbox.js.map +1 -0
- package/dist/policy.d.ts +33 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +71 -0
- package/dist/policy.js.map +1 -0
- package/dist/record.d.ts +49 -0
- package/dist/record.d.ts.map +1 -0
- package/dist/record.js +46 -0
- package/dist/record.js.map +1 -0
- package/dist/reset.d.ts +74 -0
- package/dist/reset.d.ts.map +1 -0
- package/dist/reset.js +127 -0
- package/dist/reset.js.map +1 -0
- package/dist/rows.d.ts +16 -0
- package/dist/rows.d.ts.map +1 -0
- package/dist/rows.js +103 -0
- package/dist/rows.js.map +1 -0
- package/dist/slots.d.ts +22 -0
- package/dist/slots.d.ts.map +1 -0
- package/dist/slots.js +38 -0
- package/dist/slots.js.map +1 -0
- package/dist/store.d.ts +357 -0
- package/dist/store.d.ts.map +1 -0
- package/dist/store.js +192 -0
- package/dist/store.js.map +1 -0
- package/dist/testing/clock.d.ts +14 -0
- package/dist/testing/clock.d.ts.map +1 -0
- package/dist/testing/clock.js +27 -0
- package/dist/testing/clock.js.map +1 -0
- package/dist/testing/fakeHost.d.ts +118 -0
- package/dist/testing/fakeHost.d.ts.map +1 -0
- package/dist/testing/fakeHost.js +462 -0
- package/dist/testing/fakeHost.js.map +1 -0
- package/dist/testing/faults.d.ts +97 -0
- package/dist/testing/faults.d.ts.map +1 -0
- package/dist/testing/faults.js +264 -0
- package/dist/testing/faults.js.map +1 -0
- package/dist/testing/fixtures.d.ts +15 -0
- package/dist/testing/fixtures.d.ts.map +1 -0
- package/dist/testing/fixtures.js +22 -0
- package/dist/testing/fixtures.js.map +1 -0
- package/dist/testing/index.d.ts +7 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +7 -0
- package/dist/testing/index.js.map +1 -0
- package/dist/testing/providers.d.ts +16 -0
- package/dist/testing/providers.d.ts.map +1 -0
- package/dist/testing/providers.js +36 -0
- package/dist/testing/providers.js.map +1 -0
- package/dist/testing/sweep.d.ts +46 -0
- package/dist/testing/sweep.d.ts.map +1 -0
- package/dist/testing/sweep.js +366 -0
- package/dist/testing/sweep.js.map +1 -0
- package/dist/transactions.d.ts +75 -0
- package/dist/transactions.d.ts.map +1 -0
- package/dist/transactions.js +212 -0
- package/dist/transactions.js.map +1 -0
- package/dist/transport.d.ts +125 -0
- package/dist/transport.d.ts.map +1 -0
- package/dist/transport.js +6 -0
- package/dist/transport.js.map +1 -0
- package/dist/vault.d.ts +59 -0
- package/dist/vault.d.ts.map +1 -0
- package/dist/vault.js +69 -0
- package/dist/vault.js.map +1 -0
- package/package.json +66 -3
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The crash and lost-response sweeps of build step 16. One scenario (two accounts, a circle,
|
|
3
|
+
* records of a slot kind both ways, an event kind, concurrent contexts, a device replacement) runs once with no
|
|
4
|
+
* fault to count the victim's transaction boundaries, then once per boundary and phase with the
|
|
5
|
+
* victim's process crashing there, restarting, and finishing the scenario. After every run the
|
|
6
|
+
* durable-state outcomes of protocol section 11 are checked against the host's view.
|
|
7
|
+
*/
|
|
8
|
+
import { fromHex, toHex } from "../bytes.js";
|
|
9
|
+
import { open } from "../client.js";
|
|
10
|
+
import { KavachError } from "../errors.js";
|
|
11
|
+
import { MemorySecretStore } from "../store.js";
|
|
12
|
+
import { TestClock, testPolicy } from "./clock.js";
|
|
13
|
+
import { FakeHost } from "./fakeHost.js";
|
|
14
|
+
import { FaultyStore, MaliciousTransport } from "./faults.js";
|
|
15
|
+
import { testResetKeyList, testResetKeys } from "./fixtures.js";
|
|
16
|
+
import { MemoryPlatformProvider } from "./providers.js";
|
|
17
|
+
const resetKeys = testResetKeys();
|
|
18
|
+
const resetTrust = { managementKey: resetKeys.management.publicKey, minimumVersion: 1n };
|
|
19
|
+
function newHost() {
|
|
20
|
+
const host = new FakeHost();
|
|
21
|
+
const clock = new TestClock();
|
|
22
|
+
host.now = clock.now;
|
|
23
|
+
host.resetSigner = { key: resetKeys.operational, keyId: resetKeys.operationalKeyId };
|
|
24
|
+
host.resetKeyList = testResetKeyList(resetKeys, clock.now());
|
|
25
|
+
return { host, clock };
|
|
26
|
+
}
|
|
27
|
+
function accountOf(name) {
|
|
28
|
+
return name === "bob2" ? "bob" : name;
|
|
29
|
+
}
|
|
30
|
+
/** The transport of a device: bound to the account's current certificate at the host on every call. */
|
|
31
|
+
export function hostTransport(host, account) {
|
|
32
|
+
const bind = () => {
|
|
33
|
+
const acct = host.accounts.get(account);
|
|
34
|
+
return host.asDevice(account, acct ? fromHex(acct.certificateHash) : new Uint8Array(32));
|
|
35
|
+
};
|
|
36
|
+
return {
|
|
37
|
+
get directory() {
|
|
38
|
+
return bind().directory;
|
|
39
|
+
},
|
|
40
|
+
get relay() {
|
|
41
|
+
return bind().relay;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
async function openDevice(rt, name, store, secrets, provider, transport) {
|
|
46
|
+
const events = [];
|
|
47
|
+
const client = await open({ accountName: accountOf(name), retentionPolicy: testPolicy, recoveryProvider: provider, resetTrust, secretStore: secrets, store, transport, now: rt.clock.now });
|
|
48
|
+
client.subscribe((e) => events.push(e));
|
|
49
|
+
const d = { name, client, store, secrets, events, provider, transport };
|
|
50
|
+
rt.devices.set(name, d);
|
|
51
|
+
return d;
|
|
52
|
+
}
|
|
53
|
+
function scenario(rt, stores, run) {
|
|
54
|
+
const d = (n) => {
|
|
55
|
+
const x = rt.devices.get(n);
|
|
56
|
+
if (!x)
|
|
57
|
+
throw new Error("no device " + n);
|
|
58
|
+
return x;
|
|
59
|
+
};
|
|
60
|
+
let circleId = new Uint8Array(16);
|
|
61
|
+
let aliceId = new Uint8Array(32);
|
|
62
|
+
// Distinct opaque payloads with the clock as the event time: the sweep needs bytes, not a codec.
|
|
63
|
+
const loc = (n) => [Uint8Array.of(1, n), { eventTime: rt.clock.now() }];
|
|
64
|
+
const sync = (n) => async () => {
|
|
65
|
+
rt.clock.advance(1000n);
|
|
66
|
+
return d(n).client.sync();
|
|
67
|
+
};
|
|
68
|
+
const steps = [
|
|
69
|
+
{ name: "alice.init", run: () => d("alice").client.initializeAccount() },
|
|
70
|
+
{ name: "bob.init", run: () => d("bob").client.initializeAccount() },
|
|
71
|
+
{
|
|
72
|
+
name: "alice.create",
|
|
73
|
+
run: async () => {
|
|
74
|
+
circleId = (await d("alice").client.circles.create()).circleId;
|
|
75
|
+
aliceId = (await d("alice").client.inspect()).identityId ?? aliceId;
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{ name: "bob.requestJoin", run: () => d("bob").client.circles.requestJoin(circleId, aliceId) },
|
|
79
|
+
{ name: "alice.sync#1", run: sync("alice") },
|
|
80
|
+
{ name: "alice.approve", run: () => d("alice").client.circles.approve(circleId, "bob") },
|
|
81
|
+
{ name: "alice.sync#2", run: sync("alice") },
|
|
82
|
+
{ name: "bob.sync#1", run: sync("bob") },
|
|
83
|
+
{ name: "alice.sync#3", run: sync("alice") },
|
|
84
|
+
{ name: "alice.enqueue#1", run: () => d("alice").client.enqueue(0, ...loc(1)) },
|
|
85
|
+
{ name: "alice.enqueue#2", run: () => d("alice").client.enqueue(0, ...loc(2)) },
|
|
86
|
+
{ name: "alice.sync#4", run: sync("alice") },
|
|
87
|
+
{ name: "bob.sync#2", run: sync("bob") },
|
|
88
|
+
{ name: "bob.event", run: () => d("bob").client.enqueue(1, ...loc(3)) },
|
|
89
|
+
{ name: "bob.sync#3", run: sync("bob") },
|
|
90
|
+
{ name: "alice.sync#5", run: sync("alice") },
|
|
91
|
+
{
|
|
92
|
+
name: "alice.concurrent",
|
|
93
|
+
run: async () => {
|
|
94
|
+
if (!stores.fork)
|
|
95
|
+
return;
|
|
96
|
+
// A background context: a second client over another handle on the same store.
|
|
97
|
+
const a = d("alice");
|
|
98
|
+
const bg = await open({ accountName: "alice", retentionPolicy: testPolicy, recoveryProvider: a.provider, resetTrust, secretStore: a.secrets, store: a.store.fork(), transport: a.transport, now: rt.clock.now });
|
|
99
|
+
await Promise.all([a.client.sync(), bg.enqueue(0, ...loc(4)), bg.enqueue(0, ...loc(5))]);
|
|
100
|
+
await a.client.sync();
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{ name: "bob2.restore", run: () => d("bob2").client.restoreAccount() },
|
|
104
|
+
{ name: "bob2.sync#1", run: sync("bob2") },
|
|
105
|
+
{ name: "alice.sync#6", run: sync("alice") },
|
|
106
|
+
{ name: "alice.enqueue#3", run: () => d("alice").client.enqueue(0, ...loc(6)) },
|
|
107
|
+
{ name: "alice.sync#7", run: sync("alice") },
|
|
108
|
+
{ name: "bob2.sync#2", run: sync("bob2") },
|
|
109
|
+
{ name: "bob.sync#4", run: sync("bob") },
|
|
110
|
+
{ name: "bob2.event", run: () => d("bob2").client.enqueue(1, ...loc(7)) },
|
|
111
|
+
{ name: "bob2.sync#3", run: sync("bob2") },
|
|
112
|
+
{ name: "alice.sync#8", run: sync("alice") }
|
|
113
|
+
];
|
|
114
|
+
void run;
|
|
115
|
+
return { steps, rt };
|
|
116
|
+
}
|
|
117
|
+
async function setup(stores, run, plan) {
|
|
118
|
+
const { host, clock } = newHost();
|
|
119
|
+
const rt = { host, clock, devices: new Map() };
|
|
120
|
+
const bobPlatform = new MemoryPlatformProvider("bob@platform");
|
|
121
|
+
for (const name of ["alice", "bob", "bob2"]) {
|
|
122
|
+
const inner = await stores.open(run, name);
|
|
123
|
+
const isVictim = name === plan.victim;
|
|
124
|
+
const forkInner = stores.fork ? () => stores.fork?.(run, name) : undefined;
|
|
125
|
+
const store = new FaultyStore(inner, isVictim ? plan.crash : undefined, forkInner);
|
|
126
|
+
const transport = new MaliciousTransport(hostTransport(host, accountOf(name)));
|
|
127
|
+
if (isVictim && plan.lose)
|
|
128
|
+
transport.knobs.loseResponseOf.add(plan.lose);
|
|
129
|
+
const provider = name === "alice" ? new MemoryPlatformProvider("alice@platform") : bobPlatform.twin();
|
|
130
|
+
await openDevice(rt, name, store, new MemorySecretStore(), provider, transport);
|
|
131
|
+
}
|
|
132
|
+
return rt;
|
|
133
|
+
}
|
|
134
|
+
/** The victim's process restarts: a new handle on the same durable state, the same secrets. */
|
|
135
|
+
async function restart(rt, stores, run, victim) {
|
|
136
|
+
const old = rt.devices.get(victim);
|
|
137
|
+
if (!old)
|
|
138
|
+
throw new Error("no victim");
|
|
139
|
+
const forkInner = stores.fork ? () => stores.fork?.(run, victim) : undefined;
|
|
140
|
+
const store = new FaultyStore(await stores.reopen(run, victim), undefined, forkInner);
|
|
141
|
+
const transport = new MaliciousTransport(hostTransport(rt.host, accountOf(victim)));
|
|
142
|
+
await openDevice(rt, victim, store, old.secrets, old.provider, transport);
|
|
143
|
+
}
|
|
144
|
+
function describeError(e) {
|
|
145
|
+
return e instanceof KavachError ? `${e.code}@${e.stage}` : e instanceof Error ? e.name : String(e);
|
|
146
|
+
}
|
|
147
|
+
/** Runs the steps; on the victim's crash restarts it and re-invokes the step, then continues. */
|
|
148
|
+
async function drive(sc, stores, run, victim) {
|
|
149
|
+
let crashedDuring = "";
|
|
150
|
+
let retry = "";
|
|
151
|
+
for (const step of sc.steps) {
|
|
152
|
+
const v = sc.rt.devices.get(victim);
|
|
153
|
+
if (!v)
|
|
154
|
+
throw new Error("no victim");
|
|
155
|
+
const lossesBefore = v.transport.losses.length;
|
|
156
|
+
let failed;
|
|
157
|
+
try {
|
|
158
|
+
await step.run();
|
|
159
|
+
}
|
|
160
|
+
catch (e) {
|
|
161
|
+
failed = e;
|
|
162
|
+
}
|
|
163
|
+
if (!v.store.crashed && v.transport.losses.length > lossesBefore && failed !== undefined) {
|
|
164
|
+
// The app sees a failed operation and retries it; the host already committed the write.
|
|
165
|
+
try {
|
|
166
|
+
await step.run();
|
|
167
|
+
retry = "OK";
|
|
168
|
+
}
|
|
169
|
+
catch (e) {
|
|
170
|
+
if (!(e instanceof KavachError))
|
|
171
|
+
throw e;
|
|
172
|
+
retry = describeError(e);
|
|
173
|
+
}
|
|
174
|
+
continue;
|
|
175
|
+
}
|
|
176
|
+
if (v.store.crashed) {
|
|
177
|
+
if (crashedDuring)
|
|
178
|
+
throw new Error(`crashed twice (${crashedDuring}, ${step.name})`);
|
|
179
|
+
crashedDuring = step.name;
|
|
180
|
+
await restart(sc.rt, stores, run, victim);
|
|
181
|
+
try {
|
|
182
|
+
await step.run();
|
|
183
|
+
retry = "OK";
|
|
184
|
+
}
|
|
185
|
+
catch (e) {
|
|
186
|
+
if (!(e instanceof KavachError))
|
|
187
|
+
throw e;
|
|
188
|
+
retry = describeError(e);
|
|
189
|
+
}
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (failed !== undefined)
|
|
193
|
+
throw new Error(`step ${step.name} failed without a crash: ${describeError(failed)}`);
|
|
194
|
+
}
|
|
195
|
+
return { crashedDuring, retry };
|
|
196
|
+
}
|
|
197
|
+
/** The durable-state outcomes of section 11, checked against the host after quiescence. */
|
|
198
|
+
async function checkInvariants(rt, label) {
|
|
199
|
+
const fail = (what) => {
|
|
200
|
+
throw new Error(`[${label}] ${what}`);
|
|
201
|
+
};
|
|
202
|
+
const d = (n) => rt.devices.get(n) ?? fail("no device " + n);
|
|
203
|
+
// Quiescence.
|
|
204
|
+
for (let i = 0; i < 2; i++) {
|
|
205
|
+
rt.clock.advance(1000n);
|
|
206
|
+
await d("alice").client.sync();
|
|
207
|
+
await d("bob2").client.sync();
|
|
208
|
+
}
|
|
209
|
+
const host = rt.host;
|
|
210
|
+
const alice = host.accounts.get("alice") ?? fail("alice unknown at host");
|
|
211
|
+
const bob = host.accounts.get("bob") ?? fail("bob unknown at host");
|
|
212
|
+
// Activation: exactly one replacement, never a third device, never a reset.
|
|
213
|
+
if (alice.generation !== 1n || alice.deviceIds.size !== 1)
|
|
214
|
+
fail(`alice generation ${alice.generation} devices ${alice.deviceIds.size}`);
|
|
215
|
+
if (bob.generation !== 2n || bob.deviceIds.size !== 2)
|
|
216
|
+
fail(`bob generation ${bob.generation} devices ${bob.deviceIds.size}`);
|
|
217
|
+
if (alice.previousIdentities.size || bob.previousIdentities.size)
|
|
218
|
+
fail("an identity was reset");
|
|
219
|
+
const aliceState = await d("alice").client.getState();
|
|
220
|
+
const bob2State = await d("bob2").client.getState();
|
|
221
|
+
const bobState = await d("bob").client.getState();
|
|
222
|
+
if (aliceState.status !== "ready")
|
|
223
|
+
fail(`alice is ${aliceState.status}`);
|
|
224
|
+
if (bob2State.status !== "ready")
|
|
225
|
+
fail(`bob2 is ${bob2State.status}`);
|
|
226
|
+
if (bobState.status !== "retired")
|
|
227
|
+
fail(`old bob is ${bobState.status}`);
|
|
228
|
+
if (toHex(aliceState.identityId ?? new Uint8Array()) !== alice.identityId)
|
|
229
|
+
fail("alice identity differs from the host's");
|
|
230
|
+
if (toHex(bob2State.identityId ?? new Uint8Array()) !== bob.identityId)
|
|
231
|
+
fail("bob2 identity differs from the host's");
|
|
232
|
+
if (toHex(bob2State.certificateHash ?? new Uint8Array()) !== bob.certificateHash)
|
|
233
|
+
fail("bob2 certificate differs from the host's");
|
|
234
|
+
// Streams: every epoch the host holds is the exact bytes the author saved, and the author's
|
|
235
|
+
// active epoch is the host's current one.
|
|
236
|
+
for (const name of ["alice", "bob2", "bob"]) {
|
|
237
|
+
const dev = d(name);
|
|
238
|
+
const inner = dev.store.inner;
|
|
239
|
+
const pin = await inner.read((tx) => tx.get("self", "self")) ?? fail(`${name} has no self row`);
|
|
240
|
+
const s = host.streams.get(pin.streamId) ?? fail(`${name} has no stream at the host`);
|
|
241
|
+
const rows = await inner.read((tx) => tx.list("epochs"));
|
|
242
|
+
const byEpoch = new Map(rows.map(([, r]) => [r.epoch, r]));
|
|
243
|
+
for (const [epoch, e] of s.epochs) {
|
|
244
|
+
const row = byEpoch.get(epoch) ?? fail(`${name}: host epoch ${epoch} has no local row`);
|
|
245
|
+
if (row.manifest !== toHex(e.manifest))
|
|
246
|
+
fail(`${name}: epoch ${epoch} bytes differ between host and store`);
|
|
247
|
+
}
|
|
248
|
+
for (const [, r] of rows) {
|
|
249
|
+
if (r.status === "prepared")
|
|
250
|
+
continue;
|
|
251
|
+
if (r.epoch > s.currentEpoch)
|
|
252
|
+
fail(`${name}: local epoch ${r.epoch} (${r.status}) above the host's ${s.currentEpoch}`);
|
|
253
|
+
}
|
|
254
|
+
const stream = await inner.read((tx) => tx.get("stream", "stream"));
|
|
255
|
+
if (name !== "bob") {
|
|
256
|
+
if (stream?.activeEpoch !== s.currentEpoch)
|
|
257
|
+
fail(`${name}: active epoch ${stream?.activeEpoch} but host current ${s.currentEpoch}`);
|
|
258
|
+
const active = rows.filter(([, r]) => r.status === "active");
|
|
259
|
+
if (active.length !== 1)
|
|
260
|
+
fail(`${name}: ${active.length} active epochs`);
|
|
261
|
+
}
|
|
262
|
+
// Records: every append the host saw is in the author's own history, the same recordId was
|
|
263
|
+
// never asked to accept two different wires, and no counter was reused.
|
|
264
|
+
const own = new Set((await inner.read((tx) => tx.list("history"))).filter(([, h]) => h.own).map(([, h]) => h.recordId));
|
|
265
|
+
const log = host.appendLog.filter((a) => a.streamId === pin.streamId);
|
|
266
|
+
const hashes = new Map();
|
|
267
|
+
for (const a of log) {
|
|
268
|
+
if (!own.has(a.recordId))
|
|
269
|
+
fail(`${name}: record ${a.recordId.slice(0, 8)} reached the host without a history row`);
|
|
270
|
+
const h = hashes.get(a.recordId);
|
|
271
|
+
if (h && h !== a.hash)
|
|
272
|
+
fail(`${name}: record ${a.recordId.slice(0, 8)} was sent with two different wires`);
|
|
273
|
+
hashes.set(a.recordId, a.hash);
|
|
274
|
+
if (a.status === "EQUIVOCATION" || a.status === "STALE_APPEND")
|
|
275
|
+
fail(`${name}: the host answered ${a.status}`);
|
|
276
|
+
}
|
|
277
|
+
const outbox = await inner.read((tx) => tx.list("outbox").map(([, r]) => r.status));
|
|
278
|
+
if (name !== "bob" && outbox.some((st) => st !== "accepted" && st !== "cancelled"))
|
|
279
|
+
fail(`${name}: outbox left ${outbox.join(",")}`);
|
|
280
|
+
// Cursors: the client never records a cursor the host does not hold.
|
|
281
|
+
const subs = await inner.read((tx) => tx.list("subscriptions"));
|
|
282
|
+
for (const [, sub] of subs) {
|
|
283
|
+
const hs = host.streams.get(sub.streamId);
|
|
284
|
+
const hostSub = hs?.subscriptions.get(toHex(dev.client ? (await dev.client.getState()).certificateHash ?? new Uint8Array() : new Uint8Array()));
|
|
285
|
+
if (hostSub && hostSub.cursor < BigInt(sub.committedCursor))
|
|
286
|
+
fail(`${name}: committed cursor ${sub.committedCursor} above the host's ${hostSub.cursor}`);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
// Delivery: bob2 holds alice's newest record of kind 0; alice has bob's kind 1 records.
|
|
290
|
+
const aliceId = fromHex(alice.identityId);
|
|
291
|
+
const pin = await d("bob2").client.newest(aliceId, 0);
|
|
292
|
+
const aliceStream = host.streams.get((await d("alice").store.inner.read((tx) => tx.get("self", "self")))?.streamId ?? "");
|
|
293
|
+
const accepted = host.appendLog.filter((a) => a.streamId === (aliceStream ? [...host.streams.entries()].find(([, s]) => s === aliceStream)?.[0] : "") && (a.status === "ACCEPTED" || a.status === "ALREADY_ACCEPTED"));
|
|
294
|
+
const last = [...accepted].reverse().find((a) => a.epoch === aliceStream?.currentEpoch);
|
|
295
|
+
if (last && (!pin || toHex(pin.recordId) !== last.recordId))
|
|
296
|
+
fail(`bob2's slot is ${pin ? toHex(pin.recordId).slice(0, 8) : "missing"}, alice's last is ${last.recordId.slice(0, 8)}`);
|
|
297
|
+
const events = await d("alice").client.history({ authorIdentityId: fromHex(bob.identityId), kind: 1 });
|
|
298
|
+
if (events.length < 2)
|
|
299
|
+
fail(`alice has ${events.length} kind 1 records from bob`);
|
|
300
|
+
}
|
|
301
|
+
async function withRun(stores, run, fn) {
|
|
302
|
+
try {
|
|
303
|
+
return await fn();
|
|
304
|
+
}
|
|
305
|
+
finally {
|
|
306
|
+
await stores.dispose?.(run);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Runs the scenario with no fault and returns the victim's transaction count. */
|
|
310
|
+
export async function countBoundaries(stores, victim) {
|
|
311
|
+
const run = `reference-${victim}`;
|
|
312
|
+
return withRun(stores, run, async () => {
|
|
313
|
+
const rt = await setup(stores, run, { victim });
|
|
314
|
+
const sc = scenario(rt, stores, run);
|
|
315
|
+
const { crashedDuring } = await drive(sc, stores, run, victim);
|
|
316
|
+
if (crashedDuring)
|
|
317
|
+
throw new Error("the reference run crashed");
|
|
318
|
+
// Counted before the invariant check, whose own syncs are not part of the scenario.
|
|
319
|
+
const boundaries = rt.devices.get(victim)?.store.transactions ?? 0;
|
|
320
|
+
await checkInvariants(rt, "reference");
|
|
321
|
+
return boundaries;
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
export async function crashSweep(options) {
|
|
325
|
+
const { stores, victim } = options;
|
|
326
|
+
const phases = options.phases ?? ["beforeCommit", "afterCommit"];
|
|
327
|
+
const boundaries = await countBoundaries(stores, victim);
|
|
328
|
+
const runs = [];
|
|
329
|
+
for (let at = 1; at <= boundaries; at++) {
|
|
330
|
+
if (options.only && !options.only.includes(at))
|
|
331
|
+
continue;
|
|
332
|
+
for (const phase of phases) {
|
|
333
|
+
const run = `${victim}-${phase}-${at}`;
|
|
334
|
+
await withRun(stores, run, async () => {
|
|
335
|
+
const rt = await setup(stores, run, { victim, crash: { at, phase } });
|
|
336
|
+
const sc = scenario(rt, stores, run);
|
|
337
|
+
const { crashedDuring, retry } = await drive(sc, stores, run, victim);
|
|
338
|
+
if (!crashedDuring)
|
|
339
|
+
throw new Error(`[${run}] boundary ${at} was never reached`);
|
|
340
|
+
await checkInvariants(rt, `${run} during ${crashedDuring}, retry ${retry}`);
|
|
341
|
+
runs.push({ at, phase, crashedDuring, retry });
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
return { boundaries, runs };
|
|
346
|
+
}
|
|
347
|
+
const MUTATIONS = ["registerAccount", "activateDevice", "publishVault", "publishOwnedCircle", "requestJoin", "publishEpoch", "appendRecord", "ackThrough"];
|
|
348
|
+
/** For each mutation the victim issues, the host commits it and the response is lost once. */
|
|
349
|
+
export async function lostResponseSweep(stores, victim) {
|
|
350
|
+
const out = [];
|
|
351
|
+
for (const mutation of MUTATIONS) {
|
|
352
|
+
const run = `${victim}-lost-${mutation}`;
|
|
353
|
+
await withRun(stores, run, async () => {
|
|
354
|
+
const rt = await setup(stores, run, { victim, lose: mutation });
|
|
355
|
+
const sc = scenario(rt, stores, run);
|
|
356
|
+
const { crashedDuring } = await drive(sc, stores, run, victim);
|
|
357
|
+
if (crashedDuring)
|
|
358
|
+
throw new Error("no crash was planned");
|
|
359
|
+
const v = rt.devices.get(victim);
|
|
360
|
+
await checkInvariants(rt, run);
|
|
361
|
+
out.push({ mutation, exercised: v?.transport.losses.includes(mutation) ?? false });
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
return out;
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=sweep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sweep.js","sourceRoot":"","sources":["../../src/testing/sweep.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,IAAI,EAAiC,MAAM,cAAc,CAAC;AACnE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAc,MAAM,aAAa,CAAC;AAE5D,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAsD,MAAM,aAAa,CAAC;AAClH,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAChE,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AA0CxD,MAAM,SAAS,GAAG,aAAa,EAAE,CAAC;AAClC,MAAM,UAAU,GAAG,EAAE,aAAa,EAAE,SAAS,CAAC,UAAU,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,EAAE,CAAC;AAkBzF,SAAS,OAAO;IACd,MAAM,IAAI,GAAG,IAAI,QAAQ,EAAE,CAAC;IAC5B,MAAM,KAAK,GAAG,IAAI,SAAS,EAAE,CAAC;IAC9B,IAAI,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IACrB,IAAI,CAAC,WAAW,GAAG,EAAE,GAAG,EAAE,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE,SAAS,CAAC,gBAAgB,EAAE,CAAC;IACrF,IAAI,CAAC,YAAY,GAAG,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;AACzB,CAAC;AAED,SAAS,SAAS,CAAC,IAAgB;IACjC,OAAO,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACxC,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,IAAc,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,GAAc,EAAE;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACxC,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3F,CAAC,CAAC;IACF,OAAO;QACL,IAAI,SAAS;YACX,OAAO,IAAI,EAAE,CAAC,SAAS,CAAC;QAC1B,CAAC;QACD,IAAI,KAAK;YACP,OAAO,IAAI,EAAE,CAAC,KAAK,CAAC;QACtB,CAAC;KACF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,EAAW,EAAE,IAAgB,EAAE,KAAkB,EAAE,OAA0B,EAAE,QAAgC,EAAE,SAA6B;IACtK,MAAM,MAAM,GAAkB,EAAE,CAAC;IACjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,EAAE,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;IAC5L,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACxC,MAAM,CAAC,GAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC;IAChF,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IACxB,OAAO,CAAC,CAAC;AACX,CAAC;AASD,SAAS,QAAQ,CAAC,EAAW,EAAE,MAAmB,EAAE,GAAW;IAC7D,MAAM,CAAC,GAAG,CAAC,CAAa,EAAU,EAAE;QAClC,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC5B,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;QAC1C,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,IAAI,QAAQ,GAAe,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC9C,IAAI,OAAO,GAAe,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC7C,iGAAiG;IACjG,MAAM,GAAG,GAAG,CAAC,CAAS,EAAuC,EAAE,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACrH,MAAM,IAAI,GAAG,CAAC,CAAa,EAAE,EAAE,CAAC,KAAK,IAAsB,EAAE;QAC3D,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAM,CAAC,CAAC;QACzB,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAC5B,CAAC,CAAC;IACF,MAAM,KAAK,GAAW;QACpB,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE;QACxE,EAAE,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,iBAAiB,EAAE,EAAE;QACpE;YACE,IAAI,EAAE,cAAc;YACpB,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,QAAQ,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,CAAC;gBAC/D,OAAO,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC;YACtE,CAAC;SACF;QACD,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;QAC9F,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,eAAe,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE;QACxF,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QACxC,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;QAC/E,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;QAC/E,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QACxC,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;QACvE,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QACxC,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C;YACE,IAAI,EAAE,kBAAkB;YACxB,GAAG,EAAE,KAAK,IAAI,EAAE;gBACd,IAAI,CAAC,MAAM,CAAC,IAAI;oBAAE,OAAO;gBACzB,+EAA+E;gBAC/E,MAAM,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;gBACrB,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,EAAE,WAAW,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,EAAE,CAAC,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;gBACjN,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBACzF,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACxB,CAAC;SACF;QACD,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE;QACtE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;QAC1C,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;QAC/E,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;QAC5C,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;QAC1C,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE;QACxC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;QACzE,EAAE,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE;QAC1C,EAAE,IAAI,EAAE,cAAc,EAAE,GAAG,EAAE,IAAI,CAAC,OAAO,CAAC,EAAE;KAC7C,CAAC;IACF,KAAK,GAAG,CAAC;IACT,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;AACvB,CAAC;AAED,KAAK,UAAU,KAAK,CAAC,MAAmB,EAAE,GAAW,EAAE,IAAoE;IACzH,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,OAAO,EAAE,CAAC;IAClC,MAAM,EAAE,GAAY,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IACxD,MAAM,WAAW,GAAG,IAAI,sBAAsB,CAAC,cAAc,CAAC,CAAC;IAC/D,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,EAAE,MAAM,CAAU,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC;QACtC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAU,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,IAAI,CAAU,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3F,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QACnF,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC/E,IAAI,QAAQ,IAAI,IAAI,CAAC,IAAI;YAAE,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACzE,MAAM,QAAQ,GAAG,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,sBAAsB,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACtG,MAAM,UAAU,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,iBAAiB,EAAE,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+FAA+F;AAC/F,KAAK,UAAU,OAAO,CAAC,EAAW,EAAE,MAAmB,EAAE,GAAW,EAAE,MAAkB;IACtF,MAAM,GAAG,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;IACvC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,GAAU,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,CAAU,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7F,MAAM,KAAK,GAAG,IAAI,WAAW,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACtF,MAAM,SAAS,GAAG,IAAI,kBAAkB,CAAC,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACpF,MAAM,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;AAC5E,CAAC;AAED,SAAS,aAAa,CAAC,CAAU;IAC/B,OAAO,CAAC,YAAY,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACrG,CAAC;AAED,iGAAiG;AACjG,KAAK,UAAU,KAAK,CAAC,EAAY,EAAE,MAAmB,EAAE,GAAW,EAAE,MAAkB;IACrF,IAAI,aAAa,GAAG,EAAE,CAAC;IACvB,IAAI,KAAK,GAAG,EAAE,CAAC;IACf,KAAK,MAAM,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACpC,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;QACrC,MAAM,YAAY,GAAG,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC;QAC/C,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,MAAM,GAAG,CAAC,CAAC;QACb,CAAC;QACD,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,GAAG,YAAY,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzF,wFAAwF;YACxF,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;gBACjB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC;oBAAE,MAAM,CAAC,CAAC;gBACzC,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACpB,IAAI,aAAa;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,aAAa,KAAK,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;YACrF,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC;YAC1B,MAAM,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC1C,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;gBACjB,KAAK,GAAG,IAAI,CAAC;YACf,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,IAAI,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC;oBAAE,MAAM,CAAC,CAAC;gBACzC,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YACD,SAAS;QACX,CAAC;QACD,IAAI,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,4BAA4B,aAAa,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;IAClH,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC;AAED,2FAA2F;AAC3F,KAAK,UAAU,eAAe,CAAC,EAAW,EAAE,KAAa;IACvD,MAAM,IAAI,GAAG,CAAC,IAAY,EAAS,EAAE;QACnC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,CAAa,EAAU,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;IACjF,cAAc;IACd,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,KAAM,CAAC,CAAC;QACzB,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChC,CAAC;IACD,MAAM,IAAI,GAAG,EAAE,CAAC,IAAI,CAAC;IACrB,MAAM,KAAK,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAC1E,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACpE,4EAA4E;IAC5E,IAAI,KAAK,CAAC,UAAU,KAAK,EAAE,IAAI,KAAK,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,IAAI,CAAC,oBAAoB,KAAK,CAAC,UAAU,YAAY,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IACxI,IAAI,GAAG,CAAC,UAAU,KAAK,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,IAAI,CAAC,kBAAkB,GAAG,CAAC,UAAU,YAAY,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;IAC9H,IAAI,KAAK,CAAC,kBAAkB,CAAC,IAAI,IAAI,GAAG,CAAC,kBAAkB,CAAC,IAAI;QAAE,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAChG,MAAM,UAAU,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IACtD,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IACpD,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;IAClD,IAAI,UAAU,CAAC,MAAM,KAAK,OAAO;QAAE,IAAI,CAAC,YAAY,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,IAAI,SAAS,CAAC,MAAM,KAAK,OAAO;QAAE,IAAI,CAAC,WAAW,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACtE,IAAI,QAAQ,CAAC,MAAM,KAAK,SAAS;QAAE,IAAI,CAAC,cAAc,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACzE,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,IAAI,IAAI,UAAU,EAAE,CAAC,KAAK,KAAK,CAAC,UAAU;QAAE,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAC1H,IAAI,KAAK,CAAC,SAAS,CAAC,UAAU,IAAI,IAAI,UAAU,EAAE,CAAC,KAAK,GAAG,CAAC,UAAU;QAAE,IAAI,CAAC,uCAAuC,CAAC,CAAC;IACtH,IAAI,KAAK,CAAC,SAAS,CAAC,eAAe,IAAI,IAAI,UAAU,EAAE,CAAC,KAAK,GAAG,CAAC,eAAe;QAAE,IAAI,CAAC,0CAA0C,CAAC,CAAC;IACnI,4FAA4F;IAC5F,0CAA0C;IAC1C,KAAK,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAU,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;QAC9B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,kBAAkB,CAAC,CAAC;QAChG,MAAM,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,4BAA4B,CAAC,CAAC;QACtF,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3D,KAAK,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,GAAG,IAAI,gBAAgB,KAAK,mBAAmB,CAAC,CAAC;YACxF,IAAI,GAAG,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAAE,IAAI,CAAC,GAAG,IAAI,WAAW,KAAK,sCAAsC,CAAC,CAAC;QAC9G,CAAC;QACD,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;YACzB,IAAI,CAAC,CAAC,MAAM,KAAK,UAAU;gBAAE,SAAS;YACtC,IAAI,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,YAAY;gBAAE,IAAI,CAAC,GAAG,IAAI,iBAAiB,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,sBAAsB,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;QACzH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;QACpE,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;YACnB,IAAI,MAAM,EAAE,WAAW,KAAK,CAAC,CAAC,YAAY;gBAAE,IAAI,CAAC,GAAG,IAAI,kBAAkB,MAAM,EAAE,WAAW,qBAAqB,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC;YACpI,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC;YAC7D,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,IAAI,CAAC,GAAG,IAAI,KAAK,MAAM,CAAC,MAAM,gBAAgB,CAAC,CAAC;QAC3E,CAAC;QACD,2FAA2F;QAC3F,wEAAwE;QACxE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACxH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;QACzC,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAAE,IAAI,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,yCAAyC,CAAC,CAAC;YACnH,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YACjC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI;gBAAE,IAAI,CAAC,GAAG,IAAI,YAAY,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,oCAAoC,CAAC,CAAC;YAC3G,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;YAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,cAAc,IAAI,CAAC,CAAC,MAAM,KAAK,cAAc;gBAAE,IAAI,CAAC,GAAG,IAAI,uBAAuB,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QACjH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;QACpF,IAAI,IAAI,KAAK,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,KAAK,UAAU,IAAI,EAAE,KAAK,WAAW,CAAC;YAAE,IAAI,CAAC,GAAG,IAAI,iBAAiB,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrI,qEAAqE;QACrE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC;QAChE,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;YAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YAC1C,MAAM,OAAO,GAAG,EAAE,EAAE,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,eAAe,IAAI,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,UAAU,EAAE,CAAC,CAAC,CAAC;YAChJ,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC;gBAAE,IAAI,CAAC,GAAG,IAAI,sBAAsB,GAAG,CAAC,eAAe,qBAAqB,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;QAC3J,CAAC;IACH,CAAC;IACD,wFAAwF;IACxF,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IACtD,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC;IAC1H,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,KAAK,UAAU,IAAI,CAAC,CAAC,MAAM,KAAK,kBAAkB,CAAC,CAAC,CAAC;IACvN,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,WAAW,EAAE,YAAY,CAAC,CAAC;IACxF,IAAI,IAAI,IAAI,CAAC,CAAC,GAAG,IAAI,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC,QAAQ,CAAC;QAAE,IAAI,CAAC,kBAAkB,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,qBAAqB,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;IACvL,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,gBAAgB,EAAE,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;IACvG,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,aAAa,MAAM,CAAC,MAAM,0BAA0B,CAAC,CAAC;AACpF,CAAC;AAED,KAAK,UAAU,OAAO,CAAI,MAAmB,EAAE,GAAW,EAAE,EAAoB;IAC9E,IAAI,CAAC;QACH,OAAO,MAAM,EAAE,EAAE,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,MAAM,MAAM,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,kFAAkF;AAClF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAmB,EAAE,MAAkB;IAC3E,MAAM,GAAG,GAAG,aAAa,MAAM,EAAE,CAAC;IAClC,OAAO,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;QACrC,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;QAChD,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;QACrC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;QAC/D,IAAI,aAAa;YAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAChE,oFAAoF;QACpF,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,YAAY,IAAI,CAAC,CAAC;QACnE,MAAM,eAAe,CAAC,EAAE,EAAE,WAAW,CAAC,CAAC;QACvC,OAAO,UAAU,CAAC;IACpB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAqB;IACpD,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IACnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,cAAc,EAAE,aAAa,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,MAAM,eAAe,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzD,MAAM,IAAI,GAAe,EAAE,CAAC;IAC5B,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,IAAI,UAAU,EAAE,EAAE,EAAE,EAAE,CAAC;QACxC,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,SAAS;QACzD,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,GAAG,MAAM,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;YACvC,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;gBACpC,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;gBACtE,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;gBACrC,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;gBACtE,IAAI,CAAC,aAAa;oBAAE,MAAM,IAAI,KAAK,CAAC,IAAI,GAAG,cAAc,EAAE,oBAAoB,CAAC,CAAC;gBACjF,MAAM,eAAe,CAAC,EAAE,EAAE,GAAG,GAAG,WAAW,aAAa,WAAW,KAAK,EAAE,CAAC,CAAC;gBAC5E,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,CAAC,CAAC;YACjD,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,SAAS,GAA4B,CAAC,iBAAiB,EAAE,gBAAgB,EAAE,cAAc,EAAE,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,YAAY,CAAC,CAAC;AAEpL,8FAA8F;AAC9F,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,MAAmB,EAAE,MAAkB;IAC7E,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,GAAG,MAAM,SAAS,QAAQ,EAAE,CAAC;QACzC,MAAM,OAAO,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE;YACpC,MAAM,EAAE,GAAG,MAAM,KAAK,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;YAChE,MAAM,EAAE,GAAG,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;YACrC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,KAAK,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;YAC/D,IAAI,aAAa;gBAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;YAC3D,MAAM,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACjC,MAAM,eAAe,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;YAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,KAAK,EAAE,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { type AudienceEvent } from "./audience.js";
|
|
2
|
+
import type { PreparedEpoch } from "./epoch.js";
|
|
3
|
+
import { type DeviceKeys, type OwnAccount } from "./identity.js";
|
|
4
|
+
import type { ActivationRow, CircleRow, MetaRow, SecretStore, Store, StoreState, Tx, VaultRow } from "./store.js";
|
|
5
|
+
export declare const META = "meta";
|
|
6
|
+
export declare const SELF = "self";
|
|
7
|
+
export declare const STREAM = "stream";
|
|
8
|
+
export declare const REVISION = "revision";
|
|
9
|
+
export declare const VAULT = "vault";
|
|
10
|
+
export type OpenedState = {
|
|
11
|
+
readonly kind: "fresh";
|
|
12
|
+
} | {
|
|
13
|
+
readonly kind: "initializing";
|
|
14
|
+
readonly account: OwnAccount;
|
|
15
|
+
} | {
|
|
16
|
+
readonly kind: StoreState;
|
|
17
|
+
readonly meta: MetaRow;
|
|
18
|
+
readonly account: OwnAccount;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Bind the secret store to the local store. A mismatch between the two is `RECOVERY_REQUIRED`
|
|
22
|
+
* and is resolved by device replacement, never by inventing counters.
|
|
23
|
+
*/
|
|
24
|
+
export declare function openStore(store: Store, secrets: SecretStore, accountName: string): Promise<OpenedState>;
|
|
25
|
+
/** T1a: roots into the secret store. Idempotent for the same values. */
|
|
26
|
+
export declare function t1Secrets(secrets: SecretStore, roots: {
|
|
27
|
+
accountSeed: Uint8Array;
|
|
28
|
+
deviceSeed: Uint8Array;
|
|
29
|
+
recoveryKey: Uint8Array;
|
|
30
|
+
instanceId: Uint8Array;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
/** T1b: the store header with the INITIALIZING marker, the own pin and the stream state. */
|
|
33
|
+
export declare function t1Header(tx: Tx, input: {
|
|
34
|
+
account: OwnAccount;
|
|
35
|
+
device: DeviceKeys;
|
|
36
|
+
certificate: Uint8Array;
|
|
37
|
+
instanceId: Uint8Array;
|
|
38
|
+
generation: bigint;
|
|
39
|
+
}): void;
|
|
40
|
+
/** T1c: ACTIVE once the certificate is durable at the host. */
|
|
41
|
+
export declare function t1Activate(tx: Tx): void;
|
|
42
|
+
/** T2: the exact replacement certificate and vault bytes prepared for activation. */
|
|
43
|
+
export declare function t2PrepareActivation(tx: Tx, row: ActivationRow): void;
|
|
44
|
+
export interface ChangeResult {
|
|
45
|
+
readonly changed: boolean;
|
|
46
|
+
readonly desiredRevision: bigint;
|
|
47
|
+
readonly cancelled: readonly string[];
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* T3: a verified circle or device change. Bumps the desired revision, invalidates the active
|
|
51
|
+
* epoch, burns its counters and cancels queued (not yet handed off) outbox rows sealed under the
|
|
52
|
+
* obsolete revision. Pauses with `rotation`.
|
|
53
|
+
*/
|
|
54
|
+
export declare function t3ApplyChange(tx: Tx, event: AudienceEvent): ChangeResult;
|
|
55
|
+
/**
|
|
56
|
+
* T3c: one circle row change with its bookkeeping. The row is stored, the audience event it
|
|
57
|
+
* implies (if any) rotates the sending epoch, and the vault is marked so the backup follows the
|
|
58
|
+
* rows. Every circle write except the restore from the vault itself goes through here.
|
|
59
|
+
*/
|
|
60
|
+
export declare function t3Circle(tx: Tx, row: CircleRow, event?: AudienceEvent): ChangeResult;
|
|
61
|
+
export declare function currentRevision(tx: Pick<Tx, "get">): bigint;
|
|
62
|
+
/** T4: the exact manifest, wraps, key and audience checkpoint of a prepared epoch. One unresolved epoch per stream. */
|
|
63
|
+
export declare function t4PersistPrepared(tx: Tx, prepared: PreparedEpoch): void;
|
|
64
|
+
export type PublishRecord = "PROMOTED" | "OBSOLETE";
|
|
65
|
+
/** T5: a committed publication. Promotion is conditional on the revision and the exact audience. */
|
|
66
|
+
export declare function t5Committed(tx: Tx, epoch: number, currentAudienceKey: string): PublishRecord;
|
|
67
|
+
/** T8: the owner's successor snapshot, kept until the host confirms it. */
|
|
68
|
+
export declare function t8OwnerSnapshot(tx: Tx, circleId: Uint8Array, snapshot: Uint8Array, revision: bigint, close?: boolean): void;
|
|
69
|
+
/** T9: a vault update prepared for publication (or confirmed). */
|
|
70
|
+
export declare function t9Vault(tx: Tx, row: VaultRow): void;
|
|
71
|
+
/** T9 marker: the circle rows changed in this transaction, so the vault has to be derived from them again. */
|
|
72
|
+
export declare function t9MarkVault(tx: Tx): void;
|
|
73
|
+
/** Own identity id from the header, for callers that only hold a transaction. */
|
|
74
|
+
export declare function selfIdentity(tx: Pick<Tx, "get">, accountName: string, accountKey: Uint8Array): Uint8Array;
|
|
75
|
+
//# sourceMappingURL=transactions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactions.d.ts","sourceRoot":"","sources":["../src/transactions.ts"],"names":[],"mappings":"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"}
|