@bsv/overlay 2.3.1 → 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 (201) hide show
  1. package/README.md +166 -0
  2. package/dist/cjs/mod.d.ts +3 -0
  3. package/dist/cjs/mod.d.ts.map +1 -1
  4. package/dist/cjs/mod.js +8 -1
  5. package/dist/cjs/mod.js.map +1 -1
  6. package/dist/cjs/package.json +10 -4
  7. package/dist/cjs/src/BASM.d.ts +6 -0
  8. package/dist/cjs/src/BASM.d.ts.map +1 -1
  9. package/dist/cjs/src/BASM.js +21 -8
  10. package/dist/cjs/src/BASM.js.map +1 -1
  11. package/dist/cjs/src/BASMRemote.d.ts +8 -1
  12. package/dist/cjs/src/BASMRemote.d.ts.map +1 -1
  13. package/dist/cjs/src/BASMRemote.js +179 -13
  14. package/dist/cjs/src/BASMRemote.js.map +1 -1
  15. package/dist/cjs/src/BASMValidation.d.ts +27 -0
  16. package/dist/cjs/src/BASMValidation.d.ts.map +1 -0
  17. package/dist/cjs/src/BASMValidation.js +108 -0
  18. package/dist/cjs/src/BASMValidation.js.map +1 -0
  19. package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts +11 -0
  20. package/dist/cjs/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
  21. package/dist/cjs/src/DiscoveryAdvertisementValidation.js +60 -0
  22. package/dist/cjs/src/DiscoveryAdvertisementValidation.js.map +1 -0
  23. package/dist/cjs/src/Engine.d.ts +37 -13
  24. package/dist/cjs/src/Engine.d.ts.map +1 -1
  25. package/dist/cjs/src/Engine.js +1713 -336
  26. package/dist/cjs/src/Engine.js.map +1 -1
  27. package/dist/cjs/src/EngineAdmission.d.ts +70 -0
  28. package/dist/cjs/src/EngineAdmission.d.ts.map +1 -0
  29. package/dist/cjs/src/EngineAdmission.js +297 -0
  30. package/dist/cjs/src/EngineAdmission.js.map +1 -0
  31. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts +4 -3
  32. package/dist/cjs/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  33. package/dist/cjs/src/GASP/OverlayGASPRemote.js +27 -43
  34. package/dist/cjs/src/GASP/OverlayGASPRemote.js.map +1 -1
  35. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts +22 -16
  36. package/dist/cjs/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  37. package/dist/cjs/src/GASP/OverlayGASPStorage.js +206 -57
  38. package/dist/cjs/src/GASP/OverlayGASPStorage.js.map +1 -1
  39. package/dist/cjs/src/RemoteSecurity.d.ts +50 -0
  40. package/dist/cjs/src/RemoteSecurity.d.ts.map +1 -0
  41. package/dist/cjs/src/RemoteSecurity.js +301 -0
  42. package/dist/cjs/src/RemoteSecurity.js.map +1 -0
  43. package/dist/cjs/src/storage/AdmissionStorage.d.ts +185 -0
  44. package/dist/cjs/src/storage/AdmissionStorage.d.ts.map +1 -0
  45. package/dist/cjs/src/storage/AdmissionStorage.js +93 -0
  46. package/dist/cjs/src/storage/AdmissionStorage.js.map +1 -0
  47. package/dist/cjs/src/storage/RecoveryContract.d.ts +50 -0
  48. package/dist/cjs/src/storage/RecoveryContract.d.ts.map +1 -0
  49. package/dist/cjs/src/storage/RecoveryContract.js +35 -0
  50. package/dist/cjs/src/storage/RecoveryContract.js.map +1 -0
  51. package/dist/cjs/src/storage/Storage.d.ts +32 -19
  52. package/dist/cjs/src/storage/Storage.d.ts.map +1 -1
  53. package/dist/cjs/src/storage/Storage.js +5 -0
  54. package/dist/cjs/src/storage/Storage.js.map +1 -1
  55. package/dist/cjs/src/storage/knex/KnexStorage.d.ts +8 -8
  56. package/dist/cjs/src/storage/knex/KnexStorage.d.ts.map +1 -1
  57. package/dist/cjs/src/storage/knex/KnexStorage.js +98 -61
  58. package/dist/cjs/src/storage/knex/KnexStorage.js.map +1 -1
  59. package/dist/cjs/src/storage/knex/all-migrations.d.ts.map +1 -1
  60. package/dist/cjs/src/storage/knex/all-migrations.js +5 -1
  61. package/dist/cjs/src/storage/knex/all-migrations.js.map +1 -1
  62. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
  63. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
  64. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +36 -0
  65. package/dist/cjs/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
  66. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
  67. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
  68. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js +16 -0
  69. package/dist/cjs/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
  70. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
  71. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
  72. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js +229 -0
  73. package/dist/cjs/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
  74. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
  75. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
  76. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js +675 -0
  77. package/dist/cjs/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
  78. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
  79. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
  80. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js +453 -0
  81. package/dist/cjs/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
  82. package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
  83. package/dist/cjs/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
  84. package/dist/cjs/src/storage/mongo/MongoPayloadStore.js +756 -0
  85. package/dist/cjs/src/storage/mongo/MongoPayloadStore.js.map +1 -0
  86. package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts +44 -0
  87. package/dist/cjs/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
  88. package/dist/cjs/src/storage/mongo/MongoReadGuards.js +135 -0
  89. package/dist/cjs/src/storage/mongo/MongoReadGuards.js.map +1 -0
  90. package/dist/cjs/src/storage/mongo/MongoSchema.d.ts +67 -0
  91. package/dist/cjs/src/storage/mongo/MongoSchema.d.ts.map +1 -0
  92. package/dist/cjs/src/storage/mongo/MongoSchema.js +743 -0
  93. package/dist/cjs/src/storage/mongo/MongoSchema.js.map +1 -0
  94. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
  95. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
  96. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js +368 -0
  97. package/dist/cjs/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
  98. package/dist/cjs/src/storage/mongo.d.ts +9 -0
  99. package/dist/cjs/src/storage/mongo.d.ts.map +1 -0
  100. package/dist/cjs/src/storage/mongo.js +25 -0
  101. package/dist/cjs/src/storage/mongo.js.map +1 -0
  102. package/dist/esm/mod.js +3 -0
  103. package/dist/esm/mod.js.map +1 -1
  104. package/dist/esm/src/BASM.js +21 -8
  105. package/dist/esm/src/BASM.js.map +1 -1
  106. package/dist/esm/src/BASMRemote.js +176 -12
  107. package/dist/esm/src/BASMRemote.js.map +1 -1
  108. package/dist/esm/src/BASMValidation.js +95 -0
  109. package/dist/esm/src/BASMValidation.js.map +1 -0
  110. package/dist/esm/src/DiscoveryAdvertisementValidation.js +57 -0
  111. package/dist/esm/src/DiscoveryAdvertisementValidation.js.map +1 -0
  112. package/dist/esm/src/Engine.js +1698 -326
  113. package/dist/esm/src/Engine.js.map +1 -1
  114. package/dist/esm/src/EngineAdmission.js +280 -0
  115. package/dist/esm/src/EngineAdmission.js.map +1 -0
  116. package/dist/esm/src/GASP/OverlayGASPRemote.js +27 -43
  117. package/dist/esm/src/GASP/OverlayGASPRemote.js.map +1 -1
  118. package/dist/esm/src/GASP/OverlayGASPStorage.js +200 -56
  119. package/dist/esm/src/GASP/OverlayGASPStorage.js.map +1 -1
  120. package/dist/esm/src/RemoteSecurity.js +279 -0
  121. package/dist/esm/src/RemoteSecurity.js.map +1 -0
  122. package/dist/esm/src/storage/AdmissionStorage.js +85 -0
  123. package/dist/esm/src/storage/AdmissionStorage.js.map +1 -0
  124. package/dist/esm/src/storage/RecoveryContract.js +31 -0
  125. package/dist/esm/src/storage/RecoveryContract.js.map +1 -0
  126. package/dist/esm/src/storage/Storage.js +4 -1
  127. package/dist/esm/src/storage/Storage.js.map +1 -1
  128. package/dist/esm/src/storage/knex/KnexStorage.js +98 -61
  129. package/dist/esm/src/storage/knex/KnexStorage.js.map +1 -1
  130. package/dist/esm/src/storage/knex/all-migrations.js +5 -1
  131. package/dist/esm/src/storage/knex/all-migrations.js.map +1 -1
  132. package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js +32 -0
  133. package/dist/esm/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.js.map +1 -0
  134. package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js +12 -0
  135. package/dist/esm/src/storage/knex/migrations/2026-09-20-001-spent-by.js.map +1 -0
  136. package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js +217 -0
  137. package/dist/esm/src/storage/mongo/MongoAdmissionPlan.js.map +1 -0
  138. package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js +673 -0
  139. package/dist/esm/src/storage/mongo/MongoAdmissionStorage.js.map +1 -0
  140. package/dist/esm/src/storage/mongo/MongoOverlayStorage.js +451 -0
  141. package/dist/esm/src/storage/mongo/MongoOverlayStorage.js.map +1 -0
  142. package/dist/esm/src/storage/mongo/MongoPayloadStore.js +747 -0
  143. package/dist/esm/src/storage/mongo/MongoPayloadStore.js.map +1 -0
  144. package/dist/esm/src/storage/mongo/MongoReadGuards.js +129 -0
  145. package/dist/esm/src/storage/mongo/MongoReadGuards.js.map +1 -0
  146. package/dist/esm/src/storage/mongo/MongoSchema.js +730 -0
  147. package/dist/esm/src/storage/mongo/MongoSchema.js.map +1 -0
  148. package/dist/esm/src/storage/mongo/MongoTransactionRunner.js +371 -0
  149. package/dist/esm/src/storage/mongo/MongoTransactionRunner.js.map +1 -0
  150. package/dist/esm/src/storage/mongo.js +9 -0
  151. package/dist/esm/src/storage/mongo.js.map +1 -0
  152. package/dist/types/mod.d.ts +3 -0
  153. package/dist/types/mod.d.ts.map +1 -1
  154. package/dist/types/src/BASM.d.ts +6 -0
  155. package/dist/types/src/BASM.d.ts.map +1 -1
  156. package/dist/types/src/BASMRemote.d.ts +8 -1
  157. package/dist/types/src/BASMRemote.d.ts.map +1 -1
  158. package/dist/types/src/BASMValidation.d.ts +27 -0
  159. package/dist/types/src/BASMValidation.d.ts.map +1 -0
  160. package/dist/types/src/DiscoveryAdvertisementValidation.d.ts +11 -0
  161. package/dist/types/src/DiscoveryAdvertisementValidation.d.ts.map +1 -0
  162. package/dist/types/src/Engine.d.ts +37 -13
  163. package/dist/types/src/Engine.d.ts.map +1 -1
  164. package/dist/types/src/EngineAdmission.d.ts +70 -0
  165. package/dist/types/src/EngineAdmission.d.ts.map +1 -0
  166. package/dist/types/src/GASP/OverlayGASPRemote.d.ts +4 -3
  167. package/dist/types/src/GASP/OverlayGASPRemote.d.ts.map +1 -1
  168. package/dist/types/src/GASP/OverlayGASPStorage.d.ts +22 -16
  169. package/dist/types/src/GASP/OverlayGASPStorage.d.ts.map +1 -1
  170. package/dist/types/src/RemoteSecurity.d.ts +50 -0
  171. package/dist/types/src/RemoteSecurity.d.ts.map +1 -0
  172. package/dist/types/src/storage/AdmissionStorage.d.ts +185 -0
  173. package/dist/types/src/storage/AdmissionStorage.d.ts.map +1 -0
  174. package/dist/types/src/storage/RecoveryContract.d.ts +50 -0
  175. package/dist/types/src/storage/RecoveryContract.d.ts.map +1 -0
  176. package/dist/types/src/storage/Storage.d.ts +32 -19
  177. package/dist/types/src/storage/Storage.d.ts.map +1 -1
  178. package/dist/types/src/storage/knex/KnexStorage.d.ts +8 -8
  179. package/dist/types/src/storage/knex/KnexStorage.d.ts.map +1 -1
  180. package/dist/types/src/storage/knex/all-migrations.d.ts.map +1 -1
  181. package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts +4 -0
  182. package/dist/types/src/storage/knex/migrations/2026-09-17-001-topical-uniqueness.d.ts.map +1 -0
  183. package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts +5 -0
  184. package/dist/types/src/storage/knex/migrations/2026-09-20-001-spent-by.d.ts.map +1 -0
  185. package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts +18 -0
  186. package/dist/types/src/storage/mongo/MongoAdmissionPlan.d.ts.map +1 -0
  187. package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts +112 -0
  188. package/dist/types/src/storage/mongo/MongoAdmissionStorage.d.ts.map +1 -0
  189. package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts +71 -0
  190. package/dist/types/src/storage/mongo/MongoOverlayStorage.d.ts.map +1 -0
  191. package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts +134 -0
  192. package/dist/types/src/storage/mongo/MongoPayloadStore.d.ts.map +1 -0
  193. package/dist/types/src/storage/mongo/MongoReadGuards.d.ts +44 -0
  194. package/dist/types/src/storage/mongo/MongoReadGuards.d.ts.map +1 -0
  195. package/dist/types/src/storage/mongo/MongoSchema.d.ts +67 -0
  196. package/dist/types/src/storage/mongo/MongoSchema.d.ts.map +1 -0
  197. package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts +69 -0
  198. package/dist/types/src/storage/mongo/MongoTransactionRunner.d.ts.map +1 -0
  199. package/dist/types/src/storage/mongo.d.ts +9 -0
  200. package/dist/types/src/storage/mongo.d.ts.map +1 -0
  201. package/package.json +11 -5
