@lucid-evolution/uplc 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -16,6 +16,8 @@ Before continuing, please note that this step is not part of the CI process. You
16
16
  pnpm build-local
17
17
  ```
18
18
 
19
+ The browser builds are made with wasm-pack. The Node.js builds need wasm-bindgen's `--experimental-reset-state-function`, which wasm-pack cannot pass, so `scripts/build-node.sh` runs cargo, the `wasm-bindgen` CLI and `wasm-opt` itself: both must be on the `PATH`, with the `wasm-bindgen` CLI at the version of `wasm-bindgen` in `rust/Cargo.lock` (`cargo install wasm-bindgen-cli --version <version>`).
20
+
19
21
  ## 3. Build the UPLC Package
20
22
 
21
23
  Once you've completed the previous step, you can build the UPLC package by running:
@@ -33,6 +35,12 @@ The package ships two builds of the evaluator:
33
35
 
34
36
  `@lucid-evolution/uplc` resolves to the speed build on Node, Bun and Deno, and to the size build in browser bundles and edge runtimes (`browser`, `worker`, `workerd` and `edge-light` export conditions). To pick a variant explicitly, import `@lucid-evolution/uplc/speed` or `@lucid-evolution/uplc/size`.
35
37
 
38
+ ## Recovering from a wasm trap
39
+
40
+ On Node.js (the `default` export condition), the bindings recover from a wasm trap. A trap or a stack overflow inside wasm leaves the instance unable to run anything after it, so after any binding throws, the next call first replaces the instance with a fresh one, and the error itself is rethrown unchanged. A result returned before the replacement throws when read afterwards, and freeing it, explicitly or by garbage collection, does not touch the new instance.
41
+
42
+ The browser, worker, workerd and edge-light builds do not recover: a bundler instantiates their wasm once, and wasm-bindgen cannot replace that instance. After a trap there, load the package again (for example in a new worker).
43
+
36
44
  ## Evaluating a program
37
45
 
38
46
  `eval_program_raw` evaluates a UPLC program applied to `Data` arguments, outside of any transaction. The caller builds whatever arguments the program expects, including its script context.
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+
3
+ // Recovers the Node.js bindings from a wasm trap. A trap or a stack overflow
4
+ // inside wasm unwinds without restoring the instance's stack pointer or
5
+ // releasing the state it was using, so every later call on that instance can
6
+ // fail. After a binding throws, the next call first replaces the instance with
7
+ // a fresh one (wasm-bindgen's `__wbg_reset_state`); the error itself is
8
+ // rethrown unchanged. Results that came from a replaced instance throw when
9
+ // read, and freeing them, explicitly or by garbage collection, leaves the
10
+ // current instance alone.
11
+ //
12
+ // Returns a function that wraps one binding of `bindings`.
13
+ module.exports = (bindings) => {
14
+ let replaceInstance = false;
15
+ // The results the current instance returned: only these are freed in it.
16
+ let current = new WeakSet();
17
+
18
+ for (const value of Object.values(bindings)) {
19
+ const free = value?.prototype?.free;
20
+ if (typeof free !== "function") continue;
21
+ value.prototype.free = function () {
22
+ if (current.has(this)) free.call(this);
23
+ };
24
+ if (Symbol.dispose) value.prototype[Symbol.dispose] = value.prototype.free;
25
+ }
26
+
27
+ return (binding) =>
28
+ function (...args) {
29
+ if (replaceInstance) {
30
+ bindings.__wbg_reset_state();
31
+ current = new WeakSet();
32
+ replaceInstance = false;
33
+ }
34
+ let result;
35
+ try {
36
+ result = binding.apply(this, args);
37
+ } catch (error) {
38
+ replaceInstance = true;
39
+ throw error;
40
+ }
41
+ if (typeof result === "object" && result !== null) current.add(result);
42
+ return result;
43
+ };
44
+ };
@@ -1,98 +1,6 @@
1
1
  /* tslint:disable */
2
2
  /* eslint-disable */
3
- export function eval_phase_two_raw(
4
- tx_bytes: Uint8Array,
5
- utxos_bytes_x: Uint8Array[],
6
- utxos_bytes_y: Uint8Array[],
7
- cost_mdls_bytes: Uint8Array,
8
- initial_budget_n: bigint,
9
- initial_budget_d: bigint,
10
- slot_config_x: bigint,
11
- slot_config_y: bigint,
12
- slot_config_z: number,
13
- protocol_major_version?: number | null,
14
- ): Uint8Array[];
15
- export function apply_params_to_script(
16
- params_bytes: Uint8Array,
17
- plutus_script_bytes: Uint8Array,
18
- ): Uint8Array;
19
- /**
20
- * Evaluates a UPLC program applied to Data arguments, outside of any
21
- * transaction: the caller builds whatever arguments the program expects,
22
- * including its script context.
23
- *
24
- * - `program_flat`: the program, flat-encoded without a CBOR wrapper.
25
- * - `args_cbor`: the arguments, each one CBOR-encoded Data, applied in order.
26
- * - `language`: the Plutus version to evaluate as, 1, 2 or 3.
27
- * - `protocol_major_version`: the protocol version whose semantics to use,
28
- * from 5 (Alonzo) to 12 (Dijkstra).
29
- * - `cost_model`: the cost model parameters, every one the evaluator knows
30
- * for this Plutus version (350 for Plutus V3), in the ledger's order.
31
- * - `budget_cpu`, `budget_mem`: the budget.
32
- * - `strict_budget`: charge every step as the machine takes it, and stop the
33
- * program as soon as it goes over budget, instead of charging steps and
34
- * checking the budget every 200 steps as the ledger does. Only the cost of a
35
- * program that fails differs: the ledger does not charge the steps it took
36
- * since the budget was last checked.
37
- *
38
- * Fails only when the inputs are malformed or unsupported. A program that fails
39
- * is an [`EvalProgramResult`] that is not `ok`.
40
- */
41
- export function eval_program_raw(
42
- program_flat: Uint8Array,
43
- args_cbor: Uint8Array[],
44
- language: number,
45
- protocol_major_version: number,
46
- cost_model: BigInt64Array,
47
- budget_cpu: bigint,
48
- budget_mem: bigint,
49
- strict_budget: boolean,
50
- ): EvalProgramResult;
51
- /**
52
- * Describes this build of the evaluator as JSON: the uplc crate it was built
53
- * from, the length of each Plutus version's cost model, and a digest of what a
54
- * fixed set of programs evaluate to, with their costs, under Plutus V3 and the
55
- * latest protocol version. Two builds with the same digest agree on those
56
- * programs; `selfTest` says whether this one gives the expected results.
57
- */
58
- export function uplc_build_info(): string;
59
- /**
60
- * Evaluates the builtin `tag` applied to `args` as a Plutus V3 script
61
- * evaluates it at a protocol version, without any program around it: the
62
- * result, or how it fails, is what the machine gives for the saturated
63
- * application.
64
- *
65
- * - `tag`: the builtin's flat tag (0 for addInteger to 100 for scaleValue).
66
- * The Miller-loop builtins (68 to 70) are not supported, since their
67
- * results cannot be returned.
68
- * - `args`: exactly the builtin's arguments, in order, each encoded as the
69
- * matching entry of `arg_kinds` says, a [`BuiltinValueKind`]: 0 for a
70
- * flat-encoded `(program 1.1.0 (con …))`, 1 for a compressed G1 point, 2
71
- * for a compressed G2 point, 3 for a list of G1 points, 4 for a list of G2
72
- * points, 5 for an array of G1 points and 6 for an array of G2 points, each
73
- * list or array as the compressed points one after the other. Flat cannot
74
- * encode BLS12-381 points, so they cross as their compressed bytes.
75
- * - `protocol_major_version`: from 9 (Chang, which introduced Plutus V3) to
76
- * 12 (Dijkstra). It decides which builtins are available and the semantics
77
- * they have.
78
- *
79
- * The result's `cpu` and `mem` are the builtin's charge for the application
80
- * under Plutus' default Plutus V3 cost model (not the ledger's protocol
81
- * parameters), excluding the machine's per-step costs.
82
- *
83
- * Fails only when the inputs are malformed or unsupported: an unknown or
84
- * Miller-loop tag, a number of arguments other than the builtin's arity, an
85
- * argument that does not decode as its kind says or is not a constant, an
86
- * invalid compressed point, a protocol version out of range, or a result that
87
- * none of the kinds can encode. A builtin that fails is an
88
- * [`EvalBuiltinResult`] that is not `ok`.
89
- */
90
- export function eval_builtin_raw(
91
- tag: number,
92
- args: Uint8Array[],
93
- arg_kinds: Uint8Array,
94
- protocol_major_version: number,
95
- ): EvalBuiltinResult;
3
+
96
4
  /**
97
5
  * Why the builtin given to [`eval_builtin_raw`] did not return a value: the
98
6
  * codes of the result's `error_kind`.
@@ -116,6 +24,7 @@ export enum BuiltinErrorKind {
116
24
  */
117
25
  Failed = 3,
118
26
  }
27
+
119
28
  /**
120
29
  * How a value of [`eval_builtin_raw`] is encoded: the codes of its
121
30
  * `arg_kinds` and of the result's `result_kind`.
@@ -156,16 +65,22 @@ export enum BuiltinValueKind {
156
65
  */
157
66
  G2Array = 6,
158
67
  }
68
+
159
69
  /**
160
70
  * The outcome of [`eval_builtin_raw`].
161
71
  */
162
72
  export class EvalBuiltinResult {
163
73
  private constructor();
164
74
  free(): void;
75
+ [Symbol.dispose](): void;
165
76
  /**
166
- * Whether the builtin returned a value.
77
+ * The CPU the builtin's cost model charges for this application, under
78
+ * Plutus' default cost model for Plutus V3 at the protocol version; 0
79
+ * when the builtin was not costed (error kinds 1 and 2). It leaves out the
80
+ * machine's own step costs for evaluating the application (the builtin,
81
+ * each force and each apply).
167
82
  */
168
- ok: boolean;
83
+ cpu: bigint;
169
84
  /**
170
85
  * Why the builtin did not return a value, a [`BuiltinErrorKind`]: 0 when
171
86
  * it did, 1 when it is not available to Plutus V3 at the protocol version,
@@ -174,53 +89,42 @@ export class EvalBuiltinResult {
174
89
  */
175
90
  error_kind: number;
176
91
  /**
177
- * How `result` encodes the value, a [`BuiltinValueKind`] as for the
178
- * arguments of [`eval_builtin_raw`]; 0 when there is no value.
92
+ * The evaluator's description of why the builtin did not return a value;
93
+ * empty when it did.
179
94
  */
180
- result_kind: number;
95
+ error: string;
181
96
  /**
182
- * The value the builtin returned; empty when there is none.
97
+ * The memory the builtin's cost model charges for this application; see
98
+ * `cpu`.
183
99
  */
184
- result: Uint8Array;
100
+ mem: bigint;
185
101
  /**
186
- * The CPU the builtin's cost model charges for this application, under
187
- * Plutus' default cost model for Plutus V3 at the protocol version; 0
188
- * when the builtin was not costed (error kinds 1 and 2). It leaves out the
189
- * machine's own step costs for evaluating the application (the builtin,
190
- * each force and each apply).
102
+ * Whether the builtin returned a value.
191
103
  */
192
- cpu: bigint;
104
+ ok: boolean;
193
105
  /**
194
- * The memory the builtin's cost model charges for this application; see
195
- * `cpu`.
106
+ * How `result` encodes the value, a [`BuiltinValueKind`] as for the
107
+ * arguments of [`eval_builtin_raw`]; 0 when there is no value.
196
108
  */
197
- mem: bigint;
109
+ result_kind: number;
198
110
  /**
199
- * The evaluator's description of why the builtin did not return a value;
200
- * empty when it did.
111
+ * The value the builtin returned; empty when there is none.
201
112
  */
202
- error: string;
113
+ result: Uint8Array;
203
114
  }
115
+
204
116
  /**
205
117
  * The outcome of [`eval_program_raw`].
206
118
  */
207
119
  export class EvalProgramResult {
208
120
  private constructor();
209
121
  free(): void;
210
- /**
211
- * Whether the program succeeded: it did not fail and, for Plutus V3, it
212
- * returned unit.
213
- */
214
- ok: boolean;
122
+ [Symbol.dispose](): void;
215
123
  /**
216
124
  * The CPU the program used. A program that went over budget is charged
217
125
  * what it used up to the point where the machine stopped it.
218
126
  */
219
127
  cpu: bigint;
220
- /**
221
- * The memory the program used.
222
- */
223
- mem: bigint;
224
128
  /**
225
129
  * Why the program did not succeed: 0 when it did, 1 when it went over
226
130
  * budget, 2 when it failed in any other way and 3 when a Plutus V3 program
@@ -231,4 +135,111 @@ export class EvalProgramResult {
231
135
  * The messages the program traced, in order.
232
136
  */
233
137
  logs: string[];
138
+ /**
139
+ * The memory the program used.
140
+ */
141
+ mem: bigint;
142
+ /**
143
+ * Whether the program succeeded: it did not fail and, for Plutus V3, it
144
+ * returned unit.
145
+ */
146
+ ok: boolean;
234
147
  }
148
+
149
+ export function apply_params_to_script(
150
+ params_bytes: Uint8Array,
151
+ plutus_script_bytes: Uint8Array,
152
+ ): Uint8Array;
153
+
154
+ /**
155
+ * Evaluates the builtin `tag` applied to `args` as a Plutus V3 script
156
+ * evaluates it at a protocol version, without any program around it: the
157
+ * result, or how it fails, is what the machine gives for the saturated
158
+ * application.
159
+ *
160
+ * - `tag`: the builtin's flat tag (0 for addInteger to 100 for scaleValue).
161
+ * The Miller-loop builtins (68 to 70) are not supported, since their
162
+ * results cannot be returned.
163
+ * - `args`: exactly the builtin's arguments, in order, each encoded as the
164
+ * matching entry of `arg_kinds` says, a [`BuiltinValueKind`]: 0 for a
165
+ * flat-encoded `(program 1.1.0 (con …))`, 1 for a compressed G1 point, 2
166
+ * for a compressed G2 point, 3 for a list of G1 points, 4 for a list of G2
167
+ * points, 5 for an array of G1 points and 6 for an array of G2 points, each
168
+ * list or array as the compressed points one after the other. Flat cannot
169
+ * encode BLS12-381 points, so they cross as their compressed bytes.
170
+ * - `protocol_major_version`: from 9 (Chang, which introduced Plutus V3) to
171
+ * 12 (Dijkstra). It decides which builtins are available and the semantics
172
+ * they have.
173
+ *
174
+ * The result's `cpu` and `mem` are the builtin's charge for the application
175
+ * under Plutus' default Plutus V3 cost model (not the ledger's protocol
176
+ * parameters), excluding the machine's per-step costs.
177
+ *
178
+ * Fails only when the inputs are malformed or unsupported: an unknown or
179
+ * Miller-loop tag, a number of arguments other than the builtin's arity, an
180
+ * argument that does not decode as its kind says or is not a constant, an
181
+ * invalid compressed point, a protocol version out of range, or a result that
182
+ * none of the kinds can encode. A builtin that fails is an
183
+ * [`EvalBuiltinResult`] that is not `ok`.
184
+ */
185
+ export function eval_builtin_raw(
186
+ tag: number,
187
+ args: Uint8Array[],
188
+ arg_kinds: Uint8Array,
189
+ protocol_major_version: number,
190
+ ): EvalBuiltinResult;
191
+
192
+ export function eval_phase_two_raw(
193
+ tx_bytes: Uint8Array,
194
+ utxos_bytes_x: Uint8Array[],
195
+ utxos_bytes_y: Uint8Array[],
196
+ cost_mdls_bytes: Uint8Array,
197
+ initial_budget_n: bigint,
198
+ initial_budget_d: bigint,
199
+ slot_config_x: bigint,
200
+ slot_config_y: bigint,
201
+ slot_config_z: number,
202
+ protocol_major_version?: number | null,
203
+ ): Uint8Array[];
204
+
205
+ /**
206
+ * Evaluates a UPLC program applied to Data arguments, outside of any
207
+ * transaction: the caller builds whatever arguments the program expects,
208
+ * including its script context.
209
+ *
210
+ * - `program_flat`: the program, flat-encoded without a CBOR wrapper.
211
+ * - `args_cbor`: the arguments, each one CBOR-encoded Data, applied in order.
212
+ * - `language`: the Plutus version to evaluate as, 1, 2 or 3.
213
+ * - `protocol_major_version`: the protocol version whose semantics to use,
214
+ * from 5 (Alonzo) to 12 (Dijkstra).
215
+ * - `cost_model`: the cost model parameters, every one the evaluator knows
216
+ * for this Plutus version (350 for Plutus V3), in the ledger's order.
217
+ * - `budget_cpu`, `budget_mem`: the budget.
218
+ * - `strict_budget`: charge every step as the machine takes it, and stop the
219
+ * program as soon as it goes over budget, instead of charging steps and
220
+ * checking the budget every 200 steps as the ledger does. Only the cost of a
221
+ * program that fails differs: the ledger does not charge the steps it took
222
+ * since the budget was last checked.
223
+ *
224
+ * Fails only when the inputs are malformed or unsupported. A program that fails
225
+ * is an [`EvalProgramResult`] that is not `ok`.
226
+ */
227
+ export function eval_program_raw(
228
+ program_flat: Uint8Array,
229
+ args_cbor: Uint8Array[],
230
+ language: number,
231
+ protocol_major_version: number,
232
+ cost_model: BigInt64Array,
233
+ budget_cpu: bigint,
234
+ budget_mem: bigint,
235
+ strict_budget: boolean,
236
+ ): EvalProgramResult;
237
+
238
+ /**
239
+ * Describes this build of the evaluator as JSON: the uplc crate it was built
240
+ * from, the length of each Plutus version's cost model, and a digest of what a
241
+ * fixed set of programs evaluate to, with their costs, under Plutus V3 and the
242
+ * latest protocol version. Two builds with the same digest agree on those
243
+ * programs; `selfTest` says whether this one gives the expected results.
244
+ */
245
+ export function uplc_build_info(): string;
@@ -1,5 +1,9 @@
1
+ /* @ts-self-types="./uplc_tx.d.ts" */
1
2
  import * as wasm from "./uplc_tx_bg.wasm";
2
- export * from "./uplc_tx_bg.js";
3
3
  import { __wbg_set_wasm } from "./uplc_tx_bg.js";
4
+
4
5
  __wbg_set_wasm(wasm);
5
6
  wasm.__wbindgen_start();
7
+ export {
8
+ BuiltinErrorKind, BuiltinValueKind, EvalBuiltinResult, EvalProgramResult, apply_params_to_script, eval_builtin_raw, eval_phase_two_raw, eval_program_raw, uplc_build_info
9
+ } from "./uplc_tx_bg.js";