@midnight-ntwrk/midnight-js-protocol 5.0.0-beta.7 → 5.0.0-beta.8
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 +201 -2
- package/dist/engine.d.ts +367 -0
- package/dist/engine.js +519 -0
- package/dist/engine.js.map +1 -0
- package/dist/errors.d.ts +467 -0
- package/dist/errors.js +595 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +1278 -2
- package/dist/index.js +787 -2
- package/dist/index.js.map +1 -1
- package/dist/prove.d.ts +38 -0
- package/dist/prove.js +81 -0
- package/dist/prove.js.map +1 -0
- package/dist/shared/deploy-D6yyn9P7.js +428 -0
- package/dist/shared/deploy-D6yyn9P7.js.map +1 -0
- package/dist/shared/load-C0TZnEd2.js +39 -0
- package/dist/shared/load-C0TZnEd2.js.map +1 -0
- package/dist/v8.d.ts +1 -0
- package/dist/v8.js +3 -0
- package/dist/v8.js.map +1 -0
- package/dist/version.d.ts +121 -0
- package/dist/version.js +132 -0
- package/dist/version.js.map +1 -0
- package/package.json +28 -4
package/dist/index.js
CHANGED
|
@@ -1,11 +1,796 @@
|
|
|
1
|
+
import { StateDecodeFailedError, ComposeFailedError, ComposeOptionError, NO_CIRCUIT, DownConvertFailedError, UnknownLedgerVersionError, Ledger8RuntimeInvalidError, Ledger8RuntimeMissingError, Ledger8InstanceMismatchError } from './errors.js';
|
|
2
|
+
export { MerkleNotRehashedError, PROTOCOL_ERROR_CODES, PayloadNotATransactionError, TRANSACTION_TAG_PREFIX, UnknownLedger8AxisError, UnknownProtocolVersionError } from './errors.js';
|
|
3
|
+
import * as ledgerV9 from '@midnightntwrk/ledger-v9';
|
|
4
|
+
import { ContractState } from '@midnightntwrk/ledger-v9';
|
|
5
|
+
export { ledgerV9 as ledger };
|
|
6
|
+
import { b as entryPointName, c as assertComposeEnvelope, a as assembleCallPrototype, d as composeV8DeployTx, r as resolveVerifierKeyRegistrations, p as partitionCallTranscript } from './shared/deploy-D6yyn9P7.js';
|
|
7
|
+
export { I as INITIAL_LEDGER_PARAMETERS } from './shared/deploy-D6yyn9P7.js';
|
|
8
|
+
import { hashVerifierKey } from '@midnight-ntwrk/compact-js';
|
|
1
9
|
import * as compactJs from '@midnight-ntwrk/compact-js';
|
|
2
10
|
export { compactJs };
|
|
11
|
+
import { l as loadLedger8 } from './shared/load-C0TZnEd2.js';
|
|
12
|
+
export { CURRENT_LEDGER_VERSION, LEDGER_VERSIONS, RETAINED_LEDGER_VERSIONS, networkHeadVersion, protocolVersionToLedger, versionOfRecord } from './version.js';
|
|
3
13
|
import * as compactRuntime from '@midnight-ntwrk/compact-runtime';
|
|
4
14
|
export { compactRuntime };
|
|
5
15
|
import * as platformJs from '@midnight-ntwrk/platform-js';
|
|
6
16
|
export { platformJs as platform };
|
|
7
|
-
import * as ledgerV9 from '@midnightntwrk/ledger-v9';
|
|
8
|
-
export { ledgerV9 as ledger };
|
|
9
17
|
import * as onchainRuntimeV4 from '@midnightntwrk/onchain-runtime-v4';
|
|
10
18
|
export { onchainRuntimeV4 as onchainRuntime };
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* This file is part of midnight-js.
|
|
22
|
+
* Copyright (C) Midnight Foundation
|
|
23
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
24
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
25
|
+
* You may not use this file except in compliance with the License.
|
|
26
|
+
* You may obtain a copy of the License at
|
|
27
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
28
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
29
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
30
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
31
|
+
* See the License for the specific language governing permissions and
|
|
32
|
+
* limitations under the License.
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Reads the primary state out of a raw envelope with the given era's extractor,
|
|
36
|
+
* reporting every failure as {@link StateDecodeFailedError} naming `version`.
|
|
37
|
+
*
|
|
38
|
+
* @param raw The serialized contract-state envelope.
|
|
39
|
+
* @param version The era whose extractor is used, and which every failure
|
|
40
|
+
* raised here names.
|
|
41
|
+
* @param extract The era's own envelope extractor.
|
|
42
|
+
* @returns The primary state read out of the envelope.
|
|
43
|
+
* @throws StateDecodeFailedError for every failure, carrying the extractor's
|
|
44
|
+
* own diagnosis on `cause`.
|
|
45
|
+
* @see {@link FailClosedDecoding}
|
|
46
|
+
*/
|
|
47
|
+
const extractStateWith = (raw, version, extract) => {
|
|
48
|
+
try {
|
|
49
|
+
return extract(raw);
|
|
50
|
+
}
|
|
51
|
+
catch (cause) {
|
|
52
|
+
throw new StateDecodeFailedError(version, cause);
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* Reads a raw, serialized contract-state envelope into a
|
|
57
|
+
* {@link ContractStatePojo} using the given era's own `ContractState`.
|
|
58
|
+
*
|
|
59
|
+
* Nothing that crosses back is a live WASM handle: the primary state leaves as
|
|
60
|
+
* an `EncodedStateValue` (plain objects, arrays, `Map`s, `Uint8Array`s and
|
|
61
|
+
* primitives) and each entry point as a plain record.
|
|
62
|
+
*
|
|
63
|
+
* @param raw The serialized contract-state envelope.
|
|
64
|
+
* @param version The era whose decoder is used, and which every failure raised
|
|
65
|
+
* here names.
|
|
66
|
+
* @param ledger The era module slice carrying its own `ContractState`.
|
|
67
|
+
* @returns The state and the entry points it declares, as plain data.
|
|
68
|
+
* @throws StateDecodeFailedError for every failure — the whole read is
|
|
69
|
+
* covered, not just the deserialization — with the decoder's own diagnosis on
|
|
70
|
+
* `cause`.
|
|
71
|
+
* @see {@link FailClosedDecoding}
|
|
72
|
+
* @see {@link EraSeam}
|
|
73
|
+
*/
|
|
74
|
+
const decodeContractStateWith = (raw, version, ledger) => {
|
|
75
|
+
try {
|
|
76
|
+
const decoded = ledger.ContractState.deserialize(raw);
|
|
77
|
+
const entryPoints = decoded.operations().map((entryPoint) => {
|
|
78
|
+
// Deliberately not optional-chained: an unresolvable entry point is an
|
|
79
|
+
// inconsistent state, not a blank slot -- see FailClosedDecoding.
|
|
80
|
+
const operation = decoded.operation(entryPoint);
|
|
81
|
+
if (operation === undefined) {
|
|
82
|
+
throw new Error(`contract state declares entry point '${entryPointName(entryPoint)}' but resolves no operation for it.`);
|
|
83
|
+
}
|
|
84
|
+
const { verifierKey } = operation;
|
|
85
|
+
return {
|
|
86
|
+
circuitId: entryPointName(entryPoint),
|
|
87
|
+
verifierKey,
|
|
88
|
+
verifierKeyHash: verifierKey === undefined ? undefined : hashVerifierKey(verifierKey)
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
return { state: decoded.data.state.encode(), entryPoints };
|
|
92
|
+
}
|
|
93
|
+
catch (cause) {
|
|
94
|
+
throw new StateDecodeFailedError(version, cause);
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* This file is part of midnight-js.
|
|
100
|
+
* Copyright (C) Midnight Foundation
|
|
101
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
102
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
103
|
+
* You may not use this file except in compliance with the License.
|
|
104
|
+
* You may obtain a copy of the License at
|
|
105
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
106
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
107
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
108
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
109
|
+
* See the License for the specific language governing permissions and
|
|
110
|
+
* limitations under the License.
|
|
111
|
+
*/
|
|
112
|
+
/**
|
|
113
|
+
* Reads the UTXO outputs a call's transcript claims on behalf of USERS.
|
|
114
|
+
*
|
|
115
|
+
* @param transcript One half of a call's transcript pair. Absent is the normal
|
|
116
|
+
* shape of a call with no fallible half, and yields no outputs.
|
|
117
|
+
* @param version The era every failure raised here names.
|
|
118
|
+
* @param circuitId The entry point every failure raised here names.
|
|
119
|
+
* @returns One `UtxoOutput` per user-addressed unshielded spend the transcript
|
|
120
|
+
* claims. Contract-addressed spends are skipped.
|
|
121
|
+
* @throws ComposeFailedError at stage `'call-dust-payout'` for a user-addressed
|
|
122
|
+
* dust spend.
|
|
123
|
+
* @throws ComposeFailedError at stage `'call-unsupported-payout'` for a
|
|
124
|
+
* user-addressed spend of any token type other than unshielded.
|
|
125
|
+
* @see {@link ComposeRefusalOrder}
|
|
126
|
+
*/
|
|
127
|
+
const extractUserAddressedOutputs = (transcript, version, circuitId) => {
|
|
128
|
+
if (transcript === undefined) {
|
|
129
|
+
return [];
|
|
130
|
+
}
|
|
131
|
+
const outputs = [];
|
|
132
|
+
for (const [[tokenType, publicAddress], value] of transcript.effects.claimedUnshieldedSpends) {
|
|
133
|
+
if (publicAddress.tag !== 'user') {
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
if (tokenType.tag === 'dust') {
|
|
137
|
+
throw new ComposeFailedError(version, 'call-dust-payout', circuitId);
|
|
138
|
+
}
|
|
139
|
+
if (tokenType.tag !== 'unshielded') {
|
|
140
|
+
throw new ComposeFailedError(version, 'call-unsupported-payout', circuitId);
|
|
141
|
+
}
|
|
142
|
+
outputs.push({ value, owner: publicAddress.address, type: tokenType.raw });
|
|
143
|
+
}
|
|
144
|
+
return outputs;
|
|
145
|
+
};
|
|
146
|
+
/**
|
|
147
|
+
* Builds the one unshielded offer each segment of a transaction carries, from
|
|
148
|
+
* EVERY call in the tree.
|
|
149
|
+
*
|
|
150
|
+
* @typeParam TOffer The offer type `ledger.UnshieldedOffer.new` returns.
|
|
151
|
+
* @param calls Every call in the transaction's tree — cross-contract callees
|
|
152
|
+
* as well as the root call, since any of them can produce a payout.
|
|
153
|
+
* @param ledger The era module slice carrying `UnshieldedOffer`.
|
|
154
|
+
* @param version The era every failure raised here names.
|
|
155
|
+
* @returns The guaranteed and fallible offers. A segment with nothing to pay
|
|
156
|
+
* out gets no offer at all rather than an empty one.
|
|
157
|
+
* @throws ComposeFailedError from {@link extractUserAddressedOutputs} for a
|
|
158
|
+
* user-addressed spend this seam cannot pay out.
|
|
159
|
+
* @see {@link ComposeRefusalOrder}
|
|
160
|
+
*/
|
|
161
|
+
const aggregateUnshieldedOffers = (calls, ledger, version) => {
|
|
162
|
+
const guaranteedOutputs = calls.flatMap((call) => extractUserAddressedOutputs(call.guaranteed, version, call.circuitId));
|
|
163
|
+
const fallibleOutputs = calls.flatMap((call) => extractUserAddressedOutputs(call.fallible, version, call.circuitId));
|
|
164
|
+
return {
|
|
165
|
+
guaranteed: guaranteedOutputs.length > 0 ? ledger.UnshieldedOffer.new([], guaranteedOutputs, []) : undefined,
|
|
166
|
+
fallible: fallibleOutputs.length > 0 ? ledger.UnshieldedOffer.new([], fallibleOutputs, []) : undefined
|
|
167
|
+
};
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
/*
|
|
171
|
+
* This file is part of midnight-js.
|
|
172
|
+
* Copyright (C) Midnight Foundation
|
|
173
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
174
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
175
|
+
* You may not use this file except in compliance with the License.
|
|
176
|
+
* You may obtain a copy of the License at
|
|
177
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
178
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
179
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
180
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
181
|
+
* See the License for the specific language governing permissions and
|
|
182
|
+
* limitations under the License.
|
|
183
|
+
*/
|
|
184
|
+
/**
|
|
185
|
+
* Composes a v8-native call transaction from one call's inputs and immediately
|
|
186
|
+
* serializes it. The call prototype comes from {@link assembleCallPrototype}
|
|
187
|
+
* against the injected v8 module.
|
|
188
|
+
*
|
|
189
|
+
* Never proves the transaction: the returned bytes are an UNPROVEN,
|
|
190
|
+
* tag-prefixed serialization, exactly what `Transaction.serialize()` produces
|
|
191
|
+
* before `.prove()` is ever called.
|
|
192
|
+
*
|
|
193
|
+
* @param options The call's inputs, offers and envelope options.
|
|
194
|
+
* @param v8 The v8 ledger module, as handed over by `loadLedger8`
|
|
195
|
+
* (`./load.ts`).
|
|
196
|
+
* @returns The UNPROVEN, serialized call transaction.
|
|
197
|
+
* @throws ComposeOptionError If `networkId` is empty or `ttl` is not a valid
|
|
198
|
+
* instant.
|
|
199
|
+
* @throws ComposeFailedError If `contractState` has no registered operation for
|
|
200
|
+
* `circuitId` (stage `'call-operation'`), or the operation it does have
|
|
201
|
+
* carries no verifier key (stage `'call-verifier-key'`), plus every stage
|
|
202
|
+
* {@link assembleCallPrototype} and {@link aggregateUnshieldedOffers} raise.
|
|
203
|
+
* @see {@link ComposeRefusalOrder}
|
|
204
|
+
*/
|
|
205
|
+
const composeV8CallTx = (options, v8) => {
|
|
206
|
+
const { contractAddress, contractState, networkId, ttl, guaranteedZswapOffer, fallibleZswapOffer } = options;
|
|
207
|
+
assertComposeEnvelope(options, 'v8');
|
|
208
|
+
const prototype = assembleCallPrototype(v8, {
|
|
209
|
+
circuitId: options.circuitId,
|
|
210
|
+
contractAddress,
|
|
211
|
+
transcript: options.transcript,
|
|
212
|
+
privateTranscriptOutputs: options.privateTranscriptOutputs,
|
|
213
|
+
input: options.input,
|
|
214
|
+
output: options.output,
|
|
215
|
+
communicationCommitmentRandomness: options.communicationCommitmentRandomness,
|
|
216
|
+
ledgerParameters: options.ledgerParameters,
|
|
217
|
+
operations: contractState,
|
|
218
|
+
stage: 'call-operation',
|
|
219
|
+
version: 'v8'
|
|
220
|
+
});
|
|
221
|
+
const intent = v8.Intent.new(ttl).addCall(prototype);
|
|
222
|
+
// Read the partitioned pair back off the intent rather than re-deriving it,
|
|
223
|
+
// and attach the payout on this era too -- see ComposeRefusalOrder.
|
|
224
|
+
const unshielded = aggregateUnshieldedOffers(intent.actions
|
|
225
|
+
.filter((action) => action instanceof v8.ContractCall)
|
|
226
|
+
.map((call) => ({
|
|
227
|
+
circuitId: entryPointName(call.entryPoint),
|
|
228
|
+
guaranteed: call.guaranteedTranscript,
|
|
229
|
+
fallible: call.fallibleTranscript
|
|
230
|
+
})), v8, 'v8');
|
|
231
|
+
if (unshielded.guaranteed !== undefined) {
|
|
232
|
+
intent.guaranteedUnshieldedOffer = unshielded.guaranteed;
|
|
233
|
+
}
|
|
234
|
+
if (unshielded.fallible !== undefined) {
|
|
235
|
+
intent.fallibleUnshieldedOffer = unshielded.fallible;
|
|
236
|
+
}
|
|
237
|
+
return v8.Transaction.fromPartsRandomized(networkId, guaranteedZswapOffer, fallibleZswapOffer, intent).serialize();
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
/*
|
|
241
|
+
* This file is part of midnight-js.
|
|
242
|
+
* Copyright (C) Midnight Foundation
|
|
243
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
244
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
245
|
+
* You may not use this file except in compliance with the License.
|
|
246
|
+
* You may obtain a copy of the License at
|
|
247
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
248
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
249
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
250
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
251
|
+
* See the License for the specific language governing permissions and
|
|
252
|
+
* limitations under the License.
|
|
253
|
+
*/
|
|
254
|
+
/**
|
|
255
|
+
* Bridges a raw, serialized contract state into the v8 era, reporting a
|
|
256
|
+
* rejected envelope as {@link ComposeOptionError} rather than letting a raw
|
|
257
|
+
* decoder failure escape.
|
|
258
|
+
*/
|
|
259
|
+
const readContractState$1 = (raw, v8) => {
|
|
260
|
+
try {
|
|
261
|
+
return v8.ContractState.deserialize(raw);
|
|
262
|
+
}
|
|
263
|
+
catch (cause) {
|
|
264
|
+
throw new ComposeOptionError('v8', 'contractState', cause);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
/**
|
|
268
|
+
* Reads a serialized Zswap offer into the v8 era, reporting bytes this era
|
|
269
|
+
* cannot decode as {@link ComposeOptionError}. An absent offer is the normal
|
|
270
|
+
* shape of a call that moved no shielded coins, and stays absent.
|
|
271
|
+
*
|
|
272
|
+
* @see {@link ComposeRefusalOrder}
|
|
273
|
+
*/
|
|
274
|
+
const readZswapOffer$1 = (raw, v8) => {
|
|
275
|
+
if (raw === undefined) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
try {
|
|
279
|
+
return v8.ZswapOffer.deserialize('pre-proof', raw);
|
|
280
|
+
}
|
|
281
|
+
catch (cause) {
|
|
282
|
+
throw new ComposeOptionError('v8', 'zswapOffer', cause);
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
/**
|
|
286
|
+
* Maps the era-facade's call options onto the v8-native composition leg
|
|
287
|
+
* (`./compose.ts`).
|
|
288
|
+
*
|
|
289
|
+
* This era composes exactly one call: a `calls` tree with more than one entry
|
|
290
|
+
* is refused rather than silently narrowed. A Zswap offer is NOT refused.
|
|
291
|
+
*
|
|
292
|
+
* @param options The era-facade call options.
|
|
293
|
+
* @param v8 The v8 ledger module, as handed over by `loadLedger8`
|
|
294
|
+
* (`./load.ts`).
|
|
295
|
+
* @returns The UNPROVEN, serialized call transaction.
|
|
296
|
+
* @throws ComposeOptionError If an option cannot be used: a malformed envelope
|
|
297
|
+
* option, unreadable offer or contract-state bytes, or more than one entry in
|
|
298
|
+
* `calls`.
|
|
299
|
+
* @throws ComposeFailedError If `calls` is empty (stage `'call-empty'`), and
|
|
300
|
+
* for every stage the composition leg this delegates to can raise.
|
|
301
|
+
* @see {@link ComposeRefusalOrder}
|
|
302
|
+
* @see {@link EraSeam}
|
|
303
|
+
*/
|
|
304
|
+
const composeEraV8CallTx = (options, v8) => {
|
|
305
|
+
const { calls, networkId, ttl, guaranteedZswapOffer, fallibleZswapOffer } = options;
|
|
306
|
+
// Checked here, not left to the inner leg, so both arms refuse in the same
|
|
307
|
+
// order; the re-check in the leg is idempotent -- see ComposeRefusalOrder.
|
|
308
|
+
assertComposeEnvelope(options, 'v8');
|
|
309
|
+
if (calls.length === 0) {
|
|
310
|
+
throw new ComposeFailedError('v8', 'call-empty', NO_CIRCUIT);
|
|
311
|
+
}
|
|
312
|
+
// Both offers are read before anything is composed -- see
|
|
313
|
+
// ComposeRefusalOrder.
|
|
314
|
+
const guaranteedOffer = readZswapOffer$1(guaranteedZswapOffer, v8);
|
|
315
|
+
const fallibleOffer = readZswapOffer$1(fallibleZswapOffer, v8);
|
|
316
|
+
if (calls.length > 1) {
|
|
317
|
+
throw new ComposeOptionError('v8', 'calls');
|
|
318
|
+
}
|
|
319
|
+
const [call] = calls;
|
|
320
|
+
return composeV8CallTx({
|
|
321
|
+
circuitId: call.circuitId,
|
|
322
|
+
contractAddress: call.contractAddress,
|
|
323
|
+
contractState: readContractState$1(call.contractState, v8),
|
|
324
|
+
transcript: call.transcript,
|
|
325
|
+
privateTranscriptOutputs: call.privateTranscriptOutputs,
|
|
326
|
+
input: call.input,
|
|
327
|
+
output: call.output,
|
|
328
|
+
communicationCommitmentRandomness: call.communicationCommitmentRandomness,
|
|
329
|
+
// Carried across the adapter, not dropped. Without this the retained-native arm silently
|
|
330
|
+
// partitions against this era's INITIAL parameters while the caller believed it had supplied
|
|
331
|
+
// the chain's -- the same defect this option exists to close, one layer down.
|
|
332
|
+
ledgerParameters: call.ledgerParameters,
|
|
333
|
+
networkId,
|
|
334
|
+
ttl,
|
|
335
|
+
guaranteedZswapOffer: guaranteedOffer,
|
|
336
|
+
fallibleZswapOffer: fallibleOffer
|
|
337
|
+
}, v8);
|
|
338
|
+
};
|
|
339
|
+
/**
|
|
340
|
+
* Maps the era-facade's deploy options onto the v8-native deploy leg
|
|
341
|
+
* (`./deploy.ts`).
|
|
342
|
+
*
|
|
343
|
+
* `verifierKeys` is optional on the facade but required here: this era's deploy
|
|
344
|
+
* leg registers the compiled contract's keys onto the initial state itself, so
|
|
345
|
+
* the omission is reported as {@link ComposeOptionError}.
|
|
346
|
+
*
|
|
347
|
+
* The contract state crosses into the leg by BYTES, which is what that leg
|
|
348
|
+
* takes: it deserializes into its own era rather than accepting a handle.
|
|
349
|
+
*
|
|
350
|
+
* @param options The era-facade deploy options.
|
|
351
|
+
* @param v8 The v8 ledger module, as handed over by `loadLedger8`
|
|
352
|
+
* (`./load.ts`).
|
|
353
|
+
* @returns The UNPROVEN, serialized deploy transaction, the address it deploys
|
|
354
|
+
* at, and the registered initial state.
|
|
355
|
+
* @throws ComposeOptionError If an option cannot be used: a malformed envelope
|
|
356
|
+
* option, unreadable offer bytes, or an omitted `verifierKeys` map.
|
|
357
|
+
* @throws ComposeFailedError For every stage the deploy leg this delegates to
|
|
358
|
+
* can raise.
|
|
359
|
+
* @see {@link VerifierKeys}
|
|
360
|
+
* @see {@link ComposeRefusalOrder}
|
|
361
|
+
* @see {@link EraSeam}
|
|
362
|
+
*/
|
|
363
|
+
const composeEraV8DeployTx = (options, v8) => {
|
|
364
|
+
const { contractState, verifierKeys, networkId, ttl, guaranteedZswapOffer } = options;
|
|
365
|
+
// See `composeEraV8CallTx` — hoisted so both arms refuse the envelope first.
|
|
366
|
+
assertComposeEnvelope(options, 'v8');
|
|
367
|
+
const guaranteedOffer = readZswapOffer$1(guaranteedZswapOffer, v8);
|
|
368
|
+
if (verifierKeys === undefined) {
|
|
369
|
+
throw new ComposeOptionError('v8', 'verifierKeys');
|
|
370
|
+
}
|
|
371
|
+
return composeV8DeployTx({ contractState, verifierKeys, networkId, ttl, guaranteedZswapOffer: guaranteedOffer }, v8);
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
/*
|
|
375
|
+
* This file is part of midnight-js.
|
|
376
|
+
* Copyright (C) Midnight Foundation
|
|
377
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
378
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
379
|
+
* You may not use this file except in compliance with the License.
|
|
380
|
+
* You may obtain a copy of the License at
|
|
381
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
382
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
383
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
384
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
385
|
+
* See the License for the specific language governing permissions and
|
|
386
|
+
* limitations under the License.
|
|
387
|
+
*/
|
|
388
|
+
/**
|
|
389
|
+
* Bridges a raw, serialized contract state into the v9 era, reporting a
|
|
390
|
+
* rejected envelope as {@link ComposeOptionError} -- see ComposeRefusalOrder.
|
|
391
|
+
*/
|
|
392
|
+
const readContractState = (raw) => {
|
|
393
|
+
try {
|
|
394
|
+
return ledgerV9.ContractState.deserialize(raw);
|
|
395
|
+
}
|
|
396
|
+
catch (cause) {
|
|
397
|
+
throw new ComposeOptionError('v9', 'contractState', cause);
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
/**
|
|
401
|
+
* Reads a serialized Zswap offer, reporting bytes this era cannot decode as
|
|
402
|
+
* {@link ComposeOptionError}. An absent offer is the normal shape of a call
|
|
403
|
+
* that moved no shielded coins, and stays absent.
|
|
404
|
+
*/
|
|
405
|
+
const readZswapOffer = (raw) => {
|
|
406
|
+
if (raw === undefined) {
|
|
407
|
+
return undefined;
|
|
408
|
+
}
|
|
409
|
+
try {
|
|
410
|
+
return ledgerV9.ZswapOffer.deserialize('pre-proof', raw);
|
|
411
|
+
}
|
|
412
|
+
catch (cause) {
|
|
413
|
+
throw new ComposeOptionError('v9', 'zswapOffer', cause);
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
/**
|
|
417
|
+
* Composes a v9-native call transaction from one or more contract calls and
|
|
418
|
+
* immediately serializes it.
|
|
419
|
+
*
|
|
420
|
+
* Never proves the transaction: the returned bytes are an UNPROVEN,
|
|
421
|
+
* tag-prefixed serialization, exactly what `Transaction.serialize()` produces
|
|
422
|
+
* before `.prove()` is ever called.
|
|
423
|
+
*
|
|
424
|
+
* @param options The calls to compose and the transaction-wide envelope.
|
|
425
|
+
* @returns The serialized UNPROVEN transaction.
|
|
426
|
+
* @throws ComposeFailedError if the call list is empty (stage `'call-empty'`)
|
|
427
|
+
* or a call cannot be assembled; `stage` names which step refused it.
|
|
428
|
+
* @throws ComposeOptionError if the network id, the ttl, a Zswap offer or a
|
|
429
|
+
* call's contract state is unusable.
|
|
430
|
+
* @see {@link ComposeRefusalOrder}
|
|
431
|
+
*/
|
|
432
|
+
const composeV9CallTx = (options) => {
|
|
433
|
+
const { calls, networkId, ttl, guaranteedZswapOffer, fallibleZswapOffer } = options;
|
|
434
|
+
assertComposeEnvelope(options, 'v9');
|
|
435
|
+
if (calls.length === 0) {
|
|
436
|
+
throw new ComposeFailedError('v9', 'call-empty', NO_CIRCUIT);
|
|
437
|
+
}
|
|
438
|
+
// Read both offers before composing anything -- see ComposeRefusalOrder.
|
|
439
|
+
const guaranteedOffer = readZswapOffer(guaranteedZswapOffer);
|
|
440
|
+
const fallibleOffer = readZswapOffer(fallibleZswapOffer);
|
|
441
|
+
let intent = ledgerV9.Intent.new(ttl);
|
|
442
|
+
for (const call of calls) {
|
|
443
|
+
intent = intent.addCall(assembleCallPrototype(ledgerV9, {
|
|
444
|
+
circuitId: call.circuitId,
|
|
445
|
+
contractAddress: call.contractAddress,
|
|
446
|
+
transcript: call.transcript,
|
|
447
|
+
privateTranscriptOutputs: call.privateTranscriptOutputs,
|
|
448
|
+
input: call.input,
|
|
449
|
+
output: call.output,
|
|
450
|
+
communicationCommitmentRandomness: call.communicationCommitmentRandomness,
|
|
451
|
+
ledgerParameters: call.ledgerParameters,
|
|
452
|
+
operations: readContractState(call.contractState),
|
|
453
|
+
stage: 'call-operation',
|
|
454
|
+
version: 'v9'
|
|
455
|
+
}));
|
|
456
|
+
}
|
|
457
|
+
// Read the partitioned pairs back off the intent rather than re-deriving
|
|
458
|
+
// them -- see ComposeRefusalOrder.
|
|
459
|
+
const unshielded = aggregateUnshieldedOffers(intent.actions
|
|
460
|
+
.filter((action) => action instanceof ledgerV9.ContractCall)
|
|
461
|
+
.map((call) => ({
|
|
462
|
+
circuitId: entryPointName(call.entryPoint),
|
|
463
|
+
guaranteed: call.guaranteedTranscript,
|
|
464
|
+
fallible: call.fallibleTranscript
|
|
465
|
+
})), ledgerV9, 'v9');
|
|
466
|
+
if (unshielded.guaranteed !== undefined) {
|
|
467
|
+
intent.guaranteedUnshieldedOffer = unshielded.guaranteed;
|
|
468
|
+
}
|
|
469
|
+
if (unshielded.fallible !== undefined) {
|
|
470
|
+
intent.fallibleUnshieldedOffer = unshielded.fallible;
|
|
471
|
+
}
|
|
472
|
+
return ledgerV9.Transaction.fromPartsRandomized(networkId, guaranteedOffer, fallibleOffer, intent).serialize();
|
|
473
|
+
};
|
|
474
|
+
/**
|
|
475
|
+
* Registers a verifier key for every entry point the state declares, against
|
|
476
|
+
* the map validated by {@link resolveVerifierKeyRegistrations} -- see
|
|
477
|
+
* VerifierKeys.
|
|
478
|
+
*/
|
|
479
|
+
const registerVerifierKeys = (contractState, verifierKeys) => {
|
|
480
|
+
for (const { entryPoint, circuitId, verifierKey } of resolveVerifierKeyRegistrations(contractState.operations(), verifierKeys, 'v9')) {
|
|
481
|
+
const operation = new ledgerV9.ContractOperation();
|
|
482
|
+
try {
|
|
483
|
+
operation.verifierKey = verifierKey;
|
|
484
|
+
}
|
|
485
|
+
catch (cause) {
|
|
486
|
+
throw new ComposeFailedError('v9', 'deploy-verifier-key-blob', circuitId, cause);
|
|
487
|
+
}
|
|
488
|
+
contractState.setOperation(entryPoint, operation);
|
|
489
|
+
}
|
|
490
|
+
};
|
|
491
|
+
/**
|
|
492
|
+
* Refuses a state that still declares an entry point with a blank verifier key
|
|
493
|
+
* when no key map was supplied -- see VerifierKeys.
|
|
494
|
+
*/
|
|
495
|
+
const assertStateCarriesKeys = (contractState) => {
|
|
496
|
+
for (const entryPoint of contractState.operations()) {
|
|
497
|
+
// `?.` is deliberate here, unlike in `../shared/contract-state.ts`, and so
|
|
498
|
+
// is raising the OPTION error rather than the `'deploy-verifier-key'` stage
|
|
499
|
+
// -- see VerifierKeys.
|
|
500
|
+
if (contractState.operation(entryPoint)?.verifierKey === undefined) {
|
|
501
|
+
throw new ComposeOptionError('v9', 'verifierKeys');
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
/**
|
|
506
|
+
* Composes a v9-native deploy transaction from a serialized initial contract
|
|
507
|
+
* state and immediately serializes it, returning the transaction together with
|
|
508
|
+
* the address the deployment will have and the initial state that address is
|
|
509
|
+
* derived from.
|
|
510
|
+
*
|
|
511
|
+
* Never proves the transaction: the returned bytes are an UNPROVEN,
|
|
512
|
+
* tag-prefixed serialization, exactly what `Transaction.serialize()` produces
|
|
513
|
+
* before `.prove()` is ever called.
|
|
514
|
+
*
|
|
515
|
+
* With `verifierKeys` supplied, every declared entry point is registered before
|
|
516
|
+
* the address is derived. Without it, the state is deployed exactly as given —
|
|
517
|
+
* which is checked rather than assumed, see {@link assertStateCarriesKeys}.
|
|
518
|
+
*
|
|
519
|
+
* @param options The serialized initial state, its verifier keys, and the
|
|
520
|
+
* transaction-wide envelope.
|
|
521
|
+
* @returns The serialized UNPROVEN transaction, the address the deployment
|
|
522
|
+
* will have, and the initial state that address was derived from.
|
|
523
|
+
* @throws ComposeFailedError if the supplied keys do not match the state's
|
|
524
|
+
* declared entry points, or if the ledger rejects a key blob; `stage` names
|
|
525
|
+
* which check refused it.
|
|
526
|
+
* @throws ComposeOptionError if the network id, the ttl, the Zswap offer or
|
|
527
|
+
* the state bytes are unusable, or if `verifierKeys` was omitted for a state
|
|
528
|
+
* that still declares a blank key.
|
|
529
|
+
* @see {@link VerifierKeys}
|
|
530
|
+
* @see {@link ComposeRefusalOrder}
|
|
531
|
+
*/
|
|
532
|
+
const composeV9DeployTx = (options) => {
|
|
533
|
+
const { contractState, verifierKeys, networkId, ttl, guaranteedZswapOffer } = options;
|
|
534
|
+
assertComposeEnvelope(options, 'v9');
|
|
535
|
+
const guaranteedOffer = readZswapOffer(guaranteedZswapOffer);
|
|
536
|
+
const state = readContractState(contractState);
|
|
537
|
+
if (verifierKeys === undefined) {
|
|
538
|
+
assertStateCarriesKeys(state);
|
|
539
|
+
}
|
|
540
|
+
else {
|
|
541
|
+
registerVerifierKeys(state, verifierKeys);
|
|
542
|
+
}
|
|
543
|
+
const deploy = new ledgerV9.ContractDeploy(state);
|
|
544
|
+
const intent = ledgerV9.Intent.new(ttl).addDeploy(deploy);
|
|
545
|
+
return {
|
|
546
|
+
transaction: ledgerV9.Transaction.fromParts(networkId, guaranteedOffer, undefined, intent).serialize(),
|
|
547
|
+
contractAddress: deploy.address,
|
|
548
|
+
initialState: deploy.initialState.serialize()
|
|
549
|
+
};
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
/*
|
|
553
|
+
* This file is part of midnight-js.
|
|
554
|
+
* Copyright (C) Midnight Foundation
|
|
555
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
556
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
557
|
+
* You may not use this file except in compliance with the License.
|
|
558
|
+
* You may obtain a copy of the License at
|
|
559
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
560
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
561
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
562
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
563
|
+
* See the License for the specific language governing permissions and
|
|
564
|
+
* limitations under the License.
|
|
565
|
+
*/
|
|
566
|
+
/**
|
|
567
|
+
* Reads the primary {@link EncodedStateValue} out of a raw, serialized
|
|
568
|
+
* post-fork `contract-state[v8]` envelope.
|
|
569
|
+
*
|
|
570
|
+
* Reachable without a pre-fork runtime, unlike {@link extractEncodedStateValue},
|
|
571
|
+
* which requires one for every era.
|
|
572
|
+
*
|
|
573
|
+
* @param raw The serialized `contract-state[v8]` envelope.
|
|
574
|
+
* @returns The primary state read out of the envelope.
|
|
575
|
+
* @throws DownConvertFailedError at stage `'v9 envelope extraction'` if the
|
|
576
|
+
* envelope is malformed, truncated, over-long, or tagged for the other era,
|
|
577
|
+
* carrying the runtime's own diagnosis on `cause`.
|
|
578
|
+
* @see {@link FailClosedDecoding}
|
|
579
|
+
*/
|
|
580
|
+
const extractV9EncodedStateValue = (raw) => {
|
|
581
|
+
try {
|
|
582
|
+
return ContractState.deserialize(raw).data.state.encode();
|
|
583
|
+
}
|
|
584
|
+
catch (cause) {
|
|
585
|
+
throw new DownConvertFailedError('v9 envelope extraction', cause);
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
/**
|
|
589
|
+
* One decoder per {@link LedgerVersion}:
|
|
590
|
+
*
|
|
591
|
+
* - `v9` — a post-fork `contract-state[v8]`-tagged envelope, read via
|
|
592
|
+
* `@midnightntwrk/ledger-v9`.
|
|
593
|
+
* - `v8` — a pre-fork `contract-state[v6]`-tagged envelope, read via
|
|
594
|
+
* onchain-runtime-v3, the same codec that produced it.
|
|
595
|
+
*
|
|
596
|
+
* A total `Record`, built on a null prototype and frozen -- see the
|
|
597
|
+
* SharedTableDiscipline document.
|
|
598
|
+
*/
|
|
599
|
+
const ENVELOPE_DECODERS = Object.freeze(Object.assign(Object.create(null), {
|
|
600
|
+
v8: (raw, ledger8ContractState) => ledger8ContractState.deserialize(raw).data.state.encode(),
|
|
601
|
+
// A reference to the standalone decoder, not a second copy of the same
|
|
602
|
+
// read -- see FailClosedDecoding.
|
|
603
|
+
v9: extractV9EncodedStateValue
|
|
604
|
+
}));
|
|
605
|
+
/**
|
|
606
|
+
* Extracts the primary {@link EncodedStateValue} out of a raw, serialized
|
|
607
|
+
* `ContractState` envelope, using the decoder that matches `version`.
|
|
608
|
+
*
|
|
609
|
+
* @param raw The serialized envelope.
|
|
610
|
+
* @param version The era whose decoder reads `raw`. Validated at runtime, not
|
|
611
|
+
* merely type-checked.
|
|
612
|
+
* @param ledger8ContractState The pre-fork `ContractState` statics. Required
|
|
613
|
+
* for every `version`, not just `'v8'`, and checked before any decoding
|
|
614
|
+
* happens.
|
|
615
|
+
* @returns The primary state read out of the envelope — never a silently
|
|
616
|
+
* empty or partial one.
|
|
617
|
+
* @throws UnknownLedgerVersionError if `version` is not a member of
|
|
618
|
+
* `LEDGER_VERSIONS`.
|
|
619
|
+
* @throws Ledger8RuntimeInvalidError if `ledger8ContractState` does not carry
|
|
620
|
+
* `deserialize`.
|
|
621
|
+
* @throws DownConvertFailedError at stage `'v8 envelope extraction'` or
|
|
622
|
+
* `'v9 envelope extraction'` if the envelope cannot be read, carrying the
|
|
623
|
+
* runtime's own diagnosis on `cause`.
|
|
624
|
+
* @see {@link FailClosedDecoding}
|
|
625
|
+
* @see {@link SharedTableDiscipline}
|
|
626
|
+
*/
|
|
627
|
+
const extractEncodedStateValue = (raw, version, ledger8ContractState) => {
|
|
628
|
+
const decoder = ENVELOPE_DECODERS[version];
|
|
629
|
+
if (typeof decoder !== 'function') {
|
|
630
|
+
throw new UnknownLedgerVersionError(String(version));
|
|
631
|
+
}
|
|
632
|
+
if (typeof ledger8ContractState?.deserialize !== 'function') {
|
|
633
|
+
throw new Ledger8RuntimeInvalidError('ContractState.deserialize');
|
|
634
|
+
}
|
|
635
|
+
try {
|
|
636
|
+
return decoder(raw, ledger8ContractState);
|
|
637
|
+
}
|
|
638
|
+
catch (cause) {
|
|
639
|
+
// THE STAGE IS CHECKED, not just the class: a decoder is injectable, so one
|
|
640
|
+
// that wrapped at a different stage must not pass through -- see
|
|
641
|
+
// FailClosedDecoding.
|
|
642
|
+
const stage = `${version} envelope extraction`;
|
|
643
|
+
throw cause instanceof DownConvertFailedError && cause.stage === stage
|
|
644
|
+
? cause
|
|
645
|
+
: new DownConvertFailedError(stage, cause);
|
|
646
|
+
}
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
/*
|
|
650
|
+
* This file is part of midnight-js.
|
|
651
|
+
* Copyright (C) Midnight Foundation
|
|
652
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
653
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
654
|
+
* You may not use this file except in compliance with the License.
|
|
655
|
+
* You may obtain a copy of the License at
|
|
656
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
657
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
658
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
659
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
660
|
+
* See the License for the specific language governing permissions and
|
|
661
|
+
* limitations under the License.
|
|
662
|
+
*/
|
|
663
|
+
// One memo slot per era, never one shared slot, and both arms are frozen --
|
|
664
|
+
// see SharedTableDiscipline and EraSeam.
|
|
665
|
+
let v8EraPromise;
|
|
666
|
+
let v9EraPromise;
|
|
667
|
+
/** The v9 arm. Wholly synchronous -- see the EraSeam document. */
|
|
668
|
+
const createV9Era = () => {
|
|
669
|
+
const era = {
|
|
670
|
+
version: 'v9',
|
|
671
|
+
extractState: (raw) => extractStateWith(raw, 'v9', extractV9EncodedStateValue),
|
|
672
|
+
decodeContractState: (raw) => decodeContractStateWith(raw, 'v9', ledgerV9),
|
|
673
|
+
composeCallTx: composeV9CallTx,
|
|
674
|
+
composeDeployTx: composeV9DeployTx,
|
|
675
|
+
partitionCallTranscript: (options) => {
|
|
676
|
+
// See the v8 arm: the assembler's tuple is readonly, the ledger's is not.
|
|
677
|
+
const [guaranteed, fallible] = partitionCallTranscript(ledgerV9, { ...options, version: 'v9' });
|
|
678
|
+
return [guaranteed, fallible];
|
|
679
|
+
}
|
|
680
|
+
};
|
|
681
|
+
return Object.freeze(era);
|
|
682
|
+
};
|
|
683
|
+
/**
|
|
684
|
+
* The v8 arm. Acquires the retained pre-fork ledger and binds it into closure,
|
|
685
|
+
* so the era's own methods stay synchronous -- see the EraSeam document for why
|
|
686
|
+
* the acquisition is hoisted here.
|
|
687
|
+
*/
|
|
688
|
+
const createV8Era = async () => {
|
|
689
|
+
const v8 = await loadLedger8();
|
|
690
|
+
const era = {
|
|
691
|
+
version: 'v8',
|
|
692
|
+
extractState: (raw) => extractStateWith(raw, 'v8', (bytes) => extractEncodedStateValue(bytes, 'v8', v8.ContractState)),
|
|
693
|
+
decodeContractState: (raw) => decodeContractStateWith(raw, 'v8', v8),
|
|
694
|
+
composeCallTx: (options) => composeEraV8CallTx(options, v8),
|
|
695
|
+
composeDeployTx: (options) => composeEraV8DeployTx(options, v8),
|
|
696
|
+
partitionCallTranscript: (options) => {
|
|
697
|
+
// Copied into a mutable pair rather than handed on: the assembler answers
|
|
698
|
+
// with a readonly tuple, and the ledger's own `PartitionedTranscript` --
|
|
699
|
+
// which is what every consumer of this pair is typed against -- is not.
|
|
700
|
+
const [guaranteed, fallible] = partitionCallTranscript(v8, { ...options, version: 'v8' });
|
|
701
|
+
return [guaranteed, fallible];
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
return Object.freeze(era);
|
|
705
|
+
};
|
|
706
|
+
/**
|
|
707
|
+
* Resolves one ledger era to a {@link LedgerEra} bound to it.
|
|
708
|
+
*
|
|
709
|
+
* This is the only sanctioned way to reach either era's operations. Pass the
|
|
710
|
+
* version resolved from a record or from the network head (see
|
|
711
|
+
* `protocolVersionToLedger` in `../../version.ts`) rather than a string chosen
|
|
712
|
+
* by hand.
|
|
713
|
+
*
|
|
714
|
+
* Memoised per era, so the retained pre-fork WASM is instantiated at most once
|
|
715
|
+
* per process. A FAILED v8 acquisition is not memoised: the next call retries.
|
|
716
|
+
*
|
|
717
|
+
* @param version The era to resolve.
|
|
718
|
+
* @returns The era facade bound to `version`. The same object on every call
|
|
719
|
+
* for that era, and frozen.
|
|
720
|
+
* @throws UnknownLedgerVersionError — as a rejection — if `version` is not a
|
|
721
|
+
* member of `LEDGER_VERSIONS`.
|
|
722
|
+
* @throws Ledger8RuntimeMissingError — as a rejection — if the retained
|
|
723
|
+
* pre-fork runtime cannot be acquired. It propagates unchanged, carrying the
|
|
724
|
+
* underlying cause.
|
|
725
|
+
* @see {@link EraSeam}
|
|
726
|
+
* @see {@link SharedTableDiscipline}
|
|
727
|
+
*/
|
|
728
|
+
const loadLedgerEra = (version) => {
|
|
729
|
+
switch (version) {
|
|
730
|
+
case 'v9':
|
|
731
|
+
return (v9EraPromise ??= Promise.resolve(createV9Era()));
|
|
732
|
+
case 'v8':
|
|
733
|
+
return (v8EraPromise ??= createV8Era().catch((error) => {
|
|
734
|
+
v8EraPromise = undefined;
|
|
735
|
+
throw error;
|
|
736
|
+
}));
|
|
737
|
+
default: {
|
|
738
|
+
// `const unhandled: never` is a compile-time exhaustiveness gate, and the
|
|
739
|
+
// runtime rejection is not redundant with it -- see SharedTableDiscipline.
|
|
740
|
+
const unhandled = version;
|
|
741
|
+
return Promise.reject(new UnknownLedgerVersionError(String(unhandled)));
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
|
|
746
|
+
/*
|
|
747
|
+
* This file is part of midnight-js.
|
|
748
|
+
* Copyright (C) Midnight Foundation
|
|
749
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
750
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
751
|
+
* You may not use this file except in compliance with the License.
|
|
752
|
+
* You may obtain a copy of the License at
|
|
753
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
754
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
755
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
756
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
757
|
+
* See the License for the specific language governing permissions and
|
|
758
|
+
* limitations under the License.
|
|
759
|
+
*/
|
|
760
|
+
let enginePromise;
|
|
761
|
+
/**
|
|
762
|
+
* The only sanctioned runtime path to the engine's public surface.
|
|
763
|
+
*
|
|
764
|
+
* The retained `compact-runtime@0.16` glue and
|
|
765
|
+
* `@midnight-ntwrk/onchain-runtime-v3` WASM load only on the first call — never
|
|
766
|
+
* as a side effect of importing the package root.
|
|
767
|
+
*
|
|
768
|
+
* A failed load is not memoised: the next call retries the import. Exactly two
|
|
769
|
+
* rejections propagate unchanged — {@link Ledger8RuntimeMissingError} from the
|
|
770
|
+
* retained-runtime acquisition, and {@link Ledger8InstanceMismatchError} from
|
|
771
|
+
* the construction-time instance guard — keeping their class, code and
|
|
772
|
+
* discriminants intact for callers. Every other failure is wrapped in
|
|
773
|
+
* {@link Ledger8RuntimeMissingError}, including the coded
|
|
774
|
+
* `Ledger8RuntimeInvalidError` that same guard raises for an incomplete
|
|
775
|
+
* runtime, and a raw module-resolution error on the engine chunk itself.
|
|
776
|
+
*
|
|
777
|
+
* @returns The engine's public surface, memoised after the first successful
|
|
778
|
+
* load.
|
|
779
|
+
* @throws Ledger8RuntimeMissingError If the retained runtime, or the `./engine`
|
|
780
|
+
* chunk itself, cannot be acquired.
|
|
781
|
+
* @throws Ledger8InstanceMismatchError If the construction-time instance guard
|
|
782
|
+
* found `onchain-runtime-v3` resolved to two physically distinct copies.
|
|
783
|
+
* @see {@link ModuleGraphAndLazyLoading}
|
|
784
|
+
* @see {@link EraSeam}
|
|
785
|
+
*/
|
|
786
|
+
const loadLedger8Engine = () => (enginePromise ??= import('./engine.js')
|
|
787
|
+
.then((engineModule) => engineModule.createLedger8Engine())
|
|
788
|
+
.catch((error) => {
|
|
789
|
+
enginePromise = undefined;
|
|
790
|
+
throw error instanceof Ledger8RuntimeMissingError || error instanceof Ledger8InstanceMismatchError
|
|
791
|
+
? error
|
|
792
|
+
: new Ledger8RuntimeMissingError('/engine', error);
|
|
793
|
+
}));
|
|
794
|
+
|
|
795
|
+
export { ComposeFailedError, ComposeOptionError, DownConvertFailedError, Ledger8InstanceMismatchError, Ledger8RuntimeInvalidError, Ledger8RuntimeMissingError, NO_CIRCUIT, StateDecodeFailedError, UnknownLedgerVersionError, loadLedger8, loadLedger8Engine, loadLedgerEra };
|
|
11
796
|
//# sourceMappingURL=index.js.map
|