@@ -0,0 +1,280 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { extractMerkleProofMetadata } from './BASM.js';
3
+ import { admissionSemanticDigest, asStorageUint64, getAdmissionStorage } from './storage/AdmissionStorage.js';
4
+ export const OVERLAY_ENGINE_POLICY_ID = 'overlay-engine-submit-v1';
5
+ export function getOverlayAdmissionHost(storage) {
6
+ const admission = getAdmissionStorage(storage);
7
+ if (admission === undefined || typeof storage !== 'object' || storage === null)
8
+ return undefined;
9
+ if (!('admissionScope' in storage))
10
+ return undefined;
11
+ const scope = storage.admissionScope;
12
+ if (scope === undefined ||
13
+ typeof scope.network !== 'string' ||
14
+ typeof scope.genesisHash !== 'string' ||
15
+ typeof scope.nodeId !== 'string' ||
16
+ !/^[0-9a-f]{64}$/.test(scope.genesisHash)) {
17
+ return undefined;
18
+ }
19
+ const host = storage;
20
+ return {
21
+ admission,
22
+ admissionScope: { ...scope },
23
+ // Adapters are class instances whose methods read instance state, so each
24
+ // optional method stays bound to the storage it came from.
25
+ publishAdmissionPayload: host.publishAdmissionPayload?.bind(host),
26
+ enlistedIndexTargets: host.enlistedIndexTargets?.bind(host),
27
+ getHistoryFence: host.getHistoryFence?.bind(host)
28
+ };
29
+ }
30
+ export function overlayAdmissionContextDigest(offChainValues) {
31
+ const hash = createHash('sha256');
32
+ if (offChainValues !== undefined)
33
+ hash.update(Buffer.from(offChainValues));
34
+ return hash.digest('hex');
35
+ }
36
+ export function overlayAdmissionOperationId(_mode, txid, topics) {
37
+ const topicKey = [...topics].sort((a, b) => a.localeCompare(b, 'en')).join('\n');
38
+ // Historical GASP replay and a later live retry represent the same
39
+ // transaction admission. Keep their id stable so the durable admission
40
+ // record is replayed instead of being submitted a second time.
41
+ const raw = `submit:${txid}:${topicKey}`;
42
+ if (Buffer.byteLength(raw, 'utf8') <= 512 && raw.isWellFormed())
43
+ return raw;
44
+ return `submit:${createHash('sha256').update(raw, 'utf8').digest('hex')}`;
45
+ }
46
+ export function overlayAdmissionMode(mode) {
47
+ return mode === 'current-tx' ? 'live' : 'historical';
48
+ }
49
+ async function localPayload(host, kind, bytes, txid) {
50
+ if (host.publishAdmissionPayload !== undefined) {
51
+ return await host.publishAdmissionPayload({ kind, bytes, txid });
52
+ }
53
+ return {
54
+ kind,
55
+ digest: createHash('sha256').update(bytes).digest('hex'),
56
+ byteLength: asStorageUint64(String(bytes.byteLength))
57
+ };
58
+ }
59
+ /**
60
+ * Selects the topics that require a new admission decision: topics that did
61
+ * not fail validation, are not already-applied dupes, and actually admit or
62
+ * retain something (or consume a previously-admitted coin). Already-applied
63
+ * (dupe) topics are excluded so that a retry — including a historical GASP
64
+ * replay after a live admit, or a multi-topic resubmit where only some
65
+ * topics were previously applied — never re-submits an admission decision
66
+ * for a topic that MongoAdmissionStorage.assertAppliedAvailable would reject
67
+ * as belonging to a different operation.
68
+ */
69
+ export function selectNewAdmissionTopics(validations, failedTopics) {
70
+ return validations.filter(validation => !failedTopics.has(validation.topic) &&
71
+ !validation.isDupe &&
72
+ (validation.admissibleOutputs.outputsToAdmit.length > 0 ||
73
+ validation.admissibleOutputs.coinsToRetain.length > 0 ||
74
+ validation.previousCoins.length > 0));
75
+ }
76
+ export async function buildOverlayAdmissionPlan(input) {
77
+ // Only topics with a genuinely new admission get an identity/decision entry
78
+ // and take part in the commit. Dupe topics are still reflected in `steak`
79
+ // below (with their empty admissibleOutputs), matching what the classic
80
+ // storage path already returns for a dupe, but they must never be
81
+ // resubmitted to commitAdmission: MongoAdmissionStorage.assertAppliedAvailable
82
+ // rejects an applied row whose admissionId belongs to a different
83
+ // operation, which a dupe re-included here would trigger on retry.
84
+ const accepted = selectNewAdmissionTopics(input.validations, input.failedTopics);
85
+ const identityTopics = accepted.map(validation => ({
86
+ topic: validation.topic,
87
+ policyId: OVERLAY_ENGINE_POLICY_ID
88
+ }));
89
+ if (identityTopics.length === 0)
90
+ throw new Error('Overlay admission plan has no topics');
91
+ const identity = {
92
+ scope: input.host.admissionScope,
93
+ txid: input.txid,
94
+ mode: input.mode,
95
+ contextDigest: overlayAdmissionContextDigest(input.offChainValues),
96
+ topics: identityTopics
97
+ };
98
+ const raw = await localPayload(input.host, 'raw-transaction', Buffer.from(input.tx.toBinary()), input.txid);
99
+ const payloads = [raw];
100
+ let proof;
101
+ if (input.tx.merklePath !== undefined) {
102
+ proof = await localPayload(input.host, 'merkle-path', Buffer.from(input.tx.merklePath.toBinary()));
103
+ payloads.push(proof);
104
+ }
105
+ const merkle = extractMerkleProofMetadata(input.txid, input.tx.merklePath);
106
+ const decisions = [];
107
+ const steak = {};
108
+ for (const validation of input.validations) {
109
+ steak[validation.topic] = {
110
+ outputsToAdmit: validation.admissibleOutputs.outputsToAdmit,
111
+ coinsToRetain: validation.admissibleOutputs.coinsToRetain,
112
+ coinsRemoved: validation.admissibleOutputs.coinsRemoved ?? []
113
+ };
114
+ }
115
+ for (const validation of accepted) {
116
+ const { outputsConsumed, outputsToMarkStale } = classifyCoins(input.tx, validation);
117
+ const fence = input.host.getHistoryFence === undefined
118
+ ? { chainEpoch: asStorageUint64('0'), topicHistoryGeneration: asStorageUint64('0') }
119
+ : await input.host.getHistoryFence(validation.topic);
120
+ const outputs = [];
121
+ for (const outputIndex of validation.admissibleOutputs.outputsToAdmit) {
122
+ const txOut = input.tx.outputs[outputIndex];
123
+ if (typeof txOut?.satoshis !== 'number' || !Number.isSafeInteger(txOut.satoshis))
124
+ continue;
125
+ const scriptBytes = Buffer.from(txOut.lockingScript.toBinary());
126
+ const script = await localPayload(input.host, 'locking-script', scriptBytes);
127
+ payloads.push(script);
128
+ outputs.push({
129
+ txid: input.txid,
130
+ outputIndex: asStorageUint64(String(outputIndex)),
131
+ satoshis: asStorageUint64(String(txOut.satoshis)),
132
+ score: asStorageUint64(String(Date.now())),
133
+ script: { payload: script, offset: asStorageUint64('0'), byteLength: script.byteLength }
134
+ });
135
+ }
136
+ const spends = validation.previousOutputs.flatMap(output => output === null
137
+ ? []
138
+ : [
139
+ {
140
+ outpoint: { txid: output.txid, outputIndex: asStorageUint64(String(output.outputIndex)) },
141
+ expectedVersion: '1',
142
+ spender: input.txid
143
+ }
144
+ ]);
145
+ decisions.push({
146
+ topic: validation.topic,
147
+ expectedHistory: fence,
148
+ reads: [],
149
+ spends,
150
+ evictions: outputsToMarkStale.map(item => ({
151
+ txid: item.txid,
152
+ outputIndex: asStorageUint64(String(item.previousOutputIndex))
153
+ })),
154
+ outputs,
155
+ edges: outputsConsumed.flatMap(source => outputs.map(output => ({
156
+ source: { txid: source.txid, outputIndex: asStorageUint64(String(source.outputIndex)) },
157
+ consumer: { txid: output.txid, outputIndex: output.outputIndex }
158
+ }))),
159
+ applied: appliedRecord(input, proof, merkle)
160
+ });
161
+ steak[validation.topic] = {
162
+ outputsToAdmit: validation.admissibleOutputs.outputsToAdmit,
163
+ coinsToRetain: validation.admissibleOutputs.coinsToRetain,
164
+ coinsRemoved: outputsToMarkStale.map(item => item.inputIndex)
165
+ };
166
+ }
167
+ const enlisted = new Set(input.host.enlistedIndexTargets?.() ?? []);
168
+ const outbox = Object.keys(input.lookupServices)
169
+ .filter(target => !enlisted.has(target))
170
+ .map(target => ({
171
+ eventId: `${overlayAdmissionOperationId(input.mode, input.txid, input.topics)}:lookup:${target}`,
172
+ kind: 'lookup',
173
+ target,
174
+ payloads: [raw]
175
+ }));
176
+ if (input.includePropagation && input.mode === 'live') {
177
+ outbox.push({
178
+ eventId: `${overlayAdmissionOperationId(input.mode, input.txid, input.topics)}:propagate`,
179
+ kind: 'propagation',
180
+ target: 'ship',
181
+ payloads: [raw]
182
+ });
183
+ }
184
+ return {
185
+ key: {
186
+ scope: input.host.admissionScope,
187
+ operationId: overlayAdmissionOperationId(input.mode, input.txid, input.topics),
188
+ semanticDigest: admissionSemanticDigest(identity)
189
+ },
190
+ identity,
191
+ payloads: uniquePayloads(payloads),
192
+ decisions,
193
+ outbox,
194
+ steak: JSON.stringify(steak)
195
+ };
196
+ }
197
+ export async function waitForAdmissionReceipt(admission, plan, rebuild) {
198
+ let current = plan;
199
+ for (let attempt = 0; attempt < 8; attempt += 1) {
200
+ const result = await admission.commitAdmission(current);
201
+ if (result.state === 'committed')
202
+ return result;
203
+ if (result.state === 'rejected') {
204
+ if (result.code === 'read-conflict' && attempt < 7) {
205
+ current = await rebuild();
206
+ continue;
207
+ }
208
+ throw new Error(`Overlay admission rejected: ${result.code}`);
209
+ }
210
+ const reconciled = await admission.reconcileAdmission(current.key, result.attemptId);
211
+ if (reconciled.state === 'committed')
212
+ return reconciled;
213
+ if (reconciled.state === 'aborted') {
214
+ current = await rebuild();
215
+ continue;
216
+ }
217
+ if (reconciled.state === 'rejected') {
218
+ throw new Error(`Overlay admission rejected: ${reconciled.code}`);
219
+ }
220
+ }
221
+ throw new Error('Overlay admission commit is pending');
222
+ }
223
+ function appliedRecord(input, proof, merkle) {
224
+ const applied = { txid: input.txid };
225
+ const firstSeen = input.applied?.firstSeenHeight ?? merkle?.blockHeight;
226
+ if (firstSeen !== undefined)
227
+ applied.firstSeenHeight = asStorageUint64(String(firstSeen));
228
+ if (proof !== undefined)
229
+ applied.proof = proof;
230
+ const blockHash = input.applied?.blockHash;
231
+ const height = input.applied?.blockHeight ?? merkle?.blockHeight;
232
+ const index = input.applied?.blockIndex ?? merkle?.blockIndex;
233
+ const merkleRoot = input.applied?.merkleRoot ?? merkle?.merkleRoot;
234
+ if (blockHash !== undefined &&
235
+ height !== undefined &&
236
+ index !== undefined &&
237
+ merkleRoot !== undefined) {
238
+ applied.block = {
239
+ height: asStorageUint64(String(height)),
240
+ hash: blockHash,
241
+ index: asStorageUint64(String(index)),
242
+ merkleRoot
243
+ };
244
+ }
245
+ return applied;
246
+ }
247
+ function uniquePayloads(payloads) {
248
+ const seen = new Set();
249
+ const result = [];
250
+ for (const payload of payloads) {
251
+ const key = `${payload.kind}:${payload.digest}:${payload.byteLength}`;
252
+ if (seen.has(key))
253
+ continue;
254
+ seen.add(key);
255
+ result.push(payload);
256
+ }
257
+ return result;
258
+ }
259
+ function classifyCoins(tx, validation) {
260
+ const outputsConsumed = [];
261
+ const outputsToMarkStale = [];
262
+ for (const inputIndex of validation.previousCoins) {
263
+ const input = tx.inputs[inputIndex];
264
+ const previousTXID = input.sourceTXID ?? input.sourceTransaction?.id('hex');
265
+ if (typeof previousTXID !== 'string')
266
+ continue;
267
+ if (validation.admissibleOutputs.coinsToRetain.includes(inputIndex)) {
268
+ outputsConsumed.push({ txid: previousTXID, outputIndex: input.sourceOutputIndex });
269
+ }
270
+ else {
271
+ outputsToMarkStale.push({
272
+ txid: previousTXID,
273
+ previousOutputIndex: input.sourceOutputIndex,
274
+ inputIndex
275
+ });
276
+ }
277
+ }
278
+ return { outputsConsumed, outputsToMarkStale };
279
+ }
280
+ //# sourceMappingURL=EngineAdmission.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EngineAdmission.js","sourceRoot":"","sources":["../../../src/EngineAdmission.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,14 @@
1
+ import { assertGASPInitialResponse, assertGASPNode, assertHash, assertNonnegativeInteger, assertOutpoint, assertOutputIndex, assertTopic, MAX_GASP_NODE_JSON_BYTES, MAX_GASP_PAGE_SIZE, readPeerJSON, securePeerFetch } from '../RemoteSecurity.js';
1
2
  export class OverlayGASPRemote {
2
3
  endpointURL;
3
4
  topic;
4
- constructor(endpointURL, topic) {
5
- this.endpointURL = endpointURL;
5
+ fetchImpl;
6
+ constructor(endpointURL, topic, fetchImpl) {
7
+ assertTopic(topic);
8
+ const secured = securePeerFetch(endpointURL, fetchImpl);
9
+ this.endpointURL = secured.endpoint;
6
10
  this.topic = topic;
11
+ this.fetchImpl = secured.fetchImpl;
7
12
  }
8
13
  /**
9
14
  * Given an outgoing initial request, sends the request to the foreign instance and obtains their initial response.
@@ -11,11 +16,13 @@ export class OverlayGASPRemote {
11
16
  * @returns
12
17
  */
13
18
  async getInitialResponse(request) {
14
- // Send out an HTTP request to the URL (current host for topic)
15
- // Include the topic in the request
16
- // Parse out response and return correct format
19
+ assertNonnegativeInteger(request.since, 'GASP request since');
20
+ const pageLimit = request.limit ?? MAX_GASP_PAGE_SIZE;
21
+ if (!Number.isSafeInteger(pageLimit) || pageLimit < 1 || pageLimit > MAX_GASP_PAGE_SIZE) {
22
+ throw new TypeError(`GASP request limit must be between 1 and ${MAX_GASP_PAGE_SIZE}`);
23
+ }
17
24
  const url = `${this.endpointURL}/requestSyncResponse`;
18
- const response = await fetch(url, {
25
+ const response = await this.fetchImpl(url, {
19
26
  method: 'POST',
20
27
  headers: {
21
28
  'Content-Type': 'application/json',
@@ -23,22 +30,9 @@ export class OverlayGASPRemote {
23
30
  },
24
31
  body: JSON.stringify(request)
25
32
  });
26
- if (!response.ok) {
27
- throw new Error(`HTTP error! Status: ${response.status}`);
28
- }
29
- const result = await response.json();
30
- // Validate and return the response in the correct format
31
- if (!Array.isArray(result.UTXOList) || typeof result.since !== 'number') {
32
- throw new TypeError('Invalid response format');
33
- }
34
- return {
35
- UTXOList: result.UTXOList.map((utxo) => ({
36
- txid: utxo.txid,
37
- outputIndex: utxo.outputIndex,
38
- score: utxo.score ?? 0
39
- })),
40
- since: result.since
41
- };
33
+ const result = await readPeerJSON(response);
34
+ assertGASPInitialResponse(result, pageLimit);
35
+ return result;
42
36
  }
43
37
  /**
44
38
  * Given an outgoing txid, outputIndex and optional metadata, request the associated GASP node from the foreign instance.
@@ -49,7 +43,11 @@ export class OverlayGASPRemote {
49
43
  * @returns
50
44
  */
51
45
  async requestNode(graphID, txid, outputIndex, metadata) {
52
- // Send an HTTP request with the provided info and get back a gaspNode
46
+ assertOutpoint(graphID, 'GASP request graphID');
47
+ assertHash(txid, 'GASP request txid');
48
+ assertOutputIndex(outputIndex, 'GASP request outputIndex');
49
+ if (typeof metadata !== 'boolean')
50
+ throw new TypeError('GASP request metadata flag is invalid');
53
51
  const url = `${this.endpointURL}/requestForeignGASPNode`;
54
52
  const body = {
55
53
  graphID,
@@ -57,31 +55,17 @@ export class OverlayGASPRemote {
57
55
  outputIndex,
58
56
  metadata
59
57
  };
60
- const response = await fetch(url, {
58
+ const response = await this.fetchImpl(url, {
61
59
  method: 'POST',
62
60
  headers: {
63
- 'Content-Type': 'application/json'
61
+ 'Content-Type': 'application/json',
62
+ 'X-BSV-Topic': this.topic
64
63
  },
65
64
  body: JSON.stringify(body)
66
65
  });
67
- if (!response.ok) {
68
- throw new Error(`HTTP error! Status: ${response.status}`);
69
- }
70
- const result = await response.json();
71
- // Validate and return the response in the correct format
72
- if (typeof result.graphID !== 'string' || typeof result.rawTx !== 'string' || typeof result.outputIndex !== 'number') {
73
- throw new TypeError('Invalid response format');
74
- }
75
- const gaspNode = {
76
- graphID: result.graphID,
77
- rawTx: result.rawTx,
78
- outputIndex: result.outputIndex,
79
- proof: result.proof,
80
- txMetadata: result.txMetadata,
81
- outputMetadata: result.outputMetadata,
82
- inputs: result.inputs
83
- };
84
- return gaspNode;
66
+ const result = await readPeerJSON(response, MAX_GASP_NODE_JSON_BYTES);
67
+ assertGASPNode(result, { graphID, txid, outputIndex });
68
+ return result;
85
69
  }
86
70
  // ---- Now optional methods ----
87
71
  // When are only syncing to them
@@ -1 +1 @@
1
- {"version":3,"file":"OverlayGASPRemote.js","sourceRoot":"","sources":["../../../../src/GASP/OverlayGASPRemote.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OverlayGASPRemote.js","sourceRoot":"","sources":["../../../../src/GASP/OverlayGASPRemote.ts"],"names":[],"mappings":"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"}