@peerbit/trusted-network 6.0.107 → 6.0.109
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/dist/src/v2-policy-anchor.d.ts +11 -1
- package/dist/src/v2-policy-anchor.d.ts.map +1 -1
- package/dist/src/v2-policy-anchor.js +304 -100
- package/dist/src/v2-policy-anchor.js.map +1 -1
- package/dist/src/v2-policy-engine.d.ts +10 -0
- package/dist/src/v2-policy-engine.d.ts.map +1 -1
- package/dist/src/v2-policy-engine.js +57 -12
- package/dist/src/v2-policy-engine.js.map +1 -1
- package/package.json +7 -7
- package/src/v2-policy-anchor.ts +406 -119
- package/src/v2-policy-engine.ts +76 -12
package/src/v2-policy-engine.ts
CHANGED
|
@@ -22,7 +22,9 @@ import {
|
|
|
22
22
|
* resolver instead of being accumulated in memory.
|
|
23
23
|
*/
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
/** Internal protocol ceiling; this module is not part of the package root. */
|
|
26
|
+
export const TRUSTED_NETWORK_V2_MAX_PENDING_POLICIES = 64;
|
|
27
|
+
const DEFAULT_MAX_PENDING_POLICIES_V2 = TRUSTED_NETWORK_V2_MAX_PENDING_POLICIES;
|
|
26
28
|
const PENDING_POLICY_ACCOUNTING_OVERHEAD_V2 = 64;
|
|
27
29
|
const MAX_PENDING_POLICY_ACCOUNTED_BYTES_V2 =
|
|
28
30
|
TRUSTED_NETWORK_V2_MAX_POLICY_ENTRY_BYTES * 2 +
|
|
@@ -33,7 +35,58 @@ const DEFAULT_POLICY_RESOLUTION_TIMEOUT_MS_V2 = 10 * 1000;
|
|
|
33
35
|
const MAX_TIMER_DELAY_MS_V2 = 0x7fffffff;
|
|
34
36
|
const MAX_UNAVAILABLE_REASON_LENGTH_V2 = 512;
|
|
35
37
|
|
|
36
|
-
const
|
|
38
|
+
const TYPED_ARRAY_PROTOTYPE = Object.getPrototypeOf(Uint8Array.prototype);
|
|
39
|
+
const TYPED_ARRAY_BYTE_LENGTH = Object.getOwnPropertyDescriptor(
|
|
40
|
+
TYPED_ARRAY_PROTOTYPE,
|
|
41
|
+
"byteLength",
|
|
42
|
+
)!.get!;
|
|
43
|
+
const TYPED_ARRAY_TAG = Object.getOwnPropertyDescriptor(
|
|
44
|
+
TYPED_ARRAY_PROTOTYPE,
|
|
45
|
+
Symbol.toStringTag,
|
|
46
|
+
)!.get!;
|
|
47
|
+
const ARRAY_BUFFER_IS_VIEW = ArrayBuffer.isView;
|
|
48
|
+
const UINT8_ARRAY_SET = Uint8Array.prototype.set;
|
|
49
|
+
|
|
50
|
+
const exactUint8ArrayByteLength = (input: unknown): number => {
|
|
51
|
+
if (
|
|
52
|
+
!ARRAY_BUFFER_IS_VIEW(input) ||
|
|
53
|
+
TYPED_ARRAY_TAG.call(input) !== "Uint8Array"
|
|
54
|
+
) {
|
|
55
|
+
throw new TypeError("Expected a genuine Uint8Array");
|
|
56
|
+
}
|
|
57
|
+
const byteLength = TYPED_ARRAY_BYTE_LENGTH.call(input) as number;
|
|
58
|
+
if (byteLength === 0) {
|
|
59
|
+
// The intrinsic getter reports zero for both empty and detached views. The
|
|
60
|
+
// intrinsic set distinguishes them without consulting caller properties.
|
|
61
|
+
UINT8_ARRAY_SET.call(new Uint8Array(0), input as Uint8Array);
|
|
62
|
+
}
|
|
63
|
+
return byteLength;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
const copyBytesWithLength = (
|
|
67
|
+
bytes: Uint8Array,
|
|
68
|
+
byteLength: number,
|
|
69
|
+
): Uint8Array => {
|
|
70
|
+
const copy = new Uint8Array(byteLength);
|
|
71
|
+
UINT8_ARRAY_SET.call(copy, bytes);
|
|
72
|
+
return copy;
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const copyBytes = (bytes: Uint8Array): Uint8Array => {
|
|
76
|
+
const byteLength = exactUint8ArrayByteLength(bytes);
|
|
77
|
+
return copyBytesWithLength(bytes, byteLength);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const hasExactUint8ArrayByteLength = (
|
|
81
|
+
input: unknown,
|
|
82
|
+
expected: number,
|
|
83
|
+
): input is Uint8Array => {
|
|
84
|
+
try {
|
|
85
|
+
return exactUint8ArrayByteLength(input) === expected;
|
|
86
|
+
} catch {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
};
|
|
37
90
|
|
|
38
91
|
const bytesKey = (bytes: Uint8Array): string => {
|
|
39
92
|
let key = "";
|
|
@@ -227,13 +280,16 @@ class PolicyDependencyUnavailableErrorV2 extends Error {
|
|
|
227
280
|
const capturePolicySnapshotEntryBytesV2 = (
|
|
228
281
|
entryBytes: Uint8Array,
|
|
229
282
|
): Uint8Array => {
|
|
230
|
-
|
|
283
|
+
let byteLength: number;
|
|
284
|
+
try {
|
|
285
|
+
byteLength = exactUint8ArrayByteLength(entryBytes);
|
|
286
|
+
} catch {
|
|
231
287
|
throw new Error("Policy snapshot must use canonical EntryV0 bytes");
|
|
232
288
|
}
|
|
233
|
-
if (
|
|
289
|
+
if (byteLength === 0) {
|
|
234
290
|
throw new Error("Policy snapshot must use EntryV0");
|
|
235
291
|
}
|
|
236
|
-
if (
|
|
292
|
+
if (byteLength > TRUSTED_NETWORK_V2_MAX_POLICY_ENTRY_BYTES) {
|
|
237
293
|
throw new Error(
|
|
238
294
|
`Policy snapshot entry must contain 1-${TRUSTED_NETWORK_V2_MAX_POLICY_ENTRY_BYTES} bytes`,
|
|
239
295
|
);
|
|
@@ -241,7 +297,7 @@ const capturePolicySnapshotEntryBytesV2 = (
|
|
|
241
297
|
|
|
242
298
|
// Apply the protocol byte ceiling before this first copy, decode, or crypto
|
|
243
299
|
// operation. The retained copy also prevents caller mutation during awaits.
|
|
244
|
-
return
|
|
300
|
+
return copyBytesWithLength(entryBytes, byteLength);
|
|
245
301
|
};
|
|
246
302
|
|
|
247
303
|
const authenticateCapturedPolicySnapshotEntryV2 = async (
|
|
@@ -292,12 +348,15 @@ const authenticateCapturedPolicySnapshotEntryV2 = async (
|
|
|
292
348
|
}
|
|
293
349
|
|
|
294
350
|
const payload = await authenticatedEntry.getPayloadValue();
|
|
295
|
-
|
|
351
|
+
let canonicalPayload: Uint8Array;
|
|
352
|
+
try {
|
|
353
|
+
canonicalPayload = copyBytes(payload as Uint8Array);
|
|
354
|
+
} catch {
|
|
296
355
|
throw new Error(
|
|
297
356
|
"Policy snapshot payload must contain canonical body bytes",
|
|
298
357
|
);
|
|
299
358
|
}
|
|
300
|
-
const body = decodePolicySnapshotBodyV2(
|
|
359
|
+
const body = decodePolicySnapshotBodyV2(canonicalPayload, descriptor);
|
|
301
360
|
const digest = digestPolicySnapshotBodyV2(body);
|
|
302
361
|
return {
|
|
303
362
|
body: copyBody(body),
|
|
@@ -398,8 +457,7 @@ const captureDurableStateV2 = (
|
|
|
398
457
|
};
|
|
399
458
|
case "UNAVAILABLE": {
|
|
400
459
|
if (
|
|
401
|
-
!(durableState.acceptedAncestorDigest
|
|
402
|
-
durableState.acceptedAncestorDigest.byteLength !== 32
|
|
460
|
+
!hasExactUint8ArrayByteLength(durableState.acceptedAncestorDigest, 32)
|
|
403
461
|
) {
|
|
404
462
|
throw new Error(
|
|
405
463
|
"Unavailable accepted ancestor digest must contain exactly 32 bytes",
|
|
@@ -473,8 +531,14 @@ export class TrustedNetworkV2PolicyReducer {
|
|
|
473
531
|
constructor(properties: TrustedNetworkV2PolicyReducerProperties) {
|
|
474
532
|
assertNetworkDescriptorV2(properties.descriptor);
|
|
475
533
|
const maxPending = properties.maxPending ?? DEFAULT_MAX_PENDING_POLICIES_V2;
|
|
476
|
-
if (
|
|
477
|
-
|
|
534
|
+
if (
|
|
535
|
+
!Number.isSafeInteger(maxPending) ||
|
|
536
|
+
maxPending < 1 ||
|
|
537
|
+
maxPending > TRUSTED_NETWORK_V2_MAX_PENDING_POLICIES
|
|
538
|
+
) {
|
|
539
|
+
throw new Error(
|
|
540
|
+
`maxPending must be a positive safe integer no greater than ${TRUSTED_NETWORK_V2_MAX_PENDING_POLICIES}`,
|
|
541
|
+
);
|
|
478
542
|
}
|
|
479
543
|
const maxPendingPolicyBytes =
|
|
480
544
|
properties.maxPendingPolicyBytes ?? DEFAULT_MAX_PENDING_POLICY_BYTES_V2;
|