cojson 0.9.10 → 0.9.11
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/.turbo/turbo-build.log +3 -3
- package/CHANGELOG.md +7 -0
- package/dist/native/PeerState.js +2 -1
- package/dist/native/PeerState.js.map +1 -1
- package/dist/native/PriorityBasedMessageQueue.js +54 -7
- package/dist/native/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/native/base64url.js +0 -6
- package/dist/native/base64url.js.map +1 -1
- package/dist/native/coValueCore.js +4 -10
- package/dist/native/coValueCore.js.map +1 -1
- package/dist/native/coValueState.js +5 -4
- package/dist/native/coValueState.js.map +1 -1
- package/dist/native/coValues/account.js +2 -1
- package/dist/native/coValues/account.js.map +1 -1
- package/dist/native/coValues/coList.js +0 -7
- package/dist/native/coValues/coList.js.map +1 -1
- package/dist/native/coValues/coStream.js +3 -8
- package/dist/native/coValues/coStream.js.map +1 -1
- package/dist/native/coValues/group.js +3 -2
- package/dist/native/coValues/group.js.map +1 -1
- package/dist/native/crypto/PureJSCrypto.js +2 -1
- package/dist/native/crypto/PureJSCrypto.js.map +1 -1
- package/dist/native/crypto/WasmCrypto.js +2 -1
- package/dist/native/crypto/WasmCrypto.js.map +1 -1
- package/dist/native/crypto/crypto.js +2 -4
- package/dist/native/crypto/crypto.js.map +1 -1
- package/dist/native/exports.js +2 -1
- package/dist/native/exports.js.map +1 -1
- package/dist/native/localNode.js +5 -6
- package/dist/native/localNode.js.map +1 -1
- package/dist/native/logger.js +58 -0
- package/dist/native/logger.js.map +1 -0
- package/dist/native/permissions.js +3 -4
- package/dist/native/permissions.js.map +1 -1
- package/dist/native/storage/FileSystem.js +0 -10
- package/dist/native/storage/FileSystem.js.map +1 -1
- package/dist/native/storage/index.js +14 -23
- package/dist/native/storage/index.js.map +1 -1
- package/dist/native/sync.js +20 -28
- package/dist/native/sync.js.map +1 -1
- package/dist/web/PeerState.js +2 -1
- package/dist/web/PeerState.js.map +1 -1
- package/dist/web/PriorityBasedMessageQueue.js +54 -7
- package/dist/web/PriorityBasedMessageQueue.js.map +1 -1
- package/dist/web/base64url.js +0 -6
- package/dist/web/base64url.js.map +1 -1
- package/dist/web/coValueCore.js +4 -10
- package/dist/web/coValueCore.js.map +1 -1
- package/dist/web/coValueState.js +5 -4
- package/dist/web/coValueState.js.map +1 -1
- package/dist/web/coValues/account.js +2 -1
- package/dist/web/coValues/account.js.map +1 -1
- package/dist/web/coValues/coList.js +0 -7
- package/dist/web/coValues/coList.js.map +1 -1
- package/dist/web/coValues/coStream.js +3 -8
- package/dist/web/coValues/coStream.js.map +1 -1
- package/dist/web/coValues/group.js +3 -2
- package/dist/web/coValues/group.js.map +1 -1
- package/dist/web/crypto/PureJSCrypto.js +2 -1
- package/dist/web/crypto/PureJSCrypto.js.map +1 -1
- package/dist/web/crypto/WasmCrypto.js +2 -1
- package/dist/web/crypto/WasmCrypto.js.map +1 -1
- package/dist/web/crypto/crypto.js +2 -4
- package/dist/web/crypto/crypto.js.map +1 -1
- package/dist/web/exports.js +2 -1
- package/dist/web/exports.js.map +1 -1
- package/dist/web/localNode.js +5 -6
- package/dist/web/localNode.js.map +1 -1
- package/dist/web/logger.js +58 -0
- package/dist/web/logger.js.map +1 -0
- package/dist/web/permissions.js +3 -4
- package/dist/web/permissions.js.map +1 -1
- package/dist/web/storage/FileSystem.js +0 -10
- package/dist/web/storage/FileSystem.js.map +1 -1
- package/dist/web/storage/index.js +14 -23
- package/dist/web/storage/index.js.map +1 -1
- package/dist/web/sync.js +20 -28
- package/dist/web/sync.js.map +1 -1
- package/package.json +1 -1
- package/src/PeerState.ts +4 -3
- package/src/PriorityBasedMessageQueue.ts +67 -11
- package/src/base64url.ts +1 -6
- package/src/coValueCore.ts +4 -10
- package/src/coValueState.ts +5 -4
- package/src/coValues/account.ts +2 -1
- package/src/coValues/coList.ts +0 -7
- package/src/coValues/coStream.ts +3 -8
- package/src/coValues/group.ts +3 -2
- package/src/crypto/PureJSCrypto.ts +2 -1
- package/src/crypto/WasmCrypto.ts +2 -1
- package/src/crypto/crypto.ts +2 -4
- package/src/exports.ts +2 -0
- package/src/localNode.ts +5 -9
- package/src/logger.ts +78 -0
- package/src/permissions.ts +3 -5
- package/src/storage/FileSystem.ts +0 -12
- package/src/storage/index.ts +21 -37
- package/src/sync.ts +20 -29
- package/src/tests/PeerState.test.ts +0 -3
- package/src/tests/PriorityBasedMessageQueue.test.ts +1 -1
- package/src/tests/logger.test.ts +145 -0
|
@@ -18,11 +18,12 @@ function promiseWithResolvers<R>() {
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
-
export type QueueEntry = {
|
|
22
|
-
msg:
|
|
21
|
+
export type QueueEntry<V> = {
|
|
22
|
+
msg: V;
|
|
23
23
|
promise: Promise<void>;
|
|
24
24
|
resolve: () => void;
|
|
25
25
|
reject: (_: unknown) => void;
|
|
26
|
+
next: QueueEntry<V> | undefined;
|
|
26
27
|
};
|
|
27
28
|
|
|
28
29
|
/**
|
|
@@ -33,10 +34,68 @@ type Tuple<T, N extends number, A extends unknown[] = []> = A extends {
|
|
|
33
34
|
}
|
|
34
35
|
? A
|
|
35
36
|
: Tuple<T, N, [...A, T]>;
|
|
36
|
-
type QueueTuple = Tuple<
|
|
37
|
+
type QueueTuple = Tuple<Queue<SyncMessage>, 8>;
|
|
38
|
+
|
|
39
|
+
class Queue<V> {
|
|
40
|
+
head: QueueEntry<V> | undefined = undefined;
|
|
41
|
+
tail: QueueEntry<V> | undefined = undefined;
|
|
42
|
+
|
|
43
|
+
push(msg: V) {
|
|
44
|
+
const { promise, resolve, reject } = promiseWithResolvers<void>();
|
|
45
|
+
const entry: QueueEntry<V> = {
|
|
46
|
+
msg,
|
|
47
|
+
promise,
|
|
48
|
+
resolve,
|
|
49
|
+
reject,
|
|
50
|
+
next: undefined,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
if (this.head === undefined) {
|
|
54
|
+
this.head = entry;
|
|
55
|
+
} else {
|
|
56
|
+
if (this.tail === undefined) {
|
|
57
|
+
throw new Error("Tail is null but head is not");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.tail.next = entry;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.tail = entry;
|
|
64
|
+
|
|
65
|
+
return entry;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
pull() {
|
|
69
|
+
const entry = this.head;
|
|
70
|
+
|
|
71
|
+
if (entry) {
|
|
72
|
+
this.head = entry.next;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (this.head === undefined) {
|
|
76
|
+
this.tail = undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return entry;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
isNonEmpty() {
|
|
83
|
+
return this.head !== undefined;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
37
86
|
|
|
38
87
|
export class PriorityBasedMessageQueue {
|
|
39
|
-
private queues: QueueTuple = [
|
|
88
|
+
private queues: QueueTuple = [
|
|
89
|
+
new Queue(),
|
|
90
|
+
new Queue(),
|
|
91
|
+
new Queue(),
|
|
92
|
+
new Queue(),
|
|
93
|
+
new Queue(),
|
|
94
|
+
new Queue(),
|
|
95
|
+
new Queue(),
|
|
96
|
+
new Queue(),
|
|
97
|
+
];
|
|
98
|
+
|
|
40
99
|
queueSizeCounter = metrics
|
|
41
100
|
.getMeter("cojson")
|
|
42
101
|
.createUpDownCounter("jazz.messagequeue.size", {
|
|
@@ -52,22 +111,19 @@ export class PriorityBasedMessageQueue {
|
|
|
52
111
|
constructor(private defaultPriority: CoValuePriority) {}
|
|
53
112
|
|
|
54
113
|
public push(msg: SyncMessage) {
|
|
55
|
-
const { promise, resolve, reject } = promiseWithResolvers<void>();
|
|
56
|
-
const entry: QueueEntry = { msg, promise, resolve, reject };
|
|
57
|
-
|
|
58
114
|
const priority = "priority" in msg ? msg.priority : this.defaultPriority;
|
|
59
115
|
|
|
60
|
-
this.getQueue(priority).push(
|
|
116
|
+
const entry = this.getQueue(priority).push(msg);
|
|
61
117
|
|
|
62
118
|
this.queueSizeCounter.add(1, {
|
|
63
119
|
priority,
|
|
64
120
|
});
|
|
65
121
|
|
|
66
|
-
return promise;
|
|
122
|
+
return entry.promise;
|
|
67
123
|
}
|
|
68
124
|
|
|
69
125
|
public pull() {
|
|
70
|
-
const priority = this.queues.findIndex((queue) => queue.
|
|
126
|
+
const priority = this.queues.findIndex((queue) => queue.isNonEmpty());
|
|
71
127
|
|
|
72
128
|
if (priority === -1) {
|
|
73
129
|
return;
|
|
@@ -77,6 +133,6 @@ export class PriorityBasedMessageQueue {
|
|
|
77
133
|
priority,
|
|
78
134
|
});
|
|
79
135
|
|
|
80
|
-
return this.queues[priority]?.
|
|
136
|
+
return this.queues[priority]?.pull();
|
|
81
137
|
}
|
|
82
138
|
}
|
package/src/base64url.ts
CHANGED
|
@@ -43,12 +43,7 @@ export function bytesToBase64url(bytes: Uint8Array) {
|
|
|
43
43
|
let base64 = decoder.decode(new Uint8Array(encoded.buffer, 0, n));
|
|
44
44
|
if (k === 1) base64 += "==";
|
|
45
45
|
if (k === 2) base64 += "=";
|
|
46
|
-
|
|
47
|
-
// console.log(
|
|
48
|
-
// "bytesToBase64url bandwidth in MB/s for length",
|
|
49
|
-
// (1000 * bytes.length / (after - before)) / (1024 * 1024),
|
|
50
|
-
// bytes.length
|
|
51
|
-
// );
|
|
46
|
+
|
|
52
47
|
return base64;
|
|
53
48
|
}
|
|
54
49
|
|
package/src/coValueCore.ts
CHANGED
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
import { Stringified, parseJSON, stableStringify } from "./jsonStringify.js";
|
|
25
25
|
import { JsonObject, JsonValue } from "./jsonValue.js";
|
|
26
26
|
import { LocalNode, ResolveAccountAgentError } from "./localNode.js";
|
|
27
|
+
import { logger } from "./logger.js";
|
|
27
28
|
import {
|
|
28
29
|
PermissionsDef as RulesetDef,
|
|
29
30
|
determineValidTransactions,
|
|
@@ -209,16 +210,10 @@ export class CoValueCore {
|
|
|
209
210
|
.andThen((agent) => {
|
|
210
211
|
const signerID = this.crypto.getAgentSignerID(agent);
|
|
211
212
|
|
|
212
|
-
// const beforeHash = performance.now();
|
|
213
213
|
const { expectedNewHash, newStreamingHash } = this.expectedNewHashAfter(
|
|
214
214
|
sessionID,
|
|
215
215
|
newTransactions,
|
|
216
216
|
);
|
|
217
|
-
// const afterHash = performance.now();
|
|
218
|
-
// console.log(
|
|
219
|
-
// "Hashing took",
|
|
220
|
-
// afterHash - beforeHash
|
|
221
|
-
// );
|
|
222
217
|
|
|
223
218
|
if (givenExpectedNewHash && givenExpectedNewHash !== expectedNewHash) {
|
|
224
219
|
return err({
|
|
@@ -391,7 +386,6 @@ export class CoValueCore {
|
|
|
391
386
|
streamingHash.update(transaction);
|
|
392
387
|
const after = performance.now();
|
|
393
388
|
if (after - before > 1) {
|
|
394
|
-
// console.log("Hashing blocked for", after - before);
|
|
395
389
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
396
390
|
before = performance.now();
|
|
397
391
|
}
|
|
@@ -540,7 +534,7 @@ export class CoValueCore {
|
|
|
540
534
|
}
|
|
541
535
|
|
|
542
536
|
if (!decryptedChanges) {
|
|
543
|
-
|
|
537
|
+
logger.error("Failed to decrypt transaction despite having key");
|
|
544
538
|
continue;
|
|
545
539
|
}
|
|
546
540
|
|
|
@@ -685,7 +679,7 @@ export class CoValueCore {
|
|
|
685
679
|
if (secret) {
|
|
686
680
|
return secret as KeySecret;
|
|
687
681
|
} else {
|
|
688
|
-
|
|
682
|
+
logger.warn(
|
|
689
683
|
`Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`,
|
|
690
684
|
);
|
|
691
685
|
}
|
|
@@ -725,7 +719,7 @@ export class CoValueCore {
|
|
|
725
719
|
if (secret) {
|
|
726
720
|
return secret as KeySecret;
|
|
727
721
|
} else {
|
|
728
|
-
|
|
722
|
+
logger.warn(
|
|
729
723
|
`Encrypting parent ${parentKey.id} key didn't decrypt ${keyID}`,
|
|
730
724
|
);
|
|
731
725
|
}
|
package/src/coValueState.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PeerState } from "./PeerState.js";
|
|
2
2
|
import { CoValueCore } from "./coValueCore.js";
|
|
3
3
|
import { RawCoID } from "./ids.js";
|
|
4
|
+
import { logger } from "./logger.js";
|
|
4
5
|
import { PeerID } from "./sync.js";
|
|
5
6
|
|
|
6
7
|
export const CO_VALUE_LOADING_MAX_RETRIES = 5;
|
|
@@ -282,7 +283,7 @@ async function loadCoValueFromPeers(
|
|
|
282
283
|
...coValueEntry.state.coValue.knownState(),
|
|
283
284
|
})
|
|
284
285
|
.catch((err) => {
|
|
285
|
-
|
|
286
|
+
logger.warn(`Failed to push load message to peer ${peer.id}`, err);
|
|
286
287
|
});
|
|
287
288
|
} else {
|
|
288
289
|
/**
|
|
@@ -296,14 +297,14 @@ async function loadCoValueFromPeers(
|
|
|
296
297
|
sessions: {},
|
|
297
298
|
})
|
|
298
299
|
.catch((err) => {
|
|
299
|
-
|
|
300
|
+
logger.warn(`Failed to push load message to peer ${peer.id}`, err);
|
|
300
301
|
});
|
|
301
302
|
}
|
|
302
303
|
|
|
303
304
|
if (coValueEntry.state.type === "loading") {
|
|
304
305
|
const timeout = setTimeout(() => {
|
|
305
306
|
if (coValueEntry.state.type === "loading") {
|
|
306
|
-
|
|
307
|
+
logger.warn("Failed to load coValue from peer", peer.id);
|
|
307
308
|
coValueEntry.dispatch({
|
|
308
309
|
type: "not-found-in-peer",
|
|
309
310
|
peerId: peer.id,
|
|
@@ -356,7 +357,7 @@ function sleep(ms: number) {
|
|
|
356
357
|
function getPeersWithoutErrors(peers: PeerState[], coValueId: RawCoID) {
|
|
357
358
|
return peers.filter((p) => {
|
|
358
359
|
if (p.erroredCoValues.has(coValueId)) {
|
|
359
|
-
|
|
360
|
+
logger.warn(
|
|
360
361
|
`Skipping load on errored coValue ${coValueId} from peer ${p.id}`,
|
|
361
362
|
);
|
|
362
363
|
return false;
|
package/src/coValues/account.ts
CHANGED
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
import { AgentID } from "../ids.js";
|
|
17
17
|
import { JsonObject } from "../jsonValue.js";
|
|
18
18
|
import { LocalNode } from "../localNode.js";
|
|
19
|
+
import { logger } from "../logger.js";
|
|
19
20
|
import type { AccountRole } from "../permissions.js";
|
|
20
21
|
import { RawCoMap } from "./coMap.js";
|
|
21
22
|
import { InviteSecret, RawGroup } from "./group.js";
|
|
@@ -59,7 +60,7 @@ export class RawAccount<
|
|
|
59
60
|
);
|
|
60
61
|
|
|
61
62
|
if (agents.length !== 1) {
|
|
62
|
-
|
|
63
|
+
logger.warn("Account has " + agents.length + " agents", this.id);
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
this._cachedCurrentAgentID = agents[0];
|
package/src/coValues/coList.ts
CHANGED
|
@@ -133,10 +133,6 @@ export class RawCoListView<
|
|
|
133
133
|
change.before.txIndex
|
|
134
134
|
]?.[change.before.changeIdx];
|
|
135
135
|
if (!beforeEntry) {
|
|
136
|
-
// console.error(
|
|
137
|
-
// "Insertion before missing op " +
|
|
138
|
-
// change.before
|
|
139
|
-
// );
|
|
140
136
|
continue;
|
|
141
137
|
}
|
|
142
138
|
beforeEntry.predecessors.splice(0, 0, {
|
|
@@ -156,9 +152,6 @@ export class RawCoListView<
|
|
|
156
152
|
change.after.txIndex
|
|
157
153
|
]?.[change.after.changeIdx];
|
|
158
154
|
if (!afterEntry) {
|
|
159
|
-
// console.error(
|
|
160
|
-
// "Insertion after missing op " + change.after
|
|
161
|
-
// );
|
|
162
155
|
continue;
|
|
163
156
|
}
|
|
164
157
|
afterEntry.successors.push({
|
package/src/coValues/coStream.ts
CHANGED
|
@@ -3,6 +3,7 @@ import { CoID, RawCoValue } from "../coValue.js";
|
|
|
3
3
|
import { CoValueCore } from "../coValueCore.js";
|
|
4
4
|
import { AgentID, SessionID, TransactionID } from "../ids.js";
|
|
5
5
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
6
|
+
import { logger } from "../logger.js";
|
|
6
7
|
import { CoValueKnownState } from "../sync.js";
|
|
7
8
|
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
|
|
8
9
|
import { isAccountID } from "../typeUtils/isAccountID.js";
|
|
@@ -309,7 +310,7 @@ export class RawBinaryCoStreamView<
|
|
|
309
310
|
const start = items[0];
|
|
310
311
|
|
|
311
312
|
if (start?.type !== "start") {
|
|
312
|
-
|
|
313
|
+
logger.error("Invalid binary stream start", start);
|
|
313
314
|
return;
|
|
314
315
|
}
|
|
315
316
|
|
|
@@ -328,7 +329,7 @@ export class RawBinaryCoStreamView<
|
|
|
328
329
|
}
|
|
329
330
|
|
|
330
331
|
if (item.type !== "chunk") {
|
|
331
|
-
|
|
332
|
+
logger.error("Invalid binary stream chunk", item);
|
|
332
333
|
return undefined;
|
|
333
334
|
}
|
|
334
335
|
|
|
@@ -382,7 +383,6 @@ export class RawBinaryCoStream<
|
|
|
382
383
|
chunk: Uint8Array,
|
|
383
384
|
privacy: "private" | "trusting" = "private",
|
|
384
385
|
): void {
|
|
385
|
-
// const before = performance.now();
|
|
386
386
|
this.push(
|
|
387
387
|
{
|
|
388
388
|
type: "chunk",
|
|
@@ -391,11 +391,6 @@ export class RawBinaryCoStream<
|
|
|
391
391
|
privacy,
|
|
392
392
|
false,
|
|
393
393
|
);
|
|
394
|
-
// const after = performance.now();
|
|
395
|
-
// console.log(
|
|
396
|
-
// "pushBinaryStreamChunk bandwidth in MB/s",
|
|
397
|
-
// (1000 * chunk.length) / (after - before) / (1024 * 1024)
|
|
398
|
-
// );
|
|
399
394
|
}
|
|
400
395
|
|
|
401
396
|
endBinaryStream(privacy: "private" | "trusting" = "private") {
|
package/src/coValues/group.ts
CHANGED
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
isParentGroupReference,
|
|
14
14
|
} from "../ids.js";
|
|
15
15
|
import { JsonObject } from "../jsonValue.js";
|
|
16
|
+
import { logger } from "../logger.js";
|
|
16
17
|
import { AccountRole, Role } from "../permissions.js";
|
|
17
18
|
import { expectGroup } from "../typeUtils/expectGroup.js";
|
|
18
19
|
import {
|
|
@@ -153,7 +154,7 @@ export class RawGroup<
|
|
|
153
154
|
child.state.type === "unavailable"
|
|
154
155
|
) {
|
|
155
156
|
child.loadFromPeers(peers).catch(() => {
|
|
156
|
-
|
|
157
|
+
logger.error(`Failed to load child group ${id}`);
|
|
157
158
|
});
|
|
158
159
|
}
|
|
159
160
|
|
|
@@ -321,7 +322,7 @@ export class RawGroup<
|
|
|
321
322
|
const secret = this.core.getReadKey(keyID);
|
|
322
323
|
|
|
323
324
|
if (!secret) {
|
|
324
|
-
|
|
325
|
+
logger.error("Can't find key", keyID);
|
|
325
326
|
continue;
|
|
326
327
|
}
|
|
327
328
|
|
|
@@ -7,6 +7,7 @@ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
|
7
7
|
import { RawCoID, TransactionID } from "../ids.js";
|
|
8
8
|
import { Stringified, stableStringify } from "../jsonStringify.js";
|
|
9
9
|
import { JsonValue } from "../jsonValue.js";
|
|
10
|
+
import { logger } from "../logger.js";
|
|
10
11
|
import {
|
|
11
12
|
CryptoProvider,
|
|
12
13
|
Encrypted,
|
|
@@ -192,7 +193,7 @@ export class PureJSCrypto extends CryptoProvider<Blake3State> {
|
|
|
192
193
|
try {
|
|
193
194
|
return JSON.parse(textDecoder.decode(plaintext));
|
|
194
195
|
} catch (e) {
|
|
195
|
-
|
|
196
|
+
logger.error("Failed to decrypt/parse sealed message", e);
|
|
196
197
|
return undefined;
|
|
197
198
|
}
|
|
198
199
|
}
|
package/src/crypto/WasmCrypto.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { base64URLtoBytes, bytesToBase64url } from "../base64url.js";
|
|
|
15
15
|
import { RawCoID, TransactionID } from "../ids.js";
|
|
16
16
|
import { Stringified, stableStringify } from "../jsonStringify.js";
|
|
17
17
|
import { JsonValue } from "../jsonValue.js";
|
|
18
|
+
import { logger } from "../logger.js";
|
|
18
19
|
import {
|
|
19
20
|
CryptoProvider,
|
|
20
21
|
Encrypted,
|
|
@@ -240,7 +241,7 @@ export class WasmCrypto extends CryptoProvider<Uint8Array> {
|
|
|
240
241
|
try {
|
|
241
242
|
return JSON.parse(textDecoder.decode(plaintext));
|
|
242
243
|
} catch (e) {
|
|
243
|
-
|
|
244
|
+
logger.error("Failed to decrypt/parse sealed message", e);
|
|
244
245
|
return undefined;
|
|
245
246
|
}
|
|
246
247
|
}
|
package/src/crypto/crypto.ts
CHANGED
|
@@ -4,6 +4,7 @@ import { AgentID, RawCoID, TransactionID } from "../ids.js";
|
|
|
4
4
|
import { SessionID } from "../ids.js";
|
|
5
5
|
import { Stringified, parseJSON, stableStringify } from "../jsonStringify.js";
|
|
6
6
|
import { JsonValue } from "../jsonValue.js";
|
|
7
|
+
import { logger } from "../logger.js";
|
|
7
8
|
|
|
8
9
|
export type SignerSecret = `signerSecret_z${string}`;
|
|
9
10
|
export type SignerID = `signer_z${string}`;
|
|
@@ -159,7 +160,7 @@ export abstract class CryptoProvider<Blake3State = any> {
|
|
|
159
160
|
try {
|
|
160
161
|
return parseJSON(this.decryptRaw(encrypted, keySecret, nOnceMaterial));
|
|
161
162
|
} catch (e) {
|
|
162
|
-
|
|
163
|
+
logger.error("Decryption error", e);
|
|
163
164
|
return undefined;
|
|
164
165
|
}
|
|
165
166
|
}
|
|
@@ -305,10 +306,7 @@ export class StreamingHash {
|
|
|
305
306
|
|
|
306
307
|
update(value: JsonValue): Uint8Array {
|
|
307
308
|
const encoded = textEncoder.encode(stableStringify(value));
|
|
308
|
-
// const before = performance.now();
|
|
309
309
|
this.state = this.crypto.blake3IncrementalUpdate(this.state, encoded);
|
|
310
|
-
// const after = performance.now();
|
|
311
|
-
// console.log(`Hashing throughput in MB/s`, 1000 * (encoded.length / (after - before)) / (1024 * 1024));
|
|
312
310
|
return encoded;
|
|
313
311
|
}
|
|
314
312
|
|
package/src/exports.ts
CHANGED
|
@@ -74,6 +74,7 @@ import {
|
|
|
74
74
|
|
|
75
75
|
type Value = JsonValue | AnyRawCoValue;
|
|
76
76
|
|
|
77
|
+
import { logger } from "./logger.js";
|
|
77
78
|
import { getPriorityFromHeader } from "./priority.js";
|
|
78
79
|
import { FileSystem } from "./storage/FileSystem.js";
|
|
79
80
|
import { BlockFilename, LSMStorage, WalFilename } from "./storage/index.js";
|
|
@@ -141,6 +142,7 @@ export {
|
|
|
141
142
|
emptyKnownState,
|
|
142
143
|
RawCoPlainText,
|
|
143
144
|
stringifyOpID,
|
|
145
|
+
logger,
|
|
144
146
|
};
|
|
145
147
|
|
|
146
148
|
export type {
|
package/src/localNode.ts
CHANGED
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
} from "./coValues/group.js";
|
|
28
28
|
import { AgentSecret, CryptoProvider } from "./crypto/crypto.js";
|
|
29
29
|
import { AgentID, RawCoID, SessionID, isAgentID } from "./ids.js";
|
|
30
|
+
import { logger } from "./logger.js";
|
|
30
31
|
import { Peer, PeerID, SyncManager } from "./sync.js";
|
|
31
32
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
32
33
|
|
|
@@ -230,7 +231,7 @@ export class LocalNode {
|
|
|
230
231
|
|
|
231
232
|
return node;
|
|
232
233
|
} catch (e) {
|
|
233
|
-
|
|
234
|
+
logger.error("Error withLoadedAccount", e);
|
|
234
235
|
throw e;
|
|
235
236
|
}
|
|
236
237
|
}
|
|
@@ -269,7 +270,7 @@ export class LocalNode {
|
|
|
269
270
|
this.syncManager.getServerAndStoragePeers(skipLoadingFromPeer);
|
|
270
271
|
|
|
271
272
|
await entry.loadFromPeers(peers).catch((e) => {
|
|
272
|
-
|
|
273
|
+
logger.error("Error loading from peers", id, e);
|
|
273
274
|
});
|
|
274
275
|
}
|
|
275
276
|
|
|
@@ -311,8 +312,6 @@ export class LocalNode {
|
|
|
311
312
|
let stopped = false;
|
|
312
313
|
let unsubscribe!: () => void;
|
|
313
314
|
|
|
314
|
-
// console.log("Subscribing to " + id);
|
|
315
|
-
|
|
316
315
|
this.load(id)
|
|
317
316
|
.then((coValue) => {
|
|
318
317
|
if (stopped) {
|
|
@@ -325,11 +324,10 @@ export class LocalNode {
|
|
|
325
324
|
unsubscribe = coValue.subscribe(callback);
|
|
326
325
|
})
|
|
327
326
|
.catch((e) => {
|
|
328
|
-
|
|
327
|
+
logger.error("Error subscribing to ", id, e);
|
|
329
328
|
});
|
|
330
329
|
|
|
331
330
|
return () => {
|
|
332
|
-
console.log("Unsubscribing from " + id);
|
|
333
331
|
stopped = true;
|
|
334
332
|
unsubscribe?.();
|
|
335
333
|
};
|
|
@@ -390,9 +388,7 @@ export class LocalNode {
|
|
|
390
388
|
(existingRole === "reader" && inviteRole === "readerInvite") ||
|
|
391
389
|
(existingRole && inviteRole === "writeOnlyInvite")
|
|
392
390
|
) {
|
|
393
|
-
|
|
394
|
-
"Not accepting invite that would replace or downgrade role",
|
|
395
|
-
);
|
|
391
|
+
logger.debug("Not accepting invite that would replace or downgrade role");
|
|
396
392
|
return;
|
|
397
393
|
}
|
|
398
394
|
|
package/src/logger.ts
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
export enum LogLevel {
|
|
2
|
+
DEBUG = 0,
|
|
3
|
+
INFO = 1,
|
|
4
|
+
WARN = 2,
|
|
5
|
+
ERROR = 3,
|
|
6
|
+
NONE = 4,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface LogSystem {
|
|
10
|
+
debug(message: string, ...args: any[]): void;
|
|
11
|
+
info(message: string, ...args: any[]): void;
|
|
12
|
+
warn(message: string, ...args: any[]): void;
|
|
13
|
+
error(message: string, ...args: any[]): void;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Default console-based logging system
|
|
17
|
+
export class ConsoleLogSystem implements LogSystem {
|
|
18
|
+
debug(message: string, ...args: any[]) {
|
|
19
|
+
console.debug(message, ...args);
|
|
20
|
+
}
|
|
21
|
+
info(message: string, ...args: any[]) {
|
|
22
|
+
console.info(message, ...args);
|
|
23
|
+
}
|
|
24
|
+
warn(message: string, ...args: any[]) {
|
|
25
|
+
console.warn(message, ...args);
|
|
26
|
+
}
|
|
27
|
+
error(message: string, ...args: any[]) {
|
|
28
|
+
console.error(message, ...args);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export class Logger {
|
|
33
|
+
private level: LogLevel;
|
|
34
|
+
private logSystem: LogSystem;
|
|
35
|
+
|
|
36
|
+
constructor(
|
|
37
|
+
level: LogLevel = LogLevel.INFO,
|
|
38
|
+
logSystem: LogSystem = new ConsoleLogSystem(),
|
|
39
|
+
) {
|
|
40
|
+
this.level = level;
|
|
41
|
+
this.logSystem = logSystem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
setLevel(level: LogLevel) {
|
|
45
|
+
this.level = level;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
setLogSystem(logSystem: LogSystem) {
|
|
49
|
+
this.logSystem = logSystem;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
debug(message: string, ...args: any[]) {
|
|
53
|
+
if (this.level <= LogLevel.DEBUG) {
|
|
54
|
+
this.logSystem.debug(message, ...args);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
info(message: string, ...args: any[]) {
|
|
59
|
+
if (this.level <= LogLevel.INFO) {
|
|
60
|
+
this.logSystem.info(message, ...args);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
warn(message: string, ...args: any[]) {
|
|
65
|
+
if (this.level <= LogLevel.WARN) {
|
|
66
|
+
this.logSystem.warn(message, ...args);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
error(message: string, ...args: any[]) {
|
|
71
|
+
if (this.level <= LogLevel.ERROR) {
|
|
72
|
+
this.logSystem.error(message, ...args);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Create default logger instance
|
|
78
|
+
export const logger = new Logger();
|
package/src/permissions.ts
CHANGED
|
@@ -14,6 +14,7 @@ import {
|
|
|
14
14
|
} from "./ids.js";
|
|
15
15
|
import { parseJSON } from "./jsonStringify.js";
|
|
16
16
|
import { JsonValue } from "./jsonValue.js";
|
|
17
|
+
import { logger } from "./logger.js";
|
|
17
18
|
import { accountOrAgentIDfromSessionID } from "./typeUtils/accountOrAgentIDfromSessionID.js";
|
|
18
19
|
import { expectGroup } from "./typeUtils/expectGroup.js";
|
|
19
20
|
|
|
@@ -46,7 +47,7 @@ function logPermissionError(...args: unknown[]) {
|
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
|
|
50
|
+
logger.warn("Permission error", ...args);
|
|
50
51
|
}
|
|
51
52
|
|
|
52
53
|
export function determineValidTransactions(
|
|
@@ -204,7 +205,6 @@ function determineValidTransactionsForGroup(
|
|
|
204
205
|
const writeKeys = new Set<string>();
|
|
205
206
|
|
|
206
207
|
for (const { sessionID, txIndex, tx } of allTransactionsSorted) {
|
|
207
|
-
// console.log("before", { memberState, validTransactions });
|
|
208
208
|
const transactor = accountOrAgentIDfromSessionID(sessionID);
|
|
209
209
|
|
|
210
210
|
if (tx.privacy === "private") {
|
|
@@ -458,8 +458,6 @@ function determineValidTransactionsForGroup(
|
|
|
458
458
|
|
|
459
459
|
memberState[affectedMember] = change.value;
|
|
460
460
|
validTransactions.push({ txID: { sessionID, txIndex }, tx });
|
|
461
|
-
|
|
462
|
-
// console.log("after", { memberState, validTransactions });
|
|
463
461
|
}
|
|
464
462
|
|
|
465
463
|
return { validTransactions, memberState };
|
|
@@ -473,7 +471,7 @@ function agentInAccountOrMemberInGroup(
|
|
|
473
471
|
return groupAtTime.currentAgentID().match(
|
|
474
472
|
(agentID) => agentID,
|
|
475
473
|
(e) => {
|
|
476
|
-
|
|
474
|
+
logger.error(
|
|
477
475
|
"Error while determining current agent ID in valid transactions",
|
|
478
476
|
e,
|
|
479
477
|
);
|
|
@@ -87,26 +87,15 @@ export async function writeBlock<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
|
87
87
|
const headerBytes = textEncoder.encode(JSON.stringify(blockHeader));
|
|
88
88
|
await fs.append(file, headerBytes);
|
|
89
89
|
|
|
90
|
-
// console.log(
|
|
91
|
-
// "full file",
|
|
92
|
-
// yield* $(
|
|
93
|
-
// fs.read(file as unknown as RH, 0, offset + headerBytes.length),
|
|
94
|
-
// ),
|
|
95
|
-
// );
|
|
96
|
-
|
|
97
90
|
const filename: BlockFilename = `L${level}-${(blockNumber + "").padStart(
|
|
98
91
|
3,
|
|
99
92
|
"0",
|
|
100
93
|
)}-${hash.digest().replace("hash_", "").slice(0, 15)}-H${
|
|
101
94
|
headerBytes.length
|
|
102
95
|
}.jsonl`;
|
|
103
|
-
// console.log("renaming to" + filename);
|
|
104
96
|
await fs.closeAndRename(file, filename);
|
|
105
97
|
|
|
106
98
|
return filename;
|
|
107
|
-
|
|
108
|
-
// console.log("Wrote block", filename, blockHeader);
|
|
109
|
-
// console.log("IDs in block", blockHeader.map(e => e.id));
|
|
110
99
|
}
|
|
111
100
|
|
|
112
101
|
export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
@@ -120,6 +109,5 @@ export async function writeToWal<WH, RH, FS extends FileSystem<WH, RH>>(
|
|
|
120
109
|
...chunk,
|
|
121
110
|
};
|
|
122
111
|
const bytes = textEncoder.encode(JSON.stringify(walEntry) + "\n");
|
|
123
|
-
console.log("writing to WAL", handle, id, bytes.length);
|
|
124
112
|
return fs.append(handle, bytes);
|
|
125
113
|
}
|