@bsv/overlay 2.3.0 → 2.6.1

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.
Files changed (207) hide show
  1. package/LICENSES/Open-BSV-License-4-standard-pre-2026.txt +28 -0
  2. package/README.md +171 -1
  3. package/THIRD_PARTY_NOTICES.md +49 -0
  4. package/dist/cjs/mod.d.ts +4 -1
  5. package/dist/cjs/mod.d.ts.map +1 -1
  6. package/dist/cjs/mod.js +8 -1
  7. package/dist/cjs/mod.js.map +1 -1
  8. package/dist/cjs/package.json +13 -5
  9. package/dist/cjs/src/BASM.d.ts +6 -0
  10. package/dist/cjs/src/BASM.d.ts.map +1 -1
  11. package/dist/cjs/src/BASM.js +21 -8
  12. package/dist/cjs/src/BASM.js.map +1 -1
  13. package/dist/cjs/src/BASMRemote.d.ts +8 -1
  14. package/dist/cjs/src/BASMRemote.d.ts.map +1 -1
  15. package/dist/cjs/src/BASMRemote.js +179 -13
  16. package/dist/cjs/src/BASMRemote.js.map +1 -1
  17. package/dist/cjs/src/BASMValidation.d.ts +27 -0
  18. package/dist/cjs/src/BASMValidation.d.ts.map +1 -0
  19. package/dist/cjs/src/BASMValidation.js +108 -0
  20. package/dist/cjs/src/BASMValidation.js.map +1 -0
  21. package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts +11 -0
  22. package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
  23. package/dist/cjs/src/DiscoveryAdvertisementValidation.js +60 -0
  24. package/dist/cjs/src/DiscoveryAdvertisementValidation.js.map +1 -0
  25. package/dist/cjs/src/Engine.d.ts +38 -13
  26. package/dist/cjs/src/Engine.d.ts.map +1 -1
  27. package/dist/cjs/src/Engine.js +1735 -336
  28. package/dist/cjs/src/Engine.js.map +1 -1
  29. package/dist/cjs/src/EngineAdmission.d.ts +70 -0
  30. package/dist/cjs/src/EngineAdmission.d.ts.map +1 -0
  31. package/dist/cjs/src/EngineAdmission.js +297 -0
  32. package/dist/cjs/src/EngineAdmission.js.map +1 -0
  33. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts +4 -3
  34. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  35. package/dist/cjs/src/GASP/OverlayGASPRemote.js +27 -43
  36. package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
  37. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts +22 -16
  38. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  39. package/dist/cjs/src/GASP/OverlayGASPStorage.js +206 -57
  40. package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
  41. package/dist/cjs/src/RemoteSecurity.d.ts +50 -0
  42. package/dist/cjs/src/RemoteSecurity.d.ts.map +1 -0
  43. package/dist/cjs/src/RemoteSecurity.js +301 -0
  44. package/dist/cjs/src/RemoteSecurity.js.map +1 -0
  45. package/dist/cjs/src/TopicManager.d.ts +13 -3
  46. package/dist/cjs/src/TopicManager.d.ts.map +1 -1
  47. package/dist/cjs/src/storage/AdmissionStorage.d.ts +185 -0
  48. package/dist/cjs/src/storage/AdmissionStorage.d.ts.map +1 -0
  49. package/dist/cjs/src/storage/AdmissionStorage.js +93 -0
  50. package/dist/cjs/src/storage/AdmissionStorage.js.map +1 -0
  51. package/dist/cjs/src/storage/RecoveryContract.d.ts +50 -0
  52. package/dist/cjs/src/storage/RecoveryContract.d.ts.map +1 -0
  53. package/dist/cjs/src/storage/RecoveryContract.js +35 -0
  54. package/dist/cjs/src/storage/RecoveryContract.js.map +1 -0
  55. package/dist/cjs/src/storage/Storage.d.ts +32 -19
  56. package/dist/cjs/src/storage/Storage.d.ts.map +1 -1
  57. package/dist/cjs/src/storage/Storage.js +5 -0
  58. package/dist/cjs/src/storage/Storage.js.map +1 -1
  59. package/dist/cjs/src/storage/knex/KnexStorage.d.ts +8 -8
  60. package/dist/cjs/src/storage/knex/KnexStorage.d.ts.map +1 -1
  61. package/dist/cjs/src/storage/knex/KnexStorage.js +98 -61
  62. package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
  63. package/dist/cjs/src/storage/knex/all-migrations.d.ts.map +1 -1
  64. package/dist/cjs/src/storage/knex/all-migrations.js +5 -1
  65. package/dist/cjs/src/storage/knex/all-migrations.js.map +1 -1
  66. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
  67. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
  68. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +36 -0
  69. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
  70. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
  71. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
  72. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js +16 -0
  73. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
  74. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
  75. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
  76. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js +229 -0
  77. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
  78. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
  79. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
  80. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js +675 -0
  81. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
  82. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
  83. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
  84. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js +453 -0
  85. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
  86. package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
  87. package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
  88. package/dist/cjs/src/storage/mongo/MongoPayloadStore.js +756 -0
  89. package/dist/cjs/src/storage/mongo/MongoPayloadStore.js.map +1 -0
  90. package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts +44 -0
  91. package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
  92. package/dist/cjs/src/storage/mongo/MongoReadGuards.js +135 -0
  93. package/dist/cjs/src/storage/mongo/MongoReadGuards.js.map +1 -0
  94. package/dist/cjs/src/storage/mongo/MongoSchema.d.ts +67 -0
  95. package/dist/cjs/src/storage/mongo/MongoSchema.d.ts.map +1 -0
  96. package/dist/cjs/src/storage/mongo/MongoSchema.js +743 -0
  97. package/dist/cjs/src/storage/mongo/MongoSchema.js.map +1 -0
  98. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
  99. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
  100. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js +368 -0
  101. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
  102. package/dist/cjs/src/storage/mongo.d.ts +9 -0
  103. package/dist/cjs/src/storage/mongo.d.ts.map +1 -0
  104. package/dist/cjs/src/storage/mongo.js +25 -0
  105. package/dist/cjs/src/storage/mongo.js.map +1 -0
  106. package/dist/esm/mod.js +3 -0
  107. package/dist/esm/mod.js.map +1 -1
  108. package/dist/esm/src/BASM.js +21 -8
  109. package/dist/esm/src/BASM.js.map +1 -1
  110. package/dist/esm/src/BASMRemote.js +176 -12
  111. package/dist/esm/src/BASMRemote.js.map +1 -1
  112. package/dist/esm/src/BASMValidation.js +95 -0
  113. package/dist/esm/src/BASMValidation.js.map +1 -0
  114. package/dist/esm/src/DiscoveryAdvertisementValidation.js +57 -0
  115. package/dist/esm/src/DiscoveryAdvertisementValidation.js.map +1 -0
  116. package/dist/esm/src/Engine.js +1720 -326
  117. package/dist/esm/src/Engine.js.map +1 -1
  118. package/dist/esm/src/EngineAdmission.js +280 -0
  119. package/dist/esm/src/EngineAdmission.js.map +1 -0
  120. package/dist/esm/src/GASP/OverlayGASPRemote.js +27 -43
  121. package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
  122. package/dist/esm/src/GASP/OverlayGASPStorage.js +200 -56
  123. package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
  124. package/dist/esm/src/RemoteSecurity.js +279 -0
  125. package/dist/esm/src/RemoteSecurity.js.map +1 -0
  126. package/dist/esm/src/storage/AdmissionStorage.js +85 -0
  127. package/dist/esm/src/storage/AdmissionStorage.js.map +1 -0
  128. package/dist/esm/src/storage/RecoveryContract.js +31 -0
  129. package/dist/esm/src/storage/RecoveryContract.js.map +1 -0
  130. package/dist/esm/src/storage/Storage.js +4 -1
  131. package/dist/esm/src/storage/Storage.js.map +1 -1
  132. package/dist/esm/src/storage/knex/KnexStorage.js +98 -61
  133. package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
  134. package/dist/esm/src/storage/knex/all-migrations.js +5 -1
  135. package/dist/esm/src/storage/knex/all-migrations.js.map +1 -1
  136. package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +32 -0
  137. package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
  138. package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js +12 -0
  139. package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
  140. package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js +217 -0
  141. package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
  142. package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js +673 -0
  143. package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
  144. package/dist/esm/src/storage/mongo/MongoOverlayStorage.js +451 -0
  145. package/dist/esm/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
  146. package/dist/esm/src/storage/mongo/MongoPayloadStore.js +747 -0
  147. package/dist/esm/src/storage/mongo/MongoPayloadStore.js.map +1 -0
  148. package/dist/esm/src/storage/mongo/MongoReadGuards.js +129 -0
  149. package/dist/esm/src/storage/mongo/MongoReadGuards.js.map +1 -0
  150. package/dist/esm/src/storage/mongo/MongoSchema.js +730 -0
  151. package/dist/esm/src/storage/mongo/MongoSchema.js.map +1 -0
  152. package/dist/esm/src/storage/mongo/MongoTransactionRunner.js +371 -0
  153. package/dist/esm/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
  154. package/dist/esm/src/storage/mongo.js +9 -0
  155. package/dist/esm/src/storage/mongo.js.map +1 -0
  156. package/dist/types/mod.d.ts +4 -1
  157. package/dist/types/mod.d.ts.map +1 -1
  158. package/dist/types/src/BASM.d.ts +6 -0
  159. package/dist/types/src/BASM.d.ts.map +1 -1
  160. package/dist/types/src/BASMRemote.d.ts +8 -1
  161. package/dist/types/src/BASMRemote.d.ts.map +1 -1
  162. package/dist/types/src/BASMValidation.d.ts +27 -0
  163. package/dist/types/src/BASMValidation.d.ts.map +1 -0
  164. package/dist/types/src/DiscoveryAdvertisementValidation.d.ts +11 -0
  165. package/dist/types/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
  166. package/dist/types/src/Engine.d.ts +38 -13
  167. package/dist/types/src/Engine.d.ts.map +1 -1
  168. package/dist/types/src/EngineAdmission.d.ts +70 -0
  169. package/dist/types/src/EngineAdmission.d.ts.map +1 -0
  170. package/dist/types/src/GASP/OverlayGASPRemote.d.ts +4 -3
  171. package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  172. package/dist/types/src/GASP/OverlayGASPStorage.d.ts +22 -16
  173. package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  174. package/dist/types/src/RemoteSecurity.d.ts +50 -0
  175. package/dist/types/src/RemoteSecurity.d.ts.map +1 -0
  176. package/dist/types/src/TopicManager.d.ts +13 -3
  177. package/dist/types/src/TopicManager.d.ts.map +1 -1
  178. package/dist/types/src/storage/AdmissionStorage.d.ts +185 -0
  179. package/dist/types/src/storage/AdmissionStorage.d.ts.map +1 -0
  180. package/dist/types/src/storage/RecoveryContract.d.ts +50 -0
  181. package/dist/types/src/storage/RecoveryContract.d.ts.map +1 -0
  182. package/dist/types/src/storage/Storage.d.ts +32 -19
  183. package/dist/types/src/storage/Storage.d.ts.map +1 -1
  184. package/dist/types/src/storage/knex/KnexStorage.d.ts +8 -8
  185. package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
  186. package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
  187. package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
  188. package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
  189. package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
  190. package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
  191. package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
  192. package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
  193. package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
  194. package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
  195. package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
  196. package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
  197. package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
  198. package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
  199. package/dist/types/src/storage/mongo/MongoReadGuards.d.ts +44 -0
  200. package/dist/types/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
  201. package/dist/types/src/storage/mongo/MongoSchema.d.ts +67 -0
  202. package/dist/types/src/storage/mongo/MongoSchema.d.ts.map +1 -0
  203. package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
  204. package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
  205. package/dist/types/src/storage/mongo.d.ts +9 -0
  206. package/dist/types/src/storage/mongo.d.ts.map +1 -0
  207. package/package.json +14 -6
