cojson 0.16.3 → 0.16.5
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 +20 -0
- package/dist/coValue.d.ts +1 -1
- package/dist/coValue.d.ts.map +1 -1
- package/dist/coValue.js.map +1 -1
- package/dist/coValueContentMessage.d.ts +10 -0
- package/dist/coValueContentMessage.d.ts.map +1 -0
- package/dist/coValueContentMessage.js +46 -0
- package/dist/coValueContentMessage.js.map +1 -0
- package/dist/coValueCore/coValueCore.d.ts +6 -10
- package/dist/coValueCore/coValueCore.d.ts.map +1 -1
- package/dist/coValueCore/coValueCore.js +20 -125
- package/dist/coValueCore/coValueCore.js.map +1 -1
- package/dist/coValueCore/verifiedState.d.ts +1 -0
- package/dist/coValueCore/verifiedState.d.ts.map +1 -1
- package/dist/coValueCore/verifiedState.js +14 -27
- package/dist/coValueCore/verifiedState.js.map +1 -1
- package/dist/coValues/group.d.ts +18 -10
- package/dist/coValues/group.d.ts.map +1 -1
- package/dist/coValues/group.js +237 -67
- package/dist/coValues/group.js.map +1 -1
- package/dist/ids.d.ts +3 -3
- package/dist/ids.d.ts.map +1 -1
- package/dist/ids.js.map +1 -1
- package/dist/localNode.d.ts +11 -6
- package/dist/localNode.d.ts.map +1 -1
- package/dist/localNode.js +7 -2
- package/dist/localNode.js.map +1 -1
- package/dist/queue/LocalTransactionsSyncQueue.d.ts +24 -0
- package/dist/queue/LocalTransactionsSyncQueue.d.ts.map +1 -0
- package/dist/queue/LocalTransactionsSyncQueue.js +55 -0
- package/dist/queue/LocalTransactionsSyncQueue.js.map +1 -0
- package/dist/queue/StoreQueue.d.ts +9 -6
- package/dist/queue/StoreQueue.d.ts.map +1 -1
- package/dist/queue/StoreQueue.js +10 -2
- package/dist/queue/StoreQueue.js.map +1 -1
- package/dist/storage/storageAsync.d.ts +11 -3
- package/dist/storage/storageAsync.d.ts.map +1 -1
- package/dist/storage/storageAsync.js +59 -46
- package/dist/storage/storageAsync.js.map +1 -1
- package/dist/storage/storageSync.d.ts +9 -3
- package/dist/storage/storageSync.d.ts.map +1 -1
- package/dist/storage/storageSync.js +48 -35
- package/dist/storage/storageSync.js.map +1 -1
- package/dist/storage/syncUtils.d.ts +2 -1
- package/dist/storage/syncUtils.d.ts.map +1 -1
- package/dist/storage/syncUtils.js +4 -0
- package/dist/storage/syncUtils.js.map +1 -1
- package/dist/storage/types.d.ts +3 -2
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/sync.d.ts +6 -6
- package/dist/sync.d.ts.map +1 -1
- package/dist/sync.js +33 -56
- package/dist/sync.js.map +1 -1
- package/dist/tests/StorageApiAsync.test.d.ts +2 -0
- package/dist/tests/StorageApiAsync.test.d.ts.map +1 -0
- package/dist/tests/StorageApiAsync.test.js +574 -0
- package/dist/tests/StorageApiAsync.test.js.map +1 -0
- package/dist/tests/StorageApiSync.test.d.ts +2 -0
- package/dist/tests/StorageApiSync.test.d.ts.map +1 -0
- package/dist/tests/StorageApiSync.test.js +426 -0
- package/dist/tests/StorageApiSync.test.js.map +1 -0
- package/dist/tests/StoreQueue.test.js +9 -21
- package/dist/tests/StoreQueue.test.js.map +1 -1
- package/dist/tests/SyncStateManager.test.js +18 -8
- package/dist/tests/SyncStateManager.test.js.map +1 -1
- package/dist/tests/group.inheritance.test.js +274 -2
- package/dist/tests/group.inheritance.test.js.map +1 -1
- package/dist/tests/group.removeMember.test.js +152 -1
- package/dist/tests/group.removeMember.test.js.map +1 -1
- package/dist/tests/group.roleOf.test.js +2 -2
- package/dist/tests/group.roleOf.test.js.map +1 -1
- package/dist/tests/group.test.js +81 -3
- package/dist/tests/group.test.js.map +1 -1
- package/dist/tests/sync.auth.test.js +22 -10
- package/dist/tests/sync.auth.test.js.map +1 -1
- package/dist/tests/sync.load.test.js +30 -25
- package/dist/tests/sync.load.test.js.map +1 -1
- package/dist/tests/sync.mesh.test.js +12 -6
- package/dist/tests/sync.mesh.test.js.map +1 -1
- package/dist/tests/sync.peerReconciliation.test.js +6 -4
- package/dist/tests/sync.peerReconciliation.test.js.map +1 -1
- package/dist/tests/sync.storage.test.js +8 -14
- package/dist/tests/sync.storage.test.js.map +1 -1
- package/dist/tests/sync.storageAsync.test.js +31 -14
- package/dist/tests/sync.storageAsync.test.js.map +1 -1
- package/dist/tests/sync.test.js +5 -9
- package/dist/tests/sync.test.js.map +1 -1
- package/dist/tests/sync.upload.test.js +31 -1
- package/dist/tests/sync.upload.test.js.map +1 -1
- package/dist/tests/testStorage.d.ts +2 -3
- package/dist/tests/testStorage.d.ts.map +1 -1
- package/dist/tests/testStorage.js +16 -8
- package/dist/tests/testStorage.js.map +1 -1
- package/dist/tests/testUtils.d.ts +4 -0
- package/dist/tests/testUtils.d.ts.map +1 -1
- package/dist/tests/testUtils.js +22 -4
- package/dist/tests/testUtils.js.map +1 -1
- package/dist/typeUtils/accountOrAgentIDfromSessionID.d.ts +2 -2
- package/dist/typeUtils/accountOrAgentIDfromSessionID.d.ts.map +1 -1
- package/dist/typeUtils/expectGroup.d.ts.map +1 -1
- package/dist/typeUtils/expectGroup.js +6 -5
- package/dist/typeUtils/expectGroup.js.map +1 -1
- package/package.json +1 -1
- package/src/coValue.ts +1 -4
- package/src/coValueContentMessage.ts +73 -0
- package/src/coValueCore/coValueCore.ts +36 -192
- package/src/coValueCore/verifiedState.ts +28 -35
- package/src/coValues/group.ts +329 -99
- package/src/ids.ts +3 -3
- package/src/localNode.ts +15 -10
- package/src/queue/LocalTransactionsSyncQueue.ts +96 -0
- package/src/queue/StoreQueue.ts +22 -12
- package/src/storage/storageAsync.ts +78 -56
- package/src/storage/storageSync.ts +66 -45
- package/src/storage/syncUtils.ts +9 -1
- package/src/storage/types.ts +6 -5
- package/src/sync.ts +47 -67
- package/src/tests/StorageApiAsync.test.ts +829 -0
- package/src/tests/StorageApiSync.test.ts +628 -0
- package/src/tests/StoreQueue.test.ts +10 -24
- package/src/tests/SyncStateManager.test.ts +22 -21
- package/src/tests/group.inheritance.test.ts +415 -1
- package/src/tests/group.removeMember.test.ts +244 -1
- package/src/tests/group.roleOf.test.ts +2 -2
- package/src/tests/group.test.ts +105 -5
- package/src/tests/sync.auth.test.ts +22 -10
- package/src/tests/sync.load.test.ts +32 -26
- package/src/tests/sync.mesh.test.ts +12 -6
- package/src/tests/sync.peerReconciliation.test.ts +6 -4
- package/src/tests/sync.storage.test.ts +8 -14
- package/src/tests/sync.storageAsync.test.ts +39 -14
- package/src/tests/sync.test.ts +6 -14
- package/src/tests/sync.upload.test.ts +38 -1
- package/src/tests/testStorage.ts +19 -13
- package/src/tests/testUtils.ts +29 -5
- package/src/typeUtils/accountOrAgentIDfromSessionID.ts +2 -2
- package/src/typeUtils/expectGroup.ts +8 -5
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CoValueHeader,
|
|
3
|
+
Transaction,
|
|
4
|
+
VerifiedState,
|
|
5
|
+
} from "./coValueCore/verifiedState.js";
|
|
6
|
+
import { MAX_RECOMMENDED_TX_SIZE } from "./config.js";
|
|
7
|
+
import { Signature } from "./crypto/crypto.js";
|
|
8
|
+
import { RawCoID, SessionID } from "./ids.js";
|
|
9
|
+
import { getPriorityFromHeader } from "./priority.js";
|
|
10
|
+
import { NewContentMessage, emptyKnownState } from "./sync.js";
|
|
11
|
+
|
|
12
|
+
export function createContentMessage(
|
|
13
|
+
id: RawCoID,
|
|
14
|
+
header: CoValueHeader,
|
|
15
|
+
includeHeader = true,
|
|
16
|
+
): NewContentMessage {
|
|
17
|
+
return {
|
|
18
|
+
action: "content",
|
|
19
|
+
id,
|
|
20
|
+
header: includeHeader ? header : undefined,
|
|
21
|
+
priority: getPriorityFromHeader(header),
|
|
22
|
+
new: {},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function addTransactionToContentMessage(
|
|
27
|
+
content: NewContentMessage,
|
|
28
|
+
transaction: Transaction,
|
|
29
|
+
sessionID: SessionID,
|
|
30
|
+
signature: Signature,
|
|
31
|
+
txIdx: number,
|
|
32
|
+
) {
|
|
33
|
+
const sessionContent = content.new[sessionID];
|
|
34
|
+
|
|
35
|
+
if (sessionContent) {
|
|
36
|
+
sessionContent.newTransactions.push(transaction);
|
|
37
|
+
sessionContent.lastSignature = signature;
|
|
38
|
+
} else {
|
|
39
|
+
content.new[sessionID] = {
|
|
40
|
+
after: txIdx,
|
|
41
|
+
newTransactions: [transaction],
|
|
42
|
+
lastSignature: signature,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export function getTransactionSize(transaction: Transaction) {
|
|
48
|
+
return transaction.privacy === "private"
|
|
49
|
+
? transaction.encryptedChanges.length
|
|
50
|
+
: transaction.changes.length;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function exceedsRecommendedSize(
|
|
54
|
+
baseSize: number,
|
|
55
|
+
transactionSize?: number,
|
|
56
|
+
) {
|
|
57
|
+
if (transactionSize === undefined) {
|
|
58
|
+
return baseSize > MAX_RECOMMENDED_TX_SIZE;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return baseSize + transactionSize > MAX_RECOMMENDED_TX_SIZE;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function knownStateFromContent(content: NewContentMessage) {
|
|
65
|
+
const knownState = emptyKnownState(content.id);
|
|
66
|
+
|
|
67
|
+
for (const [sessionID, session] of Object.entries(content.new)) {
|
|
68
|
+
knownState.sessions[sessionID as SessionID] =
|
|
69
|
+
session.after + session.newTransactions.length;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return knownState;
|
|
73
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { UpDownCounter, ValueType, metrics } from "@opentelemetry/api";
|
|
2
2
|
import { Result, err } from "neverthrow";
|
|
3
|
-
import { PeerState } from "../PeerState.js";
|
|
4
|
-
import { RawCoValue } from "../coValue.js";
|
|
5
|
-
import { ControlledAccountOrAgent
|
|
6
|
-
import { RawGroup } from "../coValues/group.js";
|
|
7
|
-
import { CO_VALUE_LOADING_CONFIG
|
|
3
|
+
import type { PeerState } from "../PeerState.js";
|
|
4
|
+
import type { RawCoValue } from "../coValue.js";
|
|
5
|
+
import type { ControlledAccountOrAgent } from "../coValues/account.js";
|
|
6
|
+
import type { RawGroup } from "../coValues/group.js";
|
|
7
|
+
import { CO_VALUE_LOADING_CONFIG } from "../config.js";
|
|
8
8
|
import { coreToCoValue } from "../coreToCoValue.js";
|
|
9
9
|
import {
|
|
10
10
|
CryptoProvider,
|
|
@@ -16,25 +16,15 @@ import {
|
|
|
16
16
|
SignerID,
|
|
17
17
|
StreamingHash,
|
|
18
18
|
} from "../crypto/crypto.js";
|
|
19
|
-
import {
|
|
20
|
-
RawCoID,
|
|
21
|
-
SessionID,
|
|
22
|
-
TransactionID,
|
|
23
|
-
getParentGroupId,
|
|
24
|
-
isParentGroupReference,
|
|
25
|
-
} from "../ids.js";
|
|
19
|
+
import { RawCoID, SessionID, TransactionID } from "../ids.js";
|
|
26
20
|
import { parseJSON, stableStringify } from "../jsonStringify.js";
|
|
27
21
|
import { JsonValue } from "../jsonValue.js";
|
|
28
22
|
import { LocalNode, ResolveAccountAgentError } from "../localNode.js";
|
|
29
23
|
import { logger } from "../logger.js";
|
|
30
|
-
import {
|
|
31
|
-
determineValidTransactions,
|
|
32
|
-
isKeyForKeyField,
|
|
33
|
-
} from "../permissions.js";
|
|
24
|
+
import { determineValidTransactions } from "../permissions.js";
|
|
34
25
|
import { CoValueKnownState, PeerID, emptyKnownState } from "../sync.js";
|
|
35
26
|
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
|
|
36
27
|
import { expectGroup } from "../typeUtils/expectGroup.js";
|
|
37
|
-
import { isAccountID } from "../typeUtils/isAccountID.js";
|
|
38
28
|
import { getDependedOnCoValuesFromRawData } from "./utils.js";
|
|
39
29
|
import { CoValueHeader, Transaction, VerifiedState } from "./verifiedState.js";
|
|
40
30
|
|
|
@@ -53,8 +43,6 @@ export type DecryptedTransaction = {
|
|
|
53
43
|
trusting?: boolean;
|
|
54
44
|
};
|
|
55
45
|
|
|
56
|
-
const readKeyCache = new WeakMap<CoValueCore, { [id: KeyID]: KeySecret }>();
|
|
57
|
-
|
|
58
46
|
export type AvailableCoValueCore = CoValueCore & { verified: VerifiedState };
|
|
59
47
|
|
|
60
48
|
export class CoValueCore {
|
|
@@ -380,7 +368,7 @@ export class CoValueCore {
|
|
|
380
368
|
}
|
|
381
369
|
|
|
382
370
|
knownStateWithStreaming(): CoValueKnownState {
|
|
383
|
-
if (this.
|
|
371
|
+
if (this.verified) {
|
|
384
372
|
return this.verified.knownStateWithStreaming();
|
|
385
373
|
} else {
|
|
386
374
|
return emptyKnownState(this.id);
|
|
@@ -388,7 +376,7 @@ export class CoValueCore {
|
|
|
388
376
|
}
|
|
389
377
|
|
|
390
378
|
knownState(): CoValueKnownState {
|
|
391
|
-
if (this.
|
|
379
|
+
if (this.verified) {
|
|
392
380
|
return this.verified.knownState();
|
|
393
381
|
} else {
|
|
394
382
|
return emptyKnownState(this.id);
|
|
@@ -605,8 +593,17 @@ export class CoValueCore {
|
|
|
605
593
|
)._unsafeUnwrap({ withStackTrace: true });
|
|
606
594
|
|
|
607
595
|
if (success) {
|
|
596
|
+
const session = this.verified.sessions.get(sessionID);
|
|
597
|
+
const txIdx = session ? session.transactions.length - 1 : 0;
|
|
598
|
+
|
|
608
599
|
this.node.syncManager.recordTransactionsSize([transaction], "local");
|
|
609
|
-
|
|
600
|
+
this.node.syncManager.syncLocalTransaction(
|
|
601
|
+
this.verified,
|
|
602
|
+
transaction,
|
|
603
|
+
sessionID,
|
|
604
|
+
signature,
|
|
605
|
+
txIdx,
|
|
606
|
+
);
|
|
610
607
|
}
|
|
611
608
|
|
|
612
609
|
return success;
|
|
@@ -759,20 +756,7 @@ export class CoValueCore {
|
|
|
759
756
|
}
|
|
760
757
|
|
|
761
758
|
if (this.verified.header.ruleset.type === "group") {
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
const currentKeyId = content.getCurrentReadKeyId();
|
|
765
|
-
|
|
766
|
-
if (!currentKeyId) {
|
|
767
|
-
throw new Error("No readKey set");
|
|
768
|
-
}
|
|
769
|
-
|
|
770
|
-
const secret = this.getReadKey(currentKeyId);
|
|
771
|
-
|
|
772
|
-
return {
|
|
773
|
-
secret: secret,
|
|
774
|
-
id: currentKeyId,
|
|
775
|
-
};
|
|
759
|
+
return expectGroup(this.getCurrentContent()).getCurrentReadKey();
|
|
776
760
|
} else if (this.verified.header.ruleset.type === "ownedByGroup") {
|
|
777
761
|
return this.node
|
|
778
762
|
.expectCoValueLoaded(this.verified.header.ruleset.group)
|
|
@@ -784,154 +768,36 @@ export class CoValueCore {
|
|
|
784
768
|
}
|
|
785
769
|
}
|
|
786
770
|
|
|
771
|
+
readKeyCache = new Map<KeyID, KeySecret>();
|
|
787
772
|
getReadKey(keyID: KeyID): KeySecret | undefined {
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
if (!cache) {
|
|
794
|
-
cache = {};
|
|
795
|
-
readKeyCache.set(this, cache);
|
|
796
|
-
}
|
|
797
|
-
cache[keyID] = key;
|
|
798
|
-
}
|
|
773
|
+
// We want to check the cache here, to skip re-computing the group content
|
|
774
|
+
const cachedSecret = this.readKeyCache.get(keyID);
|
|
775
|
+
|
|
776
|
+
if (cachedSecret) {
|
|
777
|
+
return cachedSecret;
|
|
799
778
|
}
|
|
800
|
-
return key;
|
|
801
|
-
}
|
|
802
779
|
|
|
803
|
-
getUncachedReadKey(keyID: KeyID): KeySecret | undefined {
|
|
804
780
|
if (!this.verified) {
|
|
805
781
|
throw new Error(
|
|
806
782
|
"CoValueCore: getUncachedReadKey called on coValue without verified state",
|
|
807
783
|
);
|
|
808
784
|
}
|
|
809
785
|
|
|
786
|
+
// Getting the readKey from accounts
|
|
810
787
|
if (this.verified.header.ruleset.type === "group") {
|
|
811
788
|
const content = expectGroup(
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
if (keyForEveryone) {
|
|
816
|
-
return keyForEveryone;
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
// Try to find key revelation for us
|
|
820
|
-
const currentAgentOrAccountID = accountOrAgentIDfromSessionID(
|
|
821
|
-
this.node.currentSessionID,
|
|
789
|
+
// load the account without private transactions, because we are here
|
|
790
|
+
// to be able to decrypt those
|
|
791
|
+
this.getCurrentContent({ ignorePrivateTransactions: true }),
|
|
822
792
|
);
|
|
823
793
|
|
|
824
|
-
|
|
825
|
-
const lookupAccountOrAgentID = isAccountID(currentAgentOrAccountID)
|
|
826
|
-
? this.id === currentAgentOrAccountID
|
|
827
|
-
? this.crypto.getAgentID(this.node.agentSecret) // in accounts, the read key is revealed for the primitive agent
|
|
828
|
-
: currentAgentOrAccountID // current account ID
|
|
829
|
-
: currentAgentOrAccountID; // current agent ID
|
|
830
|
-
|
|
831
|
-
const lastReadyKeyEdit = content.lastEditAt(
|
|
832
|
-
`${keyID}_for_${lookupAccountOrAgentID}`,
|
|
833
|
-
);
|
|
834
|
-
|
|
835
|
-
if (lastReadyKeyEdit?.value) {
|
|
836
|
-
const revealer = lastReadyKeyEdit.by;
|
|
837
|
-
const revealerAgent = this.node
|
|
838
|
-
.resolveAccountAgent(revealer, "Expected to know revealer")
|
|
839
|
-
._unsafeUnwrap({ withStackTrace: true });
|
|
840
|
-
|
|
841
|
-
const secret = this.crypto.unseal(
|
|
842
|
-
lastReadyKeyEdit.value,
|
|
843
|
-
this.crypto.getAgentSealerSecret(this.node.agentSecret), // being careful here to avoid recursion
|
|
844
|
-
this.crypto.getAgentSealerID(revealerAgent),
|
|
845
|
-
{
|
|
846
|
-
in: this.id,
|
|
847
|
-
tx: lastReadyKeyEdit.tx,
|
|
848
|
-
},
|
|
849
|
-
);
|
|
850
|
-
|
|
851
|
-
if (secret) {
|
|
852
|
-
return secret as KeySecret;
|
|
853
|
-
}
|
|
854
|
-
}
|
|
855
|
-
|
|
856
|
-
// Try to find indirect revelation through previousKeys
|
|
857
|
-
|
|
858
|
-
for (const co of content.keys()) {
|
|
859
|
-
if (isKeyForKeyField(co) && co.startsWith(keyID)) {
|
|
860
|
-
const encryptingKeyID = co.split("_for_")[1] as KeyID;
|
|
861
|
-
const encryptingKeySecret = this.getReadKey(encryptingKeyID);
|
|
862
|
-
|
|
863
|
-
if (!encryptingKeySecret) {
|
|
864
|
-
continue;
|
|
865
|
-
}
|
|
866
|
-
|
|
867
|
-
const encryptedPreviousKey = content.get(co)!;
|
|
868
|
-
|
|
869
|
-
const secret = this.crypto.decryptKeySecret(
|
|
870
|
-
{
|
|
871
|
-
encryptedID: keyID,
|
|
872
|
-
encryptingID: encryptingKeyID,
|
|
873
|
-
encrypted: encryptedPreviousKey,
|
|
874
|
-
},
|
|
875
|
-
encryptingKeySecret,
|
|
876
|
-
);
|
|
877
|
-
|
|
878
|
-
if (secret) {
|
|
879
|
-
return secret as KeySecret;
|
|
880
|
-
} else {
|
|
881
|
-
logger.warn(
|
|
882
|
-
`Encrypting ${encryptingKeyID} key didn't decrypt ${keyID}`,
|
|
883
|
-
);
|
|
884
|
-
}
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
|
|
888
|
-
// try to find revelation to parent group read keys
|
|
889
|
-
for (const co of content.keys()) {
|
|
890
|
-
if (isParentGroupReference(co)) {
|
|
891
|
-
const parentGroupID = getParentGroupId(co);
|
|
892
|
-
const parentGroup = this.node.expectCoValueLoaded(
|
|
893
|
-
parentGroupID,
|
|
894
|
-
"Expected parent group to be loaded",
|
|
895
|
-
);
|
|
896
|
-
|
|
897
|
-
const parentKeys = this.findValidParentKeys(
|
|
898
|
-
keyID,
|
|
899
|
-
content,
|
|
900
|
-
parentGroup,
|
|
901
|
-
);
|
|
902
|
-
|
|
903
|
-
for (const parentKey of parentKeys) {
|
|
904
|
-
const revelationForParentKey = content.get(
|
|
905
|
-
`${keyID}_for_${parentKey.id}`,
|
|
906
|
-
);
|
|
907
|
-
|
|
908
|
-
if (revelationForParentKey) {
|
|
909
|
-
const secret = parentGroup.crypto.decryptKeySecret(
|
|
910
|
-
{
|
|
911
|
-
encryptedID: keyID,
|
|
912
|
-
encryptingID: parentKey.id,
|
|
913
|
-
encrypted: revelationForParentKey,
|
|
914
|
-
},
|
|
915
|
-
parentKey.secret,
|
|
916
|
-
);
|
|
917
|
-
|
|
918
|
-
if (secret) {
|
|
919
|
-
return secret as KeySecret;
|
|
920
|
-
} else {
|
|
921
|
-
logger.warn(
|
|
922
|
-
`Encrypting parent ${parentKey.id} key didn't decrypt ${keyID}`,
|
|
923
|
-
);
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
}
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
|
|
930
|
-
return undefined;
|
|
794
|
+
return content.getReadKey(keyID);
|
|
931
795
|
} else if (this.verified.header.ruleset.type === "ownedByGroup") {
|
|
932
|
-
return
|
|
933
|
-
|
|
934
|
-
|
|
796
|
+
return expectGroup(
|
|
797
|
+
this.node
|
|
798
|
+
.expectCoValueLoaded(this.verified.header.ruleset.group)
|
|
799
|
+
.getCurrentContent(),
|
|
800
|
+
).getReadKey(keyID);
|
|
935
801
|
} else {
|
|
936
802
|
throw new Error(
|
|
937
803
|
"Only groups or values owned by groups have read secrets",
|
|
@@ -939,28 +805,6 @@ export class CoValueCore {
|
|
|
939
805
|
}
|
|
940
806
|
}
|
|
941
807
|
|
|
942
|
-
findValidParentKeys(keyID: KeyID, group: RawGroup, parentGroup: CoValueCore) {
|
|
943
|
-
const validParentKeys: { id: KeyID; secret: KeySecret }[] = [];
|
|
944
|
-
|
|
945
|
-
for (const co of group.keys()) {
|
|
946
|
-
if (isKeyForKeyField(co) && co.startsWith(keyID)) {
|
|
947
|
-
const encryptingKeyID = co.split("_for_")[1] as KeyID;
|
|
948
|
-
const encryptingKeySecret = parentGroup.getReadKey(encryptingKeyID);
|
|
949
|
-
|
|
950
|
-
if (!encryptingKeySecret) {
|
|
951
|
-
continue;
|
|
952
|
-
}
|
|
953
|
-
|
|
954
|
-
validParentKeys.push({
|
|
955
|
-
id: encryptingKeyID,
|
|
956
|
-
secret: encryptingKeySecret,
|
|
957
|
-
});
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
|
|
961
|
-
return validParentKeys;
|
|
962
|
-
}
|
|
963
|
-
|
|
964
808
|
getGroup(): RawGroup {
|
|
965
809
|
if (!this.verified) {
|
|
966
810
|
throw new Error(
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { Result, err, ok } from "neverthrow";
|
|
2
2
|
import { AnyRawCoValue } from "../coValue.js";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createContentMessage,
|
|
5
|
+
exceedsRecommendedSize,
|
|
6
|
+
getTransactionSize,
|
|
7
|
+
} from "../coValueContentMessage.js";
|
|
4
8
|
import {
|
|
5
9
|
CryptoProvider,
|
|
6
10
|
Encrypted,
|
|
@@ -14,7 +18,6 @@ import { RawCoID, SessionID, TransactionID } from "../ids.js";
|
|
|
14
18
|
import { Stringified } from "../jsonStringify.js";
|
|
15
19
|
import { JsonObject, JsonValue } from "../jsonValue.js";
|
|
16
20
|
import { PermissionsDef as RulesetDef } from "../permissions.js";
|
|
17
|
-
import { getPriorityFromHeader } from "../priority.js";
|
|
18
21
|
import { CoValueKnownState, NewContentMessage } from "../sync.js";
|
|
19
22
|
import { InvalidHashError, InvalidSignatureError } from "./coValueCore.js";
|
|
20
23
|
import { TryAddTransactionsError } from "./coValueCore.js";
|
|
@@ -151,6 +154,17 @@ export class VerifiedState {
|
|
|
151
154
|
return ok(true as const);
|
|
152
155
|
}
|
|
153
156
|
|
|
157
|
+
getLastSignatureCheckpoint(sessionID: SessionID): number {
|
|
158
|
+
const sessionLog = this.sessions.get(sessionID);
|
|
159
|
+
|
|
160
|
+
if (!sessionLog?.signatureAfter) return -1;
|
|
161
|
+
|
|
162
|
+
return Object.keys(sessionLog.signatureAfter).reduce(
|
|
163
|
+
(max, idx) => Math.max(max, parseInt(idx)),
|
|
164
|
+
-1,
|
|
165
|
+
);
|
|
166
|
+
}
|
|
167
|
+
|
|
154
168
|
private doAddTransactions(
|
|
155
169
|
sessionID: SessionID,
|
|
156
170
|
newTransactions: Transaction[],
|
|
@@ -165,24 +179,14 @@ export class VerifiedState {
|
|
|
165
179
|
}
|
|
166
180
|
|
|
167
181
|
const signatureAfter = sessionLog?.signatureAfter ?? {};
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
(max, idx) => (parseInt(idx) > max ? parseInt(idx) : max),
|
|
171
|
-
-1,
|
|
172
|
-
);
|
|
182
|
+
const lastInbetweenSignatureIdx =
|
|
183
|
+
this.getLastSignatureCheckpoint(sessionID);
|
|
173
184
|
|
|
174
185
|
const sizeOfTxsSinceLastInbetweenSignature = transactions
|
|
175
186
|
.slice(lastInbetweenSignatureIdx + 1)
|
|
176
|
-
.reduce(
|
|
177
|
-
(sum, tx) =>
|
|
178
|
-
sum +
|
|
179
|
-
(tx.privacy === "private"
|
|
180
|
-
? tx.encryptedChanges.length
|
|
181
|
-
: tx.changes.length),
|
|
182
|
-
0,
|
|
183
|
-
);
|
|
187
|
+
.reduce((sum, tx) => sum + getTransactionSize(tx), 0);
|
|
184
188
|
|
|
185
|
-
if (sizeOfTxsSinceLastInbetweenSignature
|
|
189
|
+
if (exceedsRecommendedSize(sizeOfTxsSinceLastInbetweenSignature)) {
|
|
186
190
|
signatureAfter[transactions.length - 1] = newSignature;
|
|
187
191
|
}
|
|
188
192
|
|
|
@@ -242,13 +246,11 @@ export class VerifiedState {
|
|
|
242
246
|
return this._cachedNewContentSinceEmpty;
|
|
243
247
|
}
|
|
244
248
|
|
|
245
|
-
let currentPiece: NewContentMessage =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
new: {},
|
|
251
|
-
};
|
|
249
|
+
let currentPiece: NewContentMessage = createContentMessage(
|
|
250
|
+
this.id,
|
|
251
|
+
this.header,
|
|
252
|
+
!knownState?.header,
|
|
253
|
+
);
|
|
252
254
|
|
|
253
255
|
const pieces = [currentPiece];
|
|
254
256
|
|
|
@@ -299,25 +301,16 @@ export class VerifiedState {
|
|
|
299
301
|
const oldPieceSize = pieceSize;
|
|
300
302
|
for (let txIdx = firstNewTxIdx; txIdx < afterLastNewTxIdx; txIdx++) {
|
|
301
303
|
const tx = log.transactions[txIdx]!;
|
|
302
|
-
pieceSize +=
|
|
303
|
-
tx.privacy === "private"
|
|
304
|
-
? tx.encryptedChanges.length
|
|
305
|
-
: tx.changes.length;
|
|
304
|
+
pieceSize += getTransactionSize(tx);
|
|
306
305
|
}
|
|
307
306
|
|
|
308
|
-
if (pieceSize
|
|
307
|
+
if (exceedsRecommendedSize(pieceSize)) {
|
|
309
308
|
if (!currentPiece.expectContentUntil && pieces.length === 1) {
|
|
310
309
|
currentPiece.expectContentUntil =
|
|
311
310
|
this.knownStateWithStreaming().sessions;
|
|
312
311
|
}
|
|
313
312
|
|
|
314
|
-
currentPiece =
|
|
315
|
-
action: "content",
|
|
316
|
-
id: this.id,
|
|
317
|
-
header: undefined,
|
|
318
|
-
new: {},
|
|
319
|
-
priority: getPriorityFromHeader(this.header),
|
|
320
|
-
};
|
|
313
|
+
currentPiece = createContentMessage(this.id, this.header, false);
|
|
321
314
|
pieces.push(currentPiece);
|
|
322
315
|
pieceSize = pieceSize - oldPieceSize;
|
|
323
316
|
}
|