@dcasegr/amm-client 0.0.0-stage → 0.38.2
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 +107 -2
- package/dist/client.d.ts +534 -0
- package/dist/client.js +1319 -0
- package/dist/errors.d.ts +17 -0
- package/dist/errors.js +75 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.js +53 -0
- package/dist/lib/config.d.ts +42 -0
- package/dist/lib/config.js +64 -0
- package/dist/lib/keys.d.ts +42 -0
- package/dist/lib/keys.js +48 -0
- package/dist/lib/overlay.d.ts +190 -0
- package/dist/lib/overlay.js +302 -0
- package/dist/lib/skein.d.ts +82 -0
- package/dist/lib/skein.js +142 -0
- package/dist/lib/tokenId.d.ts +72 -0
- package/dist/lib/tokenId.js +121 -0
- package/dist/lp/amounts.d.ts +12 -0
- package/dist/lp/amounts.js +38 -0
- package/dist/lp/close.d.ts +90 -0
- package/dist/lp/close.js +140 -0
- package/dist/lp/images.d.ts +11 -0
- package/dist/lp/images.js +45 -0
- package/dist/lp/inventory.d.ts +68 -0
- package/dist/lp/inventory.js +84 -0
- package/dist/lp/poolDeploy.d.ts +220 -0
- package/dist/lp/poolDeploy.js +291 -0
- package/dist/lp/poolRows.d.ts +13 -0
- package/dist/lp/poolRows.js +19 -0
- package/dist/lp/positions.d.ts +81 -0
- package/dist/lp/positions.js +144 -0
- package/dist/lp/rebalance.d.ts +101 -0
- package/dist/lp/rebalance.js +168 -0
- package/dist/lp/wallet.d.ts +12 -0
- package/dist/lp/wallet.js +19 -0
- package/dist/market/activeSwap.d.ts +158 -0
- package/dist/market/activeSwap.js +320 -0
- package/dist/market/plan.d.ts +85 -0
- package/dist/market/plan.js +149 -0
- package/dist/market/prices.d.ts +13 -0
- package/dist/market/prices.js +14 -0
- package/dist/market/relay.d.ts +84 -0
- package/dist/market/relay.js +201 -0
- package/dist/market/swapAction.d.ts +306 -0
- package/dist/market/swapAction.js +508 -0
- package/dist/market/swapFlow.d.ts +58 -0
- package/dist/market/swapFlow.js +86 -0
- package/dist/market/view.d.ts +58 -0
- package/dist/market/view.js +63 -0
- package/dist/pool/artifact.d.ts +23 -0
- package/dist/pool/artifact.js +38 -0
- package/dist/pool/index.d.ts +8 -0
- package/dist/pool/index.js +8 -0
- package/dist/pool/oneColor.d.ts +19 -0
- package/dist/pool/oneColor.js +39 -0
- package/dist/pool/pool.artifact.json +5069 -0
- package/dist/pool/runar-ir-schema.d.ts +21 -0
- package/dist/pool/runar-ir-schema.js +18 -0
- package/dist/pool/template.d.ts +295 -0
- package/dist/pool/template.js +715 -0
- package/dist/vendor/runar/LICENSE +21 -0
- package/dist/vendor/runar/NOTICE +15 -0
- package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.d.ts +42 -0
- package/dist/vendor/runar/runar-ir-schema/src/abi-type-encoding.js +53 -0
- package/dist/vendor/runar/runar-ir-schema/src/anf-ir.d.ts +221 -0
- package/dist/vendor/runar/runar-ir-schema/src/anf-ir.js +33 -0
- package/dist/vendor/runar/runar-ir-schema/src/artifact.d.ts +288 -0
- package/dist/vendor/runar/runar-ir-schema/src/artifact.js +8 -0
- package/dist/vendor/runar/runar-ir-schema/src/canonical-json.d.ts +43 -0
- package/dist/vendor/runar/runar-ir-schema/src/canonical-json.js +204 -0
- package/dist/vendor/runar/runar-ir-schema/src/input-limits.d.ts +89 -0
- package/dist/vendor/runar/runar-ir-schema/src/input-limits.js +100 -0
- package/dist/vendor/runar/runar-ir-schema/src/stack-ir.d.ts +118 -0
- package/dist/vendor/runar/runar-ir-schema/src/stack-ir.js +8 -0
- package/dist/vendor/runar/runar-ir-schema/src/state-layout.d.ts +56 -0
- package/dist/vendor/runar/runar-ir-schema/src/state-layout.js +145 -0
- package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.d.ts +18 -0
- package/dist/vendor/runar/runar-ir-schema/src/unknown-anf-kind-error.js +25 -0
- package/dist/vendor/runar/runar-sdk/src/anf-interpreter.d.ts +160 -0
- package/dist/vendor/runar/runar-sdk/src/anf-interpreter.js +1149 -0
- package/dist/vendor/runar/runar-sdk/src/calling.d.ts +98 -0
- package/dist/vendor/runar/runar-sdk/src/calling.js +209 -0
- package/dist/vendor/runar/runar-sdk/src/contract.d.ts +443 -0
- package/dist/vendor/runar/runar-sdk/src/contract.js +2516 -0
- package/dist/vendor/runar/runar-sdk/src/deployment.d.ts +36 -0
- package/dist/vendor/runar/runar-sdk/src/deployment.js +119 -0
- package/dist/vendor/runar/runar-sdk/src/errors.d.ts +46 -0
- package/dist/vendor/runar/runar-sdk/src/errors.js +59 -0
- package/dist/vendor/runar/runar-sdk/src/oppushtx.d.ts +23 -0
- package/dist/vendor/runar/runar-sdk/src/oppushtx.js +95 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.d.ts +31 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/envelope.js +272 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/types.d.ts +21 -0
- package/dist/vendor/runar/runar-sdk/src/ordinals/types.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/providers/provider.d.ts +65 -0
- package/dist/vendor/runar/runar-sdk/src/providers/provider.js +59 -0
- package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.d.ts +94 -0
- package/dist/vendor/runar/runar-sdk/src/providers/wallet-provider.js +297 -0
- package/dist/vendor/runar/runar-sdk/src/script-utils.d.ts +54 -0
- package/dist/vendor/runar/runar-sdk/src/script-utils.js +252 -0
- package/dist/vendor/runar/runar-sdk/src/signers/signer.d.ts +17 -0
- package/dist/vendor/runar/runar-sdk/src/signers/signer.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/spend-safety.d.ts +31 -0
- package/dist/vendor/runar/runar-sdk/src/spend-safety.js +35 -0
- package/dist/vendor/runar/runar-sdk/src/state.d.ts +54 -0
- package/dist/vendor/runar/runar-sdk/src/state.js +584 -0
- package/dist/vendor/runar/runar-sdk/src/types.d.ts +227 -0
- package/dist/vendor/runar/runar-sdk/src/types.js +4 -0
- package/dist/vendor/runar/runar-sdk/src/unsound-primitives.d.ts +30 -0
- package/dist/vendor/runar/runar-sdk/src/unsound-primitives.js +42 -0
- package/dist/vendor/runar/runar-sdk.d.ts +9 -0
- package/dist/vendor/runar/runar-sdk.js +8 -0
- package/dist/wallet/action.d.ts +28 -0
- package/dist/wallet/action.js +42 -0
- package/dist/wallet/brc29.d.ts +83 -0
- package/dist/wallet/brc29.js +80 -0
- package/dist/wallet/color.d.ts +110 -0
- package/dist/wallet/color.js +134 -0
- package/dist/wallet/swapPayouts.d.ts +35 -0
- package/dist/wallet/swapPayouts.js +146 -0
- package/package.json +39 -4
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rúnar Artifact — the final compiled output of a Rúnar compiler (Pass 6).
|
|
3
|
+
*
|
|
4
|
+
* This is what gets consumed by wallets, SDKs, and deployment tooling.
|
|
5
|
+
* It bundles the locking script, ABI metadata, optional debug info,
|
|
6
|
+
* and (for stateful contracts) state field descriptors.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 / JCS (JSON Canonicalization Scheme) serializer.
|
|
3
|
+
*
|
|
4
|
+
* Produces a deterministic, byte-identical JSON string for any JSON-compatible
|
|
5
|
+
* value. This is used to guarantee that two Rúnar compilers emitting the same
|
|
6
|
+
* ANF IR will produce identical output when serialised.
|
|
7
|
+
*
|
|
8
|
+
* Key properties:
|
|
9
|
+
* - Object keys are sorted by their UTF-16 code-unit values (per ES spec).
|
|
10
|
+
* - Numbers use ES `JSON.stringify` serialization (IEEE 754, no trailing
|
|
11
|
+
* zeros, no positive sign on exponent, etc.).
|
|
12
|
+
* - No whitespace.
|
|
13
|
+
* - `undefined` values and `undefined` array slots are not allowed (will
|
|
14
|
+
* throw).
|
|
15
|
+
* - `bigint` values are serialised as bare integers (no quotes), matching the
|
|
16
|
+
* JSON Schema `integer` type used in the ANF IR schema.
|
|
17
|
+
*
|
|
18
|
+
* DoS-bound input guards:
|
|
19
|
+
* - Recursion depth is capped at {@link InputLimits.MAX_NESTING}.
|
|
20
|
+
* - Individual string values are capped at {@link InputLimits.MAX_STRING_BYTES}.
|
|
21
|
+
* - Total serialised output is capped at {@link InputLimits.MAX_IR_BYTES}.
|
|
22
|
+
* - Bound violations throw {@link CanonicalJsonError} with `code` / `limit` /
|
|
23
|
+
* `actual` set for typed downstream handling.
|
|
24
|
+
*
|
|
25
|
+
* @see https://www.rfc-editor.org/rfc/rfc8785
|
|
26
|
+
*/
|
|
27
|
+
/**
|
|
28
|
+
* Serialise a value to canonical JSON (RFC 8785 / JCS).
|
|
29
|
+
*
|
|
30
|
+
* @throws {TypeError} if the value contains functions or symbols.
|
|
31
|
+
* @throws {CanonicalJsonError} if recursion depth, string byte length, or
|
|
32
|
+
* total output byte length exceeds the documented {@link InputLimits}.
|
|
33
|
+
*/
|
|
34
|
+
export declare function canonicalJsonStringify(value: unknown): string;
|
|
35
|
+
/**
|
|
36
|
+
* Parse a JSON string and re-serialise it to canonical form.
|
|
37
|
+
* Useful for normalising IR that was stored with pretty-printing.
|
|
38
|
+
*
|
|
39
|
+
* @throws {CanonicalJsonError} with `code: 'invalid'` if the input is not
|
|
40
|
+
* valid JSON, or with `code: 'bytes'` / `'depth'` / `'string-bytes'` if
|
|
41
|
+
* the canonicalised output would violate an {@link InputLimits} bound.
|
|
42
|
+
*/
|
|
43
|
+
export declare function canonicalise(json: string): string;
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 8785 / JCS (JSON Canonicalization Scheme) serializer.
|
|
3
|
+
*
|
|
4
|
+
* Produces a deterministic, byte-identical JSON string for any JSON-compatible
|
|
5
|
+
* value. This is used to guarantee that two Rúnar compilers emitting the same
|
|
6
|
+
* ANF IR will produce identical output when serialised.
|
|
7
|
+
*
|
|
8
|
+
* Key properties:
|
|
9
|
+
* - Object keys are sorted by their UTF-16 code-unit values (per ES spec).
|
|
10
|
+
* - Numbers use ES `JSON.stringify` serialization (IEEE 754, no trailing
|
|
11
|
+
* zeros, no positive sign on exponent, etc.).
|
|
12
|
+
* - No whitespace.
|
|
13
|
+
* - `undefined` values and `undefined` array slots are not allowed (will
|
|
14
|
+
* throw).
|
|
15
|
+
* - `bigint` values are serialised as bare integers (no quotes), matching the
|
|
16
|
+
* JSON Schema `integer` type used in the ANF IR schema.
|
|
17
|
+
*
|
|
18
|
+
* DoS-bound input guards:
|
|
19
|
+
* - Recursion depth is capped at {@link InputLimits.MAX_NESTING}.
|
|
20
|
+
* - Individual string values are capped at {@link InputLimits.MAX_STRING_BYTES}.
|
|
21
|
+
* - Total serialised output is capped at {@link InputLimits.MAX_IR_BYTES}.
|
|
22
|
+
* - Bound violations throw {@link CanonicalJsonError} with `code` / `limit` /
|
|
23
|
+
* `actual` set for typed downstream handling.
|
|
24
|
+
*
|
|
25
|
+
* @see https://www.rfc-editor.org/rfc/rfc8785
|
|
26
|
+
*/
|
|
27
|
+
import { InputLimits, CanonicalJsonError } from './input-limits.js';
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// Public API
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
/**
|
|
32
|
+
* Serialise a value to canonical JSON (RFC 8785 / JCS).
|
|
33
|
+
*
|
|
34
|
+
* @throws {TypeError} if the value contains functions or symbols.
|
|
35
|
+
* @throws {CanonicalJsonError} if recursion depth, string byte length, or
|
|
36
|
+
* total output byte length exceeds the documented {@link InputLimits}.
|
|
37
|
+
*/
|
|
38
|
+
export function canonicalJsonStringify(value) {
|
|
39
|
+
const result = serialise(value, new Set(), 0);
|
|
40
|
+
// Final output-byte-length guard (UTF-8 bytes).
|
|
41
|
+
const byteLen = Buffer.byteLength(result, 'utf8');
|
|
42
|
+
if (byteLen > InputLimits.MAX_IR_BYTES) {
|
|
43
|
+
throw new CanonicalJsonError('bytes', `canonical JSON output exceeds ${InputLimits.MAX_IR_BYTES} bytes (actual ${byteLen})`, { limit: InputLimits.MAX_IR_BYTES, actual: byteLen });
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse a JSON string and re-serialise it to canonical form.
|
|
49
|
+
* Useful for normalising IR that was stored with pretty-printing.
|
|
50
|
+
*
|
|
51
|
+
* @throws {CanonicalJsonError} with `code: 'invalid'` if the input is not
|
|
52
|
+
* valid JSON, or with `code: 'bytes'` / `'depth'` / `'string-bytes'` if
|
|
53
|
+
* the canonicalised output would violate an {@link InputLimits} bound.
|
|
54
|
+
*/
|
|
55
|
+
export function canonicalise(json) {
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = JSON.parse(json);
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
throw new CanonicalJsonError('invalid', `canonicalise: input is not valid JSON: ${e.message}`);
|
|
62
|
+
}
|
|
63
|
+
return canonicalJsonStringify(parsed);
|
|
64
|
+
}
|
|
65
|
+
// ---------------------------------------------------------------------------
|
|
66
|
+
// Serialisation engine
|
|
67
|
+
// ---------------------------------------------------------------------------
|
|
68
|
+
function serialise(value, seen, depth) {
|
|
69
|
+
// null
|
|
70
|
+
if (value === null) {
|
|
71
|
+
return 'null';
|
|
72
|
+
}
|
|
73
|
+
// Primitives
|
|
74
|
+
switch (typeof value) {
|
|
75
|
+
case 'boolean':
|
|
76
|
+
return value ? 'true' : 'false';
|
|
77
|
+
case 'number':
|
|
78
|
+
return serialiseNumber(value);
|
|
79
|
+
case 'bigint':
|
|
80
|
+
// Serialise as a bare JSON integer — no quotes.
|
|
81
|
+
return value.toString();
|
|
82
|
+
case 'string':
|
|
83
|
+
return serialiseString(value);
|
|
84
|
+
case 'undefined':
|
|
85
|
+
case 'symbol':
|
|
86
|
+
case 'function':
|
|
87
|
+
throw new TypeError(`canonical JSON does not support ${typeof value}`);
|
|
88
|
+
}
|
|
89
|
+
// Objects and arrays (typeof === 'object' at this point)
|
|
90
|
+
// Depth guard before descending into the container.
|
|
91
|
+
//
|
|
92
|
+
// R-260/R-261: the bound is MAX_WIRE_NESTING (100), not MAX_NESTING (512).
|
|
93
|
+
// canonicalJson's output crosses a tier boundary and its bound has to be the
|
|
94
|
+
// same number verifyEnvelope will PARSE on the far side — if emit allowed
|
|
95
|
+
// more than parse, a tier could produce a legal, correctly-signed envelope
|
|
96
|
+
// another tier is physically unable to read. 512 stays the `--ir` loader's
|
|
97
|
+
// bound, where the input is a trusted local file.
|
|
98
|
+
if (depth >= InputLimits.MAX_WIRE_NESTING) {
|
|
99
|
+
throw new CanonicalJsonError('depth', `canonical JSON nesting exceeds ${InputLimits.MAX_WIRE_NESTING}`, { limit: InputLimits.MAX_WIRE_NESTING, actual: depth + 1 });
|
|
100
|
+
}
|
|
101
|
+
const obj = value;
|
|
102
|
+
// Circular reference detection
|
|
103
|
+
if (seen.has(obj)) {
|
|
104
|
+
throw new TypeError('canonical JSON does not support circular references');
|
|
105
|
+
}
|
|
106
|
+
seen.add(obj);
|
|
107
|
+
// Arrays and objects (including typed arrays, Date, RegExp, etc.) both
|
|
108
|
+
// route through serialiseObject which honours `toJSON` and otherwise
|
|
109
|
+
// walks own enumerable keys.
|
|
110
|
+
const result = Array.isArray(obj)
|
|
111
|
+
? serialiseArray(obj, seen, depth + 1)
|
|
112
|
+
: serialiseObject(obj, seen, depth + 1);
|
|
113
|
+
seen.delete(obj);
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
// ---------------------------------------------------------------------------
|
|
117
|
+
// Number serialisation (ES2022 §25.5.2.1)
|
|
118
|
+
// ---------------------------------------------------------------------------
|
|
119
|
+
function serialiseNumber(n) {
|
|
120
|
+
if (!Number.isFinite(n)) {
|
|
121
|
+
throw new TypeError(`canonical JSON does not support ${n} (NaN / Infinity)`);
|
|
122
|
+
}
|
|
123
|
+
if (Object.is(n, -0)) {
|
|
124
|
+
return '0';
|
|
125
|
+
}
|
|
126
|
+
// JSON.stringify for finite numbers matches the ES spec requirement
|
|
127
|
+
// that RFC 8785 mandates.
|
|
128
|
+
return JSON.stringify(n);
|
|
129
|
+
}
|
|
130
|
+
// ---------------------------------------------------------------------------
|
|
131
|
+
// String serialisation (RFC 8785 §3.2.2.2)
|
|
132
|
+
// ---------------------------------------------------------------------------
|
|
133
|
+
function serialiseString(s) {
|
|
134
|
+
// Per-string byte-length guard.
|
|
135
|
+
const byteLen = Buffer.byteLength(s, 'utf8');
|
|
136
|
+
if (byteLen > InputLimits.MAX_STRING_BYTES) {
|
|
137
|
+
throw new CanonicalJsonError('string-bytes', `canonical JSON string field exceeds ${InputLimits.MAX_STRING_BYTES} bytes (actual ${byteLen})`, { limit: InputLimits.MAX_STRING_BYTES, actual: byteLen });
|
|
138
|
+
}
|
|
139
|
+
// RFC 8785 §3.2.2.2 / audit D6: the input MUST be well-formed Unicode.
|
|
140
|
+
// JS strings are UTF-16 code-unit sequences and may legally contain
|
|
141
|
+
// unpaired surrogates; `JSON.stringify` happily emits them, producing
|
|
142
|
+
// bytes that the six other SDK tiers reject. Walk code units, reject any
|
|
143
|
+
// unpaired surrogate, and only then delegate to `JSON.stringify` for the
|
|
144
|
+
// actual escape table (which is correct on well-formed inputs).
|
|
145
|
+
for (let i = 0; i < s.length; i++) {
|
|
146
|
+
const c = s.charCodeAt(i);
|
|
147
|
+
if (c >= 0xD800 && c <= 0xDBFF) {
|
|
148
|
+
const next = i + 1 < s.length ? s.charCodeAt(i + 1) : -1;
|
|
149
|
+
if (next < 0xDC00 || next > 0xDFFF) {
|
|
150
|
+
throw new CanonicalJsonError('lone-surrogate', `canonical JSON: lone high surrogate U+${c.toString(16).toUpperCase().padStart(4, '0')} in string`);
|
|
151
|
+
}
|
|
152
|
+
i++; // skip the valid low surrogate
|
|
153
|
+
}
|
|
154
|
+
else if (c >= 0xDC00 && c <= 0xDFFF) {
|
|
155
|
+
throw new CanonicalJsonError('lone-surrogate', `canonical JSON: lone low surrogate U+${c.toString(16).toUpperCase().padStart(4, '0')} in string`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
// JSON.stringify already produces correct escaping for most cases.
|
|
159
|
+
// RFC 8785 additionally requires that code-points U+0000–U+001F are
|
|
160
|
+
// \uXXXX-escaped (which JSON.stringify does), and that there is no
|
|
161
|
+
// gratuitous escaping of solidus '/' (JSON.stringify does NOT escape it
|
|
162
|
+
// by default in modern engines, which is correct).
|
|
163
|
+
return JSON.stringify(s);
|
|
164
|
+
}
|
|
165
|
+
// ---------------------------------------------------------------------------
|
|
166
|
+
// Array serialisation
|
|
167
|
+
// ---------------------------------------------------------------------------
|
|
168
|
+
function serialiseArray(arr, seen, depth) {
|
|
169
|
+
const parts = [];
|
|
170
|
+
for (let i = 0; i < arr.length; i++) {
|
|
171
|
+
const element = arr[i];
|
|
172
|
+
if (element === undefined) {
|
|
173
|
+
// JSON.stringify converts undefined array elements to null.
|
|
174
|
+
parts.push('null');
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
parts.push(serialise(element, seen, depth));
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return '[' + parts.join(',') + ']';
|
|
181
|
+
}
|
|
182
|
+
// ---------------------------------------------------------------------------
|
|
183
|
+
// Object serialisation (keys sorted by UTF-16 code-unit value)
|
|
184
|
+
// ---------------------------------------------------------------------------
|
|
185
|
+
function serialiseObject(obj, seen, depth) {
|
|
186
|
+
// If the object has a toJSON method, use it (Date, etc.)
|
|
187
|
+
const asAny = obj;
|
|
188
|
+
if (typeof asAny['toJSON'] === 'function') {
|
|
189
|
+
return serialise(asAny['toJSON'](), seen, depth);
|
|
190
|
+
}
|
|
191
|
+
// Collect own enumerable string keys and sort by UTF-16 code units.
|
|
192
|
+
// In ES, `Array.prototype.sort()` without a comparator uses the
|
|
193
|
+
// default string comparison which is exactly UTF-16 code-unit order.
|
|
194
|
+
const keys = Object.keys(obj).sort();
|
|
195
|
+
const parts = [];
|
|
196
|
+
for (const key of keys) {
|
|
197
|
+
const val = obj[key];
|
|
198
|
+
// JSON.stringify omits keys whose value is undefined.
|
|
199
|
+
if (val === undefined)
|
|
200
|
+
continue;
|
|
201
|
+
parts.push(serialiseString(key) + ':' + serialise(val, seen, depth));
|
|
202
|
+
}
|
|
203
|
+
return '{' + parts.join(',') + '}';
|
|
204
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared DoS-bound input limits + typed error class used by all public
|
|
3
|
+
* canonical-JSON / IR-loading entry points across the runar-ir-schema
|
|
4
|
+
* package and its downstream consumers.
|
|
5
|
+
*
|
|
6
|
+
* Justifications:
|
|
7
|
+
* - MAX_SCRIPT_BYTES = 4 MiB — the largest legitimate script measured by
|
|
8
|
+
* the script-size benchmark is `p384-wallet` at ~1.87 MB; 4 MiB gives
|
|
9
|
+
* ~2× headroom without enabling pathological 50 MB scripts. An earlier
|
|
10
|
+
* 1 MiB cap incorrectly rejected p384-wallet — calibration bug caught
|
|
11
|
+
* by the script-size baseline (Major-2).
|
|
12
|
+
* - MAX_IR_BYTES = 16 MiB — the largest compiled-IR JSON in the corpus is
|
|
13
|
+
* `conformance/tests/token-ft/expected-ir.json` at 91,018 B (0.087 MiB),
|
|
14
|
+
* so 16 MiB is ~184× headroom. An earlier note put the largest at "~2 MiB
|
|
15
|
+
* (Mode 3 STARK contracts)" and the headroom at 8×; no checked-in
|
|
16
|
+
* `expected-ir.json` has ever come within 24× of that figure. The bound is
|
|
17
|
+
* sized against a pathological producer, not against this corpus, so the
|
|
18
|
+
* real number being far larger is fine — it is the stated one that was
|
|
19
|
+
* wrong, and a wrong one invites the next person to recalibrate downward
|
|
20
|
+
* against a fiction.
|
|
21
|
+
* - MAX_NESTING = 512 — JS engine stack typically tolerates ~10k frames;
|
|
22
|
+
* 512 is well below crash threshold but accommodates legitimate deep
|
|
23
|
+
* covenant ANF. This bound serves the `--ir` loader
|
|
24
|
+
* (runar-compiler/src/index.ts), which reads a TRUSTED local file.
|
|
25
|
+
* - MAX_WIRE_NESTING = 100 — the bound for anything crossing a tier
|
|
26
|
+
* boundary: canonicalJson's emit side and verifyEnvelope's parse side.
|
|
27
|
+
* Different threat model from MAX_NESTING (unauthenticated network input,
|
|
28
|
+
* not a local file), so deliberately a separate constant rather than a
|
|
29
|
+
* shared one. 100 is the largest depth Ruby's `JSON.parse` accepts for
|
|
30
|
+
* EVERY payload shape at its native default — measured on ruby 4.0.2 /
|
|
31
|
+
* json 2.18.0, 100-deep parses for both arrays and objects, a 101-deep
|
|
32
|
+
* OBJECT raises JSON::NestingError, and a 101-deep ARRAY still parses; the
|
|
33
|
+
* gem counts the two shapes one level apart, so an earlier flat "100
|
|
34
|
+
* accepted, 101 rejected" is true of objects and false of arrays. That
|
|
35
|
+
* asymmetry is the whole reason the bound is 100 rather than 101: raising
|
|
36
|
+
* it to the depth Ruby accepts for ARRAYS would keep working on every
|
|
37
|
+
* array payload and start rejecting 101-deep OBJECTS at the Ruby tier
|
|
38
|
+
* only — a shape-dependent, one-tier failure, which is the worst kind to
|
|
39
|
+
* debug on a signed wire. 100 is
|
|
40
|
+
* also 27 below rust serde_json's hard ceiling of 127, so every tier stays
|
|
41
|
+
* inside its own library's default without hand-rolling or reconfiguring a
|
|
42
|
+
* parser, and no tier is anywhere near its stack — at 1024 Python's
|
|
43
|
+
* canonical_json dies of native stack exhaustion and the JVM crashes on a
|
|
44
|
+
* 513-deep object, so a higher bound would trade a clean typed rejection
|
|
45
|
+
* for a crash. Headroom is ample: the deepest of the 165 checked-in
|
|
46
|
+
* conformance artifacts measures depth 15, and
|
|
47
|
+
* conformance/sdk-envelope/fixtures.json tops out at 6.
|
|
48
|
+
* - MAX_STRING_BYTES = 4 MiB — the binding case is a compiled script carried
|
|
49
|
+
* as a hex string, not a verification key. The largest checked-in script is
|
|
50
|
+
* `conformance/tests/p384-wallet/expected-script.hex`: 1,963,362 script
|
|
51
|
+
* bytes = 3,926,724 hex characters, which is 93.6% of this bound. Real
|
|
52
|
+
* headroom is 1.07×. An earlier note claimed "~3× headroom" against "the
|
|
53
|
+
* largest checked-in hex pushdata (witness-assisted Groth16 VK)" — that
|
|
54
|
+
* artifact, `examples/go/SP1Verifier.groth16.vk.json`, is 3,287 bytes in
|
|
55
|
+
* total and was never the worst case; the justification named the wrong
|
|
56
|
+
* artifact and overstated the margin by ~3×.
|
|
57
|
+
*
|
|
58
|
+
* Structural consequence worth stating plainly: MAX_SCRIPT_BYTES admits
|
|
59
|
+
* 4 MiB of SCRIPT, and hex doubles it. So anything that reaches
|
|
60
|
+
* signEnvelope as a hex string through canonicalJson is capped at 2 MiB of
|
|
61
|
+
* script — HALF the advertised script bound — and the largest script in
|
|
62
|
+
* the tree already sits at 93.6% of that. The next script family that
|
|
63
|
+
* clears ~2 MiB needs a coordinated seven-tier bump of this constant, not
|
|
64
|
+
* a local one: raising it in one tier splits the wire.
|
|
65
|
+
*/
|
|
66
|
+
export declare const InputLimits: {
|
|
67
|
+
readonly MAX_IR_BYTES: number;
|
|
68
|
+
readonly MAX_SCRIPT_BYTES: number;
|
|
69
|
+
readonly MAX_NESTING: 512;
|
|
70
|
+
readonly MAX_WIRE_NESTING: 100;
|
|
71
|
+
readonly MAX_STRING_BYTES: number;
|
|
72
|
+
readonly MAX_SOURCE_BYTES: number;
|
|
73
|
+
};
|
|
74
|
+
export type InputLimitsKey = keyof typeof InputLimits;
|
|
75
|
+
/**
|
|
76
|
+
* Thrown when a public canonical-JSON / IR-loading entry point detects
|
|
77
|
+
* input that exceeds a documented InputLimits bound. Distinct typed
|
|
78
|
+
* exception so callers can distinguish DoS-bound rejection from generic
|
|
79
|
+
* RangeError / SyntaxError.
|
|
80
|
+
*/
|
|
81
|
+
export declare class CanonicalJsonError extends Error {
|
|
82
|
+
readonly code: 'depth' | 'bytes' | 'string-bytes' | 'circular' | 'invalid' | 'lone-surrogate';
|
|
83
|
+
readonly limit?: number;
|
|
84
|
+
readonly actual?: number;
|
|
85
|
+
constructor(code: 'depth' | 'bytes' | 'string-bytes' | 'circular' | 'invalid' | 'lone-surrogate', message: string, info?: {
|
|
86
|
+
limit?: number;
|
|
87
|
+
actual?: number;
|
|
88
|
+
});
|
|
89
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared DoS-bound input limits + typed error class used by all public
|
|
3
|
+
* canonical-JSON / IR-loading entry points across the runar-ir-schema
|
|
4
|
+
* package and its downstream consumers.
|
|
5
|
+
*
|
|
6
|
+
* Justifications:
|
|
7
|
+
* - MAX_SCRIPT_BYTES = 4 MiB — the largest legitimate script measured by
|
|
8
|
+
* the script-size benchmark is `p384-wallet` at ~1.87 MB; 4 MiB gives
|
|
9
|
+
* ~2× headroom without enabling pathological 50 MB scripts. An earlier
|
|
10
|
+
* 1 MiB cap incorrectly rejected p384-wallet — calibration bug caught
|
|
11
|
+
* by the script-size baseline (Major-2).
|
|
12
|
+
* - MAX_IR_BYTES = 16 MiB — the largest compiled-IR JSON in the corpus is
|
|
13
|
+
* `conformance/tests/token-ft/expected-ir.json` at 91,018 B (0.087 MiB),
|
|
14
|
+
* so 16 MiB is ~184× headroom. An earlier note put the largest at "~2 MiB
|
|
15
|
+
* (Mode 3 STARK contracts)" and the headroom at 8×; no checked-in
|
|
16
|
+
* `expected-ir.json` has ever come within 24× of that figure. The bound is
|
|
17
|
+
* sized against a pathological producer, not against this corpus, so the
|
|
18
|
+
* real number being far larger is fine — it is the stated one that was
|
|
19
|
+
* wrong, and a wrong one invites the next person to recalibrate downward
|
|
20
|
+
* against a fiction.
|
|
21
|
+
* - MAX_NESTING = 512 — JS engine stack typically tolerates ~10k frames;
|
|
22
|
+
* 512 is well below crash threshold but accommodates legitimate deep
|
|
23
|
+
* covenant ANF. This bound serves the `--ir` loader
|
|
24
|
+
* (runar-compiler/src/index.ts), which reads a TRUSTED local file.
|
|
25
|
+
* - MAX_WIRE_NESTING = 100 — the bound for anything crossing a tier
|
|
26
|
+
* boundary: canonicalJson's emit side and verifyEnvelope's parse side.
|
|
27
|
+
* Different threat model from MAX_NESTING (unauthenticated network input,
|
|
28
|
+
* not a local file), so deliberately a separate constant rather than a
|
|
29
|
+
* shared one. 100 is the largest depth Ruby's `JSON.parse` accepts for
|
|
30
|
+
* EVERY payload shape at its native default — measured on ruby 4.0.2 /
|
|
31
|
+
* json 2.18.0, 100-deep parses for both arrays and objects, a 101-deep
|
|
32
|
+
* OBJECT raises JSON::NestingError, and a 101-deep ARRAY still parses; the
|
|
33
|
+
* gem counts the two shapes one level apart, so an earlier flat "100
|
|
34
|
+
* accepted, 101 rejected" is true of objects and false of arrays. That
|
|
35
|
+
* asymmetry is the whole reason the bound is 100 rather than 101: raising
|
|
36
|
+
* it to the depth Ruby accepts for ARRAYS would keep working on every
|
|
37
|
+
* array payload and start rejecting 101-deep OBJECTS at the Ruby tier
|
|
38
|
+
* only — a shape-dependent, one-tier failure, which is the worst kind to
|
|
39
|
+
* debug on a signed wire. 100 is
|
|
40
|
+
* also 27 below rust serde_json's hard ceiling of 127, so every tier stays
|
|
41
|
+
* inside its own library's default without hand-rolling or reconfiguring a
|
|
42
|
+
* parser, and no tier is anywhere near its stack — at 1024 Python's
|
|
43
|
+
* canonical_json dies of native stack exhaustion and the JVM crashes on a
|
|
44
|
+
* 513-deep object, so a higher bound would trade a clean typed rejection
|
|
45
|
+
* for a crash. Headroom is ample: the deepest of the 165 checked-in
|
|
46
|
+
* conformance artifacts measures depth 15, and
|
|
47
|
+
* conformance/sdk-envelope/fixtures.json tops out at 6.
|
|
48
|
+
* - MAX_STRING_BYTES = 4 MiB — the binding case is a compiled script carried
|
|
49
|
+
* as a hex string, not a verification key. The largest checked-in script is
|
|
50
|
+
* `conformance/tests/p384-wallet/expected-script.hex`: 1,963,362 script
|
|
51
|
+
* bytes = 3,926,724 hex characters, which is 93.6% of this bound. Real
|
|
52
|
+
* headroom is 1.07×. An earlier note claimed "~3× headroom" against "the
|
|
53
|
+
* largest checked-in hex pushdata (witness-assisted Groth16 VK)" — that
|
|
54
|
+
* artifact, `examples/go/SP1Verifier.groth16.vk.json`, is 3,287 bytes in
|
|
55
|
+
* total and was never the worst case; the justification named the wrong
|
|
56
|
+
* artifact and overstated the margin by ~3×.
|
|
57
|
+
*
|
|
58
|
+
* Structural consequence worth stating plainly: MAX_SCRIPT_BYTES admits
|
|
59
|
+
* 4 MiB of SCRIPT, and hex doubles it. So anything that reaches
|
|
60
|
+
* signEnvelope as a hex string through canonicalJson is capped at 2 MiB of
|
|
61
|
+
* script — HALF the advertised script bound — and the largest script in
|
|
62
|
+
* the tree already sits at 93.6% of that. The next script family that
|
|
63
|
+
* clears ~2 MiB needs a coordinated seven-tier bump of this constant, not
|
|
64
|
+
* a local one: raising it in one tier splits the wire.
|
|
65
|
+
*/
|
|
66
|
+
export const InputLimits = {
|
|
67
|
+
MAX_IR_BYTES: 16 * 1024 * 1024, // 16 MiB — uncompressed ANF IR JSON
|
|
68
|
+
MAX_SCRIPT_BYTES: 4 * 1024 * 1024, // 4 MiB — single compiled Bitcoin Script
|
|
69
|
+
// (p384-wallet hits ~1.87 MB; 2× headroom)
|
|
70
|
+
MAX_NESTING: 512, // recursion depth for JSON / ANF traversal
|
|
71
|
+
// (trusted local --ir input)
|
|
72
|
+
MAX_WIRE_NESTING: 100, // recursion depth for anything crossing a
|
|
73
|
+
// tier boundary (canonicalJson emit,
|
|
74
|
+
// verifyEnvelope parse) — untrusted input
|
|
75
|
+
MAX_STRING_BYTES: 4 * 1024 * 1024, // 4 MiB — single string field inside JSON
|
|
76
|
+
// (hex doubles: an effective 2 MiB script
|
|
77
|
+
// ceiling on the wire; today's largest is
|
|
78
|
+
// at 93.6% of it)
|
|
79
|
+
MAX_SOURCE_BYTES: 4 * 1024 * 1024, // 4 MiB — single Rúnar source file
|
|
80
|
+
// (BUG-008 follow-up: source parser entry guard
|
|
81
|
+
// across all 7 tiers)
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Thrown when a public canonical-JSON / IR-loading entry point detects
|
|
85
|
+
* input that exceeds a documented InputLimits bound. Distinct typed
|
|
86
|
+
* exception so callers can distinguish DoS-bound rejection from generic
|
|
87
|
+
* RangeError / SyntaxError.
|
|
88
|
+
*/
|
|
89
|
+
export class CanonicalJsonError extends Error {
|
|
90
|
+
code;
|
|
91
|
+
limit;
|
|
92
|
+
actual;
|
|
93
|
+
constructor(code, message, info) {
|
|
94
|
+
super(message);
|
|
95
|
+
this.name = 'CanonicalJsonError';
|
|
96
|
+
this.code = code;
|
|
97
|
+
this.limit = info?.limit;
|
|
98
|
+
this.actual = info?.actual;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack IR — the low-level stack-machine representation (Pass 5 output).
|
|
3
|
+
*
|
|
4
|
+
* Each method is lowered to a flat sequence of stack operations that map
|
|
5
|
+
* almost 1-to-1 to Bitcoin Script opcodes. This representation is
|
|
6
|
+
* compiler-specific (not part of the conformance boundary).
|
|
7
|
+
*/
|
|
8
|
+
export interface StackProgram {
|
|
9
|
+
contractName: string;
|
|
10
|
+
methods: StackMethod[];
|
|
11
|
+
}
|
|
12
|
+
export interface StackMethod {
|
|
13
|
+
name: string;
|
|
14
|
+
ops: StackOp[];
|
|
15
|
+
maxStackDepth: number;
|
|
16
|
+
}
|
|
17
|
+
/** Optional source location for debug source maps. */
|
|
18
|
+
export interface StackSourceLoc {
|
|
19
|
+
file: string;
|
|
20
|
+
line: number;
|
|
21
|
+
column: number;
|
|
22
|
+
}
|
|
23
|
+
export interface PushOp {
|
|
24
|
+
op: 'push';
|
|
25
|
+
value: Uint8Array | bigint | boolean;
|
|
26
|
+
sourceLoc?: StackSourceLoc;
|
|
27
|
+
}
|
|
28
|
+
export interface DupOp {
|
|
29
|
+
op: 'dup';
|
|
30
|
+
sourceLoc?: StackSourceLoc;
|
|
31
|
+
}
|
|
32
|
+
export interface SwapOp {
|
|
33
|
+
op: 'swap';
|
|
34
|
+
sourceLoc?: StackSourceLoc;
|
|
35
|
+
}
|
|
36
|
+
export interface RollOp {
|
|
37
|
+
op: 'roll';
|
|
38
|
+
depth: number;
|
|
39
|
+
sourceLoc?: StackSourceLoc;
|
|
40
|
+
}
|
|
41
|
+
export interface PickOp {
|
|
42
|
+
op: 'pick';
|
|
43
|
+
depth: number;
|
|
44
|
+
sourceLoc?: StackSourceLoc;
|
|
45
|
+
}
|
|
46
|
+
export interface DropOp {
|
|
47
|
+
op: 'drop';
|
|
48
|
+
sourceLoc?: StackSourceLoc;
|
|
49
|
+
}
|
|
50
|
+
export interface OpcodeOp {
|
|
51
|
+
op: 'opcode';
|
|
52
|
+
code: string;
|
|
53
|
+
sourceLoc?: StackSourceLoc;
|
|
54
|
+
}
|
|
55
|
+
export interface IfOp {
|
|
56
|
+
op: 'if';
|
|
57
|
+
then: StackOp[];
|
|
58
|
+
else?: StackOp[];
|
|
59
|
+
sourceLoc?: StackSourceLoc;
|
|
60
|
+
}
|
|
61
|
+
export interface NipOp {
|
|
62
|
+
op: 'nip';
|
|
63
|
+
sourceLoc?: StackSourceLoc;
|
|
64
|
+
}
|
|
65
|
+
export interface OverOp {
|
|
66
|
+
op: 'over';
|
|
67
|
+
sourceLoc?: StackSourceLoc;
|
|
68
|
+
}
|
|
69
|
+
export interface RotOp {
|
|
70
|
+
op: 'rot';
|
|
71
|
+
sourceLoc?: StackSourceLoc;
|
|
72
|
+
}
|
|
73
|
+
export interface TuckOp {
|
|
74
|
+
op: 'tuck';
|
|
75
|
+
sourceLoc?: StackSourceLoc;
|
|
76
|
+
}
|
|
77
|
+
export interface PlaceholderOp {
|
|
78
|
+
op: 'placeholder';
|
|
79
|
+
paramIndex: number;
|
|
80
|
+
paramName: string;
|
|
81
|
+
sourceLoc?: StackSourceLoc;
|
|
82
|
+
}
|
|
83
|
+
export interface PushCodeSepIndexOp {
|
|
84
|
+
op: 'push_codesep_index';
|
|
85
|
+
sourceLoc?: StackSourceLoc;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* R-095 — pin `SIZE(_codePart)` against the code part's own DEPLOYED byte
|
|
89
|
+
* length. See `packages/runar-compiler/src/ir/stack-ir.ts` for the full
|
|
90
|
+
* contract; the emitter reserves a fixed-width 9-byte sequence and
|
|
91
|
+
* back-patches the length plus the comparison opcode after the whole script
|
|
92
|
+
* has been emitted.
|
|
93
|
+
*/
|
|
94
|
+
export interface VerifyCodePartLenOp {
|
|
95
|
+
op: 'verify_code_part_len';
|
|
96
|
+
/** Deploy-time byte growth of the template's OP_0 placeholders. */
|
|
97
|
+
delta: number;
|
|
98
|
+
/** true -> exact equality pin; false -> lower-bound pin. */
|
|
99
|
+
exact: boolean;
|
|
100
|
+
sourceLoc?: StackSourceLoc;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Opaque raw byte span produced by lowering a `raw_script` ANF node.
|
|
104
|
+
*
|
|
105
|
+
* Emitted verbatim by the emit pass. Treated as a hard barrier by every
|
|
106
|
+
* windowed optimizer (peephole) — rules must never bridge across an
|
|
107
|
+
* adjacent `raw_bytes`. Stack effect is declared via `in_arity` /
|
|
108
|
+
* `out_arity`; the analyzer reads these to keep depth tracking sound
|
|
109
|
+
* without inspecting the contents.
|
|
110
|
+
*/
|
|
111
|
+
export interface RawBytesOp {
|
|
112
|
+
op: 'raw_bytes';
|
|
113
|
+
bytes: Uint8Array;
|
|
114
|
+
in_arity: number;
|
|
115
|
+
out_arity: number;
|
|
116
|
+
sourceLoc?: StackSourceLoc;
|
|
117
|
+
}
|
|
118
|
+
export type StackOp = PushOp | DupOp | SwapOp | RollOp | PickOp | DropOp | OpcodeOp | IfOp | NipOp | OverOp | RotOp | TuckOp | PlaceholderOp | PushCodeSepIndexOp | VerifyCodePartLenOp | RawBytesOp;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stack IR — the low-level stack-machine representation (Pass 5 output).
|
|
3
|
+
*
|
|
4
|
+
* Each method is lowered to a flat sequence of stack operations that map
|
|
5
|
+
* almost 1-to-1 to Bitcoin Script opcodes. This representation is
|
|
6
|
+
* compiler-specific (not part of the conformance boundary).
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State-tail byte layout — the single source of truth for WHERE each
|
|
3
|
+
* serialized state field lives in a stateful contract's locking script.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors the SDK's `serializeState` wire format exactly:
|
|
6
|
+
*
|
|
7
|
+
* <code part> OP_RETURN <field0> <field1> ... <fieldN>
|
|
8
|
+
*
|
|
9
|
+
* - bigint / int : 8 raw bytes, little-endian sign-magnitude (OP_NUM2BIN 8)
|
|
10
|
+
* - bool : 1 raw byte (0x00 / 0x01)
|
|
11
|
+
* - PubKey : 33 raw bytes - Addr / Ripemd160 : 20 raw bytes
|
|
12
|
+
* - Sha256 : 32 raw bytes - Point : 64 raw bytes
|
|
13
|
+
* - P256Point : 64 raw bytes - P384Point : 96 raw bytes
|
|
14
|
+
* - anything else: push-data framed (variable length)
|
|
15
|
+
*
|
|
16
|
+
* The curve-point types are raw and fixed-width because `runar-lang`'s
|
|
17
|
+
* `P256Point` / `P384Point` cast constructors hard-assert 64 / 96 bytes, and
|
|
18
|
+
* all seven COMPILERS emit them as fixed raw slices in the state tail. An SDK
|
|
19
|
+
* that push-data frames them instead deploys a state section one (64 -> 0x40)
|
|
20
|
+
* or two (96 -> OP_PUSHDATA1) bytes longer than the script's own reader
|
|
21
|
+
* expects, and the first spend fails with the funds locked.
|
|
22
|
+
*
|
|
23
|
+
* Fields are concatenated in `StateField.index` order. FixedArray fields
|
|
24
|
+
* serialize as their flattened leaves back-to-back.
|
|
25
|
+
*
|
|
26
|
+
* Lives in runar-ir-schema so the compiler (which annotates `stateFields`
|
|
27
|
+
* in the artifact), the SDK's state codec, and any verifier tooling share
|
|
28
|
+
* ONE width table instead of re-deriving it.
|
|
29
|
+
*/
|
|
30
|
+
import type { StateField } from './artifact.js';
|
|
31
|
+
export type StateFieldEncoding = NonNullable<StateField['encoding']>;
|
|
32
|
+
/**
|
|
33
|
+
* Fixed serialized widths (bytes) for scalar state-field types.
|
|
34
|
+
* Types absent from this table serialize as push-data framed variable-length
|
|
35
|
+
* values ('pushdata').
|
|
36
|
+
*/
|
|
37
|
+
export declare const STATE_FIELD_WIDTHS: Readonly<Record<string, {
|
|
38
|
+
readonly size: number;
|
|
39
|
+
readonly encoding: StateFieldEncoding;
|
|
40
|
+
}>>;
|
|
41
|
+
/**
|
|
42
|
+
* Annotate state fields with their byte layout (`encoding`, `byteOffset`,
|
|
43
|
+
* `byteLength`, `tailOffset`). Returns NEW field objects (inputs are not
|
|
44
|
+
* mutated), sorted by `index` — the serialization order.
|
|
45
|
+
*
|
|
46
|
+
* `byteOffset` counts from the byte AFTER the OP_RETURN separator and is
|
|
47
|
+
* present only while every preceding field is fixed-length. `tailOffset` is
|
|
48
|
+
* a NEGATIVE offset from the END of the locking script and is present only
|
|
49
|
+
* when the field itself and every following field is fixed-length.
|
|
50
|
+
*/
|
|
51
|
+
export declare function annotateStateFieldLayout(fields: StateField[]): StateField[];
|
|
52
|
+
/**
|
|
53
|
+
* Total serialized state length in bytes (after the OP_RETURN byte), or
|
|
54
|
+
* undefined when any field is variable-length.
|
|
55
|
+
*/
|
|
56
|
+
export declare function totalStateByteLength(fields: StateField[]): number | undefined;
|