cojson 0.20.7 → 0.20.9
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 +1 -1
- package/CHANGELOG.md +26 -0
- package/dist/SyncStateManager.d.ts.map +1 -1
- package/dist/SyncStateManager.js +0 -2
- package/dist/SyncStateManager.js.map +1 -1
- package/dist/base64url.d.ts +15 -0
- package/dist/base64url.d.ts.map +1 -1
- package/dist/base64url.js +101 -5
- package/dist/base64url.js.map +1 -1
- package/dist/base64url.test.js +76 -1
- package/dist/base64url.test.js.map +1 -1
- package/dist/coValue.d.ts +2 -1
- package/dist/coValue.d.ts.map +1 -1
- package/dist/coValue.js.map +1 -1
- package/dist/coValueCore/coValueCore.d.ts +9 -11
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +92 -65
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +38 -7
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +226 -30
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/binaryCoStream.d.ts +63 -0
- package/dist/coValues/binaryCoStream.d.ts.map +1 -0
- package/dist/coValues/binaryCoStream.js +125 -0
- package/dist/coValues/binaryCoStream.js.map +1 -0
- package/dist/coValues/coList.d.ts +3 -1
- package/dist/coValues/coList.d.ts.map +1 -1
- package/dist/coValues/coList.js +15 -6
- package/dist/coValues/coList.js.map +1 -1
- package/dist/coValues/coMap.d.ts +1 -1
- package/dist/coValues/coMap.d.ts.map +1 -1
- package/dist/coValues/coMap.js +2 -2
- package/dist/coValues/coMap.js.map +1 -1
- package/dist/coValues/coStream.d.ts +0 -38
- package/dist/coValues/coStream.d.ts.map +1 -1
- package/dist/coValues/coStream.js +0 -86
- package/dist/coValues/coStream.js.map +1 -1
- package/dist/coValues/group.d.ts +44 -6
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +198 -17
- package/dist/coValues/group.js.map +1 -1
- package/dist/coreToCoValue.d.ts +2 -1
- package/dist/coreToCoValue.d.ts.map +1 -1
- package/dist/coreToCoValue.js +2 -1
- package/dist/coreToCoValue.js.map +1 -1
- package/dist/crypto/NapiCrypto.d.ts +18 -24
- package/dist/crypto/NapiCrypto.d.ts.map +1 -1
- package/dist/crypto/NapiCrypto.js +98 -60
- package/dist/crypto/NapiCrypto.js.map +1 -1
- package/dist/crypto/RNCrypto.d.ts +16 -3
- package/dist/crypto/RNCrypto.d.ts.map +1 -1
- package/dist/crypto/RNCrypto.js +117 -54
- package/dist/crypto/RNCrypto.js.map +1 -1
- package/dist/crypto/WasmCrypto.d.ts +18 -24
- package/dist/crypto/WasmCrypto.d.ts.map +1 -1
- package/dist/crypto/WasmCrypto.js +100 -61
- package/dist/crypto/WasmCrypto.js.map +1 -1
- package/dist/crypto/crypto.d.ts +55 -19
- package/dist/crypto/crypto.d.ts.map +1 -1
- package/dist/crypto/crypto.js +14 -3
- package/dist/crypto/crypto.js.map +1 -1
- package/dist/exports.d.ts +7 -3
- package/dist/exports.d.ts.map +1 -1
- package/dist/exports.js +4 -2
- package/dist/exports.js.map +1 -1
- package/dist/localNode.d.ts +3 -1
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +10 -3
- package/dist/localNode.js.map +1 -1
- package/dist/media.d.ts +1 -1
- package/dist/media.d.ts.map +1 -1
- package/dist/permissions.d.ts +2 -1
- package/dist/permissions.d.ts.map +1 -1
- package/dist/permissions.js +19 -3
- package/dist/permissions.js.map +1 -1
- package/dist/storage/sqliteAsync/client.d.ts +24 -12
- package/dist/storage/sqliteAsync/client.d.ts.map +1 -1
- package/dist/storage/sqliteAsync/client.js +70 -58
- package/dist/storage/sqliteAsync/client.js.map +1 -1
- package/dist/storage/sqliteAsync/types.d.ts +1 -1
- package/dist/storage/sqliteAsync/types.d.ts.map +1 -1
- package/dist/storage/types.d.ts +1 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +7 -1
- package/dist/sync.js.map +1 -1
- package/dist/tests/CojsonMessageChannel.test.js +2 -2
- package/dist/tests/SQLiteClientAsync.test.d.ts +2 -0
- package/dist/tests/SQLiteClientAsync.test.d.ts.map +1 -0
- package/dist/tests/SQLiteClientAsync.test.js +64 -0
- package/dist/tests/SQLiteClientAsync.test.js.map +1 -0
- package/dist/tests/StorageApiAsync.test.js +2 -8
- package/dist/tests/StorageApiAsync.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +2 -2
- package/dist/tests/WasmCrypto.test.js +1 -15
- package/dist/tests/WasmCrypto.test.js.map +1 -1
- package/dist/tests/coList.test.js +24 -5
- package/dist/tests/coList.test.js.map +1 -1
- package/dist/tests/coStream.test.js +4 -3
- package/dist/tests/coStream.test.js.map +1 -1
- package/dist/tests/coValueCore.initTransaction.test.d.ts +2 -0
- package/dist/tests/coValueCore.initTransaction.test.d.ts.map +1 -0
- package/dist/tests/coValueCore.initTransaction.test.js +438 -0
- package/dist/tests/coValueCore.initTransaction.test.js.map +1 -0
- package/dist/tests/coValueCore.test.js +11 -19
- package/dist/tests/coValueCore.test.js.map +1 -1
- package/dist/tests/crypto.test.js +83 -0
- package/dist/tests/crypto.test.js.map +1 -1
- package/dist/tests/deleteCoValue.test.js +5 -5
- package/dist/tests/deleteCoValue.test.js.map +1 -1
- package/dist/tests/group.inheritance.test.js +11 -0
- package/dist/tests/group.inheritance.test.js.map +1 -1
- package/dist/tests/group.test.js +24 -1
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/groupSealer.test.d.ts +2 -0
- package/dist/tests/groupSealer.test.d.ts.map +1 -0
- package/dist/tests/groupSealer.test.js +913 -0
- package/dist/tests/groupSealer.test.js.map +1 -0
- package/dist/tests/setup.js +5 -0
- package/dist/tests/setup.js.map +1 -1
- package/dist/tests/sync.auth.test.js +10 -10
- package/dist/tests/sync.concurrentLoad.test.js +12 -12
- package/dist/tests/sync.deleted.test.js +8 -8
- package/dist/tests/sync.garbageCollection.test.js +10 -10
- package/dist/tests/sync.invite.test.js +12 -12
- package/dist/tests/sync.known.test.js +2 -2
- package/dist/tests/sync.load.test.js +107 -107
- package/dist/tests/sync.mesh.test.js +164 -46
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.multipleServers.test.js +43 -43
- package/dist/tests/sync.peerReconciliation.test.js +29 -29
- package/dist/tests/sync.sharding.test.js +3 -3
- package/dist/tests/sync.storage.test.js +104 -104
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +56 -56
- package/dist/tests/sync.upload.test.js +22 -22
- package/dist/tests/testStorage.d.ts +2 -0
- package/dist/tests/testStorage.d.ts.map +1 -1
- package/dist/tests/testStorage.js +30 -6
- package/dist/tests/testStorage.js.map +1 -1
- package/dist/typeUtils/isCoValue.js +1 -1
- package/dist/typeUtils/isCoValue.js.map +1 -1
- package/package.json +4 -4
- package/src/SyncStateManager.ts +0 -2
- package/src/base64url.test.ts +89 -1
- package/src/base64url.ts +134 -6
- package/src/coValue.ts +2 -1
- package/src/coValueCore/coValueCore.ts +126 -84
- package/src/coValueCore/verifiedState.ts +335 -53
- package/src/coValues/binaryCoStream.ts +217 -0
- package/src/coValues/coList.ts +21 -8
- package/src/coValues/coMap.ts +3 -0
- package/src/coValues/coStream.ts +0 -170
- package/src/coValues/group.ts +270 -21
- package/src/coreToCoValue.ts +2 -1
- package/src/crypto/NapiCrypto.ts +198 -95
- package/src/crypto/RNCrypto.ts +229 -102
- package/src/crypto/WasmCrypto.ts +201 -95
- package/src/crypto/crypto.ts +118 -45
- package/src/exports.ts +11 -5
- package/src/localNode.ts +17 -1
- package/src/media.ts +1 -1
- package/src/permissions.ts +30 -7
- package/src/storage/sqliteAsync/client.ts +136 -115
- package/src/storage/sqliteAsync/types.ts +3 -1
- package/src/storage/types.ts +4 -0
- package/src/sync.ts +10 -1
- package/src/tests/CojsonMessageChannel.test.ts +2 -2
- package/src/tests/SQLiteClientAsync.test.ts +75 -0
- package/src/tests/StorageApiAsync.test.ts +4 -9
- package/src/tests/SyncStateManager.test.ts +2 -2
- package/src/tests/WasmCrypto.test.ts +1 -25
- package/src/tests/coList.test.ts +39 -5
- package/src/tests/coStream.test.ts +4 -5
- package/src/tests/coValueCore.initTransaction.test.ts +836 -0
- package/src/tests/coValueCore.test.ts +11 -22
- package/src/tests/crypto.test.ts +107 -0
- package/src/tests/deleteCoValue.test.ts +5 -5
- package/src/tests/group.inheritance.test.ts +16 -0
- package/src/tests/group.test.ts +29 -1
- package/src/tests/groupSealer.test.ts +1473 -0
- package/src/tests/setup.ts +6 -0
- package/src/tests/sync.auth.test.ts +10 -10
- package/src/tests/sync.concurrentLoad.test.ts +12 -12
- package/src/tests/sync.deleted.test.ts +8 -8
- package/src/tests/sync.garbageCollection.test.ts +10 -10
- package/src/tests/sync.invite.test.ts +12 -12
- package/src/tests/sync.known.test.ts +2 -2
- package/src/tests/sync.load.test.ts +107 -107
- package/src/tests/sync.mesh.test.ts +189 -46
- package/src/tests/sync.multipleServers.test.ts +43 -43
- package/src/tests/sync.peerReconciliation.test.ts +29 -29
- package/src/tests/sync.sharding.test.ts +3 -3
- package/src/tests/sync.storage.test.ts +104 -104
- package/src/tests/sync.storageAsync.test.ts +56 -56
- package/src/tests/sync.upload.test.ts +22 -22
- package/src/tests/testStorage.ts +39 -9
- package/src/typeUtils/isCoValue.ts +1 -1
- package/dist/coValueCore/SessionMap.d.ts +0 -55
- package/dist/coValueCore/SessionMap.d.ts.map +0 -1
- package/dist/coValueCore/SessionMap.js +0 -206
- package/dist/coValueCore/SessionMap.js.map +0 -1
- package/dist/tests/coreWasm.test.d.ts +0 -2
- package/dist/tests/coreWasm.test.d.ts.map +0 -1
- package/dist/tests/coreWasm.test.js +0 -203
- package/dist/tests/coreWasm.test.js.map +0 -1
- package/src/coValueCore/SessionMap.ts +0 -394
- package/src/tests/coreWasm.test.ts +0 -452
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
exceedsRecommendedSize,
|
|
5
5
|
getTransactionSize,
|
|
6
6
|
addTransactionToContentMessage,
|
|
7
|
-
knownStateFromContent,
|
|
8
7
|
} from "../coValueContentMessage.js";
|
|
9
8
|
import {
|
|
10
9
|
CryptoProvider,
|
|
@@ -13,6 +12,7 @@ import {
|
|
|
13
12
|
KeySecret,
|
|
14
13
|
Signature,
|
|
15
14
|
SignerID,
|
|
15
|
+
SessionMapImpl,
|
|
16
16
|
} from "../crypto/crypto.js";
|
|
17
17
|
import {
|
|
18
18
|
isDeleteSessionID,
|
|
@@ -20,17 +20,17 @@ import {
|
|
|
20
20
|
SessionID,
|
|
21
21
|
TransactionID,
|
|
22
22
|
} from "../ids.js";
|
|
23
|
-
import { Stringified } from "../jsonStringify.js";
|
|
23
|
+
import { Stringified, parseJSON } from "../jsonStringify.js";
|
|
24
24
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
25
25
|
import { PermissionsDef as RulesetDef } from "../permissions.js";
|
|
26
26
|
import { NewContentMessage } from "../sync.js";
|
|
27
|
-
import { SessionMap } from "./SessionMap.js";
|
|
28
27
|
import { ControlledAccountOrAgent } from "../coValues/account.js";
|
|
29
28
|
import {
|
|
30
29
|
CoValueKnownState,
|
|
31
30
|
getKnownStateToSend,
|
|
32
31
|
KnownStateSessions,
|
|
33
32
|
} from "../knownState.js";
|
|
33
|
+
import { TRANSACTION_CONFIG } from "../config.js";
|
|
34
34
|
|
|
35
35
|
export type CoValueHeader = {
|
|
36
36
|
type: AnyRawCoValue["type"];
|
|
@@ -68,42 +68,197 @@ export type TrustingTransaction = {
|
|
|
68
68
|
|
|
69
69
|
export type Transaction = PrivateTransaction | TrustingTransaction;
|
|
70
70
|
|
|
71
|
+
export type SessionLog = {
|
|
72
|
+
signerID?: SignerID;
|
|
73
|
+
transactions: Transaction[];
|
|
74
|
+
lastSignature: Signature | undefined;
|
|
75
|
+
signatureAfter: { [txIdx: number]: Signature | undefined };
|
|
76
|
+
sessionID: SessionID;
|
|
77
|
+
};
|
|
78
|
+
|
|
71
79
|
export class VerifiedState {
|
|
72
80
|
readonly id: RawCoID;
|
|
73
81
|
readonly crypto: CryptoProvider;
|
|
74
82
|
readonly header: CoValueHeader;
|
|
75
|
-
readonly
|
|
83
|
+
private readonly impl: SessionMapImpl;
|
|
76
84
|
public lastAccessed: number | undefined;
|
|
77
85
|
public branchSourceId?: RawCoID;
|
|
78
86
|
public branchName?: string;
|
|
79
87
|
private isDeleted: boolean = false;
|
|
80
88
|
|
|
89
|
+
// Cache for SessionLog objects to avoid re-parsing on every access
|
|
90
|
+
private sessionLogCache: Map<SessionID, SessionLog> = new Map();
|
|
91
|
+
private sessionLogCacheValid: Map<SessionID, number> = new Map(); // txCount when cached
|
|
92
|
+
|
|
93
|
+
// Cache for known state to avoid repeated FFI calls between mutations
|
|
94
|
+
private cachedKnownState: CoValueKnownState | undefined;
|
|
95
|
+
private cachedKnownStateWithStreaming: CoValueKnownState | undefined;
|
|
96
|
+
|
|
81
97
|
constructor(
|
|
82
98
|
id: RawCoID,
|
|
83
99
|
crypto: CryptoProvider,
|
|
84
100
|
header: CoValueHeader,
|
|
85
|
-
|
|
101
|
+
streamingKnownState?: KnownStateSessions,
|
|
102
|
+
skipVerify?: boolean,
|
|
86
103
|
) {
|
|
87
104
|
this.id = id;
|
|
88
105
|
this.crypto = crypto;
|
|
89
106
|
this.header = header;
|
|
90
|
-
this.sessions = sessions ?? new SessionMap(id, crypto);
|
|
91
107
|
this.branchSourceId = header.meta?.source as RawCoID | undefined;
|
|
92
108
|
this.branchName = header.meta?.branch as string | undefined;
|
|
93
|
-
}
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.sessions.clone(),
|
|
110
|
+
this.impl = crypto.createSessionMap(
|
|
111
|
+
id,
|
|
112
|
+
JSON.stringify(header),
|
|
113
|
+
TRANSACTION_CONFIG.MAX_RECOMMENDED_TX_SIZE,
|
|
114
|
+
skipVerify,
|
|
101
115
|
);
|
|
116
|
+
|
|
117
|
+
// Set streaming known state if provided
|
|
118
|
+
if (streamingKnownState) {
|
|
119
|
+
this.impl.setStreamingKnownState(JSON.stringify(streamingKnownState));
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
private invalidateCache() {
|
|
124
|
+
this.sessionLogCache.clear();
|
|
125
|
+
this.sessionLogCacheValid.clear();
|
|
126
|
+
this.invalidateKnownStateCache();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
private invalidateKnownStateCache() {
|
|
130
|
+
this.cachedKnownState = undefined;
|
|
131
|
+
this.cachedKnownStateWithStreaming = undefined;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Update the session log cache directly when adding transactions.
|
|
136
|
+
* This avoids round-trips to Rust on subsequent reads.
|
|
137
|
+
*/
|
|
138
|
+
private updateSessionLogCache(
|
|
139
|
+
sessionID: SessionID,
|
|
140
|
+
signerID: SignerID | undefined,
|
|
141
|
+
newTransactions: Transaction[],
|
|
142
|
+
newSignature: Signature,
|
|
143
|
+
) {
|
|
144
|
+
const cached = this.sessionLogCache.get(sessionID);
|
|
145
|
+
const currentTxCount = this.impl.getTransactionCount(sessionID);
|
|
146
|
+
|
|
147
|
+
if (cached) {
|
|
148
|
+
// Append to existing cache
|
|
149
|
+
for (const tx of newTransactions) {
|
|
150
|
+
cached.transactions.push(tx);
|
|
151
|
+
}
|
|
152
|
+
cached.lastSignature = newSignature;
|
|
153
|
+
if (signerID) {
|
|
154
|
+
cached.signerID = signerID;
|
|
155
|
+
}
|
|
156
|
+
// Check if we need to update signatureAfter (in-between signature)
|
|
157
|
+
this.updateLastCheckpointSignature(sessionID, cached.signatureAfter);
|
|
158
|
+
this.sessionLogCacheValid.set(sessionID, currentTxCount);
|
|
159
|
+
} else {
|
|
160
|
+
// Create new cache entry
|
|
161
|
+
const signatureAfter: { [txIdx: number]: Signature | undefined } = {};
|
|
162
|
+
this.updateLastCheckpointSignature(sessionID, signatureAfter);
|
|
163
|
+
const sessionLog: SessionLog = {
|
|
164
|
+
signerID,
|
|
165
|
+
transactions: newTransactions.slice(),
|
|
166
|
+
lastSignature: newSignature,
|
|
167
|
+
signatureAfter,
|
|
168
|
+
sessionID,
|
|
169
|
+
};
|
|
170
|
+
this.sessionLogCache.set(sessionID, sessionLog);
|
|
171
|
+
this.sessionLogCacheValid.set(sessionID, currentTxCount);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* Update the signatureAfter map with the latest checkpoint signature.
|
|
177
|
+
* Used when updating cache incrementally.
|
|
178
|
+
*/
|
|
179
|
+
private updateLastCheckpointSignature(
|
|
180
|
+
sessionID: SessionID,
|
|
181
|
+
signatureAfter: { [txIdx: number]: Signature | undefined },
|
|
182
|
+
): void {
|
|
183
|
+
const lastCheckpoint = this.impl.getLastSignatureCheckpoint(sessionID);
|
|
184
|
+
if (
|
|
185
|
+
lastCheckpoint !== undefined &&
|
|
186
|
+
lastCheckpoint !== null &&
|
|
187
|
+
lastCheckpoint >= 0
|
|
188
|
+
) {
|
|
189
|
+
const sig = this.impl.getSignatureAfter(sessionID, lastCheckpoint);
|
|
190
|
+
if (sig) {
|
|
191
|
+
signatureAfter[lastCheckpoint] = sig as Signature;
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Build the signatureAfter map for a session by iterating through all checkpoints.
|
|
198
|
+
* Used when building a fresh SessionLog from Rust data.
|
|
199
|
+
*/
|
|
200
|
+
private buildSignatureAfterMap(sessionID: SessionID): {
|
|
201
|
+
[txIdx: number]: Signature | undefined;
|
|
202
|
+
} {
|
|
203
|
+
const signatureAfter: { [txIdx: number]: Signature | undefined } = {};
|
|
204
|
+
const lastCheckpoint = this.impl.getLastSignatureCheckpoint(sessionID);
|
|
205
|
+
if (
|
|
206
|
+
lastCheckpoint !== undefined &&
|
|
207
|
+
lastCheckpoint !== null &&
|
|
208
|
+
lastCheckpoint >= 0
|
|
209
|
+
) {
|
|
210
|
+
for (let i = 0; i <= lastCheckpoint; i++) {
|
|
211
|
+
const sig = this.impl.getSignatureAfter(sessionID, i);
|
|
212
|
+
if (sig) {
|
|
213
|
+
signatureAfter[i] = sig as Signature;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return signatureAfter;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
private getSessionLog(sessionID: SessionID): SessionLog {
|
|
221
|
+
const currentTxCount = this.impl.getTransactionCount(sessionID);
|
|
222
|
+
const cachedTxCount = this.sessionLogCacheValid.get(sessionID);
|
|
223
|
+
|
|
224
|
+
// Check if cache is valid
|
|
225
|
+
if (cachedTxCount === currentTxCount) {
|
|
226
|
+
const cached = this.sessionLogCache.get(sessionID);
|
|
227
|
+
if (cached) return cached;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Fetch all transactions from Rust
|
|
231
|
+
const transactions: Transaction[] =
|
|
232
|
+
currentTxCount > 0
|
|
233
|
+
? (this.impl.getSessionTransactions(sessionID, 0) ?? [])
|
|
234
|
+
: [];
|
|
235
|
+
|
|
236
|
+
// Build signatureAfter map
|
|
237
|
+
const signatureAfter = this.buildSignatureAfterMap(sessionID);
|
|
238
|
+
|
|
239
|
+
const lastSignature = this.impl.getLastSignature(sessionID) as
|
|
240
|
+
| Signature
|
|
241
|
+
| undefined;
|
|
242
|
+
|
|
243
|
+
const sessionLog: SessionLog = {
|
|
244
|
+
signerID: undefined, // We don't track this in Rust currently
|
|
245
|
+
transactions,
|
|
246
|
+
lastSignature,
|
|
247
|
+
signatureAfter,
|
|
248
|
+
sessionID,
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
// Cache the result
|
|
252
|
+
this.sessionLogCache.set(sessionID, sessionLog);
|
|
253
|
+
this.sessionLogCacheValid.set(sessionID, currentTxCount);
|
|
254
|
+
|
|
255
|
+
return sessionLog;
|
|
102
256
|
}
|
|
103
257
|
|
|
104
258
|
markAsDeleted() {
|
|
105
259
|
this.isDeleted = true;
|
|
106
|
-
this.
|
|
260
|
+
this.impl.markAsDeleted();
|
|
261
|
+
this.invalidateCache();
|
|
107
262
|
}
|
|
108
263
|
|
|
109
264
|
tryAddTransactions(
|
|
@@ -113,13 +268,29 @@ export class VerifiedState {
|
|
|
113
268
|
newSignature: Signature,
|
|
114
269
|
skipVerify: boolean = false,
|
|
115
270
|
) {
|
|
116
|
-
this.
|
|
271
|
+
if (this.isDeleted && !isDeleteSessionID(sessionID)) {
|
|
272
|
+
throw new Error("Cannot add transactions to a deleted coValue");
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Convert transactions to JSON array
|
|
276
|
+
const txJson = JSON.stringify(newTransactions);
|
|
277
|
+
|
|
278
|
+
this.impl.addTransactions(
|
|
117
279
|
sessionID,
|
|
118
280
|
signerID,
|
|
119
|
-
|
|
281
|
+
txJson,
|
|
120
282
|
newSignature,
|
|
121
283
|
skipVerify,
|
|
122
284
|
);
|
|
285
|
+
|
|
286
|
+
// Update cache directly instead of invalidating
|
|
287
|
+
this.updateSessionLogCache(
|
|
288
|
+
sessionID,
|
|
289
|
+
signerID,
|
|
290
|
+
newTransactions,
|
|
291
|
+
newSignature,
|
|
292
|
+
);
|
|
293
|
+
this.invalidateKnownStateCache();
|
|
123
294
|
}
|
|
124
295
|
|
|
125
296
|
makeNewTrustingTransaction(
|
|
@@ -128,16 +299,45 @@ export class VerifiedState {
|
|
|
128
299
|
changes: JsonValue[],
|
|
129
300
|
meta: JsonObject | undefined,
|
|
130
301
|
madeAt: number,
|
|
131
|
-
) {
|
|
132
|
-
|
|
302
|
+
): { signature: Signature; transaction: Transaction } {
|
|
303
|
+
if (this.isDeleted) {
|
|
304
|
+
throw new Error(
|
|
305
|
+
"Cannot make new trusting transaction on a deleted coValue",
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const changesJson = JSON.stringify(changes);
|
|
310
|
+
const metaJson = meta ? JSON.stringify(meta) : undefined;
|
|
311
|
+
const signerSecret = signerAgent.currentSignerSecret();
|
|
312
|
+
|
|
313
|
+
const resultJson = this.impl.makeNewTrustingTransaction(
|
|
133
314
|
sessionID,
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
315
|
+
signerSecret,
|
|
316
|
+
changesJson,
|
|
317
|
+
metaJson,
|
|
137
318
|
madeAt,
|
|
138
319
|
);
|
|
139
320
|
|
|
140
|
-
|
|
321
|
+
const result = JSON.parse(resultJson) as {
|
|
322
|
+
signature: string;
|
|
323
|
+
transaction: Transaction;
|
|
324
|
+
};
|
|
325
|
+
|
|
326
|
+
const signature = result.signature as Signature;
|
|
327
|
+
|
|
328
|
+
// Update cache directly instead of invalidating
|
|
329
|
+
this.updateSessionLogCache(
|
|
330
|
+
sessionID,
|
|
331
|
+
signerAgent.id as unknown as SignerID,
|
|
332
|
+
[result.transaction],
|
|
333
|
+
signature,
|
|
334
|
+
);
|
|
335
|
+
this.invalidateKnownStateCache();
|
|
336
|
+
|
|
337
|
+
return {
|
|
338
|
+
signature,
|
|
339
|
+
transaction: result.transaction,
|
|
340
|
+
};
|
|
141
341
|
}
|
|
142
342
|
|
|
143
343
|
makeNewPrivateTransaction(
|
|
@@ -148,33 +348,92 @@ export class VerifiedState {
|
|
|
148
348
|
keySecret: KeySecret,
|
|
149
349
|
meta: JsonObject | undefined,
|
|
150
350
|
madeAt: number,
|
|
151
|
-
) {
|
|
152
|
-
|
|
351
|
+
): { signature: Signature; transaction: Transaction } {
|
|
352
|
+
if (this.isDeleted) {
|
|
353
|
+
throw new Error(
|
|
354
|
+
"Cannot make new private transaction on a deleted coValue",
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const changesJson = JSON.stringify(changes);
|
|
359
|
+
const metaJson = meta ? JSON.stringify(meta) : undefined;
|
|
360
|
+
const signerSecret = signerAgent.currentSignerSecret();
|
|
361
|
+
|
|
362
|
+
const resultJson = this.impl.makeNewPrivateTransaction(
|
|
153
363
|
sessionID,
|
|
154
|
-
|
|
155
|
-
|
|
364
|
+
signerSecret,
|
|
365
|
+
changesJson,
|
|
156
366
|
keyID,
|
|
157
367
|
keySecret,
|
|
158
|
-
|
|
368
|
+
metaJson,
|
|
159
369
|
madeAt,
|
|
160
370
|
);
|
|
161
371
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const sessionLog = this.sessions.get(sessionID);
|
|
372
|
+
const result = JSON.parse(resultJson) as {
|
|
373
|
+
signature: string;
|
|
374
|
+
transaction: Transaction;
|
|
375
|
+
};
|
|
167
376
|
|
|
168
|
-
|
|
377
|
+
const signature = result.signature as Signature;
|
|
169
378
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
379
|
+
// Update cache directly instead of invalidating
|
|
380
|
+
this.updateSessionLogCache(
|
|
381
|
+
sessionID,
|
|
382
|
+
signerAgent.id as unknown as SignerID,
|
|
383
|
+
[result.transaction],
|
|
384
|
+
signature,
|
|
173
385
|
);
|
|
386
|
+
this.invalidateKnownStateCache();
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
signature,
|
|
390
|
+
transaction: result.transaction,
|
|
391
|
+
};
|
|
174
392
|
}
|
|
175
393
|
|
|
176
394
|
setStreamingKnownState(streamingKnownState: KnownStateSessions) {
|
|
177
|
-
this.
|
|
395
|
+
if (this.isDeleted) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
this.impl.setStreamingKnownState(JSON.stringify(streamingKnownState));
|
|
399
|
+
this.cachedKnownStateWithStreaming = undefined;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
getSession(sessionID: SessionID): SessionLog | undefined {
|
|
403
|
+
const txCount = this.impl.getTransactionCount(sessionID);
|
|
404
|
+
if (txCount === -1) {
|
|
405
|
+
return undefined;
|
|
406
|
+
}
|
|
407
|
+
return this.getSessionLog(sessionID);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
getTransactionsCount(sessionID: SessionID): number | undefined {
|
|
411
|
+
const txCount = this.impl.getTransactionCount(sessionID);
|
|
412
|
+
if (txCount === -1) {
|
|
413
|
+
return undefined;
|
|
414
|
+
}
|
|
415
|
+
return txCount;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
get sessionCount(): number {
|
|
419
|
+
return this.impl.getSessionIds().length;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
getSessions(): Map<SessionID, SessionLog> {
|
|
423
|
+
// Build a Map from all sessions
|
|
424
|
+
const map = new Map<SessionID, SessionLog>();
|
|
425
|
+
const sessionIds = this.impl.getSessionIds() as SessionID[];
|
|
426
|
+
for (const sessionID of sessionIds) {
|
|
427
|
+
map.set(sessionID, this.getSessionLog(sessionID));
|
|
428
|
+
}
|
|
429
|
+
return map;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
*sessionEntries(): IterableIterator<[SessionID, SessionLog]> {
|
|
433
|
+
const sessionIds = this.impl.getSessionIds() as SessionID[];
|
|
434
|
+
for (const sessionID of sessionIds) {
|
|
435
|
+
yield [sessionID, this.getSessionLog(sessionID)];
|
|
436
|
+
}
|
|
178
437
|
}
|
|
179
438
|
|
|
180
439
|
newContentSince(
|
|
@@ -217,7 +476,7 @@ export class VerifiedState {
|
|
|
217
476
|
|
|
218
477
|
const sessionSent = knownState?.sessions;
|
|
219
478
|
|
|
220
|
-
for (const [sessionID, log] of this.
|
|
479
|
+
for (const [sessionID, log] of this.getSessions()) {
|
|
221
480
|
if (this.isDeleted && !isDeleteSessionID(sessionID)) {
|
|
222
481
|
continue;
|
|
223
482
|
}
|
|
@@ -329,24 +588,27 @@ export class VerifiedState {
|
|
|
329
588
|
return piecesWithContent;
|
|
330
589
|
}
|
|
331
590
|
|
|
332
|
-
knownState() {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
return this.sessions.knownStateWithStreaming ?? this.knownState();
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
immutableKnownState() {
|
|
341
|
-
return this.sessions.getImmutableKnownState();
|
|
591
|
+
knownState(): CoValueKnownState {
|
|
592
|
+
if (!this.cachedKnownState) {
|
|
593
|
+
this.cachedKnownState = this.impl.getKnownState() as CoValueKnownState;
|
|
594
|
+
}
|
|
595
|
+
return this.cachedKnownState;
|
|
342
596
|
}
|
|
343
597
|
|
|
344
|
-
|
|
345
|
-
|
|
598
|
+
knownStateWithStreaming(): CoValueKnownState {
|
|
599
|
+
if (!this.cachedKnownStateWithStreaming) {
|
|
600
|
+
const result = this.impl.getKnownStateWithStreaming();
|
|
601
|
+
if (!result || result === undefined) {
|
|
602
|
+
this.cachedKnownStateWithStreaming = this.knownState();
|
|
603
|
+
} else {
|
|
604
|
+
this.cachedKnownStateWithStreaming = result as CoValueKnownState;
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
return this.cachedKnownStateWithStreaming;
|
|
346
608
|
}
|
|
347
609
|
|
|
348
610
|
isStreaming(): boolean {
|
|
349
|
-
return Boolean(this.
|
|
611
|
+
return Boolean(this.impl.getKnownStateWithStreaming());
|
|
350
612
|
}
|
|
351
613
|
|
|
352
614
|
decryptTransaction(
|
|
@@ -354,7 +616,15 @@ export class VerifiedState {
|
|
|
354
616
|
txIndex: number,
|
|
355
617
|
keySecret: KeySecret,
|
|
356
618
|
): JsonValue[] | undefined {
|
|
357
|
-
|
|
619
|
+
const decrypted = this.impl.decryptTransaction(
|
|
620
|
+
sessionID,
|
|
621
|
+
txIndex,
|
|
622
|
+
keySecret,
|
|
623
|
+
);
|
|
624
|
+
if (!decrypted) {
|
|
625
|
+
return undefined;
|
|
626
|
+
}
|
|
627
|
+
return parseJSON(decrypted as Stringified<JsonValue[]>);
|
|
358
628
|
}
|
|
359
629
|
|
|
360
630
|
decryptTransactionMeta(
|
|
@@ -362,7 +632,19 @@ export class VerifiedState {
|
|
|
362
632
|
txIndex: number,
|
|
363
633
|
keySecret: KeySecret,
|
|
364
634
|
): JsonObject | undefined {
|
|
365
|
-
|
|
635
|
+
const sessionLog = this.getSession(sessionID);
|
|
636
|
+
if (!sessionLog?.transactions[txIndex]?.meta) {
|
|
637
|
+
return undefined;
|
|
638
|
+
}
|
|
639
|
+
const decrypted = this.impl.decryptTransactionMeta(
|
|
640
|
+
sessionID,
|
|
641
|
+
txIndex,
|
|
642
|
+
keySecret,
|
|
643
|
+
);
|
|
644
|
+
if (!decrypted) {
|
|
645
|
+
return undefined;
|
|
646
|
+
}
|
|
647
|
+
return parseJSON(decrypted as Stringified<JsonObject>);
|
|
366
648
|
}
|
|
367
649
|
}
|
|
368
650
|
|