@peerbit/trusted-network 6.0.109 → 6.0.111
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 +12 -23
- package/dist/src/v2-policy-anchor.d.ts.map +1 -1
- package/dist/src/v2-policy-anchor.js +318 -666
- package/dist/src/v2-policy-anchor.js.map +1 -1
- package/dist/src/v2.d.ts +52 -5
- package/dist/src/v2.d.ts.map +1 -1
- package/dist/src/v2.js +225 -6
- package/dist/src/v2.js.map +1 -1
- package/package.json +7 -6
- package/src/v2-policy-anchor.ts +423 -754
- package/src/v2.ts +209 -6
package/src/v2.ts
CHANGED
|
@@ -19,17 +19,19 @@ import { compare, concat, equals } from "uint8arrays";
|
|
|
19
19
|
* Decode-only TrustedNetwork v2 codec scaffold.
|
|
20
20
|
*
|
|
21
21
|
* This module is intentionally absent from the package entry point. It pins
|
|
22
|
-
* the policy
|
|
23
|
-
*
|
|
22
|
+
* the policy, resource-fence-body, and operation-proof wire contracts without
|
|
23
|
+
* exposing a usable controller, resource validator, or encryption path.
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
export const TRUSTED_NETWORK_V2_PROTOCOL_VERSION = 2;
|
|
27
27
|
export const TRUSTED_NETWORK_V2_POLICY_HASH_SHA256 = 1;
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
30
|
+
* Authority-record profile 1 accepts only a policy-snapshot or resource-fence
|
|
31
|
+
* EntryV0 whose normal toSignable() bytes (including causal metadata) have
|
|
32
|
+
* exactly one successfully verified signature. The signer's canonical
|
|
33
|
+
* public-key bytes must equal the descriptor authority. Protected-resource
|
|
34
|
+
* adapters must define a separate bounded profile for operation entries.
|
|
33
35
|
*/
|
|
34
36
|
export const TRUSTED_NETWORK_V2_ENTRY_V0_AUTHORITY_ONLY_SIGNATURE_PROFILE = 1;
|
|
35
37
|
|
|
@@ -45,6 +47,10 @@ export const TRUSTED_NETWORK_V2_NETWORK_ID_DOMAIN =
|
|
|
45
47
|
export const TRUSTED_NETWORK_V2_POLICY_DIGEST_DOMAIN =
|
|
46
48
|
"peerbit/trusted-network/v2/policy-body/v1";
|
|
47
49
|
|
|
50
|
+
/** Fixed first-profile record lengths. Changing either requires a new variant. */
|
|
51
|
+
export const TRUSTED_NETWORK_V2_RESOURCE_FENCE_BODY_BYTES = 186;
|
|
52
|
+
export const TRUSTED_NETWORK_V2_OPERATION_POLICY_PROOF_BYTES = 146;
|
|
53
|
+
|
|
48
54
|
export const TrustedNetworkRole = Object.freeze({
|
|
49
55
|
ADMIN: 0x01,
|
|
50
56
|
WRITER: 0x02,
|
|
@@ -60,6 +66,29 @@ export const TRUSTED_NETWORK_V2_KNOWN_ROLE_BITS =
|
|
|
60
66
|
|
|
61
67
|
const ZERO_DIGEST = new Uint8Array(32);
|
|
62
68
|
const textEncoder = new TextEncoder();
|
|
69
|
+
const TYPED_ARRAY_PROTOTYPE = Object.getPrototypeOf(Uint8Array.prototype);
|
|
70
|
+
const TYPED_ARRAY_BYTE_LENGTH = Object.getOwnPropertyDescriptor(
|
|
71
|
+
TYPED_ARRAY_PROTOTYPE,
|
|
72
|
+
"byteLength",
|
|
73
|
+
)!.get!;
|
|
74
|
+
const TYPED_ARRAY_TAG = Object.getOwnPropertyDescriptor(
|
|
75
|
+
TYPED_ARRAY_PROTOTYPE,
|
|
76
|
+
Symbol.toStringTag,
|
|
77
|
+
)!.get!;
|
|
78
|
+
|
|
79
|
+
const exactUint8ArrayByteLength = (value: unknown): number => {
|
|
80
|
+
if (
|
|
81
|
+
!ArrayBuffer.isView(value) ||
|
|
82
|
+
TYPED_ARRAY_TAG.call(value) !== "Uint8Array"
|
|
83
|
+
) {
|
|
84
|
+
throw new TypeError("Expected a genuine Uint8Array");
|
|
85
|
+
}
|
|
86
|
+
const byteLength = TYPED_ARRAY_BYTE_LENGTH.call(value) as number;
|
|
87
|
+
if (byteLength === 0) {
|
|
88
|
+
Uint8Array.prototype.set.call(new Uint8Array(0), value as Uint8Array);
|
|
89
|
+
}
|
|
90
|
+
return byteLength;
|
|
91
|
+
};
|
|
63
92
|
|
|
64
93
|
const assertByte = (value: number, label: string): void => {
|
|
65
94
|
if (!Number.isInteger(value) || value < 0 || value > 0xff) {
|
|
@@ -80,7 +109,13 @@ const assertU64 = (value: bigint, label: string): void => {
|
|
|
80
109
|
};
|
|
81
110
|
|
|
82
111
|
const assertBytes32 = (value: Uint8Array, label: string): void => {
|
|
83
|
-
|
|
112
|
+
let byteLength: number;
|
|
113
|
+
try {
|
|
114
|
+
byteLength = exactUint8ArrayByteLength(value);
|
|
115
|
+
} catch {
|
|
116
|
+
throw new Error(`${label} must contain exactly 32 bytes`);
|
|
117
|
+
}
|
|
118
|
+
if (byteLength !== 32) {
|
|
84
119
|
throw new Error(`${label} must contain exactly 32 bytes`);
|
|
85
120
|
}
|
|
86
121
|
};
|
|
@@ -190,6 +225,80 @@ export class PolicySnapshotBodyV2 {
|
|
|
190
225
|
}
|
|
191
226
|
}
|
|
192
227
|
|
|
228
|
+
/** Canonical unsigned payload intended for an authenticated resource fence. */
|
|
229
|
+
@variant([2, 2])
|
|
230
|
+
export class ResourceFenceV2 {
|
|
231
|
+
@field({ type: fixedArray("u8", 32) })
|
|
232
|
+
networkId: Uint8Array;
|
|
233
|
+
|
|
234
|
+
@field({ type: fixedArray("u8", 32) })
|
|
235
|
+
resourceId: Uint8Array;
|
|
236
|
+
|
|
237
|
+
@field({ type: "u64" })
|
|
238
|
+
fenceSequence: bigint;
|
|
239
|
+
|
|
240
|
+
@field({ type: fixedArray("u8", 32) })
|
|
241
|
+
previousFenceDigest: Uint8Array;
|
|
242
|
+
|
|
243
|
+
@field({ type: "u64" })
|
|
244
|
+
policySequence: bigint;
|
|
245
|
+
|
|
246
|
+
@field({ type: fixedArray("u8", 32) })
|
|
247
|
+
policyDigest: Uint8Array;
|
|
248
|
+
|
|
249
|
+
@field({ type: "u64" })
|
|
250
|
+
contentEpoch: bigint;
|
|
251
|
+
|
|
252
|
+
@field({ type: fixedArray("u8", 32) })
|
|
253
|
+
epochManifestDigest: Uint8Array;
|
|
254
|
+
|
|
255
|
+
constructor(properties?: {
|
|
256
|
+
networkId: Uint8Array;
|
|
257
|
+
resourceId: Uint8Array;
|
|
258
|
+
fenceSequence: bigint;
|
|
259
|
+
previousFenceDigest: Uint8Array;
|
|
260
|
+
policySequence: bigint;
|
|
261
|
+
policyDigest: Uint8Array;
|
|
262
|
+
contentEpoch: bigint;
|
|
263
|
+
epochManifestDigest: Uint8Array;
|
|
264
|
+
}) {
|
|
265
|
+
if (properties) Object.assign(this, properties);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/** Constant-size policy commitment intended for a signed resource operation. */
|
|
270
|
+
@variant([2, 3])
|
|
271
|
+
export class OperationPolicyProofV2 {
|
|
272
|
+
@field({ type: fixedArray("u8", 32) })
|
|
273
|
+
networkId: Uint8Array;
|
|
274
|
+
|
|
275
|
+
@field({ type: fixedArray("u8", 32) })
|
|
276
|
+
resourceId: Uint8Array;
|
|
277
|
+
|
|
278
|
+
@field({ type: "u64" })
|
|
279
|
+
policySequence: bigint;
|
|
280
|
+
|
|
281
|
+
@field({ type: fixedArray("u8", 32) })
|
|
282
|
+
policyDigest: Uint8Array;
|
|
283
|
+
|
|
284
|
+
@field({ type: fixedArray("u8", 32) })
|
|
285
|
+
fenceDigest: Uint8Array;
|
|
286
|
+
|
|
287
|
+
@field({ type: "u64" })
|
|
288
|
+
contentEpoch: bigint;
|
|
289
|
+
|
|
290
|
+
constructor(properties?: {
|
|
291
|
+
networkId: Uint8Array;
|
|
292
|
+
resourceId: Uint8Array;
|
|
293
|
+
policySequence: bigint;
|
|
294
|
+
policyDigest: Uint8Array;
|
|
295
|
+
fenceDigest: Uint8Array;
|
|
296
|
+
contentEpoch: bigint;
|
|
297
|
+
}) {
|
|
298
|
+
if (properties) Object.assign(this, properties);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
193
302
|
@variant("trusted_network_v2")
|
|
194
303
|
export class TrustedNetworkV2 extends Program<never> {
|
|
195
304
|
@field({ type: NetworkDescriptorV2 })
|
|
@@ -353,3 +462,97 @@ export const decodePolicySnapshotBodyV2 = (
|
|
|
353
462
|
assertPolicySnapshotBodyV2(body, descriptor);
|
|
354
463
|
return body;
|
|
355
464
|
};
|
|
465
|
+
|
|
466
|
+
export const assertResourceFenceV2 = (
|
|
467
|
+
fence: ResourceFenceV2,
|
|
468
|
+
descriptor: NetworkDescriptorV2,
|
|
469
|
+
): void => {
|
|
470
|
+
assertNetworkDescriptorV2(descriptor);
|
|
471
|
+
assertBytes32(fence.networkId, "networkId");
|
|
472
|
+
if (!equals(fence.networkId, deriveNetworkIdV2(descriptor))) {
|
|
473
|
+
throw new Error("Resource fence belongs to another network");
|
|
474
|
+
}
|
|
475
|
+
assertBytes32(fence.resourceId, "resourceId");
|
|
476
|
+
assertU64(fence.fenceSequence, "fenceSequence");
|
|
477
|
+
assertBytes32(fence.previousFenceDigest, "previousFenceDigest");
|
|
478
|
+
if (fence.fenceSequence === 0n) {
|
|
479
|
+
if (!equals(fence.previousFenceDigest, ZERO_DIGEST)) {
|
|
480
|
+
throw new Error(
|
|
481
|
+
"Initial resource fence must use the zero previous digest",
|
|
482
|
+
);
|
|
483
|
+
}
|
|
484
|
+
} else if (equals(fence.previousFenceDigest, ZERO_DIGEST)) {
|
|
485
|
+
throw new Error("A non-initial resource fence must name its predecessor");
|
|
486
|
+
}
|
|
487
|
+
assertU64(fence.policySequence, "policySequence");
|
|
488
|
+
assertBytes32(fence.policyDigest, "policyDigest");
|
|
489
|
+
assertU64(fence.contentEpoch, "contentEpoch");
|
|
490
|
+
assertBytes32(fence.epochManifestDigest, "epochManifestDigest");
|
|
491
|
+
};
|
|
492
|
+
|
|
493
|
+
export const assertOperationPolicyProofV2 = (
|
|
494
|
+
proof: OperationPolicyProofV2,
|
|
495
|
+
descriptor: NetworkDescriptorV2,
|
|
496
|
+
): void => {
|
|
497
|
+
assertNetworkDescriptorV2(descriptor);
|
|
498
|
+
assertBytes32(proof.networkId, "networkId");
|
|
499
|
+
if (!equals(proof.networkId, deriveNetworkIdV2(descriptor))) {
|
|
500
|
+
throw new Error("Operation policy proof belongs to another network");
|
|
501
|
+
}
|
|
502
|
+
assertBytes32(proof.resourceId, "resourceId");
|
|
503
|
+
assertU64(proof.policySequence, "policySequence");
|
|
504
|
+
assertBytes32(proof.policyDigest, "policyDigest");
|
|
505
|
+
assertBytes32(proof.fenceDigest, "fenceDigest");
|
|
506
|
+
assertU64(proof.contentEpoch, "contentEpoch");
|
|
507
|
+
};
|
|
508
|
+
|
|
509
|
+
const decodeExactCanonicalV2 = <T>(
|
|
510
|
+
bytes: Uint8Array,
|
|
511
|
+
exactLength: number,
|
|
512
|
+
type: new () => T,
|
|
513
|
+
): T => {
|
|
514
|
+
let byteLength: number;
|
|
515
|
+
try {
|
|
516
|
+
byteLength = exactUint8ArrayByteLength(bytes);
|
|
517
|
+
} catch {
|
|
518
|
+
throw new Error(
|
|
519
|
+
`TrustedNetwork v2 record must contain ${exactLength} bytes`,
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
if (byteLength !== exactLength) {
|
|
523
|
+
throw new Error(
|
|
524
|
+
`TrustedNetwork v2 record must contain ${exactLength} bytes`,
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
const captured = new Uint8Array(byteLength);
|
|
528
|
+
Uint8Array.prototype.set.call(captured, bytes);
|
|
529
|
+
const value = deserialize(captured, type);
|
|
530
|
+
assertCanonicalEncoding(captured, value);
|
|
531
|
+
return value;
|
|
532
|
+
};
|
|
533
|
+
|
|
534
|
+
export const decodeResourceFenceV2 = (
|
|
535
|
+
bytes: Uint8Array,
|
|
536
|
+
descriptor: NetworkDescriptorV2,
|
|
537
|
+
): ResourceFenceV2 => {
|
|
538
|
+
const fence = decodeExactCanonicalV2(
|
|
539
|
+
bytes,
|
|
540
|
+
TRUSTED_NETWORK_V2_RESOURCE_FENCE_BODY_BYTES,
|
|
541
|
+
ResourceFenceV2,
|
|
542
|
+
);
|
|
543
|
+
assertResourceFenceV2(fence, descriptor);
|
|
544
|
+
return fence;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
export const decodeOperationPolicyProofV2 = (
|
|
548
|
+
bytes: Uint8Array,
|
|
549
|
+
descriptor: NetworkDescriptorV2,
|
|
550
|
+
): OperationPolicyProofV2 => {
|
|
551
|
+
const proof = decodeExactCanonicalV2(
|
|
552
|
+
bytes,
|
|
553
|
+
TRUSTED_NETWORK_V2_OPERATION_POLICY_PROOF_BYTES,
|
|
554
|
+
OperationPolicyProofV2,
|
|
555
|
+
);
|
|
556
|
+
assertOperationPolicyProofV2(proof, descriptor);
|
|
557
|
+
return proof;
|
|
558
|
+
};
|