@xyo-network/service-kit-xl1 0.2.2 → 0.3.0
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/README.md +64 -0
- package/dist/browser/createFleetAuthority.d.ts +11 -1
- package/dist/browser/createFleetAuthority.d.ts.map +1 -1
- package/dist/browser/fleetForeign.d.ts +5 -0
- package/dist/browser/fleetForeign.d.ts.map +1 -0
- package/dist/browser/fleetHistory.d.ts +37 -0
- package/dist/browser/fleetHistory.d.ts.map +1 -0
- package/dist/browser/fleetHistoryCache.d.ts +22 -0
- package/dist/browser/fleetHistoryCache.d.ts.map +1 -0
- package/dist/browser/fleetMeter.d.ts +26 -0
- package/dist/browser/fleetMeter.d.ts.map +1 -0
- package/dist/browser/fleetPage.d.ts +5 -0
- package/dist/browser/fleetPage.d.ts.map +1 -0
- package/dist/browser/fleetProfile.d.ts +13 -0
- package/dist/browser/fleetProfile.d.ts.map +1 -0
- package/dist/browser/fleetProjection.d.ts +1 -0
- package/dist/browser/fleetProjection.d.ts.map +1 -1
- package/dist/browser/fleetQuery.d.ts +8 -0
- package/dist/browser/fleetQuery.d.ts.map +1 -0
- package/dist/browser/fleetQuerySelection.d.ts +3 -0
- package/dist/browser/fleetQuerySelection.d.ts.map +1 -0
- package/dist/browser/fleetReaders.d.ts +10 -0
- package/dist/browser/fleetReaders.d.ts.map +1 -0
- package/dist/browser/fleetRequests.d.ts +3 -0
- package/dist/browser/fleetRequests.d.ts.map +1 -0
- package/dist/browser/fleetScope.d.ts +4 -0
- package/dist/browser/fleetScope.d.ts.map +1 -0
- package/dist/browser/fleetSelectedPayloadSource.d.ts +4 -0
- package/dist/browser/fleetSelectedPayloadSource.d.ts.map +1 -0
- package/dist/browser/index.d.ts +5 -0
- package/dist/browser/index.d.ts.map +1 -1
- package/dist/browser/index.mjs +769 -92
- package/dist/browser/index.mjs.map +4 -4
- package/dist/node/createFleetAuthority.d.ts +11 -1
- package/dist/node/createFleetAuthority.d.ts.map +1 -1
- package/dist/node/fleetForeign.d.ts +5 -0
- package/dist/node/fleetForeign.d.ts.map +1 -0
- package/dist/node/fleetHistory.d.ts +37 -0
- package/dist/node/fleetHistory.d.ts.map +1 -0
- package/dist/node/fleetHistoryCache.d.ts +22 -0
- package/dist/node/fleetHistoryCache.d.ts.map +1 -0
- package/dist/node/fleetMeter.d.ts +26 -0
- package/dist/node/fleetMeter.d.ts.map +1 -0
- package/dist/node/fleetPage.d.ts +5 -0
- package/dist/node/fleetPage.d.ts.map +1 -0
- package/dist/node/fleetProfile.d.ts +13 -0
- package/dist/node/fleetProfile.d.ts.map +1 -0
- package/dist/node/fleetProjection.d.ts +1 -0
- package/dist/node/fleetProjection.d.ts.map +1 -1
- package/dist/node/fleetQuery.d.ts +8 -0
- package/dist/node/fleetQuery.d.ts.map +1 -0
- package/dist/node/fleetQuerySelection.d.ts +3 -0
- package/dist/node/fleetQuerySelection.d.ts.map +1 -0
- package/dist/node/fleetReaders.d.ts +10 -0
- package/dist/node/fleetReaders.d.ts.map +1 -0
- package/dist/node/fleetRequests.d.ts +3 -0
- package/dist/node/fleetRequests.d.ts.map +1 -0
- package/dist/node/fleetScope.d.ts +4 -0
- package/dist/node/fleetScope.d.ts.map +1 -0
- package/dist/node/fleetSelectedPayloadSource.d.ts +4 -0
- package/dist/node/fleetSelectedPayloadSource.d.ts.map +1 -0
- package/dist/node/index.d.ts +5 -0
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.mjs +769 -92
- package/dist/node/index.mjs.map +4 -4
- package/package.json +12 -12
package/dist/browser/index.mjs
CHANGED
|
@@ -5,14 +5,14 @@ import {
|
|
|
5
5
|
verifyFleetPayload
|
|
6
6
|
} from "@xyo-network/service-kit-protocol";
|
|
7
7
|
import {
|
|
8
|
-
AddressZod,
|
|
8
|
+
AddressZod as AddressZod4,
|
|
9
9
|
FleetControlSchema,
|
|
10
10
|
FleetMemberSchema,
|
|
11
11
|
FleetPublicationScopeSchema,
|
|
12
12
|
FleetPublicationScopeZod,
|
|
13
13
|
FleetSchema,
|
|
14
14
|
FleetZod,
|
|
15
|
-
HashZod
|
|
15
|
+
HashZod as HashZod5
|
|
16
16
|
} from "@xyo-network/service-kit-schemas";
|
|
17
17
|
import {
|
|
18
18
|
createXl1FinalizedPublicationEvidence
|
|
@@ -81,26 +81,263 @@ function operationControl(signal, timeoutMs, startedAt) {
|
|
|
81
81
|
}
|
|
82
82
|
var fleetNow = now;
|
|
83
83
|
|
|
84
|
-
// src/
|
|
85
|
-
function
|
|
86
|
-
const
|
|
84
|
+
// src/fleetHistory.ts
|
|
85
|
+
function historicalPublisherCandidates(controls) {
|
|
86
|
+
const candidates = /* @__PURE__ */ new Map();
|
|
87
|
+
for (const fact of controls) {
|
|
88
|
+
const payload = fact.payload;
|
|
89
|
+
if (payload.operation !== "grant-publisher" || candidates.has(fact.root)) continue;
|
|
90
|
+
candidates.set(fact.root, Object.freeze({
|
|
91
|
+
controlRoot: fact.root,
|
|
92
|
+
controlBlock: fact.block,
|
|
93
|
+
fleetRoot: payload.fleetRoot,
|
|
94
|
+
memberRoot: payload.memberRoot,
|
|
95
|
+
scopeRoot: payload.scopeRoot,
|
|
96
|
+
publisherAddress: payload.publisherAddress,
|
|
97
|
+
...payload.expiresAtBlock !== void 0 && { expiresAtBlock: payload.expiresAtBlock }
|
|
98
|
+
}));
|
|
99
|
+
}
|
|
100
|
+
return Object.freeze(candidates.values().toArray());
|
|
101
|
+
}
|
|
102
|
+
function historicalPublisherResult(result, controls, fleetRoot) {
|
|
87
103
|
const context2 = {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
104
|
+
anchor: result.anchor,
|
|
105
|
+
assurance: result.assurance,
|
|
106
|
+
chainId: result.chainId,
|
|
107
|
+
genesisRoot: result.genesisRoot,
|
|
108
|
+
historyScope: result.historyScope,
|
|
109
|
+
network: result.network,
|
|
110
|
+
owner: result.owner,
|
|
111
|
+
selection: "historical-ever-granted-discovery-only",
|
|
112
|
+
...result.resources !== void 0 && { resources: result.resources },
|
|
113
|
+
...fleetRoot !== void 0 && { fleetRoot }
|
|
91
114
|
};
|
|
92
|
-
|
|
115
|
+
return result.status === "complete" ? Object.freeze({
|
|
116
|
+
...context2,
|
|
117
|
+
...result.scopeCompleteness !== void 0 && { scopeCompleteness: result.scopeCompleteness },
|
|
118
|
+
status: "complete",
|
|
119
|
+
correspondence: result.correspondence,
|
|
120
|
+
coveredRange: result.coveredRange,
|
|
121
|
+
history: result.history,
|
|
122
|
+
candidates: historicalPublisherCandidates(controls)
|
|
123
|
+
}) : Object.freeze({
|
|
124
|
+
...context2,
|
|
125
|
+
status: result.status,
|
|
126
|
+
code: result.code
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/fleetMeter.ts
|
|
131
|
+
var encoder = new TextEncoder();
|
|
132
|
+
function spend(budget, bytes) {
|
|
133
|
+
budget.bytes += bytes;
|
|
134
|
+
if (budget.bytes > budget.maximum) throw new RangeError("Declaration response exceeds its reserved allowance");
|
|
135
|
+
}
|
|
136
|
+
function text(budget, value) {
|
|
137
|
+
if (value.length > budget.maximum - budget.bytes) throw new RangeError("Declaration text exceeds its reserved allowance");
|
|
138
|
+
spend(budget, encoder.encode(JSON.stringify(value)).byteLength);
|
|
139
|
+
}
|
|
140
|
+
function compositeSnapshot(value, budget, depth) {
|
|
141
|
+
const array = Array.isArray(value);
|
|
142
|
+
if (Object.getPrototypeOf(value) !== (array ? Array.prototype : Object.prototype)) throw new TypeError("Declaration response requires plain JSON");
|
|
143
|
+
if (array && value.length > budget.limits.maxNodes - budget.nodes) throw new RangeError("Declaration response exceeds node bounds");
|
|
144
|
+
const keys = Reflect.ownKeys(value);
|
|
145
|
+
const expected = array ? Array.from({ length: value.length }, (_, index) => String(index)) : keys;
|
|
146
|
+
if (array && (keys.length !== value.length + 1 || keys.at(-1) !== "length")) throw new TypeError("Declaration arrays require dense own slots");
|
|
147
|
+
if (expected.length > budget.limits.maxNodes - budget.nodes) throw new RangeError("Declaration response exceeds node bounds");
|
|
148
|
+
spend(budget, 2);
|
|
149
|
+
const entries = expected.map((key, index) => {
|
|
150
|
+
if (typeof key !== "string" || key === "__proto__") throw new TypeError("Declaration keys require plain strings");
|
|
151
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
152
|
+
if (descriptor?.enumerable !== true || !("value" in descriptor)) throw new TypeError("Declaration accessors are unsupported");
|
|
153
|
+
if (index > 0) spend(budget, 1);
|
|
154
|
+
if (!array) {
|
|
155
|
+
text(budget, key);
|
|
156
|
+
spend(budget, 1);
|
|
157
|
+
}
|
|
158
|
+
return [key, jsonSnapshot(descriptor.value, budget, depth + 1)];
|
|
159
|
+
});
|
|
160
|
+
return Object.freeze(array ? entries.map(([, item]) => item) : Object.fromEntries(entries));
|
|
161
|
+
}
|
|
162
|
+
function jsonSnapshot(value, budget, depth = 0) {
|
|
163
|
+
if (++budget.nodes > budget.limits.maxNodes || depth > budget.limits.maxDepth) throw new RangeError("Declaration response exceeds structure bounds");
|
|
164
|
+
if (value === null || typeof value === "boolean" || typeof value === "number") {
|
|
165
|
+
if (typeof value === "number" && !Number.isFinite(value)) throw new TypeError("Declaration response requires finite JSON");
|
|
166
|
+
spend(budget, JSON.stringify(value).length);
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
if (typeof value === "string") {
|
|
170
|
+
text(budget, value);
|
|
171
|
+
return value;
|
|
172
|
+
}
|
|
173
|
+
if (typeof value !== "object" || budget.ancestors.has(value)) throw new TypeError("Declaration response requires acyclic own-data JSON");
|
|
174
|
+
budget.ancestors.add(value);
|
|
175
|
+
try {
|
|
176
|
+
return compositeSnapshot(value, budget, depth);
|
|
177
|
+
} finally {
|
|
178
|
+
budget.ancestors.delete(value);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function logicalJsonSnapshot(value, maximum, limits) {
|
|
182
|
+
const budget = {
|
|
183
|
+
bytes: 0,
|
|
184
|
+
nodes: 0,
|
|
185
|
+
maximum,
|
|
186
|
+
limits,
|
|
187
|
+
ancestors: /* @__PURE__ */ new WeakSet()
|
|
188
|
+
};
|
|
189
|
+
const snapshot = jsonSnapshot(value, budget);
|
|
190
|
+
return { value: snapshot, bytes: budget.bytes };
|
|
191
|
+
}
|
|
192
|
+
var FleetMeter = class {
|
|
193
|
+
#ceiling;
|
|
194
|
+
#closed = false;
|
|
195
|
+
#declarations = 0;
|
|
196
|
+
#limits;
|
|
197
|
+
#native = 0;
|
|
198
|
+
#reserved = 0;
|
|
199
|
+
constructor(ceiling, limits) {
|
|
200
|
+
this.#ceiling = ceiling;
|
|
201
|
+
this.#limits = limits;
|
|
202
|
+
}
|
|
203
|
+
close() {
|
|
204
|
+
this.#closed = true;
|
|
205
|
+
}
|
|
206
|
+
native(bytes) {
|
|
207
|
+
if (bytes === void 0 || !Number.isSafeInteger(bytes) || bytes < 0) throw new FleetAuthorityError("conflict", "native-resources");
|
|
208
|
+
this.#native += bytes;
|
|
209
|
+
if (this.#native + this.#declarations + this.#reserved > this.#ceiling) throw new FleetAuthorityError("resource-limit", "aggregate-bytes");
|
|
210
|
+
}
|
|
211
|
+
async read(get, roots, options) {
|
|
212
|
+
const allowance = Math.min(options?.maxBodyBytes ?? this.#limits.maxBodyBytes, this.remaining());
|
|
213
|
+
this.#reserved += allowance;
|
|
214
|
+
const response = await get(roots, {
|
|
215
|
+
...options,
|
|
216
|
+
signal: options?.signal ?? new AbortController().signal,
|
|
217
|
+
maxBodyBytes: allowance
|
|
218
|
+
});
|
|
219
|
+
if (this.#closed || options?.signal !== void 0 && aborted(options.signal)) throw new FleetAuthorityError("incomplete", "declaration-late");
|
|
220
|
+
if (!Array.isArray(response) || response.length > this.#limits.maxCandidatesPerSeed) throw new FleetAuthorityError("resource-limit", "declaration-response");
|
|
221
|
+
const budget = {
|
|
222
|
+
bytes: 0,
|
|
223
|
+
nodes: 0,
|
|
224
|
+
maximum: allowance,
|
|
225
|
+
limits: this.#limits,
|
|
226
|
+
ancestors: /* @__PURE__ */ new WeakSet()
|
|
227
|
+
};
|
|
228
|
+
const snapshot = jsonSnapshot(response, budget);
|
|
229
|
+
this.#reserved -= allowance;
|
|
230
|
+
this.#declarations += budget.bytes;
|
|
231
|
+
return snapshot;
|
|
232
|
+
}
|
|
233
|
+
remaining() {
|
|
234
|
+
const remaining = this.#ceiling - this.#native - this.#declarations - this.#reserved;
|
|
235
|
+
if (this.#closed || remaining <= 0) throw new FleetAuthorityError("resource-limit", "aggregate-bytes");
|
|
236
|
+
return remaining;
|
|
237
|
+
}
|
|
238
|
+
resources() {
|
|
239
|
+
const decodedBytes = this.#native + this.#declarations;
|
|
93
240
|
return Object.freeze({
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
241
|
+
decodedBytes,
|
|
242
|
+
chargedBytes: decodedBytes + this.#reserved,
|
|
243
|
+
nativeDecodedBytes: this.#native,
|
|
244
|
+
declarationDecodedBytes: this.#declarations,
|
|
245
|
+
declarationReservedBytes: this.#reserved
|
|
97
246
|
});
|
|
98
247
|
}
|
|
99
|
-
|
|
248
|
+
};
|
|
249
|
+
function chargeNativeResources(meter, resources) {
|
|
250
|
+
meter?.native(resources?.decodedBytes);
|
|
100
251
|
}
|
|
101
252
|
|
|
102
|
-
// src/
|
|
103
|
-
|
|
253
|
+
// src/fleetHistoryCache.ts
|
|
254
|
+
function snapshotFleetVerifiedHistory(input) {
|
|
255
|
+
if (input === void 0) return;
|
|
256
|
+
if (input === null || typeof input !== "object" || Object.getPrototypeOf(input) !== Object.prototype || Reflect.ownKeys(input).length !== 2) throw new TypeError("Select strict verified owner-history bounds");
|
|
257
|
+
const values = Object.fromEntries(["maxBytes", "maxOwners"].map((key) => {
|
|
258
|
+
const slot = Object.getOwnPropertyDescriptor(input, key);
|
|
259
|
+
if (slot?.enumerable !== true || !("value" in slot) || typeof slot.value !== "number" || !Number.isSafeInteger(slot.value) || slot.value <= 0) throw new TypeError("Select positive own-data history bounds");
|
|
260
|
+
return [key, slot.value];
|
|
261
|
+
}));
|
|
262
|
+
if (values.maxOwners > 16 || values.maxBytes > 128 * 1024 * 1024) throw new RangeError("Verified history storage exceeds its bounded profile");
|
|
263
|
+
return Object.freeze(values);
|
|
264
|
+
}
|
|
265
|
+
var encoder2 = new TextEncoder();
|
|
266
|
+
var decoder = new TextDecoder("utf-8", { fatal: true });
|
|
267
|
+
var VerifiedFleetHistory = class {
|
|
268
|
+
#bytes = 0;
|
|
269
|
+
#entries = /* @__PURE__ */ new Map();
|
|
270
|
+
#limits;
|
|
271
|
+
#maxDepth;
|
|
272
|
+
constructor(limits, maxDepth) {
|
|
273
|
+
this.#limits = limits;
|
|
274
|
+
this.#maxDepth = maxDepth;
|
|
275
|
+
}
|
|
276
|
+
get(owner) {
|
|
277
|
+
const entry = this.#entries.get(owner);
|
|
278
|
+
if (entry === void 0) return;
|
|
279
|
+
this.#entries.delete(owner);
|
|
280
|
+
this.#entries.set(owner, entry);
|
|
281
|
+
const decoded = JSON.parse(decoder.decode(entry.data));
|
|
282
|
+
return logicalJsonSnapshot(decoded, this.#limits.maxBytes, { maxDepth: this.#maxDepth, maxNodes: this.#limits.maxBytes }).value;
|
|
283
|
+
}
|
|
284
|
+
publish(input) {
|
|
285
|
+
const prior = this.#entries.get(input.owner);
|
|
286
|
+
if (prior !== void 0) {
|
|
287
|
+
if (prior.anchor.blockNumber > input.anchor.blockNumber) return;
|
|
288
|
+
if (prior.anchor.blockNumber === input.anchor.blockNumber && prior.anchor.blockRoot !== input.anchor.blockRoot) throw new FleetAuthorityError("conflict", "history-anchor");
|
|
289
|
+
}
|
|
290
|
+
let snapshot;
|
|
291
|
+
try {
|
|
292
|
+
snapshot = logicalJsonSnapshot(input, this.#limits.maxBytes, { maxDepth: this.#maxDepth, maxNodes: this.#limits.maxBytes });
|
|
293
|
+
} catch {
|
|
294
|
+
throw new FleetAuthorityError("resource-limit", "history-bytes");
|
|
295
|
+
}
|
|
296
|
+
while (this.#bytes + snapshot.bytes > this.#limits.maxBytes || this.#entries.size >= this.#limits.maxOwners) {
|
|
297
|
+
const oldest = this.#entries.keys().next().value;
|
|
298
|
+
if (oldest === void 0) throw new FleetAuthorityError("resource-limit", "history-bytes");
|
|
299
|
+
this.#bytes -= this.#entries.get(oldest).data.byteLength;
|
|
300
|
+
this.#entries.delete(oldest);
|
|
301
|
+
}
|
|
302
|
+
const data = encoder2.encode(JSON.stringify(snapshot.value));
|
|
303
|
+
if (data.byteLength !== snapshot.bytes) throw new FleetAuthorityError("conflict", "history-size");
|
|
304
|
+
const replacing = this.#entries.get(input.owner);
|
|
305
|
+
if (replacing !== void 0) this.#bytes -= replacing.data.byteLength;
|
|
306
|
+
this.#entries.set(input.owner, { anchor: input.anchor, data });
|
|
307
|
+
this.#bytes += data.byteLength;
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
|
|
311
|
+
// src/fleetScope.ts
|
|
312
|
+
import { HashZod as HashZod3 } from "@xyo-network/service-kit-schemas";
|
|
313
|
+
|
|
314
|
+
// src/fleetForeign.ts
|
|
315
|
+
import { AddressZod, HashZod } from "@xyo-network/service-kit-schemas";
|
|
316
|
+
|
|
317
|
+
// src/fleetProfile.ts
|
|
318
|
+
import {
|
|
319
|
+
snapshotFinalizedForeignTransactions,
|
|
320
|
+
snapshotFinalizedForkLineage,
|
|
321
|
+
snapshotFinalizedVerifiedPrefix
|
|
322
|
+
} from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
|
|
323
|
+
|
|
324
|
+
// src/fleetQuerySelection.ts
|
|
325
|
+
import { snapshotFinalizedQuerySelection } from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
|
|
326
|
+
function snapshotFleetQuerySelection(input) {
|
|
327
|
+
const selection = snapshotFinalizedQuerySelection(input);
|
|
328
|
+
if (selection !== input) throw new TypeError("Native query selection snapshot must preserve the exact policy");
|
|
329
|
+
return selection;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// src/fleetSelectedPayloadSource.ts
|
|
333
|
+
import { snapshotFinalizedSelectedPayloadSource } from "@xyo-network/xl1-sdk/protocol-sdk/finalized-publication";
|
|
334
|
+
function snapshotFleetSelectedPayloadSource(input, maxSourceUrlBytes) {
|
|
335
|
+
const captured = snapshotFinalizedSelectedPayloadSource(input, maxSourceUrlBytes);
|
|
336
|
+
if (input !== void 0 && captured === void 0) throw new TypeError("Selected payload source snapshot must preserve the requested selection");
|
|
337
|
+
return captured;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
// src/fleetProfile.ts
|
|
104
341
|
function ownRecord(input, required, optional = []) {
|
|
105
342
|
if (input === null || typeof input !== "object" || Object.getPrototypeOf(input) !== Object.prototype) throw new TypeError("Use a strict own-data profile/request");
|
|
106
343
|
const keys = Reflect.ownKeys(input);
|
|
@@ -111,15 +348,26 @@ function ownRecord(input, required, optional = []) {
|
|
|
111
348
|
return [key, descriptor.value];
|
|
112
349
|
}));
|
|
113
350
|
}
|
|
114
|
-
function finiteProfile(input, keys) {
|
|
351
|
+
function finiteProfile(input, keys, largeBytes = false) {
|
|
115
352
|
const values = ownRecord(input, keys);
|
|
116
|
-
if (Object.
|
|
353
|
+
if (Object.entries(values).some(([key, value]) => typeof value !== "number" || !Number.isSafeInteger(value) || value <= 0 || value > 2147483647 && !(largeBytes && key === "maxAggregateBytes"))) throw new RangeError("Every finite positive bound is required");
|
|
117
354
|
return Object.freeze(values);
|
|
118
355
|
}
|
|
119
356
|
function pinProfile(input) {
|
|
120
|
-
const profile = ownRecord(input, ["evidence", "foldLimits", "limits", "resolutionLimits", "seeds"]);
|
|
121
|
-
const evidence = ownRecord(profile.evidence, ["assurance", "chainId", "genesisRoot", "limits", "network", "source"]);
|
|
122
|
-
const source = ownRecord(evidence.source, ["bodyBaseUrl", "finalizedBaseUrl", "headUrl"], ["fetch"]);
|
|
357
|
+
const profile = ownRecord(input, ["evidence", "foldLimits", "limits", "resolutionLimits", "seeds"], ["verifiedHistory"]);
|
|
358
|
+
const evidence = ownRecord(profile.evidence, ["assurance", "chainId", "genesisRoot", "limits", "network", "source"], ["forkLineage", "verifiedPrefix", "foreignTransactions", "querySelection"]);
|
|
359
|
+
const source = ownRecord(evidence.source, ["bodyBaseUrl", "finalizedBaseUrl", "headUrl"], ["fetch", "blockFrames", "selectedPayloadSource"]);
|
|
360
|
+
const forkLineage = snapshotFinalizedForkLineage(evidence.forkLineage, evidence.chainId);
|
|
361
|
+
const blockFrames = source.blockFrames === void 0 ? void 0 : pinBlockFrames(source.blockFrames);
|
|
362
|
+
const verifiedPrefix = pinVerifiedPrefix(evidence.verifiedPrefix);
|
|
363
|
+
const foreignTransactions = snapshotFinalizedForeignTransactions(evidence.foreignTransactions);
|
|
364
|
+
if (foreignTransactions !== void 0 && (forkLineage === void 0 || blockFrames === void 0 || verifiedPrefix === void 0)) {
|
|
365
|
+
throw new TypeError("Foreign transaction exclusion requires explicit fork, frame and verified-prefix profiles");
|
|
366
|
+
}
|
|
367
|
+
if (verifiedPrefix !== void 0 && (forkLineage === void 0 || blockFrames === void 0)) throw new TypeError("Verified native prefix requires explicit fork and original-block frame profiles");
|
|
368
|
+
const querySelection = snapshotFleetQuerySelection(evidence.querySelection);
|
|
369
|
+
const verifiedHistory = snapshotFleetVerifiedHistory(profile.verifiedHistory);
|
|
370
|
+
if (verifiedHistory !== void 0 && verifiedPrefix === void 0) throw new TypeError("Verified owner history requires native verified-prefix support");
|
|
123
371
|
const evidenceLimits = finiteProfile(evidence.limits, [
|
|
124
372
|
"maxAggregateBytes",
|
|
125
373
|
"maxBlocks",
|
|
@@ -133,11 +381,20 @@ function pinProfile(input) {
|
|
|
133
381
|
"maxSourceUrlBytes",
|
|
134
382
|
"perCallTimeoutMs",
|
|
135
383
|
"totalTimeoutMs"
|
|
136
|
-
]);
|
|
384
|
+
], verifiedPrefix !== void 0);
|
|
385
|
+
const selectedPayloadSource = snapshotFleetSelectedPayloadSource(source.selectedPayloadSource, evidenceLimits.maxSourceUrlBytes);
|
|
137
386
|
const fixedEvidence = Object.freeze({
|
|
138
387
|
...evidence,
|
|
139
388
|
limits: evidenceLimits,
|
|
140
|
-
|
|
389
|
+
...forkLineage !== void 0 && { forkLineage },
|
|
390
|
+
...verifiedPrefix !== void 0 && { verifiedPrefix },
|
|
391
|
+
...foreignTransactions !== void 0 && { foreignTransactions },
|
|
392
|
+
...querySelection !== void 0 && { querySelection },
|
|
393
|
+
source: Object.freeze({
|
|
394
|
+
...source,
|
|
395
|
+
...blockFrames !== void 0 && { blockFrames },
|
|
396
|
+
...selectedPayloadSource !== void 0 && { selectedPayloadSource }
|
|
397
|
+
})
|
|
141
398
|
});
|
|
142
399
|
const limits = finiteProfile(profile.limits, [
|
|
143
400
|
"maxBlocks",
|
|
@@ -164,22 +421,349 @@ function pinProfile(input) {
|
|
|
164
421
|
limits,
|
|
165
422
|
foldLimits,
|
|
166
423
|
resolutionLimits,
|
|
424
|
+
verifiedHistory,
|
|
167
425
|
seeds: profile.seeds
|
|
168
426
|
};
|
|
169
427
|
}
|
|
170
|
-
function
|
|
171
|
-
const
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
428
|
+
function pinBlockFrames(input) {
|
|
429
|
+
const frames = ownRecord(input, ["indexBaseUrl", "maxStep"]);
|
|
430
|
+
if (typeof frames.indexBaseUrl !== "string" || frames.indexBaseUrl.length === 0 || typeof frames.maxStep !== "number" || !Number.isSafeInteger(frames.maxStep) || frames.maxStep < 0 || frames.maxStep > 3) throw new TypeError("Select a bounded original-block frame source");
|
|
431
|
+
return Object.freeze({ indexBaseUrl: frames.indexBaseUrl, maxStep: frames.maxStep });
|
|
432
|
+
}
|
|
433
|
+
function pinVerifiedPrefix(input) {
|
|
434
|
+
if (input === void 0) return snapshotFinalizedVerifiedPrefix(input);
|
|
435
|
+
const fields = ownRecord(input, ["maxEntries", "maxBytes"], ["shareKey"]);
|
|
436
|
+
const captured = snapshotFinalizedVerifiedPrefix(fields);
|
|
437
|
+
if (captured === void 0 || captured.maxEntries !== fields.maxEntries || captured.maxBytes !== fields.maxBytes || Reflect.get(captured, "shareKey") !== fields.shareKey) throw new TypeError("Native verified-prefix snapshot must preserve its exact selection");
|
|
438
|
+
return captured;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/fleetForeign.ts
|
|
442
|
+
function field(input, key) {
|
|
443
|
+
if (input === null || typeof input !== "object") throw new FleetAuthorityError("conflict", "scan-foreign-header");
|
|
444
|
+
const slot = Object.getOwnPropertyDescriptor(input, key);
|
|
445
|
+
if (slot?.enumerable !== true || !("value" in slot)) throw new FleetAuthorityError("conflict", "scan-foreign-header");
|
|
446
|
+
return slot.value;
|
|
447
|
+
}
|
|
448
|
+
function position(value) {
|
|
449
|
+
return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
|
|
450
|
+
}
|
|
451
|
+
function validateSlots(header) {
|
|
452
|
+
const hashes = field(header.transaction, "payload_hashes");
|
|
453
|
+
const schemas = field(header.transaction, "payload_schemas");
|
|
454
|
+
if (!Array.isArray(hashes) || !Array.isArray(schemas) || !Array.isArray(header.payloads) || hashes.length !== schemas.length || hashes.length !== header.payloads.length) throw new FleetAuthorityError("conflict", "scan-foreign-slots");
|
|
455
|
+
for (let index = 0; index < hashes.length; index++) {
|
|
456
|
+
const hash = field(hashes, String(index));
|
|
457
|
+
const schema = field(schemas, String(index));
|
|
458
|
+
const slot = ownRecord(field(header.payloads, String(index)), ["payloadOrdinal", "payloadRoot", "schema", "selected"]);
|
|
459
|
+
if (typeof schema !== "string" || schema.length === 0 || !HashZod.safeParse(hash).success || slot.payloadOrdinal !== index || slot.payloadRoot !== hash || slot.schema !== schema || slot.selected !== false) throw new FleetAuthorityError("conflict", "scan-foreign-slots");
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
function validateDomain(header, profile) {
|
|
463
|
+
const ancestors = profile.evidence.forkLineage?.map((edge) => edge.parentChainId) ?? [];
|
|
464
|
+
if (header.network !== profile.evidence.network || header.genesisRoot !== profile.evidence.genesisRoot || header.carryingChainId !== profile.evidence.chainId || header.chainId === profile.evidence.chainId || !ancestors.includes(header.chainId) || header.reason !== "verified-ancestor-domain-not-authority" || field(header.transaction, "chain") !== header.chainId || field(header.transaction, "from") !== header.signer || !AddressZod.safeParse(header.signer).success || !HashZod.safeParse(header.blockRoot).success || !HashZod.safeParse(header.transactionRoot).success) throw new FleetAuthorityError("conflict", "scan-foreign-domain");
|
|
465
|
+
}
|
|
466
|
+
function validateHeader(input, page, profile, from, to) {
|
|
467
|
+
const header = ownRecord(input, [
|
|
468
|
+
"network",
|
|
469
|
+
"chainId",
|
|
470
|
+
"genesisRoot",
|
|
471
|
+
"blockNumber",
|
|
472
|
+
"blockRoot",
|
|
473
|
+
"transactionRoot",
|
|
474
|
+
"transactionIndex",
|
|
475
|
+
"transactionPayloadOrdinal",
|
|
476
|
+
"signer",
|
|
477
|
+
"transaction",
|
|
478
|
+
"payloads",
|
|
479
|
+
"carryingChainId",
|
|
480
|
+
"reason"
|
|
481
|
+
]);
|
|
482
|
+
validateDomain(header, profile);
|
|
483
|
+
if (!position(header.blockNumber) || header.blockNumber < from || header.blockNumber > to || !position(header.transactionIndex) || !position(header.transactionPayloadOrdinal) || header.transactionPayloadOrdinal < header.transactionIndex) throw new FleetAuthorityError("conflict", "scan-foreign-position");
|
|
484
|
+
if (page.blockClocks.every((clock) => !(clock.blockNumber === header.blockNumber && clock.blockRoot === header.blockRoot && clock.chainId === header.carryingChainId)) || page.headers.some((ordinary) => ordinary.blockNumber === header.blockNumber && ordinary.transactionIndex === header.transactionIndex)) {
|
|
485
|
+
throw new FleetAuthorityError("conflict", "scan-foreign-correspondence");
|
|
486
|
+
}
|
|
487
|
+
validateSlots(header);
|
|
488
|
+
return {
|
|
489
|
+
block: header.blockNumber,
|
|
490
|
+
index: header.transactionIndex,
|
|
491
|
+
ordinal: header.transactionPayloadOrdinal
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
function validateForeignHeaders(page, profile, from, to) {
|
|
495
|
+
const result = page;
|
|
496
|
+
if (profile.evidence.foreignTransactions === void 0) {
|
|
497
|
+
if (result.foreignTransactionHeaders !== void 0) throw new FleetAuthorityError("conflict", "scan-foreign-profile");
|
|
498
|
+
return 0;
|
|
499
|
+
}
|
|
500
|
+
if (!Array.isArray(result.foreignTransactionHeaders) || result.foreignTransactionHeaders.length > profile.evidence.limits.maxRoots) throw new FleetAuthorityError("conflict", "scan-foreign-headers");
|
|
501
|
+
let previous;
|
|
502
|
+
for (let index = 0; index < result.foreignTransactionHeaders.length; index++) {
|
|
503
|
+
const header = validateHeader(field(result.foreignTransactionHeaders, String(index)), page, profile, from, to);
|
|
504
|
+
if (previous !== void 0 && (header.block < previous.block || header.block === previous.block && (header.index <= previous.index || header.ordinal <= previous.ordinal))) throw new FleetAuthorityError("conflict", "scan-foreign-order");
|
|
505
|
+
previous = header;
|
|
506
|
+
}
|
|
507
|
+
return result.foreignTransactionHeaders.length;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/fleetQuery.ts
|
|
511
|
+
import { AddressZod as AddressZod2, HashZod as HashZod2 } from "@xyo-network/service-kit-schemas";
|
|
512
|
+
var grade = "verified-block-committed-query-selection";
|
|
513
|
+
var encoder3 = new TextEncoder();
|
|
514
|
+
function fail(code = "scan-query-exclusion") {
|
|
515
|
+
throw new FleetAuthorityError("conflict", code);
|
|
516
|
+
}
|
|
517
|
+
function spend2(budget, nodes, bytes = 0) {
|
|
518
|
+
budget.nodes += nodes;
|
|
519
|
+
budget.bytes += bytes;
|
|
520
|
+
if (budget.nodes > budget.profile.evidence.limits.maxDecodedNodes || budget.bytes > budget.profile.evidence.limits.maxAggregateBytes) {
|
|
521
|
+
throw new FleetAuthorityError("resource-limit", "scan-query-metadata");
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
function field2(input, key) {
|
|
525
|
+
const slot = input !== null && typeof input === "object" ? Object.getOwnPropertyDescriptor(input, key) : void 0;
|
|
526
|
+
return slot?.enumerable === true && "value" in slot ? slot.value : fail();
|
|
527
|
+
}
|
|
528
|
+
function position2(input) {
|
|
529
|
+
return typeof input === "number" && Number.isSafeInteger(input) && input >= 0;
|
|
530
|
+
}
|
|
531
|
+
function dense(input, maximum, budget) {
|
|
532
|
+
if (!Array.isArray(input) || input.length > maximum || Reflect.ownKeys(input).length !== input.length + 1) return fail();
|
|
533
|
+
spend2(budget, input.length + 1);
|
|
534
|
+
for (let i = 0; i < input.length; i++) field2(input, String(i));
|
|
535
|
+
return input;
|
|
536
|
+
}
|
|
537
|
+
function strings(input, budget, address = false) {
|
|
538
|
+
const values = dense(input, budget.profile.evidence.limits.maxRoots, budget);
|
|
539
|
+
for (const value of values) {
|
|
540
|
+
if (typeof value !== "string" || value.length === 0 || value.length > budget.profile.evidence.limits.maxResponseBytes || address && !AddressZod2.safeParse(value).success) return fail();
|
|
541
|
+
spend2(budget, 0, encoder3.encode(value).byteLength);
|
|
542
|
+
}
|
|
543
|
+
return values;
|
|
544
|
+
}
|
|
545
|
+
function scopeMatches(input, expected, budget) {
|
|
546
|
+
const keys = ["authorizers", "chainIds", "schemas"].filter((key) => expected[key] !== void 0);
|
|
547
|
+
const snapshot = ownRecord(input, keys);
|
|
548
|
+
for (const key of keys) {
|
|
549
|
+
const selected = snapshot[key];
|
|
550
|
+
if (!Array.isArray(selected) || selected.length !== expected[key].length) fail("scan-query-request");
|
|
551
|
+
const values = strings(selected, budget, key !== "schemas");
|
|
552
|
+
if (values.some((value, index) => value !== expected[key][index])) fail("scan-query-request");
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
function chainAt(profile, block) {
|
|
556
|
+
let chain = profile.evidence.chainId;
|
|
557
|
+
const lineage = profile.evidence.forkLineage ?? [];
|
|
558
|
+
for (const edge of lineage) {
|
|
559
|
+
if (block > edge.forkedAtBlockNumber) break;
|
|
560
|
+
chain = edge.parentChainId;
|
|
561
|
+
}
|
|
562
|
+
return chain;
|
|
563
|
+
}
|
|
564
|
+
function occupiedPositions(page, budget) {
|
|
565
|
+
const occupied = /* @__PURE__ */ new Set();
|
|
566
|
+
for (const rows of [page.headers, page.occurrences, page.foreignTransactionHeaders ?? []]) {
|
|
567
|
+
for (const row of dense(rows, budget.profile.evidence.limits.maxRoots, budget)) {
|
|
568
|
+
const block = field2(row, "blockNumber");
|
|
569
|
+
const index = field2(row, "transactionIndex");
|
|
570
|
+
const ordinal = field2(row, "transactionPayloadOrdinal");
|
|
571
|
+
if (!position2(block) || !position2(index) || !position2(ordinal)) fail();
|
|
572
|
+
occupied.add(`${block}:index:${index}`);
|
|
573
|
+
occupied.add(`${block}:ordinal:${ordinal}`);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return occupied;
|
|
577
|
+
}
|
|
578
|
+
function clockRows(page, budget) {
|
|
579
|
+
const clocks = /* @__PURE__ */ new Map();
|
|
580
|
+
for (const row of dense(page.blockClocks, budget.profile.evidence.limits.maxBlocks, budget)) {
|
|
581
|
+
const block = field2(row, "blockNumber");
|
|
582
|
+
if (!position2(block) || clocks.has(block)) fail("scan-query-clock");
|
|
583
|
+
clocks.set(block, row);
|
|
584
|
+
}
|
|
585
|
+
return clocks;
|
|
586
|
+
}
|
|
587
|
+
function validateClock(row, clocks, profile) {
|
|
588
|
+
const clock = clocks.get(row.blockNumber);
|
|
589
|
+
if (clock === void 0 || field2(clock, "network") !== profile.evidence.network || field2(clock, "genesisRoot") !== profile.evidence.genesisRoot || field2(clock, "blockRoot") !== row.blockRoot || field2(clock, "chainId") !== row.carryingChainId) fail("scan-query-clock");
|
|
590
|
+
const time = field2(clock, "time");
|
|
591
|
+
if (field2(time, "status") === "authenticated" && (field2(time, "payloadOrdinal") === row.transactionPayloadOrdinal || field2(time, "payloadRoot") === row.transactionRoot)) fail("scan-query-time");
|
|
592
|
+
}
|
|
593
|
+
function validatePosition(row, profile, from, to) {
|
|
594
|
+
if (!position2(row.blockNumber) || row.blockNumber < from || row.blockNumber > to || !position2(row.transactionIndex) || !position2(row.transactionPayloadOrdinal) || row.transactionPayloadOrdinal < row.transactionIndex || row.carryingChainId !== chainAt(profile, row.blockNumber) || !AddressZod2.safeParse(row.declaredChainId).success || !AddressZod2.safeParse(row.declaredFrom).success || !HashZod2.safeParse(row.blockRoot).success || !HashZod2.safeParse(row.transactionRoot).success) fail();
|
|
595
|
+
}
|
|
596
|
+
function validateRecord(input, expected, profile, from, to, clocks, occupied, budget) {
|
|
597
|
+
const row = ownRecord(input, [
|
|
598
|
+
"blockNumber",
|
|
599
|
+
"blockRoot",
|
|
600
|
+
"carryingChainId",
|
|
601
|
+
"transactionIndex",
|
|
602
|
+
"transactionPayloadOrdinal",
|
|
603
|
+
"transactionRoot",
|
|
604
|
+
"declaredChainId",
|
|
605
|
+
"declaredFrom",
|
|
606
|
+
"declaredAddresses",
|
|
607
|
+
"declaredPayloadSchemas",
|
|
608
|
+
"reason",
|
|
609
|
+
"requestSnapshot"
|
|
610
|
+
]);
|
|
611
|
+
spend2(budget, 12);
|
|
612
|
+
validatePosition(row, profile, from, to);
|
|
613
|
+
const addresses = strings(row.declaredAddresses, budget, true);
|
|
614
|
+
const schemas = strings(row.declaredPayloadSchemas, budget);
|
|
615
|
+
if (addresses.length === 0 || new Set(addresses).size !== addresses.length) fail();
|
|
616
|
+
scopeMatches(row.requestSnapshot, expected, budget);
|
|
617
|
+
const claimed = /* @__PURE__ */ new Set([row.declaredFrom, ...addresses]);
|
|
618
|
+
const noAuthorizer = expected.authorizers?.every((value) => !claimed.has(value)) === true;
|
|
619
|
+
const noSchema = expected.schemas?.every((value) => !schemas.includes(value)) === true;
|
|
620
|
+
const reason = noAuthorizer ? "no-requested-authorizer" : noSchema ? "no-requested-schema" : void 0;
|
|
621
|
+
if (reason === void 0 || row.reason !== reason) fail("scan-query-reason");
|
|
622
|
+
const indexKey = `${row.blockNumber}:index:${row.transactionIndex}`;
|
|
623
|
+
const ordinalKey = `${row.blockNumber}:ordinal:${row.transactionPayloadOrdinal}`;
|
|
624
|
+
if (occupied.has(indexKey) || occupied.has(ordinalKey)) fail("scan-query-overlap");
|
|
625
|
+
occupied.add(indexKey);
|
|
626
|
+
occupied.add(ordinalKey);
|
|
627
|
+
if (pageExcluded(profile, row.blockNumber, from, to)) fail("scan-query-excluded-chain");
|
|
628
|
+
validateClock(row, clocks, profile);
|
|
629
|
+
return {
|
|
630
|
+
block: row.blockNumber,
|
|
631
|
+
index: row.transactionIndex,
|
|
632
|
+
ordinal: row.transactionPayloadOrdinal
|
|
633
|
+
};
|
|
634
|
+
}
|
|
635
|
+
function pageExcluded(profile, block, from, to) {
|
|
636
|
+
return profile.evidence.verifiedPrefix !== void 0 && profile.evidence.forkLineage?.some((edge) => block >= from && block <= to && block <= edge.forkedAtBlockNumber) === true;
|
|
637
|
+
}
|
|
638
|
+
function validateQueryExclusions(page, profile, from, to, expectedScope) {
|
|
639
|
+
const result = page;
|
|
640
|
+
if (profile.evidence.querySelection === void 0) {
|
|
641
|
+
if (result.blockCommittedQueryExclusions !== void 0 || result.scopeCompleteness === grade) fail("scan-query-profile");
|
|
642
|
+
return;
|
|
643
|
+
}
|
|
644
|
+
try {
|
|
645
|
+
if (expectedScope === void 0 || expectedScope.headersOnly !== void 0 || expectedScope.authorizers === void 0 && expectedScope.schemas === void 0 || [expectedScope.authorizers, expectedScope.chainIds, expectedScope.schemas].some((values) => values?.length === 0) || result.scopeCompleteness !== grade) fail("scan-query-grade");
|
|
646
|
+
const budget = {
|
|
647
|
+
nodes: 0,
|
|
648
|
+
bytes: 0,
|
|
649
|
+
profile
|
|
650
|
+
};
|
|
651
|
+
scopeMatches(page.scope, expectedScope, budget);
|
|
652
|
+
const rows = dense(result.blockCommittedQueryExclusions, profile.evidence.limits.maxRoots, budget);
|
|
653
|
+
const occupied = occupiedPositions(page, budget);
|
|
654
|
+
const clocks = clockRows(page, budget);
|
|
655
|
+
let previous;
|
|
656
|
+
for (const row of rows) {
|
|
657
|
+
const current = validateRecord(row, expectedScope, profile, from, to, clocks, occupied, budget);
|
|
658
|
+
if (previous !== void 0 && (current.block < previous.block || current.block === previous.block && (current.index <= previous.index || current.ordinal <= previous.ordinal))) fail("scan-query-order");
|
|
659
|
+
previous = current;
|
|
660
|
+
}
|
|
661
|
+
return grade;
|
|
662
|
+
} catch (error) {
|
|
663
|
+
if (error instanceof FleetAuthorityError) throw error;
|
|
664
|
+
return fail();
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
|
|
668
|
+
// src/fleetScope.ts
|
|
669
|
+
function validateRange(input, expected, profile) {
|
|
670
|
+
const range = ownRecord(input, ["chainId", "fromBlockNumber", "fromBlockRoot", "toBlockNumber", "toBlockRoot"]);
|
|
671
|
+
const {
|
|
672
|
+
edge,
|
|
673
|
+
first,
|
|
674
|
+
last
|
|
675
|
+
} = expected;
|
|
676
|
+
if (range.chainId !== edge.parentChainId || range.chainId === profile.evidence.chainId || range.fromBlockNumber !== first || range.toBlockNumber !== last || !HashZod3.safeParse(range.fromBlockRoot).success || !HashZod3.safeParse(range.toBlockRoot).success || first === 0 && range.fromBlockRoot !== profile.evidence.genesisRoot || last === edge.forkedAtBlockNumber && range.toBlockRoot !== edge.forkedAtBlockRoot || first === last && range.fromBlockRoot !== range.toBlockRoot) throw new FleetAuthorityError("conflict", "scan-exclusions");
|
|
677
|
+
}
|
|
678
|
+
function validateGrade(actual, query, foreign) {
|
|
679
|
+
if (query !== void 0) return;
|
|
680
|
+
if (actual !== "verified-native-header-selection-with-domain-exclusions" && foreign > 0) throw new FleetAuthorityError("conflict", "scan-foreign-grade");
|
|
681
|
+
const legacy = ["verified-native-header-selection", "verified-native-header-selection-with-chain-exclusions", "verified-native-header-selection-with-domain-exclusions"];
|
|
682
|
+
if (!legacy.includes(actual)) throw new FleetAuthorityError("conflict", "scan-scope-mode");
|
|
683
|
+
}
|
|
684
|
+
function validateScopeMode(page, profile, from, to, expectedScope) {
|
|
685
|
+
const query = validateQueryExclusions(page, profile, from, to, expectedScope);
|
|
686
|
+
const foreign = validateForeignHeaders(page, profile, from, to);
|
|
687
|
+
const result = page;
|
|
688
|
+
validateGrade(result.scopeCompleteness, query, foreign);
|
|
689
|
+
if (result.scopeCompleteness === "verified-native-header-selection" || query !== void 0 && (profile.evidence.forkLineage === void 0 || profile.evidence.verifiedPrefix === void 0)) {
|
|
690
|
+
if (result.excludedChainRanges !== void 0 && result.excludedChainRanges.length > 0) throw new FleetAuthorityError("conflict", "scan-exclusions");
|
|
691
|
+
return query;
|
|
692
|
+
}
|
|
693
|
+
const lineage = profile.evidence.forkLineage;
|
|
694
|
+
if (lineage === void 0 || profile.evidence.verifiedPrefix === void 0 || !Array.isArray(result.excludedChainRanges)) throw new FleetAuthorityError("conflict", "scan-scope-mode");
|
|
695
|
+
const expected = lineage.map((edge, index) => ({
|
|
696
|
+
edge,
|
|
697
|
+
first: Math.max(from, (lineage[index + 1]?.forkedAtBlockNumber ?? -1) + 1),
|
|
698
|
+
last: Math.min(to, edge.forkedAtBlockNumber)
|
|
699
|
+
})).filter(({ first, last }) => first <= last).toReversed();
|
|
700
|
+
if (query === void 0 && (result.scopeCompleteness === "verified-native-header-selection-with-domain-exclusions" ? foreign : expected.length) === 0 || result.excludedChainRanges.length !== expected.length) throw new FleetAuthorityError("conflict", "scan-exclusion-coverage");
|
|
701
|
+
for (const [index, range] of result.excludedChainRanges.entries()) validateRange(range, expected[index], profile);
|
|
702
|
+
return query;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
// src/fleetPage.ts
|
|
706
|
+
function nativeFailure(page) {
|
|
707
|
+
const statuses = ["cancelled", "deadline", "conflict", "unsupported", "resource-limit"];
|
|
708
|
+
const status = statuses.includes(page.status) ? page.status : "incomplete";
|
|
709
|
+
return new FleetAuthorityError(status, `native-${page.issues[0]?.code ?? page.status}`);
|
|
710
|
+
}
|
|
711
|
+
function validateForkPage(page, profile, request) {
|
|
712
|
+
const clock = page.anchorClock;
|
|
713
|
+
if (page.scope.chainIds?.length !== 1 || page.scope.chainIds[0] !== profile.evidence.chainId || clock?.chainId !== profile.evidence.chainId || clock.network !== profile.evidence.network || clock.genesisRoot !== profile.evidence.genesisRoot || clock.blockNumber !== request.anchor.blockNumber || clock.blockRoot !== request.anchor.blockRoot) throw new FleetAuthorityError("conflict", "scan-current-chain");
|
|
714
|
+
}
|
|
715
|
+
function validateFleetPage(page, profile, request, from, to, scope) {
|
|
716
|
+
const actual = [
|
|
717
|
+
page.network,
|
|
718
|
+
page.chainId,
|
|
719
|
+
page.genesisRoot,
|
|
720
|
+
page.anchor.blockNumber,
|
|
721
|
+
page.anchor.blockRoot,
|
|
722
|
+
page.assurance,
|
|
723
|
+
page.requestedRange.fromBlockNumber,
|
|
724
|
+
page.requestedRange.toBlockNumber
|
|
725
|
+
];
|
|
726
|
+
const expected = [
|
|
727
|
+
profile.evidence.network,
|
|
728
|
+
profile.evidence.chainId,
|
|
729
|
+
profile.evidence.genesisRoot,
|
|
730
|
+
request.anchor.blockNumber,
|
|
731
|
+
request.anchor.blockRoot,
|
|
732
|
+
"source-trusted-finalized-replay",
|
|
733
|
+
from,
|
|
734
|
+
to
|
|
735
|
+
];
|
|
736
|
+
if (actual.some((value, index) => value !== expected[index])) throw new FleetAuthorityError("conflict", "scan-binding");
|
|
737
|
+
if (profile.evidence.querySelection !== void 0 && page.status !== "complete") throw nativeFailure(page);
|
|
738
|
+
const basis = validateScopeMode(page, profile, from, to, scope);
|
|
739
|
+
if (page.scope.authorizers?.length !== 1 || page.scope.authorizers[0] !== request.owner || page.scope.schemas?.length !== scope.schemas.length || page.scope.schemas.some((family, index) => family !== scope.schemas[index])) throw new FleetAuthorityError("conflict", "scan-scope");
|
|
740
|
+
if (page.status !== "complete") throw nativeFailure(page);
|
|
741
|
+
if (profile.evidence.forkLineage !== void 0) validateForkPage(page, profile, request);
|
|
742
|
+
if (page.coveredRange?.fromBlockNumber !== from || page.coveredRange.toBlockNumber !== to || page.continuation !== void 0 || page.issues.length > 0) {
|
|
743
|
+
throw new FleetAuthorityError("incomplete", "scan-coverage");
|
|
744
|
+
}
|
|
745
|
+
return basis;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// src/fleetProjection.ts
|
|
749
|
+
function nextPublisherProjection(result) {
|
|
750
|
+
const { publicationBlock: projectionBlock, ...original } = result;
|
|
751
|
+
const context2 = {
|
|
752
|
+
...original,
|
|
753
|
+
projection: "pending-N+1",
|
|
754
|
+
projectionBlock
|
|
755
|
+
};
|
|
756
|
+
if (result.status === "authorized" || result.status === "absent") {
|
|
757
|
+
return Object.freeze({
|
|
758
|
+
...context2,
|
|
759
|
+
status: result.status === "authorized" ? "projected-granted" : "projected-absent",
|
|
760
|
+
coveredRange: Object.freeze({ fromBlockNumber: 0, toBlockNumber: result.anchor.blockNumber })
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
return Object.freeze(context2);
|
|
182
764
|
}
|
|
765
|
+
|
|
766
|
+
// src/fleetReaders.ts
|
|
183
767
|
function pinReaders(seeds, profile) {
|
|
184
768
|
if (!Array.isArray(seeds) || seeds.length === 0 || seeds.length > profile.resolutionLimits.maxSeeds) throw new RangeError("Explicit bounded root readers required");
|
|
185
769
|
const ids = /* @__PURE__ */ new Set();
|
|
@@ -195,7 +779,7 @@ function pinReaders(seeds, profile) {
|
|
|
195
779
|
return Object.freeze({ id: seed.id, reader: Object.freeze({ get }) });
|
|
196
780
|
}));
|
|
197
781
|
}
|
|
198
|
-
function capacityReaders(seeds, state, maximum, capacity) {
|
|
782
|
+
function capacityReaders(seeds, state, maximum, capacity, meter) {
|
|
199
783
|
return Object.freeze(seeds.map((seed) => Object.freeze({
|
|
200
784
|
id: seed.id,
|
|
201
785
|
reader: Object.freeze({
|
|
@@ -206,7 +790,7 @@ function capacityReaders(seeds, state, maximum, capacity) {
|
|
|
206
790
|
}
|
|
207
791
|
state.active++;
|
|
208
792
|
try {
|
|
209
|
-
return await seed.reader.get(...args);
|
|
793
|
+
return await (meter === void 0 ? seed.reader.get(...args) : meter.read(seed.reader.get.bind(seed.reader), ...args));
|
|
210
794
|
} finally {
|
|
211
795
|
state.active--;
|
|
212
796
|
}
|
|
@@ -214,6 +798,26 @@ function capacityReaders(seeds, state, maximum, capacity) {
|
|
|
214
798
|
})
|
|
215
799
|
})));
|
|
216
800
|
}
|
|
801
|
+
|
|
802
|
+
// src/fleetRequests.ts
|
|
803
|
+
import { AddressZod as AddressZod3, HashZod as HashZod4 } from "@xyo-network/service-kit-schemas";
|
|
804
|
+
function pinRequest(input, next = false) {
|
|
805
|
+
const values = ownRecord(input, ["anchor", "owner", "publicationBlock"], ["fleetRoot", "signal", "maxAggregateBytes"]);
|
|
806
|
+
const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
|
|
807
|
+
HashZod4.parse(anchor.blockRoot);
|
|
808
|
+
AddressZod3.parse(values.owner);
|
|
809
|
+
if (values.maxAggregateBytes !== void 0 && (typeof values.maxAggregateBytes !== "number" || !Number.isSafeInteger(values.maxAggregateBytes) || values.maxAggregateBytes <= 0)) throw new RangeError("Select a finite positive aggregate request ceiling");
|
|
810
|
+
if (values.fleetRoot !== void 0) HashZod4.parse(values.fleetRoot);
|
|
811
|
+
if (!Number.isSafeInteger(anchor.blockNumber) || anchor.blockNumber < 0 || anchor.blockNumber >= Number.MAX_SAFE_INTEGER || typeof values.publicationBlock !== "number" || !Number.isSafeInteger(values.publicationBlock) || values.publicationBlock < 0 || (next ? values.publicationBlock !== anchor.blockNumber + 1 : values.publicationBlock > anchor.blockNumber)) throw new RangeError("Select an exact publication height within the anchor");
|
|
812
|
+
return Object.freeze({
|
|
813
|
+
...values,
|
|
814
|
+
anchor: Object.freeze(anchor),
|
|
815
|
+
signal: captureSignal(values.signal)
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
// src/createFleetAuthority.ts
|
|
820
|
+
var b4Families = Object.freeze([FleetSchema, FleetMemberSchema, FleetPublicationScopeSchema, FleetControlSchema]);
|
|
217
821
|
function context(profile, request) {
|
|
218
822
|
return Object.freeze({
|
|
219
823
|
assurance: "source-trusted-finalized-replay",
|
|
@@ -229,38 +833,8 @@ function context(profile, request) {
|
|
|
229
833
|
function positionAfter(left, right) {
|
|
230
834
|
return left.blockNumber > right.blockNumber || left.blockNumber === right.blockNumber && (left.transactionIndex > right.transactionIndex || left.transactionIndex === right.transactionIndex && left.payloadOrdinal > right.payloadOrdinal);
|
|
231
835
|
}
|
|
232
|
-
function
|
|
233
|
-
|
|
234
|
-
const status = statuses.includes(page.status) ? page.status : "incomplete";
|
|
235
|
-
return new FleetAuthorityError(status, `native-${page.issues[0]?.code ?? page.status}`);
|
|
236
|
-
}
|
|
237
|
-
function validatePage(page, profile, request, from, to) {
|
|
238
|
-
const actual = [
|
|
239
|
-
page.network,
|
|
240
|
-
page.chainId,
|
|
241
|
-
page.genesisRoot,
|
|
242
|
-
page.anchor.blockNumber,
|
|
243
|
-
page.anchor.blockRoot,
|
|
244
|
-
page.assurance,
|
|
245
|
-
page.requestedRange.fromBlockNumber,
|
|
246
|
-
page.requestedRange.toBlockNumber
|
|
247
|
-
];
|
|
248
|
-
const expected = [
|
|
249
|
-
profile.evidence.network,
|
|
250
|
-
profile.evidence.chainId,
|
|
251
|
-
profile.evidence.genesisRoot,
|
|
252
|
-
request.anchor.blockNumber,
|
|
253
|
-
request.anchor.blockRoot,
|
|
254
|
-
"source-trusted-finalized-replay",
|
|
255
|
-
from,
|
|
256
|
-
to
|
|
257
|
-
];
|
|
258
|
-
if (actual.some((value, index) => value !== expected[index])) throw new FleetAuthorityError("conflict", "scan-binding");
|
|
259
|
-
if (page.scopeCompleteness !== "verified-native-header-selection" || page.scope.authorizers?.length !== 1 || page.scope.authorizers[0] !== request.owner || page.scope.schemas?.length !== b4Families.length || page.scope.schemas.some((family, index) => family !== b4Families[index])) throw new FleetAuthorityError("conflict", "scan-scope");
|
|
260
|
-
if (page.status !== "complete") throw nativeFailure(page);
|
|
261
|
-
if (page.coveredRange?.fromBlockNumber !== from || page.coveredRange.toBlockNumber !== to || page.continuation !== void 0 || page.issues.length > 0) {
|
|
262
|
-
throw new FleetAuthorityError("incomplete", "scan-coverage");
|
|
263
|
-
}
|
|
836
|
+
function scanCeiling(meter, maximum) {
|
|
837
|
+
return meter === void 0 ? {} : { maxAggregateBytes: Math.min(maximum, meter.remaining()) };
|
|
264
838
|
}
|
|
265
839
|
function createFleetAuthority(input) {
|
|
266
840
|
const profile = pinProfile(input);
|
|
@@ -268,6 +842,8 @@ function createFleetAuthority(input) {
|
|
|
268
842
|
const readState = { active: 0 };
|
|
269
843
|
const seeds = pinReaders(profile.seeds, profile);
|
|
270
844
|
let activeCalls = 0;
|
|
845
|
+
const historyDepth = Math.min(2147483647, Math.max(profile.evidence.limits.maxDecodedDepth, profile.resolutionLimits.maxDepth) + 8);
|
|
846
|
+
const history = profile.verifiedHistory === void 0 ? void 0 : new VerifiedFleetHistory(profile.verifiedHistory, historyDepth);
|
|
271
847
|
async function resolved(root, family, work) {
|
|
272
848
|
work.control.assertActive();
|
|
273
849
|
const cached = work.roots.get(root);
|
|
@@ -294,23 +870,31 @@ function createFleetAuthority(input) {
|
|
|
294
870
|
if (family !== FleetControlSchema) work.declarations.set(root, Object.freeze({ root, payload: result.payload }));
|
|
295
871
|
return result.payload;
|
|
296
872
|
}
|
|
297
|
-
async function scan(request,
|
|
873
|
+
async function scan(request, work, fromBlockNumber = 0) {
|
|
874
|
+
const { control, meter } = work;
|
|
298
875
|
if (request.anchor.blockNumber + 1 > profile.limits.maxBlocks) throw new FleetAuthorityError("resource-limit", "history-blocks");
|
|
299
876
|
const occurrences = [];
|
|
300
|
-
let
|
|
301
|
-
for (let from = 0; from <= request.anchor.blockNumber; ) {
|
|
877
|
+
for (let from = fromBlockNumber; from <= request.anchor.blockNumber; ) {
|
|
302
878
|
control.assertActive();
|
|
303
|
-
if (++pages > profile.limits.maxPages) throw new FleetAuthorityError("resource-limit", "scan-pages");
|
|
879
|
+
if (++work.pages.count > profile.limits.maxPages) throw new FleetAuthorityError("resource-limit", "scan-pages");
|
|
304
880
|
const to = Math.min(request.anchor.blockNumber, from + profile.evidence.limits.maxBlocks - 1);
|
|
881
|
+
const scope = Object.freeze({
|
|
882
|
+
authorizers: Object.freeze([request.owner]),
|
|
883
|
+
schemas: b4Families,
|
|
884
|
+
...profile.evidence.forkLineage !== void 0 && { chainIds: Object.freeze([profile.evidence.chainId]) }
|
|
885
|
+
});
|
|
305
886
|
const page = await evidence.scanScoped({
|
|
306
887
|
anchor: request.anchor,
|
|
307
888
|
fromBlockNumber: from,
|
|
308
889
|
toBlockNumber: to,
|
|
309
890
|
signal: control.signal,
|
|
310
|
-
|
|
891
|
+
...scanCeiling(meter, profile.evidence.limits.maxAggregateBytes),
|
|
892
|
+
scope
|
|
311
893
|
});
|
|
894
|
+
chargeNativeResources(meter, page.resources);
|
|
312
895
|
control.assertActive();
|
|
313
|
-
|
|
896
|
+
const basis = validateFleetPage(page, profile, request, from, to, scope);
|
|
897
|
+
if (basis !== void 0) work.queryBasis.scopeCompleteness = basis;
|
|
314
898
|
for (const fact of page.occurrences) {
|
|
315
899
|
const previous = occurrences.at(-1);
|
|
316
900
|
if (fact.network !== profile.evidence.network || fact.chainId !== profile.evidence.chainId || fact.genesisRoot !== profile.evidence.genesisRoot || fact.signer !== request.owner || !b4Families.includes(fact.schema) || fact.blockNumber < from || fact.blockNumber > to || previous !== void 0 && !positionAfter(fact, previous)) throw new FleetAuthorityError("conflict", "occurrence-binding-order");
|
|
@@ -367,8 +951,7 @@ function createFleetAuthority(input) {
|
|
|
367
951
|
if (roots.size > profile.limits.maxFleets) throw new FleetAuthorityError("resource-limit", "fleets");
|
|
368
952
|
return { roots, controls };
|
|
369
953
|
}
|
|
370
|
-
async function
|
|
371
|
-
const occurrences = await scan(request, work.control);
|
|
954
|
+
async function foldWork(request, work, occurrences) {
|
|
372
955
|
const { roots, controls } = await collect(request, work, occurrences);
|
|
373
956
|
const views = [];
|
|
374
957
|
for (const root of roots) {
|
|
@@ -405,7 +988,10 @@ function createFleetAuthority(input) {
|
|
|
405
988
|
assurance: "source-trusted-finalized-replay"
|
|
406
989
|
}));
|
|
407
990
|
}
|
|
408
|
-
|
|
991
|
+
const basis = work.queryBasis.scopeCompleteness;
|
|
992
|
+
if (profile.evidence.querySelection === void 0 !== (basis === void 0)) throw new FleetAuthorityError("conflict", "history-query-basis");
|
|
993
|
+
const result = Object.freeze({
|
|
994
|
+
...basis !== void 0 && { scopeCompleteness: basis },
|
|
409
995
|
...context(profile, request),
|
|
410
996
|
status: "complete",
|
|
411
997
|
correspondence: "native-sdk-verified",
|
|
@@ -413,44 +999,112 @@ function createFleetAuthority(input) {
|
|
|
413
999
|
coveredRange: Object.freeze({ fromBlockNumber: 0, toBlockNumber: request.anchor.blockNumber }),
|
|
414
1000
|
views: Object.freeze(views)
|
|
415
1001
|
});
|
|
1002
|
+
return { result, controls };
|
|
1003
|
+
}
|
|
1004
|
+
function restore(entry, work) {
|
|
1005
|
+
const expected = profile.evidence.querySelection === void 0 ? void 0 : "verified-block-committed-query-selection";
|
|
1006
|
+
if (entry.scopeCompleteness !== expected) throw new FleetAuthorityError("conflict", "history-query-policy");
|
|
1007
|
+
if (entry.scopeCompleteness !== void 0) work.queryBasis.scopeCompleteness = entry.scopeCompleteness;
|
|
1008
|
+
for (const [root, payload] of entry.roots) {
|
|
1009
|
+
if (!work.roots.has(root) && work.roots.size >= profile.limits.maxRootReads) throw new FleetAuthorityError("resource-limit", "root-reads");
|
|
1010
|
+
work.roots.set(root, payload);
|
|
1011
|
+
if (payload.schema !== FleetControlSchema) work.declarations.set(root, Object.freeze({ root, payload }));
|
|
1012
|
+
}
|
|
1013
|
+
}
|
|
1014
|
+
async function replayWork(request, work) {
|
|
1015
|
+
const prior = history?.get(request.owner);
|
|
1016
|
+
let occurrences;
|
|
1017
|
+
if (prior === void 0) occurrences = await scan(request, work);
|
|
1018
|
+
else {
|
|
1019
|
+
restore(prior, work);
|
|
1020
|
+
const sameHeight = request.anchor.blockNumber === prior.anchor.blockNumber;
|
|
1021
|
+
if (sameHeight && request.anchor.blockRoot !== prior.anchor.blockRoot) throw new FleetAuthorityError("conflict", "history-anchor");
|
|
1022
|
+
if (sameHeight) occurrences = prior.occurrences;
|
|
1023
|
+
else if (request.anchor.blockNumber < prior.anchor.blockNumber) {
|
|
1024
|
+
await scan(request, work, request.anchor.blockNumber);
|
|
1025
|
+
occurrences = prior.occurrences.filter((fact) => fact.blockNumber <= request.anchor.blockNumber);
|
|
1026
|
+
} else {
|
|
1027
|
+
await scan({ ...request, anchor: prior.anchor }, work, prior.anchor.blockNumber);
|
|
1028
|
+
occurrences = [...prior.occurrences, ...await scan(request, work, prior.anchor.blockNumber + 1)];
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
if (occurrences.length > profile.limits.maxOccurrences) throw new FleetAuthorityError("resource-limit", "occurrences");
|
|
1032
|
+
if (history !== void 0 && (prior === void 0 || request.anchor.blockNumber > prior.anchor.blockNumber)) {
|
|
1033
|
+
const completeRequest = {
|
|
1034
|
+
...request,
|
|
1035
|
+
fleetRoot: void 0,
|
|
1036
|
+
publicationBlock: request.anchor.blockNumber + 1
|
|
1037
|
+
};
|
|
1038
|
+
const complete = await foldWork(completeRequest, work, occurrences);
|
|
1039
|
+
work.control.assertActive();
|
|
1040
|
+
history.publish({
|
|
1041
|
+
owner: request.owner,
|
|
1042
|
+
anchor: request.anchor,
|
|
1043
|
+
occurrences,
|
|
1044
|
+
roots: work.roots.entries().toArray(),
|
|
1045
|
+
...complete.result.scopeCompleteness !== void 0 && { scopeCompleteness: complete.result.scopeCompleteness }
|
|
1046
|
+
});
|
|
1047
|
+
if (request.fleetRoot === void 0 && request.publicationBlock === completeRequest.publicationBlock) return complete;
|
|
1048
|
+
}
|
|
1049
|
+
return await foldWork(request, work, occurrences);
|
|
1050
|
+
}
|
|
1051
|
+
async function enumerateWork(request, work) {
|
|
1052
|
+
const replay = await replayWork(request, work);
|
|
1053
|
+
return replay.result;
|
|
416
1054
|
}
|
|
417
1055
|
async function execute(request, startedAt, operation) {
|
|
418
1056
|
const control = operationControl(request.signal, profile.limits.totalTimeoutMs, startedAt);
|
|
419
1057
|
let admitted = false;
|
|
1058
|
+
let meter;
|
|
420
1059
|
try {
|
|
1060
|
+
const bound = BigInt(profile.limits.maxPages) * BigInt(profile.evidence.limits.maxAggregateBytes) + BigInt(profile.limits.maxRootReads) * BigInt(profile.resolutionLimits.maxSeeds) * BigInt(profile.resolutionLimits.maxBodyBytes);
|
|
1061
|
+
if (request.maxAggregateBytes !== void 0 || profile.evidence.verifiedPrefix !== void 0) {
|
|
1062
|
+
meter = new FleetMeter(request.maxAggregateBytes ?? Number(bound > BigInt(Number.MAX_SAFE_INTEGER) ? BigInt(Number.MAX_SAFE_INTEGER) : bound), profile.resolutionLimits);
|
|
1063
|
+
}
|
|
1064
|
+
if (request.maxAggregateBytes !== void 0 && BigInt(request.maxAggregateBytes) > bound) throw new FleetAuthorityError("resource-limit", "aggregate-ceiling");
|
|
421
1065
|
control.assertActive();
|
|
422
1066
|
if (activeCalls >= profile.limits.maxConcurrentCalls) throw new FleetAuthorityError("resource-limit", "composition-capacity");
|
|
423
1067
|
activeCalls++;
|
|
424
1068
|
admitted = true;
|
|
425
1069
|
const capacity = { limited: false };
|
|
426
|
-
|
|
1070
|
+
const result = await operation({
|
|
427
1071
|
control,
|
|
1072
|
+
...meter !== void 0 && { meter },
|
|
428
1073
|
roots: /* @__PURE__ */ new Map(),
|
|
1074
|
+
pages: { count: 0 },
|
|
1075
|
+
queryBasis: {},
|
|
429
1076
|
declarations: /* @__PURE__ */ new Map(),
|
|
430
1077
|
capacity,
|
|
431
|
-
seeds: capacityReaders(seeds, readState, profile.limits.maxConcurrentReads, capacity)
|
|
1078
|
+
seeds: capacityReaders(seeds, readState, profile.limits.maxConcurrentReads, capacity, meter)
|
|
432
1079
|
});
|
|
1080
|
+
return meter === void 0 ? result : Object.freeze({ ...result, resources: meter.resources() });
|
|
433
1081
|
} catch (error) {
|
|
434
1082
|
const failure = error instanceof FleetAuthorityError ? error : new FleetAuthorityError("incomplete", "composition-source");
|
|
435
1083
|
return Object.freeze({
|
|
436
1084
|
...context(profile, request),
|
|
437
1085
|
status: failure.status,
|
|
438
|
-
code: failure.code
|
|
1086
|
+
code: failure.code,
|
|
1087
|
+
...meter !== void 0 && { resources: meter.resources() }
|
|
439
1088
|
});
|
|
440
1089
|
} finally {
|
|
441
1090
|
if (admitted) activeCalls--;
|
|
1091
|
+
meter?.close();
|
|
442
1092
|
control.dispose();
|
|
443
1093
|
}
|
|
444
1094
|
}
|
|
445
1095
|
async function publisherWork(request, scopeRoot, publisherAddress, work) {
|
|
1096
|
+
const retained = history?.get(request.owner);
|
|
1097
|
+
if (retained !== void 0) restore(retained, work);
|
|
446
1098
|
const scope = FleetPublicationScopeZod.parse(await resolved(scopeRoot, FleetPublicationScopeSchema, work));
|
|
447
1099
|
const result = await enumerateWork({ ...request, fleetRoot: scope.fleetRoot }, work);
|
|
1100
|
+
const basis = result.scopeCompleteness === void 0 ? {} : { scopeCompleteness: result.scopeCompleteness };
|
|
448
1101
|
const view = result.views[0];
|
|
449
1102
|
const matches = view?.fleetActive ? view.grants.filter((grant2) => grant2.scopeRoot === scopeRoot && grant2.publisherAddress === publisherAddress) : [];
|
|
450
1103
|
if (matches.length > 1) throw new FleetAuthorityError("conflict", "publisher-ambiguity");
|
|
451
1104
|
const grant = matches[0];
|
|
452
1105
|
return grant === void 0 ? Object.freeze({
|
|
453
1106
|
...context(profile, request),
|
|
1107
|
+
...basis,
|
|
454
1108
|
status: "absent",
|
|
455
1109
|
correspondence: "native-sdk-verified",
|
|
456
1110
|
history: "complete-genesis-to-anchor",
|
|
@@ -458,6 +1112,7 @@ function createFleetAuthority(input) {
|
|
|
458
1112
|
publisherAddress
|
|
459
1113
|
}) : Object.freeze({
|
|
460
1114
|
...context(profile, request),
|
|
1115
|
+
...basis,
|
|
461
1116
|
status: "authorized",
|
|
462
1117
|
correspondence: "native-sdk-verified",
|
|
463
1118
|
history: "complete-genesis-to-anchor",
|
|
@@ -474,30 +1129,49 @@ function createFleetAuthority(input) {
|
|
|
474
1129
|
const request = pinRequest(inputRequest);
|
|
475
1130
|
return await execute(request, startedAt, (work) => enumerateWork(request, work));
|
|
476
1131
|
},
|
|
1132
|
+
async enumerateHistoricalPublishers(inputRequest) {
|
|
1133
|
+
const startedAt = fleetNow();
|
|
1134
|
+
const values = ownRecord(inputRequest, ["anchor", "owner"], ["fleetRoot", "signal", "maxAggregateBytes"]);
|
|
1135
|
+
const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
|
|
1136
|
+
const request = pinRequest({
|
|
1137
|
+
...values,
|
|
1138
|
+
anchor,
|
|
1139
|
+
publicationBlock: anchor.blockNumber + 1
|
|
1140
|
+
}, true);
|
|
1141
|
+
let controls = [];
|
|
1142
|
+
const result = await execute(request, startedAt, async (work) => {
|
|
1143
|
+
const replay = await replayWork(request, work);
|
|
1144
|
+
controls = replay.controls;
|
|
1145
|
+
return replay.result;
|
|
1146
|
+
});
|
|
1147
|
+
return historicalPublisherResult(result, controls, request.fleetRoot);
|
|
1148
|
+
},
|
|
477
1149
|
async resolvePublisher(inputRequest) {
|
|
478
1150
|
const startedAt = fleetNow();
|
|
479
|
-
const values = ownRecord(inputRequest, ["anchor", "owner", "publicationBlock", "publisherAddress", "scopeRoot"], ["signal"]);
|
|
480
|
-
const publisherAddress =
|
|
481
|
-
const scopeRoot =
|
|
1151
|
+
const values = ownRecord(inputRequest, ["anchor", "owner", "publicationBlock", "publisherAddress", "scopeRoot"], ["signal", "maxAggregateBytes"]);
|
|
1152
|
+
const publisherAddress = AddressZod4.parse(values.publisherAddress);
|
|
1153
|
+
const scopeRoot = HashZod5.parse(values.scopeRoot);
|
|
482
1154
|
const request = pinRequest({
|
|
483
1155
|
anchor: values.anchor,
|
|
484
1156
|
owner: values.owner,
|
|
485
1157
|
publicationBlock: values.publicationBlock,
|
|
486
|
-
...values.signal !== void 0 && { signal: values.signal }
|
|
1158
|
+
...values.signal !== void 0 && { signal: values.signal },
|
|
1159
|
+
...values.maxAggregateBytes !== void 0 && { maxAggregateBytes: values.maxAggregateBytes }
|
|
487
1160
|
});
|
|
488
1161
|
return await execute(request, startedAt, (work) => publisherWork(request, scopeRoot, publisherAddress, work));
|
|
489
1162
|
},
|
|
490
1163
|
async projectNextPublisher(inputRequest) {
|
|
491
1164
|
const startedAt = fleetNow();
|
|
492
|
-
const values = ownRecord(inputRequest, ["anchor", "owner", "publisherAddress", "scopeRoot"], ["signal"]);
|
|
1165
|
+
const values = ownRecord(inputRequest, ["anchor", "owner", "publisherAddress", "scopeRoot"], ["signal", "maxAggregateBytes"]);
|
|
493
1166
|
const anchor = ownRecord(values.anchor, ["blockNumber", "blockRoot"]);
|
|
494
|
-
const publisherAddress =
|
|
495
|
-
const scopeRoot =
|
|
1167
|
+
const publisherAddress = AddressZod4.parse(values.publisherAddress);
|
|
1168
|
+
const scopeRoot = HashZod5.parse(values.scopeRoot);
|
|
496
1169
|
const request = pinRequest({
|
|
497
1170
|
anchor,
|
|
498
1171
|
owner: values.owner,
|
|
499
1172
|
publicationBlock: anchor.blockNumber + 1,
|
|
500
|
-
...values.signal !== void 0 && { signal: values.signal }
|
|
1173
|
+
...values.signal !== void 0 && { signal: values.signal },
|
|
1174
|
+
...values.maxAggregateBytes !== void 0 && { maxAggregateBytes: values.maxAggregateBytes }
|
|
501
1175
|
}, true);
|
|
502
1176
|
const result = await execute(request, startedAt, (work) => publisherWork(request, scopeRoot, publisherAddress, work));
|
|
503
1177
|
return nextPublisherProjection(result);
|
|
@@ -559,18 +1233,18 @@ function endpointPolicy(value) {
|
|
|
559
1233
|
return value;
|
|
560
1234
|
}
|
|
561
1235
|
function parsedEndpoint(value, policyValue) {
|
|
562
|
-
const
|
|
1236
|
+
const text2 = endpointText(value);
|
|
563
1237
|
const policy = endpointPolicy(policyValue);
|
|
564
1238
|
let parsed;
|
|
565
1239
|
try {
|
|
566
|
-
parsed = new URL(
|
|
1240
|
+
parsed = new URL(text2);
|
|
567
1241
|
} catch {
|
|
568
1242
|
throw new TypeError("endpoint must be an unambiguous absolute HTTP(S) URL");
|
|
569
1243
|
}
|
|
570
1244
|
if (parsed.protocol !== "http:" && parsed.protocol !== "https:" || parsed.hostname === "" || parsed.username !== "" || parsed.password !== "") {
|
|
571
1245
|
throw new TypeError("endpoint must be an unambiguous absolute HTTP(S) URL");
|
|
572
1246
|
}
|
|
573
|
-
const inputWithoutTrailingSlashes =
|
|
1247
|
+
const inputWithoutTrailingSlashes = text2.replace(/\/+$/u, "");
|
|
574
1248
|
const parsedWithoutTrailingSlashes = parsed.href.replace(/\/+$/u, "");
|
|
575
1249
|
if (parsedWithoutTrailingSlashes !== inputWithoutTrailingSlashes) {
|
|
576
1250
|
throw new TypeError("endpoint must not require URL normalization");
|
|
@@ -642,6 +1316,9 @@ async function createXl1DataLakeSeed(options) {
|
|
|
642
1316
|
}
|
|
643
1317
|
export {
|
|
644
1318
|
createFleetAuthority,
|
|
645
|
-
createXl1DataLakeSeed
|
|
1319
|
+
createXl1DataLakeSeed,
|
|
1320
|
+
snapshotFleetQuerySelection,
|
|
1321
|
+
snapshotFleetSelectedPayloadSource,
|
|
1322
|
+
snapshotFleetVerifiedHistory
|
|
646
1323
|
};
|
|
647
1324
|
//# sourceMappingURL=index.mjs.map
|