@peerbit/trusted-network 6.0.112 → 6.0.114

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/src/v2.ts CHANGED
@@ -42,6 +42,13 @@ export const TRUSTED_NETWORK_V2_ENTRY_V0_AUTHORITY_ONLY_SIGNATURE_PROFILE = 1;
42
42
  */
43
43
  export const TRUSTED_NETWORK_V2_MAX_POLICY_ENTRY_BYTES = 128 * 1024;
44
44
 
45
+ /**
46
+ * Consensus bounds for a canonical signed resource-fence EntryV0. These are
47
+ * protocol constants, not resource-adapter configuration.
48
+ */
49
+ export const TRUSTED_NETWORK_V2_MAX_RESOURCE_FENCE_ENTRY_BYTES = 8 * 1024;
50
+ export const TRUSTED_NETWORK_V2_MAX_RESOURCE_FENCE_DIRECT_PARENTS = 64;
51
+
45
52
  export const TRUSTED_NETWORK_V2_NETWORK_ID_DOMAIN =
46
53
  "peerbit/trusted-network/v2/network-id/v1";
47
54
  export const TRUSTED_NETWORK_V2_POLICY_DIGEST_DOMAIN =
@@ -76,7 +83,7 @@ const TYPED_ARRAY_TAG = Object.getOwnPropertyDescriptor(
76
83
  Symbol.toStringTag,
77
84
  )!.get!;
78
85
 
79
- const exactUint8ArrayByteLength = (value: unknown): number => {
86
+ export const exactUint8ArrayByteLengthV2 = (value: unknown): number => {
80
87
  if (
81
88
  !ArrayBuffer.isView(value) ||
82
89
  TYPED_ARRAY_TAG.call(value) !== "Uint8Array"
@@ -90,6 +97,20 @@ const exactUint8ArrayByteLength = (value: unknown): number => {
90
97
  return byteLength;
91
98
  };
92
99
 
100
+ export const copyUint8ArrayWithLengthV2 = (
101
+ value: Uint8Array,
102
+ byteLength: number,
103
+ ): Uint8Array => {
104
+ const copy = new Uint8Array(byteLength);
105
+ Uint8Array.prototype.set.call(copy, value);
106
+ return copy;
107
+ };
108
+
109
+ export const copyUint8ArrayV2 = (value: Uint8Array): Uint8Array => {
110
+ const byteLength = exactUint8ArrayByteLengthV2(value);
111
+ return copyUint8ArrayWithLengthV2(value, byteLength);
112
+ };
113
+
93
114
  const assertByte = (value: number, label: string): void => {
94
115
  if (!Number.isInteger(value) || value < 0 || value > 0xff) {
95
116
  throw new Error(`${label} must be a u8`);
@@ -111,7 +132,7 @@ const assertU64 = (value: bigint, label: string): void => {
111
132
  const assertBytes32 = (value: Uint8Array, label: string): void => {
112
133
  let byteLength: number;
113
134
  try {
114
- byteLength = exactUint8ArrayByteLength(value);
135
+ byteLength = exactUint8ArrayByteLengthV2(value);
115
136
  } catch {
116
137
  throw new Error(`${label} must contain exactly 32 bytes`);
117
138
  }
@@ -457,6 +478,31 @@ export const decodePolicySnapshotBodyV2 = (
457
478
  bytes: Uint8Array,
458
479
  descriptor: NetworkDescriptorV2,
459
480
  ): PolicySnapshotBodyV2 => {
481
+ const byteLength = exactUint8ArrayByteLengthV2(bytes);
482
+ // [2, 1] variant (2), network id (32), sequence (8), and previous
483
+ // digest (32) place the bindings vec<u32 LE> count at offset 74 and its
484
+ // elements at offset 78. Bound that count by captured input before Borsh can
485
+ // allocate from it. This is only a feasibility guard, not a member cap.
486
+ const bindingsCountOffset = 74;
487
+ const bindingsOffset = 78;
488
+ if (byteLength < bindingsOffset) {
489
+ throw new Error("Policy snapshot body has truncated bindings framing");
490
+ }
491
+ const bindingsCount =
492
+ bytes[bindingsCountOffset]! +
493
+ bytes[bindingsCountOffset + 1]! * 0x100 +
494
+ bytes[bindingsCountOffset + 2]! * 0x10000 +
495
+ bytes[bindingsCountOffset + 3]! * 0x1000000;
496
+ // An Ed25519 key variant and key consume 33 bytes; roles and the absent
497
+ // encryption-commitment option consume one byte each. This 35-byte minimum
498
+ // is structural, so it bounds allocation without imposing a policy size.
499
+ const minimumBindingBytes = 35;
500
+ if (
501
+ bindingsCount >
502
+ Math.floor((byteLength - bindingsOffset) / minimumBindingBytes)
503
+ ) {
504
+ throw new Error("Policy snapshot body has impossible bindings count");
505
+ }
460
506
  const body = deserialize(bytes, PolicySnapshotBodyV2);
461
507
  assertCanonicalEncoding(bytes, body);
462
508
  assertPolicySnapshotBodyV2(body, descriptor);
@@ -513,7 +559,7 @@ const decodeExactCanonicalV2 = <T>(
513
559
  ): T => {
514
560
  let byteLength: number;
515
561
  try {
516
- byteLength = exactUint8ArrayByteLength(bytes);
562
+ byteLength = exactUint8ArrayByteLengthV2(bytes);
517
563
  } catch {
518
564
  throw new Error(
519
565
  `TrustedNetwork v2 record must contain ${exactLength} bytes`,
@@ -524,8 +570,7 @@ const decodeExactCanonicalV2 = <T>(
524
570
  `TrustedNetwork v2 record must contain ${exactLength} bytes`,
525
571
  );
526
572
  }
527
- const captured = new Uint8Array(byteLength);
528
- Uint8Array.prototype.set.call(captured, bytes);
573
+ const captured = copyUint8ArrayWithLengthV2(bytes, byteLength);
529
574
  const value = deserialize(captured, type);
530
575
  assertCanonicalEncoding(captured, value);
531
576
  return value;