cojson 0.7.0-alpha.36 → 0.7.0-alpha.38
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/.eslintrc.cjs +3 -2
- package/.prettierrc.js +9 -0
- package/.turbo/turbo-build.log +3 -36
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-test.log +1106 -0
- package/CHANGELOG.md +12 -0
- package/README.md +3 -1
- package/dist/base64url.test.js +25 -0
- package/dist/base64url.test.js.map +1 -0
- package/dist/coValueCore.js +16 -15
- package/dist/coValueCore.js.map +1 -1
- package/dist/coValues/account.js +16 -15
- package/dist/coValues/account.js.map +1 -1
- package/dist/coValues/group.js +13 -14
- package/dist/coValues/group.js.map +1 -1
- package/dist/coreToCoValue.js.map +1 -1
- package/dist/crypto/PureJSCrypto.js +89 -0
- package/dist/crypto/PureJSCrypto.js.map +1 -0
- package/dist/crypto/WasmCrypto.js +127 -0
- package/dist/crypto/WasmCrypto.js.map +1 -0
- package/dist/crypto/crypto.js +151 -0
- package/dist/crypto/crypto.js.map +1 -0
- package/dist/ids.js +4 -2
- package/dist/ids.js.map +1 -1
- package/dist/index.js +5 -9
- package/dist/index.js.map +1 -1
- package/dist/jsonStringify.js.map +1 -1
- package/dist/localNode.js +24 -24
- package/dist/localNode.js.map +1 -1
- package/dist/permissions.js.map +1 -1
- package/dist/storage/FileSystem.js +2 -2
- package/dist/storage/FileSystem.js.map +1 -1
- package/dist/storage/chunksAndKnownStates.js +2 -2
- package/dist/storage/chunksAndKnownStates.js.map +1 -1
- package/dist/storage/index.js.map +1 -1
- package/dist/sync.js +6 -2
- package/dist/sync.js.map +1 -1
- package/dist/tests/account.test.js +58 -0
- package/dist/tests/account.test.js.map +1 -0
- package/dist/tests/coList.test.js +76 -0
- package/dist/tests/coList.test.js.map +1 -0
- package/dist/tests/coMap.test.js +136 -0
- package/dist/tests/coMap.test.js.map +1 -0
- package/dist/tests/coStream.test.js +172 -0
- package/dist/tests/coStream.test.js.map +1 -0
- package/dist/tests/coValueCore.test.js +114 -0
- package/dist/tests/coValueCore.test.js.map +1 -0
- package/dist/tests/crypto.test.js +118 -0
- package/dist/tests/crypto.test.js.map +1 -0
- package/dist/tests/cryptoImpl.test.js +113 -0
- package/dist/tests/cryptoImpl.test.js.map +1 -0
- package/dist/tests/group.test.js +34 -0
- package/dist/tests/group.test.js.map +1 -0
- package/dist/tests/permissions.test.js +1060 -0
- package/dist/tests/permissions.test.js.map +1 -0
- package/dist/tests/sync.test.js +816 -0
- package/dist/tests/sync.test.js.map +1 -0
- package/dist/tests/testUtils.js +10 -9
- package/dist/tests/testUtils.js.map +1 -1
- package/dist/typeUtils/accountOrAgentIDfromSessionID.js.map +1 -1
- package/dist/typeUtils/isAccountID.js.map +1 -1
- package/dist/typeUtils/isCoValue.js.map +1 -1
- package/package.json +14 -28
- package/src/base64url.test.ts +6 -6
- package/src/coValue.ts +1 -1
- package/src/coValueCore.ts +87 -85
- package/src/coValues/account.ts +26 -28
- package/src/coValues/coList.ts +10 -10
- package/src/coValues/coMap.ts +10 -10
- package/src/coValues/coStream.ts +17 -17
- package/src/coValues/group.ts +93 -109
- package/src/coreToCoValue.ts +5 -2
- package/src/crypto/PureJSCrypto.ts +200 -0
- package/src/crypto/WasmCrypto.ts +259 -0
- package/src/crypto/crypto.ts +336 -0
- package/src/ids.ts +8 -7
- package/src/index.ts +14 -26
- package/src/jsonStringify.ts +6 -4
- package/src/jsonValue.ts +2 -2
- package/src/localNode.ts +86 -80
- package/src/media.ts +3 -3
- package/src/permissions.ts +14 -16
- package/src/storage/FileSystem.ts +31 -30
- package/src/storage/chunksAndKnownStates.ts +24 -17
- package/src/storage/index.ts +42 -38
- package/src/streamUtils.ts +12 -12
- package/src/sync.ts +56 -40
- package/src/tests/account.test.ts +8 -12
- package/src/tests/coList.test.ts +19 -25
- package/src/tests/coMap.test.ts +25 -30
- package/src/tests/coStream.test.ts +28 -38
- package/src/tests/coValueCore.test.ts +35 -36
- package/src/tests/crypto.test.ts +66 -72
- package/src/tests/cryptoImpl.test.ts +183 -0
- package/src/tests/group.test.ts +16 -17
- package/src/tests/permissions.test.ts +237 -254
- package/src/tests/sync.test.ts +119 -120
- package/src/tests/testUtils.ts +22 -19
- package/src/typeUtils/accountOrAgentIDfromSessionID.ts +1 -2
- package/src/typeUtils/expectGroup.ts +1 -1
- package/src/typeUtils/isAccountID.ts +0 -1
- package/src/typeUtils/isCoValue.ts +1 -2
- package/tsconfig.json +0 -1
- package/dist/crypto.js +0 -255
- package/dist/crypto.js.map +0 -1
- package/src/crypto.ts +0 -485
|
@@ -1,30 +1,20 @@
|
|
|
1
|
-
import { expect, test
|
|
2
|
-
import {
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { expectStream } from "../coValue.js";
|
|
3
3
|
import { RawBinaryCoStream } from "../coValues/coStream.js";
|
|
4
|
-
import {
|
|
5
|
-
import { MAX_RECOMMENDED_TX_SIZE, cojsonReady } from "../index.js";
|
|
4
|
+
import { MAX_RECOMMENDED_TX_SIZE, WasmCrypto } from "../index.js";
|
|
6
5
|
import { LocalNode } from "../localNode.js";
|
|
7
|
-
import { accountOrAgentIDfromSessionID } from "../typeUtils/accountOrAgentIDfromSessionID.js";
|
|
8
6
|
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
if (!("crypto" in globalThis)) {
|
|
12
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
-
(globalThis as any).crypto = webcrypto;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
beforeEach(async () => {
|
|
17
|
-
await cojsonReady;
|
|
18
|
-
});
|
|
8
|
+
const Crypto = await WasmCrypto.create();
|
|
19
9
|
|
|
20
10
|
test("Empty CoStream works", () => {
|
|
21
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
11
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
22
12
|
|
|
23
13
|
const coValue = node.createCoValue({
|
|
24
14
|
type: "costream",
|
|
25
15
|
ruleset: { type: "unsafeAllowAll" },
|
|
26
16
|
meta: null,
|
|
27
|
-
...createdNowUnique(),
|
|
17
|
+
...Crypto.createdNowUnique(),
|
|
28
18
|
});
|
|
29
19
|
|
|
30
20
|
const content = expectStream(coValue.getCurrentContent());
|
|
@@ -35,13 +25,13 @@ test("Empty CoStream works", () => {
|
|
|
35
25
|
});
|
|
36
26
|
|
|
37
27
|
test("Can push into CoStream", () => {
|
|
38
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
28
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
39
29
|
|
|
40
30
|
const coValue = node.createCoValue({
|
|
41
31
|
type: "costream",
|
|
42
32
|
ruleset: { type: "unsafeAllowAll" },
|
|
43
33
|
meta: null,
|
|
44
|
-
...createdNowUnique(),
|
|
34
|
+
...Crypto.createdNowUnique(),
|
|
45
35
|
});
|
|
46
36
|
|
|
47
37
|
const content = expectStream(coValue.getCurrentContent());
|
|
@@ -61,13 +51,13 @@ test("Can push into CoStream", () => {
|
|
|
61
51
|
});
|
|
62
52
|
|
|
63
53
|
test("Empty RawBinaryCoStream works", () => {
|
|
64
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
54
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
65
55
|
|
|
66
56
|
const coValue = node.createCoValue({
|
|
67
57
|
type: "costream",
|
|
68
58
|
ruleset: { type: "unsafeAllowAll" },
|
|
69
59
|
meta: { type: "binary" },
|
|
70
|
-
...createdNowUnique(),
|
|
60
|
+
...Crypto.createdNowUnique(),
|
|
71
61
|
});
|
|
72
62
|
|
|
73
63
|
const content = coValue.getCurrentContent();
|
|
@@ -87,13 +77,13 @@ test("Empty RawBinaryCoStream works", () => {
|
|
|
87
77
|
});
|
|
88
78
|
|
|
89
79
|
test("Can push into RawBinaryCoStream", () => {
|
|
90
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
80
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
91
81
|
|
|
92
82
|
const coValue = node.createCoValue({
|
|
93
83
|
type: "costream",
|
|
94
84
|
ruleset: { type: "unsafeAllowAll" },
|
|
95
85
|
meta: { type: "binary" },
|
|
96
|
-
...createdNowUnique(),
|
|
86
|
+
...Crypto.createdNowUnique(),
|
|
97
87
|
});
|
|
98
88
|
|
|
99
89
|
const content = coValue.getCurrentContent();
|
|
@@ -108,7 +98,7 @@ test("Can push into RawBinaryCoStream", () => {
|
|
|
108
98
|
|
|
109
99
|
content.startBinaryStream(
|
|
110
100
|
{ mimeType: "text/plain", fileName: "test.txt" },
|
|
111
|
-
"trusting"
|
|
101
|
+
"trusting",
|
|
112
102
|
);
|
|
113
103
|
content.pushBinaryStreamChunk(new Uint8Array([1, 2, 3]), "trusting");
|
|
114
104
|
content.pushBinaryStreamChunk(new Uint8Array([4, 5, 6]), "trusting");
|
|
@@ -123,13 +113,13 @@ test("Can push into RawBinaryCoStream", () => {
|
|
|
123
113
|
});
|
|
124
114
|
|
|
125
115
|
test("When adding large transactions (small fraction of MAX_RECOMMENDED_TX_SIZE), we store an inbetween signature every time we reach MAX_RECOMMENDED_TX_SIZE and split up newContentSince accordingly", () => {
|
|
126
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
116
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
127
117
|
|
|
128
118
|
const coValue = node.createCoValue({
|
|
129
119
|
type: "costream",
|
|
130
120
|
ruleset: { type: "unsafeAllowAll" },
|
|
131
121
|
meta: { type: "binary" },
|
|
132
|
-
...createdNowUnique(),
|
|
122
|
+
...Crypto.createdNowUnique(),
|
|
133
123
|
});
|
|
134
124
|
|
|
135
125
|
const content = coValue.getCurrentContent();
|
|
@@ -144,7 +134,7 @@ test("When adding large transactions (small fraction of MAX_RECOMMENDED_TX_SIZE)
|
|
|
144
134
|
|
|
145
135
|
content.startBinaryStream(
|
|
146
136
|
{ mimeType: "text/plain", fileName: "test.txt" },
|
|
147
|
-
"trusting"
|
|
137
|
+
"trusting",
|
|
148
138
|
);
|
|
149
139
|
|
|
150
140
|
for (let i = 0; i < 10; i++) {
|
|
@@ -179,27 +169,27 @@ test("When adding large transactions (small fraction of MAX_RECOMMENDED_TX_SIZE)
|
|
|
179
169
|
expect(newContent.length).toEqual(5);
|
|
180
170
|
expect(newContent[0]!.header).toBeDefined();
|
|
181
171
|
expect(newContent[1]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
182
|
-
sessionEntry.signatureAfter[3]
|
|
172
|
+
sessionEntry.signatureAfter[3],
|
|
183
173
|
);
|
|
184
174
|
expect(newContent[2]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
185
|
-
sessionEntry.signatureAfter[6]
|
|
175
|
+
sessionEntry.signatureAfter[6],
|
|
186
176
|
);
|
|
187
177
|
expect(newContent[3]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
188
|
-
sessionEntry.signatureAfter[9]
|
|
178
|
+
sessionEntry.signatureAfter[9],
|
|
189
179
|
);
|
|
190
180
|
expect(newContent[4]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
191
|
-
sessionEntry.lastSignature
|
|
181
|
+
sessionEntry.lastSignature,
|
|
192
182
|
);
|
|
193
183
|
});
|
|
194
184
|
|
|
195
185
|
test("When adding large transactions (bigger than MAX_RECOMMENDED_TX_SIZE), we store an inbetween signature after every large transaction and split up newContentSince accordingly", () => {
|
|
196
|
-
const node = new LocalNode(...randomAnonymousAccountAndSessionID());
|
|
186
|
+
const node = new LocalNode(...randomAnonymousAccountAndSessionID(), Crypto);
|
|
197
187
|
|
|
198
188
|
const coValue = node.createCoValue({
|
|
199
189
|
type: "costream",
|
|
200
190
|
ruleset: { type: "unsafeAllowAll" },
|
|
201
191
|
meta: { type: "binary" },
|
|
202
|
-
...createdNowUnique(),
|
|
192
|
+
...Crypto.createdNowUnique(),
|
|
203
193
|
});
|
|
204
194
|
|
|
205
195
|
const content = coValue.getCurrentContent();
|
|
@@ -214,7 +204,7 @@ test("When adding large transactions (bigger than MAX_RECOMMENDED_TX_SIZE), we s
|
|
|
214
204
|
|
|
215
205
|
content.startBinaryStream(
|
|
216
206
|
{ mimeType: "text/plain", fileName: "test.txt" },
|
|
217
|
-
"trusting"
|
|
207
|
+
"trusting",
|
|
218
208
|
);
|
|
219
209
|
|
|
220
210
|
const chunk = new Uint8Array(MAX_RECOMMENDED_TX_SIZE + 100);
|
|
@@ -242,15 +232,15 @@ test("When adding large transactions (bigger than MAX_RECOMMENDED_TX_SIZE), we s
|
|
|
242
232
|
expect(newContent.length).toEqual(5);
|
|
243
233
|
expect(newContent[0]!.header).toBeDefined();
|
|
244
234
|
expect(newContent[1]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
245
|
-
sessionEntry.signatureAfter[1]
|
|
235
|
+
sessionEntry.signatureAfter[1],
|
|
246
236
|
);
|
|
247
237
|
expect(newContent[2]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
248
|
-
sessionEntry.signatureAfter[2]
|
|
238
|
+
sessionEntry.signatureAfter[2],
|
|
249
239
|
);
|
|
250
240
|
expect(newContent[3]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
251
|
-
sessionEntry.signatureAfter[3]
|
|
241
|
+
sessionEntry.signatureAfter[3],
|
|
252
242
|
);
|
|
253
243
|
expect(newContent[4]!.new[node.currentSessionID]!.lastSignature).toEqual(
|
|
254
|
-
sessionEntry.lastSignature
|
|
244
|
+
sessionEntry.lastSignature,
|
|
255
245
|
);
|
|
256
|
-
});
|
|
246
|
+
});
|
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
import { expect, test,
|
|
1
|
+
import { expect, test, vi } from "vitest";
|
|
2
2
|
import { Transaction } from "../coValueCore.js";
|
|
3
3
|
import { LocalNode } from "../localNode.js";
|
|
4
|
-
import { createdNowUnique, getAgentSignerSecret, newRandomAgentSecret, sign } from "../crypto.js";
|
|
5
4
|
import { randomAnonymousAccountAndSessionID } from "./testUtils.js";
|
|
6
5
|
import { MapOpPayload } from "../coValues/coMap.js";
|
|
7
6
|
import { Role } from "../permissions.js";
|
|
8
|
-
import { cojsonReady } from "../index.js";
|
|
9
7
|
import { stableStringify } from "../jsonStringify.js";
|
|
8
|
+
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
if (!("crypto" in globalThis)) {
|
|
13
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
-
(globalThis as any).crypto = webcrypto;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
beforeEach(async () => {
|
|
18
|
-
await cojsonReady;
|
|
19
|
-
});
|
|
10
|
+
const Crypto = await WasmCrypto.create();
|
|
20
11
|
|
|
21
12
|
test("Can create coValue with new agent credentials and add transaction to it", () => {
|
|
22
13
|
const [account, sessionID] = randomAnonymousAccountAndSessionID();
|
|
23
|
-
const node = new LocalNode(account, sessionID);
|
|
14
|
+
const node = new LocalNode(account, sessionID, Crypto);
|
|
24
15
|
|
|
25
16
|
const coValue = node.createCoValue({
|
|
26
17
|
type: "costream",
|
|
27
18
|
ruleset: { type: "unsafeAllowAll" },
|
|
28
19
|
meta: null,
|
|
29
|
-
...createdNowUnique(),
|
|
20
|
+
...Crypto.createdNowUnique(),
|
|
30
21
|
});
|
|
31
22
|
|
|
32
23
|
const transaction: Transaction = {
|
|
@@ -41,7 +32,7 @@ test("Can create coValue with new agent credentials and add transaction to it",
|
|
|
41
32
|
|
|
42
33
|
const { expectedNewHash } = coValue.expectedNewHashAfter(
|
|
43
34
|
node.currentSessionID,
|
|
44
|
-
[transaction]
|
|
35
|
+
[transaction],
|
|
45
36
|
);
|
|
46
37
|
|
|
47
38
|
expect(
|
|
@@ -49,21 +40,21 @@ test("Can create coValue with new agent credentials and add transaction to it",
|
|
|
49
40
|
node.currentSessionID,
|
|
50
41
|
[transaction],
|
|
51
42
|
expectedNewHash,
|
|
52
|
-
sign(account.currentSignerSecret(), expectedNewHash)
|
|
53
|
-
)
|
|
43
|
+
Crypto.sign(account.currentSignerSecret(), expectedNewHash),
|
|
44
|
+
),
|
|
54
45
|
).toBe(true);
|
|
55
46
|
});
|
|
56
47
|
|
|
57
48
|
test("transactions with wrong signature are rejected", () => {
|
|
58
|
-
const wrongAgent = newRandomAgentSecret();
|
|
49
|
+
const wrongAgent = Crypto.newRandomAgentSecret();
|
|
59
50
|
const [agentSecret, sessionID] = randomAnonymousAccountAndSessionID();
|
|
60
|
-
const node = new LocalNode(agentSecret, sessionID);
|
|
51
|
+
const node = new LocalNode(agentSecret, sessionID, Crypto);
|
|
61
52
|
|
|
62
53
|
const coValue = node.createCoValue({
|
|
63
54
|
type: "costream",
|
|
64
55
|
ruleset: { type: "unsafeAllowAll" },
|
|
65
56
|
meta: null,
|
|
66
|
-
...createdNowUnique(),
|
|
57
|
+
...Crypto.createdNowUnique(),
|
|
67
58
|
});
|
|
68
59
|
|
|
69
60
|
const transaction: Transaction = {
|
|
@@ -78,7 +69,7 @@ test("transactions with wrong signature are rejected", () => {
|
|
|
78
69
|
|
|
79
70
|
const { expectedNewHash } = coValue.expectedNewHashAfter(
|
|
80
71
|
node.currentSessionID,
|
|
81
|
-
[transaction]
|
|
72
|
+
[transaction],
|
|
82
73
|
);
|
|
83
74
|
|
|
84
75
|
expect(
|
|
@@ -86,20 +77,23 @@ test("transactions with wrong signature are rejected", () => {
|
|
|
86
77
|
node.currentSessionID,
|
|
87
78
|
[transaction],
|
|
88
79
|
expectedNewHash,
|
|
89
|
-
sign(
|
|
90
|
-
|
|
80
|
+
Crypto.sign(
|
|
81
|
+
Crypto.getAgentSignerSecret(wrongAgent),
|
|
82
|
+
expectedNewHash,
|
|
83
|
+
),
|
|
84
|
+
),
|
|
91
85
|
).toBe(false);
|
|
92
86
|
});
|
|
93
87
|
|
|
94
88
|
test("transactions with correctly signed, but wrong hash are rejected", () => {
|
|
95
89
|
const [account, sessionID] = randomAnonymousAccountAndSessionID();
|
|
96
|
-
const node = new LocalNode(account, sessionID);
|
|
90
|
+
const node = new LocalNode(account, sessionID, Crypto);
|
|
97
91
|
|
|
98
92
|
const coValue = node.createCoValue({
|
|
99
93
|
type: "costream",
|
|
100
94
|
ruleset: { type: "unsafeAllowAll" },
|
|
101
95
|
meta: null,
|
|
102
|
-
...createdNowUnique(),
|
|
96
|
+
...Crypto.createdNowUnique(),
|
|
103
97
|
});
|
|
104
98
|
|
|
105
99
|
const transaction: Transaction = {
|
|
@@ -124,7 +118,7 @@ test("transactions with correctly signed, but wrong hash are rejected", () => {
|
|
|
124
118
|
},
|
|
125
119
|
]),
|
|
126
120
|
},
|
|
127
|
-
]
|
|
121
|
+
],
|
|
128
122
|
);
|
|
129
123
|
|
|
130
124
|
expect(
|
|
@@ -132,14 +126,14 @@ test("transactions with correctly signed, but wrong hash are rejected", () => {
|
|
|
132
126
|
node.currentSessionID,
|
|
133
127
|
[transaction],
|
|
134
128
|
expectedNewHash,
|
|
135
|
-
sign(account.currentSignerSecret(), expectedNewHash)
|
|
136
|
-
)
|
|
129
|
+
Crypto.sign(account.currentSignerSecret(), expectedNewHash),
|
|
130
|
+
),
|
|
137
131
|
).toBe(false);
|
|
138
132
|
});
|
|
139
133
|
|
|
140
134
|
test("New transactions in a group correctly update owned values, including subscriptions", async () => {
|
|
141
135
|
const [account, sessionID] = randomAnonymousAccountAndSessionID();
|
|
142
|
-
const node = new LocalNode(account, sessionID);
|
|
136
|
+
const node = new LocalNode(account, sessionID, Crypto);
|
|
143
137
|
|
|
144
138
|
const group = node.createGroup();
|
|
145
139
|
|
|
@@ -147,7 +141,7 @@ test("New transactions in a group correctly update owned values, including subsc
|
|
|
147
141
|
|
|
148
142
|
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
149
143
|
|
|
150
|
-
|
|
144
|
+
const map = group.createMap();
|
|
151
145
|
|
|
152
146
|
map.set("hello", "world");
|
|
153
147
|
|
|
@@ -164,23 +158,28 @@ test("New transactions in a group correctly update owned values, including subsc
|
|
|
164
158
|
{
|
|
165
159
|
op: "set",
|
|
166
160
|
key: account.id,
|
|
167
|
-
value: "revoked"
|
|
168
|
-
} satisfies MapOpPayload<typeof account.id, Role
|
|
169
|
-
])
|
|
161
|
+
value: "revoked",
|
|
162
|
+
} satisfies MapOpPayload<typeof account.id, Role>,
|
|
163
|
+
]),
|
|
170
164
|
} satisfies Transaction;
|
|
171
165
|
|
|
172
166
|
const { expectedNewHash } = group.core.expectedNewHashAfter(sessionID, [
|
|
173
167
|
resignationThatWeJustLearnedAbout,
|
|
174
168
|
]);
|
|
175
169
|
|
|
176
|
-
const signature = sign(
|
|
170
|
+
const signature = Crypto.sign(
|
|
177
171
|
node.account.currentSignerSecret(),
|
|
178
|
-
expectedNewHash
|
|
172
|
+
expectedNewHash,
|
|
179
173
|
);
|
|
180
174
|
|
|
181
175
|
expect(map.core.getValidSortedTransactions().length).toBe(1);
|
|
182
176
|
|
|
183
|
-
const manuallyAdddedTxSuccess = group.core.tryAddTransactions(
|
|
177
|
+
const manuallyAdddedTxSuccess = group.core.tryAddTransactions(
|
|
178
|
+
node.currentSessionID,
|
|
179
|
+
[resignationThatWeJustLearnedAbout],
|
|
180
|
+
expectedNewHash,
|
|
181
|
+
signature,
|
|
182
|
+
);
|
|
184
183
|
|
|
185
184
|
expect(manuallyAdddedTxSuccess).toBe(true);
|
|
186
185
|
|
package/src/tests/crypto.test.ts
CHANGED
|
@@ -1,93 +1,84 @@
|
|
|
1
|
-
import { expect, test
|
|
2
|
-
import {
|
|
3
|
-
getSealerID,
|
|
4
|
-
getSignerID,
|
|
5
|
-
secureHash,
|
|
6
|
-
newRandomSealer,
|
|
7
|
-
newRandomSigner,
|
|
8
|
-
seal,
|
|
9
|
-
sign,
|
|
10
|
-
unseal,
|
|
11
|
-
verify,
|
|
12
|
-
shortHash,
|
|
13
|
-
newRandomKeySecret,
|
|
14
|
-
encryptForTransaction,
|
|
15
|
-
decryptForTransaction,
|
|
16
|
-
encryptKeySecret,
|
|
17
|
-
decryptKeySecret,
|
|
18
|
-
} from "../crypto.js";
|
|
1
|
+
import { expect, test } from "vitest";
|
|
2
|
+
import { WasmCrypto } from "../crypto/WasmCrypto.js";
|
|
19
3
|
import { base58, base64url } from "@scure/base";
|
|
20
4
|
import { x25519 } from "@noble/curves/ed25519";
|
|
21
5
|
import { xsalsa20_poly1305 } from "@noble/ciphers/salsa";
|
|
22
6
|
import { blake3 } from "@noble/hashes/blake3";
|
|
23
|
-
import stableStringify from "fast-json-stable-stringify";
|
|
24
7
|
import { SessionID } from "../ids.js";
|
|
25
|
-
import {
|
|
8
|
+
import { stableStringify } from "../jsonStringify.js";
|
|
26
9
|
|
|
27
|
-
|
|
28
|
-
if (!("crypto" in globalThis)) {
|
|
29
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
|
-
(globalThis as any).crypto = webcrypto;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
beforeEach(async () => {
|
|
34
|
-
await cojsonReady;
|
|
35
|
-
});
|
|
10
|
+
const Crypto = await WasmCrypto.create();
|
|
36
11
|
|
|
37
12
|
test("Signatures round-trip and use stable stringify", () => {
|
|
38
13
|
const data = { b: "world", a: "hello" };
|
|
39
|
-
const signer = newRandomSigner();
|
|
40
|
-
const signature = sign(signer, data);
|
|
14
|
+
const signer = Crypto.newRandomSigner();
|
|
15
|
+
const signature = Crypto.sign(signer, data);
|
|
41
16
|
|
|
42
17
|
expect(signature).toMatch(/^signature_z/);
|
|
43
18
|
expect(
|
|
44
|
-
verify(
|
|
19
|
+
Crypto.verify(
|
|
20
|
+
signature,
|
|
21
|
+
{ a: "hello", b: "world" },
|
|
22
|
+
Crypto.getSignerID(signer),
|
|
23
|
+
),
|
|
45
24
|
).toBe(true);
|
|
46
25
|
});
|
|
47
26
|
|
|
48
27
|
test("Invalid signatures don't verify", () => {
|
|
49
28
|
const data = { b: "world", a: "hello" };
|
|
50
|
-
const signer = newRandomSigner();
|
|
51
|
-
const signer2 = newRandomSigner();
|
|
52
|
-
const wrongSignature = sign(signer2, data);
|
|
29
|
+
const signer = Crypto.newRandomSigner();
|
|
30
|
+
const signer2 = Crypto.newRandomSigner();
|
|
31
|
+
const wrongSignature = Crypto.sign(signer2, data);
|
|
53
32
|
|
|
54
|
-
expect(
|
|
33
|
+
expect(
|
|
34
|
+
Crypto.verify(wrongSignature, data, Crypto.getSignerID(signer)),
|
|
35
|
+
).toBe(false);
|
|
55
36
|
});
|
|
56
37
|
|
|
57
38
|
test("encrypting round-trips, but invalid receiver can't unseal", () => {
|
|
58
39
|
const data = { b: "world", a: "hello" };
|
|
59
|
-
const sender = newRandomSealer();
|
|
60
|
-
const sealer = newRandomSealer();
|
|
61
|
-
const wrongSealer = newRandomSealer();
|
|
40
|
+
const sender = Crypto.newRandomSealer();
|
|
41
|
+
const sealer = Crypto.newRandomSealer();
|
|
42
|
+
const wrongSealer = Crypto.newRandomSealer();
|
|
62
43
|
|
|
63
44
|
const nOnceMaterial = {
|
|
64
45
|
in: "co_zTEST",
|
|
65
46
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 0 },
|
|
66
47
|
} as const;
|
|
67
48
|
|
|
68
|
-
const sealed = seal({
|
|
49
|
+
const sealed = Crypto.seal({
|
|
69
50
|
message: data,
|
|
70
51
|
from: sender,
|
|
71
|
-
to: getSealerID(sealer),
|
|
52
|
+
to: Crypto.getSealerID(sealer),
|
|
72
53
|
nOnceMaterial,
|
|
73
54
|
});
|
|
74
55
|
|
|
75
|
-
expect(
|
|
76
|
-
|
|
77
|
-
|
|
56
|
+
expect(
|
|
57
|
+
Crypto.unseal(
|
|
58
|
+
sealed,
|
|
59
|
+
sealer,
|
|
60
|
+
Crypto.getSealerID(sender),
|
|
61
|
+
nOnceMaterial,
|
|
62
|
+
),
|
|
63
|
+
).toEqual(data);
|
|
78
64
|
expect(() =>
|
|
79
|
-
unseal(
|
|
65
|
+
Crypto.unseal(
|
|
66
|
+
sealed,
|
|
67
|
+
wrongSealer,
|
|
68
|
+
Crypto.getSealerID(sender),
|
|
69
|
+
nOnceMaterial,
|
|
70
|
+
),
|
|
80
71
|
).toThrow(/Wrong tag/);
|
|
81
72
|
|
|
82
73
|
// trying with wrong sealer secret, by hand
|
|
83
74
|
const nOnce = blake3(
|
|
84
|
-
new TextEncoder().encode(stableStringify(nOnceMaterial))
|
|
75
|
+
new TextEncoder().encode(stableStringify(nOnceMaterial)),
|
|
85
76
|
).slice(0, 24);
|
|
86
77
|
const sealer3priv = base58.decode(
|
|
87
|
-
wrongSealer.substring("sealerSecret_z".length)
|
|
78
|
+
wrongSealer.substring("sealerSecret_z".length),
|
|
88
79
|
);
|
|
89
80
|
const senderPub = base58.decode(
|
|
90
|
-
getSealerID(sender).substring("sealer_z".length)
|
|
81
|
+
Crypto.getSealerID(sender).substring("sealer_z".length),
|
|
91
82
|
);
|
|
92
83
|
const sealedBytes = base64url.decode(sealed.substring("sealed_U".length));
|
|
93
84
|
const sharedSecret = x25519.getSharedSecret(sealer3priv, senderPub);
|
|
@@ -98,34 +89,34 @@ test("encrypting round-trips, but invalid receiver can't unseal", () => {
|
|
|
98
89
|
});
|
|
99
90
|
|
|
100
91
|
test("Hashing is deterministic", () => {
|
|
101
|
-
expect(secureHash({ b: "world", a: "hello" })).toEqual(
|
|
102
|
-
secureHash({ a: "hello", b: "world" })
|
|
92
|
+
expect(Crypto.secureHash({ b: "world", a: "hello" })).toEqual(
|
|
93
|
+
Crypto.secureHash({ a: "hello", b: "world" }),
|
|
103
94
|
);
|
|
104
95
|
|
|
105
|
-
expect(shortHash({ b: "world", a: "hello" })).toEqual(
|
|
106
|
-
shortHash({ a: "hello", b: "world" })
|
|
96
|
+
expect(Crypto.shortHash({ b: "world", a: "hello" })).toEqual(
|
|
97
|
+
Crypto.shortHash({ a: "hello", b: "world" }),
|
|
107
98
|
);
|
|
108
99
|
});
|
|
109
100
|
|
|
110
101
|
test("Encryption for transactions round-trips", () => {
|
|
111
|
-
const { secret } = newRandomKeySecret();
|
|
102
|
+
const { secret } = Crypto.newRandomKeySecret();
|
|
112
103
|
|
|
113
|
-
const encrypted1 = encryptForTransaction({ a: "hello" }, secret, {
|
|
104
|
+
const encrypted1 = Crypto.encryptForTransaction({ a: "hello" }, secret, {
|
|
114
105
|
in: "co_zTEST",
|
|
115
106
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 0 },
|
|
116
107
|
});
|
|
117
108
|
|
|
118
|
-
const encrypted2 = encryptForTransaction({ b: "world" }, secret, {
|
|
109
|
+
const encrypted2 = Crypto.encryptForTransaction({ b: "world" }, secret, {
|
|
119
110
|
in: "co_zTEST",
|
|
120
111
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 1 },
|
|
121
112
|
});
|
|
122
113
|
|
|
123
|
-
const decrypted1 = decryptForTransaction(encrypted1, secret, {
|
|
114
|
+
const decrypted1 = Crypto.decryptForTransaction(encrypted1, secret, {
|
|
124
115
|
in: "co_zTEST",
|
|
125
116
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 0 },
|
|
126
117
|
});
|
|
127
118
|
|
|
128
|
-
const decrypted2 = decryptForTransaction(encrypted2, secret, {
|
|
119
|
+
const decrypted2 = Crypto.decryptForTransaction(encrypted2, secret, {
|
|
129
120
|
in: "co_zTEST",
|
|
130
121
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 1 },
|
|
131
122
|
});
|
|
@@ -134,25 +125,25 @@ test("Encryption for transactions round-trips", () => {
|
|
|
134
125
|
});
|
|
135
126
|
|
|
136
127
|
test("Encryption for transactions doesn't decrypt with a wrong key", () => {
|
|
137
|
-
const { secret } = newRandomKeySecret();
|
|
138
|
-
const { secret: secret2 } = newRandomKeySecret();
|
|
128
|
+
const { secret } = Crypto.newRandomKeySecret();
|
|
129
|
+
const { secret: secret2 } = Crypto.newRandomKeySecret();
|
|
139
130
|
|
|
140
|
-
const encrypted1 = encryptForTransaction({ a: "hello" }, secret, {
|
|
131
|
+
const encrypted1 = Crypto.encryptForTransaction({ a: "hello" }, secret, {
|
|
141
132
|
in: "co_zTEST",
|
|
142
133
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 0 },
|
|
143
134
|
});
|
|
144
135
|
|
|
145
|
-
const encrypted2 = encryptForTransaction({ b: "world" }, secret, {
|
|
136
|
+
const encrypted2 = Crypto.encryptForTransaction({ b: "world" }, secret, {
|
|
146
137
|
in: "co_zTEST",
|
|
147
138
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 1 },
|
|
148
139
|
});
|
|
149
140
|
|
|
150
|
-
const decrypted1 = decryptForTransaction(encrypted1, secret2, {
|
|
141
|
+
const decrypted1 = Crypto.decryptForTransaction(encrypted1, secret2, {
|
|
151
142
|
in: "co_zTEST",
|
|
152
143
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 0 },
|
|
153
144
|
});
|
|
154
145
|
|
|
155
|
-
const decrypted2 = decryptForTransaction(encrypted2, secret2, {
|
|
146
|
+
const decrypted2 = Crypto.decryptForTransaction(encrypted2, secret2, {
|
|
156
147
|
in: "co_zTEST",
|
|
157
148
|
tx: { sessionID: "co_zTEST_session_zTEST" as SessionID, txIndex: 1 },
|
|
158
149
|
});
|
|
@@ -161,34 +152,37 @@ test("Encryption for transactions doesn't decrypt with a wrong key", () => {
|
|
|
161
152
|
});
|
|
162
153
|
|
|
163
154
|
test("Encryption of keySecrets round-trips", () => {
|
|
164
|
-
const toEncrypt = newRandomKeySecret();
|
|
165
|
-
const encrypting = newRandomKeySecret();
|
|
155
|
+
const toEncrypt = Crypto.newRandomKeySecret();
|
|
156
|
+
const encrypting = Crypto.newRandomKeySecret();
|
|
166
157
|
|
|
167
158
|
const keys = {
|
|
168
159
|
toEncrypt,
|
|
169
160
|
encrypting,
|
|
170
161
|
};
|
|
171
162
|
|
|
172
|
-
const encrypted = encryptKeySecret(keys);
|
|
163
|
+
const encrypted = Crypto.encryptKeySecret(keys);
|
|
173
164
|
|
|
174
|
-
const decrypted = decryptKeySecret(encrypted, encrypting.secret);
|
|
165
|
+
const decrypted = Crypto.decryptKeySecret(encrypted, encrypting.secret);
|
|
175
166
|
|
|
176
167
|
expect(decrypted).toEqual(toEncrypt.secret);
|
|
177
168
|
});
|
|
178
169
|
|
|
179
170
|
test("Encryption of keySecrets doesn't decrypt with a wrong key", () => {
|
|
180
|
-
const toEncrypt = newRandomKeySecret();
|
|
181
|
-
const encrypting = newRandomKeySecret();
|
|
182
|
-
const encryptingWrong = newRandomKeySecret();
|
|
171
|
+
const toEncrypt = Crypto.newRandomKeySecret();
|
|
172
|
+
const encrypting = Crypto.newRandomKeySecret();
|
|
173
|
+
const encryptingWrong = Crypto.newRandomKeySecret();
|
|
183
174
|
|
|
184
175
|
const keys = {
|
|
185
176
|
toEncrypt,
|
|
186
177
|
encrypting,
|
|
187
178
|
};
|
|
188
179
|
|
|
189
|
-
const encrypted = encryptKeySecret(keys);
|
|
180
|
+
const encrypted = Crypto.encryptKeySecret(keys);
|
|
190
181
|
|
|
191
|
-
const decrypted = decryptKeySecret(
|
|
182
|
+
const decrypted = Crypto.decryptKeySecret(
|
|
183
|
+
encrypted,
|
|
184
|
+
encryptingWrong.secret,
|
|
185
|
+
);
|
|
192
186
|
|
|
193
187
|
expect(decrypted).toBeUndefined();
|
|
194
188
|
});
|