@@ -0,0 +1,279 @@
1
+ import { Transaction, createPublicHTTPSFetch } from '@bsv/sdk';
2
+ export const MAX_GASP_PAGE_SIZE = 10_000;
3
+ export const MAX_BASM_TXIDS = 256;
4
+ export const MAX_REMOTE_JSON_BYTES = 64 * 1024 * 1024;
5
+ export const MAX_GASP_NODE_JSON_BYTES = 32 * 1024 * 1024;
6
+ export const MAX_RAW_TRANSACTION_BYTES = 32 * 1024 * 1024;
7
+ export const REMOTE_BODY_TIMEOUT_MS = 30_000;
8
+ const MAX_TOPIC_BYTES = 256;
9
+ const MAX_METADATA_BYTES = 1024 * 1024;
10
+ const MAX_GASP_INPUTS = 100_000;
11
+ const MAX_ERROR_SNIPPET_BYTES = 1024;
12
+ const HASH_HEX = /^[0-9a-fA-F]{64}$/;
13
+ const EVEN_HEX = /^(?:[0-9a-fA-F]{2})+$/;
14
+ function isRecord(value) {
15
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
16
+ }
17
+ export function validateAdmittanceInstructions(value, tx, previousCoins) {
18
+ if (!isRecord(value) ||
19
+ !Array.isArray(value.outputsToAdmit) ||
20
+ !Array.isArray(value.coinsToRetain)) {
21
+ throw new TypeError('Topic manager returned invalid admittance instructions');
22
+ }
23
+ const validateIndexes = (indexes, limit, label) => {
24
+ const seen = new Set();
25
+ return indexes.map(index => {
26
+ if (typeof index !== 'number' ||
27
+ !Number.isSafeInteger(index) ||
28
+ index < 0 ||
29
+ index >= limit ||
30
+ seen.has(index)) {
31
+ throw new TypeError(`Topic manager returned invalid ${label}`);
32
+ }
33
+ seen.add(index);
34
+ return index;
35
+ });
36
+ };
37
+ const outputsToAdmit = validateIndexes(value.outputsToAdmit, tx.outputs.length, 'outputsToAdmit');
38
+ const coinsToRetain = validateIndexes(value.coinsToRetain, tx.inputs.length, 'coinsToRetain');
39
+ const previousCoinSet = new Set(previousCoins);
40
+ if (coinsToRetain.some(index => !previousCoinSet.has(index))) {
41
+ throw new TypeError('Topic manager retained an input that is not a previous topical coin');
42
+ }
43
+ return { outputsToAdmit, coinsToRetain };
44
+ }
45
+ export function assertTopic(topic, label = 'topic') {
46
+ if (typeof topic !== 'string' ||
47
+ topic.length === 0 ||
48
+ new TextEncoder().encode(topic).byteLength > MAX_TOPIC_BYTES ||
49
+ Array.from(topic).some(character => {
50
+ const codePoint = character.codePointAt(0) ?? 0;
51
+ return codePoint <= 0x1f || codePoint === 0x7f;
52
+ })) {
53
+ throw new TypeError(`${label} is invalid`);
54
+ }
55
+ }
56
+ export function assertRegistryName(value, label) {
57
+ assertTopic(value, label);
58
+ if (value === '__proto__' || value === 'prototype' || value === 'constructor') {
59
+ throw new TypeError(`${label} uses a reserved object property name`);
60
+ }
61
+ }
62
+ export function assertHash(value, label) {
63
+ if (typeof value !== 'string' || !HASH_HEX.test(value)) {
64
+ throw new TypeError(`${label} must be 32 bytes of hex`);
65
+ }
66
+ }
67
+ export function assertOutputIndex(value, label) {
68
+ if (!Number.isSafeInteger(value) || value < 0 || value > 0xffffffff) {
69
+ throw new TypeError(`${label} must be an unsigned 32-bit integer`);
70
+ }
71
+ }
72
+ export function assertNonnegativeInteger(value, label) {
73
+ if (!Number.isSafeInteger(value) || value < 0) {
74
+ throw new TypeError(`${label} must be a non-negative safe integer`);
75
+ }
76
+ }
77
+ export function assertOutpoint(value, label) {
78
+ if (typeof value !== 'string')
79
+ throw new TypeError(`${label} is invalid`);
80
+ const separator = value.lastIndexOf('.');
81
+ if (separator !== 64)
82
+ throw new TypeError(`${label} is invalid`);
83
+ assertHash(value.slice(0, separator), `${label} txid`);
84
+ const index = value.slice(separator + 1);
85
+ if (!/^(0|[1-9]\d*)$/.test(index))
86
+ throw new TypeError(`${label} is invalid`);
87
+ assertOutputIndex(Number(index), `${label} output index`);
88
+ }
89
+ export function assertHexBytes(value, label, maxBytes, allowEmpty = false) {
90
+ if (typeof value !== 'string' ||
91
+ (!allowEmpty && value.length === 0) ||
92
+ value.length > maxBytes * 2 ||
93
+ (value.length !== 0 && !EVEN_HEX.test(value))) {
94
+ throw new TypeError(`${label} must be bounded, even-length hexadecimal data`);
95
+ }
96
+ }
97
+ export function assertTxidList(value, label, options = {}) {
98
+ const max = options.max ?? MAX_BASM_TXIDS;
99
+ if (!Array.isArray(value) || (!options.allowEmpty && value.length === 0) || value.length > max) {
100
+ throw new TypeError(`${label} must contain between ${options.allowEmpty === true ? 0 : 1} and ${max} txids`);
101
+ }
102
+ const seen = new Set();
103
+ for (const [index, txid] of value.entries()) {
104
+ assertHash(txid, `${label}[${index}]`);
105
+ const canonical = txid.toLowerCase();
106
+ if (seen.has(canonical))
107
+ throw new TypeError(`${label} contains duplicate txids`);
108
+ seen.add(canonical);
109
+ }
110
+ }
111
+ export function normalizePeerEndpoint(endpoint) {
112
+ const url = new URL(endpoint);
113
+ if (url.protocol !== 'https:' ||
114
+ url.username !== '' ||
115
+ url.password !== '' ||
116
+ url.hash !== '' ||
117
+ url.search !== '') {
118
+ throw new TypeError('Overlay peer endpoints must be credential-free HTTPS URLs without query or fragment data');
119
+ }
120
+ return url.toString().replace(/\/$/, '');
121
+ }
122
+ export function securePeerFetch(endpoint, supplied) {
123
+ const normalized = normalizePeerEndpoint(endpoint);
124
+ return {
125
+ endpoint: normalized,
126
+ fetchImpl: supplied ?? createPublicHTTPSFetch(new URL(normalized).origin)
127
+ };
128
+ }
129
+ async function readBody(response, maxBytes, truncate = false) {
130
+ const declared = response.headers?.get?.('content-length');
131
+ if (declared !== null && declared !== undefined) {
132
+ if (!truncate && (!/^(0|[1-9]\d*)$/.test(declared) || Number(declared) > maxBytes)) {
133
+ await response.body?.cancel();
134
+ throw new RangeError(`Overlay peer response exceeds ${maxBytes} bytes`);
135
+ }
136
+ }
137
+ if (response.body === null || response.body === undefined) {
138
+ const text = await response.text();
139
+ if (new TextEncoder().encode(text).byteLength > maxBytes) {
140
+ throw new RangeError(`Overlay peer response exceeds ${maxBytes} bytes`);
141
+ }
142
+ return text;
143
+ }
144
+ const reader = response.body.getReader();
145
+ const chunks = [];
146
+ let total = 0;
147
+ let timeout;
148
+ try {
149
+ const bytes = await Promise.race([
150
+ (async () => {
151
+ while (true) {
152
+ const { done, value } = await reader.read();
153
+ if (done)
154
+ break;
155
+ if (truncate && total + value.byteLength > maxBytes) {
156
+ chunks.push(value.slice(0, maxBytes - total));
157
+ total = maxBytes;
158
+ break;
159
+ }
160
+ total += value.byteLength;
161
+ if (total > maxBytes) {
162
+ throw new RangeError(`Overlay peer response exceeds ${maxBytes} bytes`);
163
+ }
164
+ chunks.push(value);
165
+ }
166
+ const combined = new Uint8Array(total);
167
+ let offset = 0;
168
+ for (const chunk of chunks) {
169
+ combined.set(chunk, offset);
170
+ offset += chunk.byteLength;
171
+ }
172
+ return combined;
173
+ })(),
174
+ new Promise((_resolve, reject) => {
175
+ timeout = setTimeout(() => reject(new Error('Overlay peer response body timed out')), REMOTE_BODY_TIMEOUT_MS);
176
+ })
177
+ ]);
178
+ return new TextDecoder('utf-8', { fatal: true }).decode(bytes);
179
+ }
180
+ finally {
181
+ if (timeout !== undefined)
182
+ clearTimeout(timeout);
183
+ await reader.cancel().catch(() => { });
184
+ reader.releaseLock();
185
+ }
186
+ }
187
+ export async function readPeerJSON(response, maxBytes = MAX_REMOTE_JSON_BYTES) {
188
+ const contentType = response.headers?.get?.('content-type');
189
+ if (contentType !== null &&
190
+ contentType !== undefined &&
191
+ !/^application\/(?:[\w.-]+\+)?json(?:\s*;|$)/i.test(contentType)) {
192
+ await response.body?.cancel();
193
+ throw new TypeError('Overlay peer response is not JSON');
194
+ }
195
+ const text = await readBody(response, response.ok ? maxBytes : Math.min(maxBytes, MAX_ERROR_SNIPPET_BYTES), !response.ok);
196
+ if (!response.ok) {
197
+ const snippet = new TextDecoder().decode(new TextEncoder().encode(text).slice(0, MAX_ERROR_SNIPPET_BYTES));
198
+ throw new Error(`Overlay peer returned HTTP ${response.status}: ${JSON.stringify(snippet)}`);
199
+ }
200
+ if (text.length === 0)
201
+ throw new TypeError('Overlay peer returned an empty JSON response');
202
+ try {
203
+ return JSON.parse(text);
204
+ }
205
+ catch {
206
+ throw new TypeError('Overlay peer returned malformed JSON');
207
+ }
208
+ }
209
+ export function assertGASPInitialResponse(value, maxOutputs) {
210
+ if (!isRecord(value) || !Array.isArray(value.UTXOList) || value.UTXOList.length > maxOutputs) {
211
+ throw new TypeError('Invalid GASP initial response');
212
+ }
213
+ assertNonnegativeInteger(value.since, 'GASP response since');
214
+ const seen = new Set();
215
+ for (const [index, item] of value.UTXOList.entries()) {
216
+ if (!isRecord(item))
217
+ throw new TypeError(`GASP UTXOList[${index}] is invalid`);
218
+ assertHash(item.txid, `GASP UTXOList[${index}].txid`);
219
+ assertOutputIndex(item.outputIndex, `GASP UTXOList[${index}].outputIndex`);
220
+ assertNonnegativeInteger(item.score, `GASP UTXOList[${index}].score`);
221
+ const outpoint = `${item.txid.toLowerCase()}.${item.outputIndex}`;
222
+ if (seen.has(outpoint))
223
+ throw new TypeError('GASP initial response contains duplicate outpoints');
224
+ seen.add(outpoint);
225
+ }
226
+ }
227
+ export function assertGASPNode(value, expected) {
228
+ if (!isRecord(value))
229
+ throw new TypeError('Invalid GASP node response');
230
+ assertOutpoint(value.graphID, 'GASP node graphID');
231
+ if (value.graphID !== expected.graphID)
232
+ throw new TypeError('GASP node graphID does not match the request');
233
+ assertOutputIndex(value.outputIndex, 'GASP node outputIndex');
234
+ if (value.outputIndex !== expected.outputIndex) {
235
+ throw new TypeError('GASP node outputIndex does not match the request');
236
+ }
237
+ assertHexBytes(value.rawTx, 'GASP node rawTx', MAX_RAW_TRANSACTION_BYTES);
238
+ let actualTxid;
239
+ try {
240
+ actualTxid = Transaction.fromHex(value.rawTx).id('hex');
241
+ }
242
+ catch {
243
+ throw new TypeError('GASP node rawTx is not a valid transaction');
244
+ }
245
+ if (actualTxid.toLowerCase() !== expected.txid.toLowerCase()) {
246
+ throw new TypeError('GASP node transaction does not match the requested txid');
247
+ }
248
+ for (const field of ['proof', 'txMetadata', 'outputMetadata']) {
249
+ if (value[field] !== undefined) {
250
+ assertHexBytes(value[field], `GASP node ${field}`, field === 'proof' ? MAX_RAW_TRANSACTION_BYTES : MAX_METADATA_BYTES, true);
251
+ }
252
+ }
253
+ if (value.inputs !== undefined) {
254
+ if (!isRecord(value.inputs) || Object.keys(value.inputs).length > MAX_GASP_INPUTS) {
255
+ throw new TypeError('GASP node inputs are invalid');
256
+ }
257
+ for (const [outpoint, metadata] of Object.entries(value.inputs)) {
258
+ assertOutpoint(outpoint, 'GASP node input outpoint');
259
+ if (!isRecord(metadata))
260
+ throw new TypeError('GASP node input metadata is invalid');
261
+ assertHash(metadata.hash, 'GASP node input metadata hash');
262
+ }
263
+ }
264
+ }
265
+ export function assertRawTransactionMatches(txid, rawTx) {
266
+ assertHash(txid, 'transaction txid');
267
+ assertHexBytes(rawTx, 'raw transaction', MAX_RAW_TRANSACTION_BYTES);
268
+ let actual;
269
+ try {
270
+ actual = Transaction.fromHex(rawTx).id('hex');
271
+ }
272
+ catch {
273
+ throw new TypeError('Peer returned an invalid raw transaction');
274
+ }
275
+ if (actual.toLowerCase() !== txid.toLowerCase()) {
276
+ throw new TypeError('Peer raw transaction does not match its txid');
277
+ }
278
+ }
279
+ //# sourceMappingURL=RemoteSecurity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RemoteSecurity.js","sourceRoot":"","sources":["../../../src/RemoteSecurity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,85 @@
1
+ import { createHash } from 'node:crypto';
2
+ /** Shape detection is a declaration, not proof that an adapter is durable. */
3
+ export function getAdmissionStorage(storage) {
4
+ if (typeof storage !== 'object' || storage === null || !('admission' in storage))
5
+ return undefined;
6
+ const candidate = storage.admission;
7
+ if (typeof candidate !== 'object' || candidate === null)
8
+ return undefined;
9
+ if (!('protocol' in candidate) || candidate.protocol !== 'overlay-admission-v1')
10
+ return undefined;
11
+ if (!('commitAdmission' in candidate) || typeof candidate.commitAdmission !== 'function')
12
+ return undefined;
13
+ if (!('reconcileAdmission' in candidate) || typeof candidate.reconcileAdmission !== 'function')
14
+ return undefined;
15
+ return candidate;
16
+ }
17
+ export function isReplaySafeProjection(projection) {
18
+ return (typeof projection === 'object' &&
19
+ projection !== null &&
20
+ 'protocol' in projection &&
21
+ projection.protocol === 'overlay-projection-v1' &&
22
+ 'applyEvent' in projection &&
23
+ typeof projection.applyEvent === 'function' &&
24
+ 'reconcile' in projection &&
25
+ typeof projection.reconcile === 'function');
26
+ }
27
+ export function parseStorageUint64(value) {
28
+ if (typeof value !== 'string' || !/^(0|[1-9]\d{0,19})$/.test(value))
29
+ throw new Error('Invalid storage uint64');
30
+ const result = BigInt(value);
31
+ if (result > BigInt('18446744073709551615'))
32
+ throw new Error('Invalid storage uint64');
33
+ return result;
34
+ }
35
+ export function asStorageUint64(value) {
36
+ parseStorageUint64(value);
37
+ return value;
38
+ }
39
+ /** Validate the wire outpoint domain before conversion to an exact STEAK number. */
40
+ export function parseStorageOutputIndex(value) {
41
+ const result = parseStorageUint64(value);
42
+ if (result > BigInt('4294967295'))
43
+ throw new Error('Invalid storage output index');
44
+ return Number(result);
45
+ }
46
+ /**
47
+ * SHA-256 of UTF-8 length-framed fields, see specs/overlay/persistence-v1.md.
48
+ * Mutable reads/decisions and proof variants are deliberately outside semantic
49
+ * identity. Their validation and atomic read predicates remain mandatory.
50
+ */
51
+ export function admissionSemanticDigest(identity) {
52
+ if (!/^[0-9a-f]{64}$/.test(identity.txid) ||
53
+ !/^[0-9a-f]{64}$/.test(identity.scope.genesisHash) ||
54
+ !/^[0-9a-f]{64}$/.test(identity.contextDigest)) {
55
+ throw new Error('Invalid admission hash');
56
+ }
57
+ if (identity.mode !== 'live' && identity.mode !== 'historical')
58
+ throw new Error('Invalid admission mode');
59
+ const topics = [...identity.topics].sort((a, b) => Buffer.compare(Buffer.from(a.topic), Buffer.from(b.topic)));
60
+ if (topics.length === 0 ||
61
+ topics.some((item, index) => index > 0 && item.topic === topics[index - 1].topic)) {
62
+ throw new Error('Invalid admission topics');
63
+ }
64
+ const fields = [
65
+ 'overlay-admission-v1',
66
+ identity.scope.network,
67
+ identity.scope.genesisHash,
68
+ identity.scope.nodeId,
69
+ identity.txid,
70
+ identity.mode,
71
+ identity.contextDigest,
72
+ String(topics.length),
73
+ ...topics.flatMap(({ topic, policyId }) => [topic, policyId])
74
+ ];
75
+ const hash = createHash('sha256');
76
+ for (const field of fields) {
77
+ if (field.length === 0 || !field.isWellFormed())
78
+ throw new Error('Invalid admission identity');
79
+ const bytes = Buffer.from(field, 'utf8');
80
+ hash.update(String(bytes.length) + ':');
81
+ hash.update(bytes);
82
+ }
83
+ return hash.digest('hex');
84
+ }
85
+ //# sourceMappingURL=AdmissionStorage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AdmissionStorage.js","sourceRoot":"","sources":["../../../../src/storage/AdmissionStorage.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import { parseStorageUint64 } from './AdmissionStorage.js';
2
+ /** Use database time and this predicate INSIDE the checkpoint/publication CAS. */
3
+ export function isRecoveryLeaseCurrent(expected, current, nowMs) {
4
+ return (expected.scope.network === current.scope.network &&
5
+ expected.scope.genesisHash === current.scope.genesisHash &&
6
+ expected.scope.nodeId === current.scope.nodeId &&
7
+ expected.topic === current.topic &&
8
+ expected.peerId === current.peerId &&
9
+ expected.jobId === current.jobId &&
10
+ parseStorageUint64(expected.chainEpoch) === parseStorageUint64(current.chainEpoch) &&
11
+ parseStorageUint64(expected.topicHistoryGeneration) ===
12
+ parseStorageUint64(current.topicHistoryGeneration) &&
13
+ parseStorageUint64(expected.leaseToken) === parseStorageUint64(current.leaseToken) &&
14
+ parseStorageUint64(current.expiresAtMs) > parseStorageUint64(nowMs));
15
+ }
16
+ /** Gate for a durable finalization/cursor transaction; never advances a cursor. */
17
+ export function canAdvanceGaspCursor(evidence) {
18
+ if (!evidence.pageFinalized)
19
+ return false;
20
+ switch (evidence.mode) {
21
+ case 'negotiated-tuple':
22
+ return evidence.negotiated;
23
+ case 'inclusive-since':
24
+ return evidence.inclusiveSemanticsProven && evidence.equalScoreDrained;
25
+ case 'full-resync':
26
+ return evidence.noSkipSemanticsProven && evidence.resyncCompleted;
27
+ default:
28
+ return false;
29
+ }
30
+ }
31
+ //# sourceMappingURL=RecoveryContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RecoveryContract.js","sourceRoot":"","sources":["../../../../src/storage/RecoveryContract.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAInB,MAAM,uBAAuB,CAAA;AAW9B,kFAAkF;AAClF,MAAM,UAAU,sBAAsB,CACpC,QAAuB,EACvB,OAAsB,EACtB,KAAoB;IAEpB,OAAO,CACL,QAAQ,CAAC,KAAK,CAAC,OAAO,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO;QAChD,QAAQ,CAAC,KAAK,CAAC,WAAW,KAAK,OAAO,CAAC,KAAK,CAAC,WAAW;QACxD,QAAQ,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,KAAK,CAAC,MAAM;QAC9C,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK;QAChC,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,MAAM;QAClC,QAAQ,CAAC,KAAK,KAAK,OAAO,CAAC,KAAK;QAChC,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC;QAClF,kBAAkB,CAAC,QAAQ,CAAC,sBAAsB,CAAC;YACjD,kBAAkB,CAAC,OAAO,CAAC,sBAAsB,CAAC;QACpD,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,kBAAkB,CAAC,OAAO,CAAC,UAAU,CAAC;QAClF,kBAAkB,CAAC,OAAO,CAAC,WAAW,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,CACpE,CAAA;AACH,CAAC;AAsCD,mFAAmF;AACnF,MAAM,UAAU,oBAAoB,CAAC,QAA4B;IAC/D,IAAI,CAAC,QAAQ,CAAC,aAAa;QAAE,OAAO,KAAK,CAAA;IACzC,QAAQ,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,KAAK,kBAAkB;YACrB,OAAO,QAAQ,CAAC,UAAU,CAAA;QAC5B,KAAK,iBAAiB;YACpB,OAAO,QAAQ,CAAC,wBAAwB,IAAI,QAAQ,CAAC,iBAAiB,CAAA;QACxE,KAAK,aAAa;YAChB,OAAO,QAAQ,CAAC,qBAAqB,IAAI,QAAQ,CAAC,eAAe,CAAA;QACnE;YACE,OAAO,KAAK,CAAA;IAChB,CAAC;AACH,CAAC"}
@@ -1,2 +1,5 @@
1
- export {};
1
+ /** True when the optional admission field is present. Protocol detection is separate. */
2
+ export function storageHasAdmission(storage) {
3
+ return storage.admission !== undefined;
4
+ }
2
5
  //# sourceMappingURL=Storage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../../../../src/storage/Storage.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"Storage.js","sourceRoot":"","sources":["../../../../src/storage/Storage.ts"],"names":[],"mappings":"AAoVA,yFAAyF;AACzF,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO,OAAO,CAAC,SAAS,KAAK,SAAS,CAAA;AACxC,CAAC"}