@typeberry/lib 0.5.10-ca4935b → 0.5.10-ec38e0b
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/package.json +1 -1
- package/packages/jam/block/work-package.d.ts +7 -7
- package/packages/jam/block/work-package.d.ts.map +1 -1
- package/packages/jam/block/work-package.js +12 -12
- package/packages/jam/executor/pvm-executor.d.ts +7 -0
- package/packages/jam/executor/pvm-executor.d.ts.map +1 -1
- package/packages/jam/executor/pvm-executor.js +15 -0
- package/packages/jam/in-core/externalities/refine.d.ts +2 -2
- package/packages/jam/in-core/externalities/refine.d.ts.map +1 -1
- package/packages/jam/in-core/externalities/refine.js +10 -3
- package/packages/jam/in-core/externalities/refine.test.js +53 -0
- package/packages/jam/in-core/in-core.d.ts +7 -22
- package/packages/jam/in-core/in-core.d.ts.map +1 -1
- package/packages/jam/in-core/in-core.js +16 -184
- package/packages/jam/in-core/in-core.test.js +47 -15
- package/packages/jam/in-core/is-authorized.d.ts +33 -0
- package/packages/jam/in-core/is-authorized.d.ts.map +1 -0
- package/packages/jam/in-core/is-authorized.js +72 -0
- package/packages/jam/in-core/is-authorized.test.d.ts +2 -0
- package/packages/jam/in-core/is-authorized.test.d.ts.map +1 -0
- package/packages/jam/in-core/is-authorized.test.js +125 -0
- package/packages/jam/in-core/refine.d.ts +34 -0
- package/packages/jam/in-core/refine.d.ts.map +1 -0
- package/packages/jam/in-core/refine.js +176 -0
- package/packages/jam/in-core/refine.test.d.ts +2 -0
- package/packages/jam/in-core/refine.test.d.ts.map +1 -0
- package/packages/jam/in-core/refine.test.js +6 -0
- package/packages/jam/jam-host-calls/accumulate/bless.js +9 -9
- package/packages/jam/jam-host-calls/externalities/partial-state.d.ts +1 -1
- package/packages/jam/jam-host-calls/externalities/refine-externalities.d.ts +1 -1
- package/packages/jam/jam-host-calls/externalities/refine-externalities.d.ts.map +1 -1
- package/packages/jam/jam-host-calls/general/fetch.d.ts +40 -40
- package/packages/jam/jam-host-calls/general/fetch.d.ts.map +1 -1
- package/packages/jam/jam-host-calls/general/fetch.js +30 -30
- package/packages/jam/jam-host-calls/general/fetch.test.js +17 -14
- package/packages/jam/jamnp-s/protocol/ce-133-work-package-submission.d.ts +2 -2
- package/packages/jam/transition/accumulate/accumulation-result-merge-utils.js +48 -39
- package/packages/jam/transition/externalities/accumulate-externalities.d.ts +2 -2
- package/packages/jam/transition/externalities/accumulate-externalities.d.ts.map +1 -1
- package/packages/jam/transition/externalities/accumulate-externalities.js +20 -7
- package/packages/jam/transition/externalities/accumulate-externalities.test.js +74 -4
- package/packages/jam/transition/externalities/index.d.ts +1 -0
- package/packages/jam/transition/externalities/index.d.ts.map +1 -1
- package/packages/jam/transition/externalities/index.js +1 -0
- package/packages/jam/transition/externalities/is-authorized-fetch-externalities.d.ts +22 -0
- package/packages/jam/transition/externalities/is-authorized-fetch-externalities.d.ts.map +1 -0
- package/packages/jam/transition/externalities/is-authorized-fetch-externalities.js +41 -0
- package/packages/jam/transition/externalities/refine-fetch-externalities.d.ts +7 -7
- package/packages/jam/transition/externalities/refine-fetch-externalities.d.ts.map +1 -1
- package/packages/jam/transition/externalities/refine-fetch-externalities.js +17 -9
|
@@ -14,7 +14,7 @@ import { HostCallResult } from "./results.js";
|
|
|
14
14
|
* Ω_Y signature: Ω_Y(ρ, φ, μ, p, n, r, i, ī, x̄, 𝐢, ...)
|
|
15
15
|
*
|
|
16
16
|
* Context parameter mapping
|
|
17
|
-
*
|
|
17
|
+
* IsAuthorized: Ω_Y(ρ, φ, μ, 𝐩, ∅, ∅, ∅, ∅, ∅, ∅, ∅)
|
|
18
18
|
* https://graypaper.fluffylabs.dev/#/ab2cdbd/2e43012e4301?v=0.7.2
|
|
19
19
|
* Refine: Ω_Y(ρ, φ, μ, p, H₀, r, i, ī, x̄, ∅, (m,e))
|
|
20
20
|
* https://graypaper.fluffylabs.dev/#/ab2cdbd/2fe0012fe001?v=0.7.2
|
|
@@ -22,13 +22,13 @@ import { HostCallResult } from "./results.js";
|
|
|
22
22
|
* https://graypaper.fluffylabs.dev/#/ab2cdbd/30c00030c000?v=0.7.2
|
|
23
23
|
*
|
|
24
24
|
* Kind availability per context:
|
|
25
|
-
* Kind 0 (constants)
|
|
26
|
-
* Kind 1 (n)
|
|
27
|
-
* Kind 2 (r)
|
|
28
|
-
* Kind 3-4 (x̄ extrinsics)
|
|
29
|
-
* Kind 5-6 (ī imports)
|
|
30
|
-
* Kind 7-13 (p work pkg)
|
|
31
|
-
* Kind 14-15 (𝐢 acc items)
|
|
25
|
+
* Kind 0 (constants) - all contexts
|
|
26
|
+
* Kind 1 (n) - Refine (H₀), Accumulate (η'₀)
|
|
27
|
+
* Kind 2 (r) - Refine only
|
|
28
|
+
* Kind 3-4 (x̄ extrinsics) - Refine only
|
|
29
|
+
* Kind 5-6 (ī imports) - Refine only
|
|
30
|
+
* Kind 7-13 (p work pkg) - IsAuthorized, Refine
|
|
31
|
+
* Kind 14-15 (𝐢 acc items) - Accumulate only
|
|
32
32
|
*/
|
|
33
33
|
export var FetchContext;
|
|
34
34
|
(function (FetchContext) {
|
|
@@ -76,25 +76,25 @@ export class Fetch {
|
|
|
76
76
|
}
|
|
77
77
|
getValue(kind, regs) {
|
|
78
78
|
const ext = this.fetch;
|
|
79
|
-
// Kind 0: constants
|
|
79
|
+
// Kind 0: constants - all contexts
|
|
80
80
|
if (kind === FetchKind.Constants) {
|
|
81
81
|
return ext.constants();
|
|
82
82
|
}
|
|
83
|
-
// Kind 1: entropy
|
|
83
|
+
// Kind 1: entropy - Refine, Accumulate
|
|
84
84
|
if (kind === FetchKind.Entropy) {
|
|
85
85
|
if (ext.context === FetchContext.IsAuthorized) {
|
|
86
86
|
return null;
|
|
87
87
|
}
|
|
88
88
|
return ext.entropy();
|
|
89
89
|
}
|
|
90
|
-
// Kind 2: authorizer trace
|
|
90
|
+
// Kind 2: authorizer trace - Refine only
|
|
91
91
|
if (kind === FetchKind.AuthorizerTrace) {
|
|
92
92
|
if (ext.context !== FetchContext.Refine) {
|
|
93
93
|
return null;
|
|
94
94
|
}
|
|
95
95
|
return ext.authorizerTrace();
|
|
96
96
|
}
|
|
97
|
-
// Kind 3: other work item extrinsics
|
|
97
|
+
// Kind 3: other work item extrinsics - Refine only
|
|
98
98
|
if (kind === FetchKind.OtherWorkItemExtrinsics) {
|
|
99
99
|
if (ext.context !== FetchContext.Refine) {
|
|
100
100
|
return null;
|
|
@@ -103,7 +103,7 @@ export class Fetch {
|
|
|
103
103
|
const index = regs.get(12);
|
|
104
104
|
return ext.workItemExtrinsic(workItem, index);
|
|
105
105
|
}
|
|
106
|
-
// Kind 4: my extrinsics
|
|
106
|
+
// Kind 4: my extrinsics - Refine only
|
|
107
107
|
if (kind === FetchKind.MyExtrinsics) {
|
|
108
108
|
if (ext.context !== FetchContext.Refine) {
|
|
109
109
|
return null;
|
|
@@ -111,7 +111,7 @@ export class Fetch {
|
|
|
111
111
|
const index = regs.get(11);
|
|
112
112
|
return ext.workItemExtrinsic(null, index);
|
|
113
113
|
}
|
|
114
|
-
// Kind 5: other work item imports
|
|
114
|
+
// Kind 5: other work item imports - Refine only
|
|
115
115
|
if (kind === FetchKind.OtherWorkItemImports) {
|
|
116
116
|
if (ext.context !== FetchContext.Refine) {
|
|
117
117
|
return null;
|
|
@@ -120,7 +120,7 @@ export class Fetch {
|
|
|
120
120
|
const index = regs.get(12);
|
|
121
121
|
return ext.workItemImport(workItem, index);
|
|
122
122
|
}
|
|
123
|
-
// Kind 6: my imports
|
|
123
|
+
// Kind 6: my imports - Refine only
|
|
124
124
|
if (kind === FetchKind.MyImports) {
|
|
125
125
|
if (ext.context !== FetchContext.Refine) {
|
|
126
126
|
return null;
|
|
@@ -128,42 +128,42 @@ export class Fetch {
|
|
|
128
128
|
const index = regs.get(11);
|
|
129
129
|
return ext.workItemImport(null, index);
|
|
130
130
|
}
|
|
131
|
-
// Kind 7: work package
|
|
131
|
+
// Kind 7: work package - IsAuthorized, Refine
|
|
132
132
|
if (kind === FetchKind.WorkPackage) {
|
|
133
133
|
if (ext.context === FetchContext.Accumulate) {
|
|
134
134
|
return null;
|
|
135
135
|
}
|
|
136
136
|
return ext.workPackage();
|
|
137
137
|
}
|
|
138
|
-
// Kind 8:
|
|
139
|
-
if (kind === FetchKind.
|
|
138
|
+
// Kind 8: auth configuration - IsAuthorized, Refine
|
|
139
|
+
if (kind === FetchKind.AuthConfiguration) {
|
|
140
140
|
if (ext.context === FetchContext.Accumulate) {
|
|
141
141
|
return null;
|
|
142
142
|
}
|
|
143
|
-
return ext.
|
|
143
|
+
return ext.authConfiguration();
|
|
144
144
|
}
|
|
145
|
-
// Kind 9: authorization token
|
|
146
|
-
if (kind === FetchKind.
|
|
145
|
+
// Kind 9: authorization token - IsAuthorized, Refine
|
|
146
|
+
if (kind === FetchKind.AuthToken) {
|
|
147
147
|
if (ext.context === FetchContext.Accumulate) {
|
|
148
148
|
return null;
|
|
149
149
|
}
|
|
150
|
-
return ext.
|
|
150
|
+
return ext.authToken();
|
|
151
151
|
}
|
|
152
|
-
// Kind 10: refine context
|
|
152
|
+
// Kind 10: refine context - IsAuthorized, Refine
|
|
153
153
|
if (kind === FetchKind.RefineContext) {
|
|
154
154
|
if (ext.context === FetchContext.Accumulate) {
|
|
155
155
|
return null;
|
|
156
156
|
}
|
|
157
157
|
return ext.refineContext();
|
|
158
158
|
}
|
|
159
|
-
// Kind 11: all work items
|
|
159
|
+
// Kind 11: all work items - IsAuthorized, Refine
|
|
160
160
|
if (kind === FetchKind.AllWorkItems) {
|
|
161
161
|
if (ext.context === FetchContext.Accumulate) {
|
|
162
162
|
return null;
|
|
163
163
|
}
|
|
164
164
|
return ext.allWorkItems();
|
|
165
165
|
}
|
|
166
|
-
// Kind 12: one work item
|
|
166
|
+
// Kind 12: one work item - IsAuthorized, Refine
|
|
167
167
|
if (kind === FetchKind.OneWorkItem) {
|
|
168
168
|
if (ext.context === FetchContext.Accumulate) {
|
|
169
169
|
return null;
|
|
@@ -171,7 +171,7 @@ export class Fetch {
|
|
|
171
171
|
const workItem = regs.get(11);
|
|
172
172
|
return ext.oneWorkItem(workItem);
|
|
173
173
|
}
|
|
174
|
-
// Kind 13: work item payload
|
|
174
|
+
// Kind 13: work item payload - IsAuthorized, Refine
|
|
175
175
|
if (kind === FetchKind.WorkItemPayload) {
|
|
176
176
|
if (ext.context === FetchContext.Accumulate) {
|
|
177
177
|
return null;
|
|
@@ -179,14 +179,14 @@ export class Fetch {
|
|
|
179
179
|
const workItem = regs.get(11);
|
|
180
180
|
return ext.workItemPayload(workItem);
|
|
181
181
|
}
|
|
182
|
-
// Kind 14: all transfers and operands
|
|
182
|
+
// Kind 14: all transfers and operands - Accumulate only
|
|
183
183
|
if (kind === FetchKind.AllTransfersAndOperands) {
|
|
184
184
|
if (ext.context !== FetchContext.Accumulate) {
|
|
185
185
|
return null;
|
|
186
186
|
}
|
|
187
187
|
return ext.allTransfersAndOperands();
|
|
188
188
|
}
|
|
189
|
-
// Kind 15: one transfer or operand
|
|
189
|
+
// Kind 15: one transfer or operand - Accumulate only
|
|
190
190
|
if (kind === FetchKind.OneTransferOrOperand) {
|
|
191
191
|
if (ext.context !== FetchContext.Accumulate) {
|
|
192
192
|
return null;
|
|
@@ -207,8 +207,8 @@ export var FetchKind;
|
|
|
207
207
|
FetchKind[FetchKind["OtherWorkItemImports"] = 5] = "OtherWorkItemImports";
|
|
208
208
|
FetchKind[FetchKind["MyImports"] = 6] = "MyImports";
|
|
209
209
|
FetchKind[FetchKind["WorkPackage"] = 7] = "WorkPackage";
|
|
210
|
-
FetchKind[FetchKind["
|
|
211
|
-
FetchKind[FetchKind["
|
|
210
|
+
FetchKind[FetchKind["AuthConfiguration"] = 8] = "AuthConfiguration";
|
|
211
|
+
FetchKind[FetchKind["AuthToken"] = 9] = "AuthToken";
|
|
212
212
|
FetchKind[FetchKind["RefineContext"] = 10] = "RefineContext";
|
|
213
213
|
FetchKind[FetchKind["AllWorkItems"] = 11] = "AllWorkItems";
|
|
214
214
|
FetchKind[FetchKind["OneWorkItem"] = 12] = "OneWorkItem";
|
|
@@ -35,9 +35,12 @@ describe("Fetch", () => {
|
|
|
35
35
|
it("should write empty result and set IN_OUT_REG to NONE if fetch returns null", async () => {
|
|
36
36
|
const currentServiceId = tryAsServiceId(10_000);
|
|
37
37
|
const fetchMock = new RefineFetchMock();
|
|
38
|
-
//
|
|
38
|
+
// oneWorkItem returns null when the work item index has no mock response registered
|
|
39
39
|
const blob = BytesBlob.blobFromNumbers([]);
|
|
40
|
-
const { registers, memory, readBack } = prepareRegsAndMemory(blob, FetchKind.
|
|
40
|
+
const { registers, memory, readBack } = prepareRegsAndMemory(blob, FetchKind.OneWorkItem);
|
|
41
|
+
// set work item index to one that has no response → oneWorkItem returns null
|
|
42
|
+
registers.set(11, tryAsU64(999));
|
|
43
|
+
fetchMock.oneWorkItemResponses.set("999", null);
|
|
41
44
|
const fetch = new Fetch(currentServiceId, fetchMock);
|
|
42
45
|
const result = await fetch.execute(gas, registers, memory);
|
|
43
46
|
assert.strictEqual(result, undefined);
|
|
@@ -203,7 +206,7 @@ describe("Fetch", () => {
|
|
|
203
206
|
const blob = BytesBlob.blobFromNumbers([201, 202, 203]);
|
|
204
207
|
const fetchMock = new RefineFetchMock();
|
|
205
208
|
fetchMock.authorizerResponse = blob;
|
|
206
|
-
const { registers, memory, readBack, expectedLength } = prepareRegsAndMemory(blob, FetchKind.
|
|
209
|
+
const { registers, memory, readBack, expectedLength } = prepareRegsAndMemory(blob, FetchKind.AuthConfiguration);
|
|
207
210
|
const fetch = new Fetch(currentServiceId, fetchMock);
|
|
208
211
|
const result = await fetch.execute(gas, registers, memory);
|
|
209
212
|
assert.strictEqual(result, undefined);
|
|
@@ -215,7 +218,7 @@ describe("Fetch", () => {
|
|
|
215
218
|
const blob = BytesBlob.blobFromNumbers([210, 211, 212]);
|
|
216
219
|
const fetchMock = new RefineFetchMock();
|
|
217
220
|
fetchMock.authorizationTokenResponse = blob;
|
|
218
|
-
const { registers, memory, readBack, expectedLength } = prepareRegsAndMemory(blob, FetchKind.
|
|
221
|
+
const { registers, memory, readBack, expectedLength } = prepareRegsAndMemory(blob, FetchKind.AuthToken);
|
|
219
222
|
const fetch = new Fetch(currentServiceId, fetchMock);
|
|
220
223
|
const result = await fetch.execute(gas, registers, memory);
|
|
221
224
|
assert.strictEqual(result, undefined);
|
|
@@ -314,8 +317,8 @@ describe("Fetch", () => {
|
|
|
314
317
|
FetchKind.OtherWorkItemImports,
|
|
315
318
|
FetchKind.MyImports,
|
|
316
319
|
FetchKind.WorkPackage,
|
|
317
|
-
FetchKind.
|
|
318
|
-
FetchKind.
|
|
320
|
+
FetchKind.AuthConfiguration,
|
|
321
|
+
FetchKind.AuthToken,
|
|
319
322
|
FetchKind.RefineContext,
|
|
320
323
|
FetchKind.AllWorkItems,
|
|
321
324
|
FetchKind.OneWorkItem,
|
|
@@ -373,14 +376,14 @@ class RefineFetchMock {
|
|
|
373
376
|
workItemPayloadData = [];
|
|
374
377
|
constantsResponse = null;
|
|
375
378
|
entropyResponse = null;
|
|
376
|
-
authorizerTraceResponse =
|
|
379
|
+
authorizerTraceResponse = BytesBlob.empty();
|
|
377
380
|
workItemExtrinsicResponses = new Map();
|
|
378
381
|
workItemImportResponses = new Map();
|
|
379
|
-
workPackageResponse =
|
|
380
|
-
authorizerResponse =
|
|
381
|
-
authorizationTokenResponse =
|
|
382
|
-
refineContextResponse =
|
|
383
|
-
allWorkItemsResponse =
|
|
382
|
+
workPackageResponse = BytesBlob.empty();
|
|
383
|
+
authorizerResponse = BytesBlob.empty();
|
|
384
|
+
authorizationTokenResponse = BytesBlob.empty();
|
|
385
|
+
refineContextResponse = BytesBlob.empty();
|
|
386
|
+
allWorkItemsResponse = BytesBlob.empty();
|
|
384
387
|
oneWorkItemResponses = new Map();
|
|
385
388
|
workItemPayloadResponses = new Map();
|
|
386
389
|
constants() {
|
|
@@ -417,10 +420,10 @@ class RefineFetchMock {
|
|
|
417
420
|
workPackage() {
|
|
418
421
|
return this.workPackageResponse;
|
|
419
422
|
}
|
|
420
|
-
|
|
423
|
+
authConfiguration() {
|
|
421
424
|
return this.authorizerResponse;
|
|
422
425
|
}
|
|
423
|
-
|
|
426
|
+
authToken() {
|
|
424
427
|
return this.authorizationTokenResponse;
|
|
425
428
|
}
|
|
426
429
|
refineContext() {
|
|
@@ -29,8 +29,8 @@ export declare class CoreWorkPackage extends WithDebug {
|
|
|
29
29
|
lookupAnchorSlot: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"TimeSlot[u32]">, import("@typeberry/bytes").Bytes<4>>;
|
|
30
30
|
prerequisites: import("@typeberry/codec").Descriptor<(import("@typeberry/bytes").Bytes<32> & import("@typeberry/utils").WithOpaque<"WorkPackageHash">)[], import("@typeberry/codec").SequenceView<import("@typeberry/bytes").Bytes<32> & import("@typeberry/utils").WithOpaque<"WorkPackageHash">, import("@typeberry/bytes").Bytes<32>>>;
|
|
31
31
|
}>>;
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
authToken: import("@typeberry/codec").Descriptor<BytesBlob, BytesBlob>;
|
|
33
|
+
authConfiguration: import("@typeberry/codec").Descriptor<BytesBlob, BytesBlob>;
|
|
34
34
|
items: import("@typeberry/codec").Descriptor<import("@typeberry/collections").FixedSizeArray<import("@typeberry/block").WorkItem, import("@typeberry/numbers").U8>, import("@typeberry/codec").SequenceView<import("@typeberry/block").WorkItem, import("@typeberry/codec").ViewOf<import("@typeberry/block").WorkItem, {
|
|
35
35
|
service: import("@typeberry/codec").Descriptor<number & import("@typeberry/numbers").WithBytesRepresentation<4> & import("@typeberry/utils").WithOpaque<"ServiceId[u32]">, import("@typeberry/bytes").Bytes<4>>;
|
|
36
36
|
codeHash: import("@typeberry/codec").Descriptor<import("@typeberry/bytes").Bytes<32> & import("@typeberry/utils").WithOpaque<"CodeHash">, import("@typeberry/bytes").Bytes<32>>;
|
|
@@ -44,47 +44,56 @@ function mergePrivilegedServices(mergeContext, [serviceId, { stateUpdate }]) {
|
|
|
44
44
|
const currentDelegator = currentPrivilegedServices.delegator;
|
|
45
45
|
const currentAssigners = currentPrivilegedServices.assigners;
|
|
46
46
|
const { privilegedServices } = stateUpdate;
|
|
47
|
-
if (privilegedServices
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
let shouldUpdateAssigners = false;
|
|
73
|
-
const newAssigners = currentAssigners.map((currentAssigner, coreIndex) => {
|
|
74
|
-
if (serviceId === currentAssigner) {
|
|
75
|
-
const newAssigner = updatePrivilegedService(currentPrivilegedServices.assigners[coreIndex], privilegedServicesUpdatedByManager.assigners[coreIndex], privilegedServices.assigners[coreIndex]);
|
|
76
|
-
shouldUpdateAssigners = shouldUpdateAssigners || newAssigner !== currentAssigner;
|
|
77
|
-
return newAssigner;
|
|
78
|
-
}
|
|
79
|
-
return currentAssigner;
|
|
47
|
+
if (privilegedServices === null) {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
// initial value (ignore the update, because it might not be authorized)
|
|
51
|
+
if (outputState.privilegedServices === null) {
|
|
52
|
+
outputState.privilegedServices = PrivilegedServices.create({
|
|
53
|
+
...currentPrivilegedServices,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
// manager can override everything and it always takes precedence over
|
|
57
|
+
// everything else
|
|
58
|
+
if (serviceId === currentManager) {
|
|
59
|
+
outputState.privilegedServices = PrivilegedServices.create({
|
|
60
|
+
...privilegedServices,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
// current registrar can transfer out it's permissions, but only if
|
|
64
|
+
// it wasn't overwritten by manager in current run
|
|
65
|
+
if (serviceId === currentRegistrar) {
|
|
66
|
+
const newRegistrar = updatePrivilegedService(currentPrivilegedServices.registrar, privilegedServicesUpdatedByManager.registrar, privilegedServices.registrar);
|
|
67
|
+
outputState.privilegedServices = PrivilegedServices.create({
|
|
68
|
+
...outputState.privilegedServices,
|
|
69
|
+
registrar: newRegistrar,
|
|
80
70
|
});
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
71
|
+
}
|
|
72
|
+
// current delegator can transfer out it's permissions, but only if
|
|
73
|
+
// it wasn't overwritten by manager in current run
|
|
74
|
+
if (serviceId === currentDelegator) {
|
|
75
|
+
const newDelegator = updatePrivilegedService(currentPrivilegedServices.delegator, privilegedServicesUpdatedByManager.delegator, privilegedServices.delegator);
|
|
76
|
+
outputState.privilegedServices = PrivilegedServices.create({
|
|
77
|
+
...outputState.privilegedServices,
|
|
78
|
+
delegator: newDelegator,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
let shouldUpdateAssigners = false;
|
|
82
|
+
// same with assigners - they are free to transfer out their core
|
|
83
|
+
const newAssigners = currentAssigners.map((currentAssigner, coreIndex) => {
|
|
84
|
+
if (serviceId === currentAssigner) {
|
|
85
|
+
const newAssigner = updatePrivilegedService(currentPrivilegedServices.assigners[coreIndex], privilegedServicesUpdatedByManager.assigners[coreIndex], privilegedServices.assigners[coreIndex]);
|
|
86
|
+
shouldUpdateAssigners = shouldUpdateAssigners || newAssigner !== currentAssigner;
|
|
87
|
+
return newAssigner;
|
|
87
88
|
}
|
|
89
|
+
return currentAssigner;
|
|
90
|
+
});
|
|
91
|
+
if (shouldUpdateAssigners) {
|
|
92
|
+
const newAssignersPerCore = tryAsPerCore(newAssigners, chainSpec);
|
|
93
|
+
outputState.privilegedServices = PrivilegedServices.create({
|
|
94
|
+
...outputState.privilegedServices,
|
|
95
|
+
assigners: newAssignersPerCore,
|
|
96
|
+
});
|
|
88
97
|
}
|
|
89
98
|
}
|
|
90
99
|
function mergeValidatorsData(mergeContext, [serviceId, { stateUpdate }]) {
|
|
@@ -2,7 +2,7 @@ import { type CodeHash, type CoreIndex, type PerValidator, type ServiceGas, type
|
|
|
2
2
|
import type { PreimageHash } from "#@typeberry/block/preimage.js";
|
|
3
3
|
import type { AuthorizerHash } from "#@typeberry/block/refine-context.js";
|
|
4
4
|
import { Bytes, type BytesBlob } from "#@typeberry/bytes";
|
|
5
|
-
import type
|
|
5
|
+
import { type FixedSizeArray } from "#@typeberry/collections";
|
|
6
6
|
import type { ChainSpec } from "#@typeberry/config";
|
|
7
7
|
import { type Blake2b, type OpaqueHash } from "#@typeberry/hash";
|
|
8
8
|
import { AccumulationStateUpdate, EjectError, ForgetPreimageError, type general, NewServiceError, type PartiallyUpdatedState, type PartialState, type PreimageStatus, ProvidePreimageError, RequestPreimageError, type TRANSFER_MEMO_BYTES, TransferError, UnprivilegedError, UpdatePrivilegesError } from "#@typeberry/jam-host-calls";
|
|
@@ -64,7 +64,7 @@ export declare class AccumulateExternalities implements PartialState, general.Ac
|
|
|
64
64
|
upgradeService(codeHash: CodeHash, gas: U64, allowance: U64): void;
|
|
65
65
|
updateValidatorsData(validatorsData: PerValidator<ValidatorData>): Result<OK, UnprivilegedError>;
|
|
66
66
|
checkpoint(): void;
|
|
67
|
-
updateAuthorizationQueue(coreIndex: CoreIndex, authQueue: FixedSizeArray<AuthorizerHash, AUTHORIZATION_QUEUE_SIZE>,
|
|
67
|
+
updateAuthorizationQueue(coreIndex: CoreIndex, authQueue: FixedSizeArray<AuthorizerHash, AUTHORIZATION_QUEUE_SIZE>, newAssigner: ServiceId | null): Result<OK, UpdatePrivilegesError>;
|
|
68
68
|
updatePrivilegedServices(manager: ServiceId | null, assigners: PerCore<ServiceId>, delegator: ServiceId | null, registrar: ServiceId | null, autoAccumulateServices: Map<ServiceId, ServiceGas>): Result<OK, UpdatePrivilegesError>;
|
|
69
69
|
yield(hash: OpaqueHash): void;
|
|
70
70
|
providePreimage(serviceId: ServiceId | null, preimage: BytesBlob): Result<OK, ProvidePreimageError>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accumulate-externalities.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/externalities/accumulate-externalities.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,QAAQ,EACb,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,QAAQ,EAId,MAAM,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,EAAE,KAAK,EAAE,KAAK,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"accumulate-externalities.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/externalities/accumulate-externalities.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { tryAsServiceGas, tryAsServiceId, tryAsTimeSlot, } from "#@typeberry/block";
|
|
2
2
|
import { MIN_PUBLIC_SERVICE_INDEX } from "#@typeberry/block/gp-constants.js";
|
|
3
3
|
import { Bytes } from "#@typeberry/bytes";
|
|
4
|
+
import { asKnownSize } from "#@typeberry/collections";
|
|
4
5
|
import { HASH_SIZE } from "#@typeberry/hash";
|
|
5
6
|
import { AccumulationStateUpdate, clampU64ToU32, EjectError, ForgetPreimageError, NewServiceError, PendingTransfer, PreimageStatusKind, ProvidePreimageError, RequestPreimageError, slotsToPreimageStatus, TransferError, UnprivilegedError, UpdatePrivilegesError, writeServiceIdAsLeBytes, } from "#@typeberry/jam-host-calls";
|
|
6
7
|
import { Logger } from "#@typeberry/logger";
|
|
@@ -354,19 +355,31 @@ export class AccumulateExternalities {
|
|
|
354
355
|
/** https://graypaper.fluffylabs.dev/#/9a08063/362202362202?v=0.6.6 */
|
|
355
356
|
this.checkpointedState = AccumulationStateUpdate.copyFrom(this.updatedState.stateUpdate);
|
|
356
357
|
}
|
|
357
|
-
updateAuthorizationQueue(coreIndex, authQueue,
|
|
358
|
+
updateAuthorizationQueue(coreIndex, authQueue, newAssigner) {
|
|
358
359
|
/** https://graypaper.fluffylabs.dev/#/7e6ff6a/36a40136a401?v=0.6.7 */
|
|
359
360
|
// NOTE `coreIndex` is already verified in the HC, so this is infallible.
|
|
360
|
-
const
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
361
|
+
const privilegedServices = this.updatedState.getPrivilegedServices();
|
|
362
|
+
const currentAssigners = privilegedServices.assigners;
|
|
363
|
+
const assigner = currentAssigners[coreIndex];
|
|
364
|
+
if (assigner !== this.currentServiceId) {
|
|
365
|
+
logger.trace `Current service id (${this.currentServiceId}) is not an auth manager of core ${coreIndex} (expected: ${assigner}) and cannot update authorization queue.`;
|
|
366
|
+
return Result.error(UpdatePrivilegesError.UnprivilegedService, () => `Service ${this.currentServiceId} not assigner for core ${coreIndex} (expected: ${assigner})`);
|
|
367
|
+
}
|
|
368
|
+
if (newAssigner === null) {
|
|
366
369
|
logger.trace `The new auth manager is not a valid service id.`;
|
|
367
370
|
return Result.error(UpdatePrivilegesError.InvalidServiceId, () => `New auth manager is null for core ${coreIndex}`);
|
|
368
371
|
}
|
|
372
|
+
// update the authorization queue
|
|
369
373
|
this.updatedState.stateUpdate.authorizationQueues.set(coreIndex, authQueue);
|
|
374
|
+
// move permissions to the new assigner
|
|
375
|
+
const assigners = currentAssigners.slice();
|
|
376
|
+
assigners[coreIndex] = newAssigner;
|
|
377
|
+
this.updatedState.stateUpdate.privilegedServices = PrivilegedServices.create({
|
|
378
|
+
...privilegedServices,
|
|
379
|
+
// since coreindex is validated, we do not alter the size,
|
|
380
|
+
// hence it's safe to convert back
|
|
381
|
+
assigners: asKnownSize(assigners),
|
|
382
|
+
});
|
|
370
383
|
return Result.ok(OK);
|
|
371
384
|
}
|
|
372
385
|
updatePrivilegedServices(manager, assigners, delegator, registrar, autoAccumulateServices) {
|
|
@@ -6,7 +6,7 @@ import { asKnownSize, FixedSizeArray, HashDictionary } from "#@typeberry/collect
|
|
|
6
6
|
import { tinyChainSpec } from "#@typeberry/config";
|
|
7
7
|
import { BANDERSNATCH_KEY_BYTES, BLS_KEY_BYTES, ED25519_KEY_BYTES } from "#@typeberry/crypto";
|
|
8
8
|
import { Blake2b, HASH_SIZE } from "#@typeberry/hash";
|
|
9
|
-
import { EjectError, ForgetPreimageError, NewServiceError, PartiallyUpdatedState, PendingTransfer, PreimageStatusKind, ProvidePreimageError, RequestPreimageError, TRANSFER_MEMO_BYTES, TransferError, UnprivilegedError, UpdatePrivilegesError, writeServiceIdAsLeBytes, } from "#@typeberry/jam-host-calls";
|
|
9
|
+
import { CURRENT_SERVICE_ID, EjectError, ForgetPreimageError, NewServiceError, PartiallyUpdatedState, PendingTransfer, PreimageStatusKind, ProvidePreimageError, RequestPreimageError, TRANSFER_MEMO_BYTES, TransferError, UnprivilegedError, UpdatePrivilegesError, writeServiceIdAsLeBytes, } from "#@typeberry/jam-host-calls";
|
|
10
10
|
import { tryAsU32, tryAsU64 } from "#@typeberry/numbers";
|
|
11
11
|
import { AUTHORIZATION_QUEUE_SIZE, InMemoryService, InMemoryState, LookupHistoryItem, PreimageItem, PrivilegedServices, ServiceAccountInfo, StorageItem, tryAsLookupHistorySlots, tryAsPerCore, UpdatePreimage, UpdateService, VALIDATOR_META_BYTES, ValidatorData, } from "#@typeberry/state";
|
|
12
12
|
import { testState } from "#@typeberry/state/test.utils.js";
|
|
@@ -663,16 +663,28 @@ describe("PartialState.upgradeService", () => {
|
|
|
663
663
|
});
|
|
664
664
|
});
|
|
665
665
|
describe("PartialState.updateAuthorizationQueue", () => {
|
|
666
|
-
it("should update the authorization queue for
|
|
666
|
+
it("should update the authorization queue and transfer the assigner for the given core", () => {
|
|
667
667
|
const state = partiallyUpdatedState();
|
|
668
|
+
const initialPrivileged = state.state.privilegedServices;
|
|
668
669
|
const partialState = new AccumulateExternalities(tinyChainSpec, blake2b, state, tryAsServiceId(0), tryAsServiceId(10), tryAsTimeSlot(16));
|
|
669
670
|
const coreIndex = tryAsCoreIndex(0);
|
|
670
|
-
const
|
|
671
|
+
const newAssigner = tryAsServiceId(99);
|
|
671
672
|
const queue = FixedSizeArray.new(Array.from({ length: AUTHORIZATION_QUEUE_SIZE }, () => Bytes.fill(HASH_SIZE, 0xee).asOpaque()), AUTHORIZATION_QUEUE_SIZE);
|
|
672
673
|
// when
|
|
673
|
-
partialState.updateAuthorizationQueue(coreIndex, queue,
|
|
674
|
+
const result = partialState.updateAuthorizationQueue(coreIndex, queue, newAssigner);
|
|
674
675
|
// then
|
|
676
|
+
deepEqual(result, Result.ok(OK));
|
|
675
677
|
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), queue);
|
|
678
|
+
// the privilegedServices update must be written, with only the targeted
|
|
679
|
+
// core's assigner transferred; all other fields must be preserved.
|
|
680
|
+
const updated = state.stateUpdate.privilegedServices;
|
|
681
|
+
assert.ok(updated !== null, "stateUpdate.privilegedServices should be written");
|
|
682
|
+
assert.strictEqual(updated.assigners[0], newAssigner);
|
|
683
|
+
assert.strictEqual(updated.assigners[1], initialPrivileged.assigners[1]);
|
|
684
|
+
assert.strictEqual(updated.manager, initialPrivileged.manager);
|
|
685
|
+
assert.strictEqual(updated.delegator, initialPrivileged.delegator);
|
|
686
|
+
assert.strictEqual(updated.registrar, initialPrivileged.registrar);
|
|
687
|
+
assert.strictEqual(updated.autoAccumulateServices, initialPrivileged.autoAccumulateServices);
|
|
676
688
|
});
|
|
677
689
|
it("should return InvalidServiceId when given auth manager is invalid", () => {
|
|
678
690
|
const state = partiallyUpdatedState();
|
|
@@ -685,6 +697,8 @@ describe("PartialState.updateAuthorizationQueue", () => {
|
|
|
685
697
|
// then
|
|
686
698
|
deepEqual(result, Result.error(UpdatePrivilegesError.InvalidServiceId, () => "New auth manager is null for core 0"));
|
|
687
699
|
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), undefined);
|
|
700
|
+
// no partial privilegedServices write on error
|
|
701
|
+
assert.strictEqual(state.stateUpdate.privilegedServices, null);
|
|
688
702
|
});
|
|
689
703
|
it("should return UnprivilegedService when current service is not privileged", () => {
|
|
690
704
|
const state = partiallyUpdatedState();
|
|
@@ -701,6 +715,8 @@ describe("PartialState.updateAuthorizationQueue", () => {
|
|
|
701
715
|
// then
|
|
702
716
|
deepEqual(result, Result.error(UpdatePrivilegesError.UnprivilegedService, () => "Service 0 not assigner for core 0 (expected: 1)"));
|
|
703
717
|
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), undefined);
|
|
718
|
+
// no partial privilegedServices write on error
|
|
719
|
+
assert.strictEqual(state.stateUpdate.privilegedServices, null);
|
|
704
720
|
});
|
|
705
721
|
it("should return UnprivilegedService before InvalidServiceId if given auth manager is incorrect, but current servis is also unprivileged", () => {
|
|
706
722
|
const state = partiallyUpdatedState();
|
|
@@ -717,6 +733,60 @@ describe("PartialState.updateAuthorizationQueue", () => {
|
|
|
717
733
|
// then
|
|
718
734
|
deepEqual(result, Result.error(UpdatePrivilegesError.UnprivilegedService, () => "Service 0 not assigner for core 0 (expected: 1)"));
|
|
719
735
|
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), undefined);
|
|
736
|
+
// no partial privilegedServices write on error
|
|
737
|
+
assert.strictEqual(state.stateUpdate.privilegedServices, null);
|
|
738
|
+
});
|
|
739
|
+
it("should succeed on a self-transfer using CURRENT_SERVICE_ID", () => {
|
|
740
|
+
const state = partiallyUpdatedState();
|
|
741
|
+
// inject a service info for CURRENT_SERVICE_ID so it can act as the
|
|
742
|
+
// current (and assigning) service on core 0
|
|
743
|
+
const baseService = state.state.services.get(tryAsServiceId(0));
|
|
744
|
+
if (baseService === undefined) {
|
|
745
|
+
throw new Error("Invalid service!");
|
|
746
|
+
}
|
|
747
|
+
state.state.services.set(CURRENT_SERVICE_ID, new InMemoryService(CURRENT_SERVICE_ID, {
|
|
748
|
+
info: baseService.data.info,
|
|
749
|
+
preimages: HashDictionary.new(),
|
|
750
|
+
lookupHistory: HashDictionary.new(),
|
|
751
|
+
storage: new Map(),
|
|
752
|
+
}));
|
|
753
|
+
state.state.privilegedServices = PrivilegedServices.create({
|
|
754
|
+
...state.state.privilegedServices,
|
|
755
|
+
assigners: asOpaqueType(FixedSizeArray.new([CURRENT_SERVICE_ID, tryAsServiceId(0)], tinyChainSpec.coresCount)),
|
|
756
|
+
});
|
|
757
|
+
const partialState = new AccumulateExternalities(tinyChainSpec, blake2b, state, CURRENT_SERVICE_ID, tryAsServiceId(10), tryAsTimeSlot(16));
|
|
758
|
+
const coreIndex = tryAsCoreIndex(0);
|
|
759
|
+
const queue = FixedSizeArray.new(Array.from({ length: AUTHORIZATION_QUEUE_SIZE }, () => Bytes.fill(HASH_SIZE, 0xee).asOpaque()), AUTHORIZATION_QUEUE_SIZE);
|
|
760
|
+
// when
|
|
761
|
+
const result = partialState.updateAuthorizationQueue(coreIndex, queue, CURRENT_SERVICE_ID);
|
|
762
|
+
// then
|
|
763
|
+
deepEqual(result, Result.ok(OK));
|
|
764
|
+
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), queue);
|
|
765
|
+
const updated = state.stateUpdate.privilegedServices;
|
|
766
|
+
assert.ok(updated !== null, "stateUpdate.privilegedServices should be written");
|
|
767
|
+
assert.strictEqual(updated.assigners[0], CURRENT_SERVICE_ID);
|
|
768
|
+
assert.strictEqual(updated.assigners[1], tryAsServiceId(0));
|
|
769
|
+
});
|
|
770
|
+
it("should prevent the previous assigner from re-assigning after transfer", () => {
|
|
771
|
+
const state = partiallyUpdatedState();
|
|
772
|
+
const partialState = new AccumulateExternalities(tinyChainSpec, blake2b, state, tryAsServiceId(0), tryAsServiceId(10), tryAsTimeSlot(16));
|
|
773
|
+
const coreIndex = tryAsCoreIndex(0);
|
|
774
|
+
const newAssigner = tryAsServiceId(99);
|
|
775
|
+
const firstQueue = FixedSizeArray.new(Array.from({ length: AUTHORIZATION_QUEUE_SIZE }, () => Bytes.fill(HASH_SIZE, 0xee).asOpaque()), AUTHORIZATION_QUEUE_SIZE);
|
|
776
|
+
const secondQueue = FixedSizeArray.new(Array.from({ length: AUTHORIZATION_QUEUE_SIZE }, () => Bytes.fill(HASH_SIZE, 0xff).asOpaque()), AUTHORIZATION_QUEUE_SIZE);
|
|
777
|
+
// when: first call succeeds and transfers the assigner to service 99
|
|
778
|
+
const first = partialState.updateAuthorizationQueue(coreIndex, firstQueue, newAssigner);
|
|
779
|
+
// and the previous assigner (service 0) immediately tries to re-assign
|
|
780
|
+
const second = partialState.updateAuthorizationQueue(coreIndex, secondQueue, tryAsServiceId(0));
|
|
781
|
+
// then
|
|
782
|
+
deepEqual(first, Result.ok(OK));
|
|
783
|
+
deepEqual(second, Result.error(UpdatePrivilegesError.UnprivilegedService, () => "Service 0 not assigner for core 0 (expected: 99)"));
|
|
784
|
+
// the first queue remains — the failing second call must not overwrite it
|
|
785
|
+
assert.deepStrictEqual(state.stateUpdate.authorizationQueues.get(coreIndex), firstQueue);
|
|
786
|
+
// and the transferred assigner is still in place
|
|
787
|
+
const updated = state.stateUpdate.privilegedServices;
|
|
788
|
+
assert.ok(updated !== null);
|
|
789
|
+
assert.strictEqual(updated.assigners[0], newAssigner);
|
|
720
790
|
});
|
|
721
791
|
});
|
|
722
792
|
describe("PartialState.updatePrivilegedServices", () => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from "./accumulate-externalities.js";
|
|
2
2
|
export * from "./accumulate-fetch-externalities.js";
|
|
3
3
|
export * from "./fetch-externalities.js";
|
|
4
|
+
export * from "./is-authorized-fetch-externalities.js";
|
|
4
5
|
export * from "./refine-fetch-externalities.js";
|
|
5
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/externalities/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/externalities/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,qCAAqC,CAAC;AACpD,cAAc,0BAA0B,CAAC;AACzC,cAAc,wCAAwC,CAAC;AACvD,cAAc,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { BytesBlob } from "#@typeberry/bytes";
|
|
2
|
+
import type { ChainSpec } from "#@typeberry/config";
|
|
3
|
+
import { general } from "#@typeberry/jam-host-calls";
|
|
4
|
+
import type { U64 } from "#@typeberry/numbers";
|
|
5
|
+
export declare class IsAuthorizedFetchExternalities implements general.IIsAuthorizedFetch {
|
|
6
|
+
private readonly chainSpec;
|
|
7
|
+
private readonly params;
|
|
8
|
+
readonly context = general.FetchContext.IsAuthorized;
|
|
9
|
+
constructor(chainSpec: ChainSpec, params: {
|
|
10
|
+
authToken: BytesBlob;
|
|
11
|
+
authConfiguration: BytesBlob;
|
|
12
|
+
});
|
|
13
|
+
constants(): BytesBlob;
|
|
14
|
+
workPackage(): BytesBlob;
|
|
15
|
+
authConfiguration(): BytesBlob;
|
|
16
|
+
authToken(): BytesBlob;
|
|
17
|
+
refineContext(): BytesBlob;
|
|
18
|
+
allWorkItems(): BytesBlob;
|
|
19
|
+
oneWorkItem(_workItem: U64): BytesBlob | null;
|
|
20
|
+
workItemPayload(_workItem: U64): BytesBlob | null;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=is-authorized-fetch-externalities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"is-authorized-fetch-externalities.d.ts","sourceRoot":"","sources":["../../../../../../packages/jam/transition/externalities/is-authorized-fetch-externalities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,2BAA2B,CAAC;AACpD,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAG9C,qBAAa,8BAA+B,YAAW,OAAO,CAAC,kBAAkB;IAI7E,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,MAAM;IAJzB,QAAQ,CAAC,OAAO,qCAAqC;gBAGlC,SAAS,EAAE,SAAS,EACpB,MAAM,EAAE;QACvB,SAAS,EAAE,SAAS,CAAC;QACrB,iBAAiB,EAAE,SAAS,CAAC;KAC9B;IAGH,SAAS,IAAI,SAAS;IAKtB,WAAW,IAAI,SAAS;IAIxB,iBAAiB,IAAI,SAAS;IAI9B,SAAS,IAAI,SAAS;IAKtB,aAAa,IAAI,SAAS;IAK1B,YAAY,IAAI,SAAS;IAKzB,WAAW,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,GAAG,IAAI;IAK7C,eAAe,CAAC,SAAS,EAAE,GAAG,GAAG,SAAS,GAAG,IAAI;CAGlD"}
|