@sig-net/midnight 0.11.0 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +19 -13
  2. package/dist/abi-serde.d.ts +89 -0
  3. package/dist/abi-serde.d.ts.map +1 -0
  4. package/dist/abi-serde.js +400 -0
  5. package/dist/abi-serde.js.map +1 -0
  6. package/dist/constants.d.ts +31 -23
  7. package/dist/constants.d.ts.map +1 -1
  8. package/dist/constants.js +38 -32
  9. package/dist/constants.js.map +1 -1
  10. package/dist/ecdsa-attestation.d.ts +38 -18
  11. package/dist/ecdsa-attestation.d.ts.map +1 -1
  12. package/dist/ecdsa-attestation.js +52 -25
  13. package/dist/ecdsa-attestation.js.map +1 -1
  14. package/dist/epsilon-derivation.js +1 -1
  15. package/dist/epsilon-derivation.js.map +1 -1
  16. package/dist/index.d.ts +1 -0
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +1 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/managed/compiler/contract-info.json +180 -122
  21. package/dist/managed/compiler/contract-manifest.json +8 -8
  22. package/dist/managed/contract/index.d.ts +38 -28
  23. package/dist/managed/contract/index.js +302 -149
  24. package/dist/managed/contract/index.js.map +1 -1
  25. package/dist/signature-requests-state-reader.d.ts +13 -13
  26. package/dist/signature-requests-state-reader.js +22 -22
  27. package/dist/signature-requests-state-reader.js.map +1 -1
  28. package/dist/signature-response-verification.d.ts +1 -1
  29. package/dist/signature-response-verification.js +3 -3
  30. package/dist/signature-response-verification.js.map +1 -1
  31. package/dist/signet-contract-state-reader.d.ts +33 -36
  32. package/dist/signet-contract-state-reader.d.ts.map +1 -1
  33. package/dist/signet-contract-state-reader.js +26 -28
  34. package/dist/signet-contract-state-reader.js.map +1 -1
  35. package/dist/signet-evtype2tx-requests.d.ts +21 -21
  36. package/dist/signet-evtype2tx-requests.js +16 -16
  37. package/dist/signet-evtype2tx-requests.js.map +1 -1
  38. package/dist/signet-request-response-reader.d.ts +27 -25
  39. package/dist/signet-request-response-reader.d.ts.map +1 -1
  40. package/dist/signet-request-response-reader.js +32 -30
  41. package/dist/signet-request-response-reader.js.map +1 -1
  42. package/dist/signet-requests.d.ts +27 -27
  43. package/dist/signet-requests.d.ts.map +1 -1
  44. package/dist/signet-requests.js +28 -29
  45. package/dist/signet-requests.js.map +1 -1
  46. package/package.json +3 -2
  47. package/src/Signet.compact +80 -65
  48. package/src/circuits.compact +45 -2
package/README.md CHANGED
@@ -13,7 +13,7 @@ The client-agnostic [Sig Network](https://sig.network) protocol library for the
13
13
  ```compact
14
14
  import "@sig-net/midnight/src/Signet";
15
15
  ```
16
- - **Compiled pure circuits** (`pureCircuits`): the executable reference implementation of the client-agnostic circuits (the attestation digest, response verification, the deploy-time key pin, the notification packer, the ABI word builders and readers). Off-chain code calls these compiled artefacts instead of re-porting the algorithms, so it always agrees with what the contracts prove.
16
+ - **Compiled pure circuits** (`pureCircuits`): the executable reference implementation of the client-agnostic circuits (the deploy-time key pin, the notification packer, the ABI word builders and readers). Off-chain code calls these compiled artefacts, so it always agrees with what the contracts prove. The attestation digest and response verification are not among them: their compiled circuits are fixed-width oracles used only by this package's tests, and the sanctioned off-chain path is the TypeScript twin (`calculateSignetAttestationDigest` plus ordinary ECDSA verification against the expected MPC response key), which those tests pin byte-for-byte against the oracles.
17
17
  - **TypeScript twins of the wire structs** and signet request-id computation.
18
18
  - **State readers, request feed and resolver**: poll the signet contract for pending requests and their signature / remote-execution responses.
19
19
  - **Crypto helpers**: epsilon derivation and ECDSA attestation verification.
@@ -33,8 +33,8 @@ The flow comprises 5 steps:
33
33
  1. Client calls a contract on Midnight which requests a signature for a transaction destined for a foreign chain. The signature is made with a key derived for the requesting contract (see [Derived keys](#derived-keys)).
34
34
  2. The Sig Network MPC honours the request, generating the transaction signature and posting it back to Midnight.
35
35
  3. Client extracts the signature, using it to submit the signed transaction to the foreign chain.
36
- 4. The Sig Network MPC observes the foreign transaction and posts the output of the execution (signed) back to Midnight.
37
- 5. Client extracts the signed foreign execution output and submits it back to the Midnight contract, which verifies the MPC's signature over it in-circuit against the contract's own response key (see [Derived keys](#derived-keys)), completing the foreign transaction execution.
36
+ 4. The Sig Network MPC observes the foreign transaction and posts an attestation of the execution back to Midnight: the attestation digest `keccak256(requestId || serializedOutput)` plus its ECDSA signature over that digest. The output itself travels off chain.
37
+ 5. Client obtains the execution output off chain (it broadcast the transaction in step 3, so it can read the result), extracts the posted attestation and submits both back to the Midnight contract, which recomputes the digest from the output bytes and verifies the MPC's signature in-circuit against the contract's own response key (see [Derived keys](#derived-keys)), completing the foreign transaction execution.
38
38
 
39
39
  ## Derived keys
40
40
 
@@ -50,7 +50,7 @@ The path is 32 opaque bytes of the contract's choosing (e.g. a fixed literal for
50
50
 
51
51
  ### Response key
52
52
 
53
- The key the MPC signs foreign execution outputs with when posting them back to Midnight:
53
+ The key the MPC signs remote execution attestations with when posting them back to Midnight:
54
54
 
55
55
  `responseKey = f(mpcRootKey[keyVersion], contractAddress, "midnight response key")`
56
56
 
@@ -95,7 +95,7 @@ Set up your contract for integration with the Sig Network MPC's sign bidirection
95
95
  sealed ledger signetSigner: SignetSigner;
96
96
 
97
97
  // Required: This contract's MPC response key, set in step 3.
98
- // Used to verify RespondBidirectionalEvents containing the serialised output of foreign chain execution.
98
+ // Used to verify RespondBidirectionalEvents attesting the serialised output of foreign chain execution.
99
99
  export ledger mpcResponseKey: Secp256k1Point;
100
100
 
101
101
  // Recommended: contract-local source of request nonces, so identical
@@ -109,7 +109,7 @@ Set up your contract for integration with the Sig Network MPC's sign bidirection
109
109
  sealed ledger deployer: Bytes<32>;
110
110
 
111
111
  // Recommended: supplies the deployer's identity secret from private state
112
- // off-chain; only its commitment (below) ever reaches the ledger.
112
+ // off-chain. Only its commitment (below) ever reaches the ledger.
113
113
  witness witnessDeployerSecretKey(): Bytes<32>;
114
114
 
115
115
  // Recommended: the deployer identity commitment scheme. Exported so deploy
@@ -172,7 +172,7 @@ const reader = new SignetRequestResponseReader({
172
172
  const expectedSigner = deriveEvmAddress(mpcRootPublicKey, myContractAddress, "my-path");
173
173
  ```
174
174
 
175
- 1. Store a signature request and notify the MPC via cross contract call. Build (or overwrite) every part of the transaction your contract enforces in-circuit, calldata above all (see [EVM Type 2 transactions and ABI calldata words](#evm-type-2-transactions-and-abi-calldata-words)); never pass caller input through unchecked:
175
+ 1. Store a signature request and notify the MPC via cross contract call. Build (or overwrite) every part of the transaction your contract enforces in-circuit, calldata above all (see [EVM Type 2 transactions and ABI calldata words](#evm-type-2-transactions-and-abi-calldata-words)), and never pass caller input through unchecked:
176
176
 
177
177
  ```compact
178
178
  // Construct SignBidirectionalEvent signature request and calculate its RequestId
@@ -209,18 +209,18 @@ const expectedSigner = deriveEvmAddress(mpcRootPublicKey, myContractAddress, "my
209
209
  await new JsonRpcProvider(foreignChainRpcUrl).broadcastTransaction(signedTx.serialized);
210
210
  ```
211
211
 
212
- 4. Poll the Signet singleton for the MPC's signed remote execution output (posted once the MPC observes the transaction execute on the foreign chain). Posts are stored unverified, so treat them as candidates: the authoritative check is your contract's verify circuit in step 5:
212
+ 4. Poll the Signet singleton for the MPC's attestation of the remote execution output (posted once the MPC observes the transaction execute on the foreign chain). The event carries only the attestation digest and the signature over it: the serialised output itself travels off chain (you broadcast the transaction in step 3, so you can read its result). Posts are stored unverified, so treat them as candidates: the authoritative check is your contract's verify circuit in step 5:
213
213
 
214
214
  ```ts
215
215
  const [respondBidirectionalEvent] = await reader.getRespondBidirectionalEvents(requestId);
216
216
  // Empty array: not posted yet, poll again.
217
217
  ```
218
218
 
219
- 5. Deliver the response to your contract, which verifies it in-circuit against the response key pinned in Setup step 3 and consumes the request:
219
+ 5. Deliver the response and the serialised output to your contract, which recomputes the attestation digest, verifies the event in-circuit against the response key pinned in Setup step 3, and consumes the request. The width argument is the exact packed size of your respond serialisation schema (a single bool packs to 1 byte):
220
220
 
221
221
  ```compact
222
222
  assert(
223
- verifyRespondBidirectionalEvent(requestId, respondBidirectionalEvent, mpcResponseKey),
223
+ verifyRespondBidirectionalEvent<1>(requestId, serializedOutput, respondBidirectionalEvent, mpcResponseKey),
224
224
  "Invalid attestation signature"
225
225
  );
226
226
  signBidirectionalEventMap.remove(requestId);
@@ -268,13 +268,19 @@ const calldata = EvmCalldata<2> {
268
268
  };
269
269
  ```
270
270
 
271
- The readers run the same rules in the other direction, rejecting any non-canonical word instead of silently truncating or coercing it. A `RespondBidirectionalEvent`'s `serializedOutput` is the ABI-encoded return data of the remote call, so a settle circuit can decode an ERC20 `transfer`'s `bool` return from the first output word:
271
+ The readers run the same rules in the other direction, rejecting any non-canonical word outright (no silent truncation or coercion). Note that the builders and readers apply to CALLDATA words only. The serialised output a settle circuit verifies (the explicit `serializedOutput` argument `verifyRespondBidirectionalEvent` binds to the event's attestation digest) is NOT ABI words: it is the packed respond payload produced from the request's respond serialisation schema (a bool packs to 1 byte). The circuit reads it with a single stdlib `deserialize<T, N>` call, where `T` is a struct mirroring the schema and `N` is the schema's packed size. For an ERC20 `transfer`'s `bool` return under a one-field bool schema:
272
272
 
273
273
  ```compact
274
- const success = abiWordToBool(slice<32>(respondBidirectionalEvent.serializedOutput, 0));
275
- assert(success, "Remote transfer failed");
274
+ struct TransferResult {
275
+ success: Boolean;
276
+ }
277
+
278
+ const result = deserialize<TransferResult, 1>(serializedOutput);
279
+ assert(result.success, "Remote transfer failed");
276
280
  ```
277
281
 
282
+ **Respond schema range trap:** the respond serialisation maps `uint256`, `address` and `field` to Compact `Field`, whose values must lie strictly below the BLS12-381 Fr modulus (just under 2^255). An EVM `uint256` at or above Fr (a max-uint256 allowance readback is the everyday case) cannot be respond-serialised, and `serializeRespondOutput` throws at respond time. When the full 256-bit range matters, declare the field as `bytes32` in the respond schema instead.
283
+
278
284
  The same builders and readers exist as TypeScript twins under identical names, for composing expected words off-chain (UIs, expected-record builders, tests). They are kept in lockstep with the compiled circuits by this package's test suite.
279
285
 
280
286
  ## More examples
@@ -0,0 +1,89 @@
1
+ import { ethers } from "ethers";
2
+ /** Fixed-width schema types: the byte size follows entirely from the type. */
3
+ export type AbiFixedType = "bool" | "address" | "field" | `uint${number}` | `bytes${number}`;
4
+ export interface AbiFixedField {
5
+ name: string;
6
+ type: AbiFixedType;
7
+ }
8
+ /**
9
+ * A dynamic string/bytes field. `maxBytes` is the fixed Compact buffer
10
+ * capacity (Compact types are fixed-size, so capacity is part of the type).
11
+ */
12
+ export interface AbiDynamicField {
13
+ name: string;
14
+ type: "string" | "bytes";
15
+ maxBytes: number;
16
+ }
17
+ /** A dynamic array field. `maxItems` is the fixed Compact vector capacity. */
18
+ export interface AbiArrayField {
19
+ name: string;
20
+ type: `${AbiFixedType}[]`;
21
+ maxItems: number;
22
+ }
23
+ export type AbiSchemaField = AbiFixedField | AbiDynamicField | AbiArrayField;
24
+ /** An ABI-style schema exactly as carried on chain (JSON array of fields). */
25
+ export type AbiSchema = AbiSchemaField[];
26
+ /** Any form a respond schema arrives in: parsed, JSON text, or NUL-padded raw bytes. */
27
+ export type AbiSchemaInput = AbiSchema | string | Uint8Array;
28
+ /**
29
+ * A decode-side schema field: `type` is ANY type string the ABI library
30
+ * accepts (the canonical ABI grammar, so signed ints, tuples and unbounded
31
+ * arrays are all fine here). The restricted {@link AbiSchemaField} vocabulary
32
+ * is a respond-side concern only, and is assignable to this shape.
33
+ */
34
+ export interface EvmSchemaField {
35
+ name: string;
36
+ type: string;
37
+ }
38
+ /** Any form a decode schema arrives in: parsed, JSON text, or NUL-padded raw bytes. */
39
+ export type EvmSchemaInput = readonly EvmSchemaField[] | string | Uint8Array;
40
+ /**
41
+ * Decoded output values, keyed by schema field name. Numerics are bigint,
42
+ * bools boolean, address/bytesN/bytes/string are the forms ethers produces
43
+ * (hex or text strings) or Uint8Array, arrays are plain arrays.
44
+ * `serializeRespondOutput` accepts all of these (plus plain numbers and
45
+ * numeric strings, the forms indexer JSON typically yields).
46
+ */
47
+ export type AbiDecodedValue = bigint | boolean | number | string | Uint8Array | AbiDecodedValue[];
48
+ export type AbiDecodedOutput = {
49
+ [field: string]: AbiDecodedValue;
50
+ };
51
+ /**
52
+ * Decode a raw EVM call result (eth_call return data / debug_trace output)
53
+ * into named values, driven by the request's outputDeserializationSchema.
54
+ *
55
+ * Type validation is FULLY delegated to ethers (the canonical ABI grammar,
56
+ * mirroring the MPC's delegation to alloy): this function only checks the
57
+ * schema's shape, then hands the type strings straight to the ABI coder.
58
+ *
59
+ * Returns a plain object keyed by field name (never an ethers `Result`, so it
60
+ * survives JSON round-trips and structural comparison), with nested ethers
61
+ * Results flattened to plain arrays.
62
+ *
63
+ * @param schema - The outputDeserializationSchema: parsed, JSON text, or the raw NUL-padded on-chain bytes.
64
+ * @param callResult - The ABI-encoded return data (hex string or bytes).
65
+ * @returns The decoded values keyed by schema field name.
66
+ */
67
+ export declare function deserializeEvmOutput(schema: EvmSchemaInput, callResult: ethers.BytesLike): AbiDecodedOutput;
68
+ /**
69
+ * Encode decoded output values into the respond payload, driven by the
70
+ * request's respondSerializationSchema. The bytes are exactly what a consumer
71
+ * contract reads with `deserialize<T, N>` and what the MPC attests, so
72
+ * clients can recompute and verify them independently.
73
+ *
74
+ * The result is the PACKED value, unpadded and unbounded: its length follows
75
+ * entirely from the schema. Padding to any fixed container width is the
76
+ * caller's concern.
77
+ *
78
+ * Strict: values are range-checked (Uint widths, the Field modulus, the
79
+ * 2^160 address bound), dynamic payloads must fit their capacity (no silent
80
+ * truncation), and signed integer types are rejected outright.
81
+ *
82
+ * @param schema - The respondSerializationSchema: parsed, JSON text, or the raw NUL-padded on-chain bytes.
83
+ * @param output - Decoded values keyed by field name (from {@link deserializeEvmOutput} or any source using the same forms).
84
+ * @returns The packed respond bytes.
85
+ */
86
+ export declare function serializeRespondOutput(schema: AbiSchemaInput, output: AbiDecodedOutput): Uint8Array;
87
+ export declare function isAbiDynamicField(field: AbiSchemaField): field is AbiDynamicField;
88
+ export declare function isAbiArrayField(field: AbiSchemaField): field is AbiArrayField;
89
+ //# sourceMappingURL=abi-serde.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi-serde.d.ts","sourceRoot":"","sources":["../src/abi-serde.ts"],"names":[],"mappings":"AA0DA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAYhC,8EAA8E;AAC9E,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,SAAS,GACT,OAAO,GACP,OAAO,MAAM,EAAE,GACf,QAAQ,MAAM,EAAE,CAAC;AAErB,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,YAAY,IAAI,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,cAAc,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,CAAC;AAE7E,8EAA8E;AAC9E,MAAM,MAAM,SAAS,GAAG,cAAc,EAAE,CAAC;AAEzC,wFAAwF;AACxF,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,GAAG,UAAU,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,uFAAuF;AACvF,MAAM,MAAM,cAAc,GAAG,SAAS,cAAc,EAAE,GAAG,MAAM,GAAG,UAAU,CAAC;AAM7E;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GACvB,MAAM,GACN,OAAO,GACP,MAAM,GACN,MAAM,GACN,UAAU,GACV,eAAe,EAAE,CAAC;AAEtB,MAAM,MAAM,gBAAgB,GAAG;IAAE,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,CAAC;AAMpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,cAAc,EACtB,UAAU,EAAE,MAAM,CAAC,SAAS,GAC3B,gBAAgB,CAWlB;AAMD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,cAAc,EACtB,MAAM,EAAE,gBAAgB,GACvB,UAAU,CAYZ;AAWD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,eAAe,CAEjF;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,KAAK,IAAI,aAAa,CAE7E"}
@@ -0,0 +1,400 @@
1
+ // The two schema-driven conversions every signet participant performs on the
2
+ // respond path, named after the protocol fields that drive them:
3
+ //
4
+ // EVM call result --deserializeEvmOutput--> decoded values
5
+ // (outputDeserializationSchema)
6
+ // decoded values --serializeRespondOutput--> RespondBidirectionalEvent bytes
7
+ // (respondSerializationSchema)
8
+ //
9
+ // Who runs them:
10
+ // - fakenet (and eventually the real MPC): both, back to back, after the
11
+ // destination-chain transaction confirms.
12
+ // - signet clients: both, to independently recompute the exact respond
13
+ // bytes the MPC attested (read the EVM result off chain, re-encode, then
14
+ // hand the result to their Compact contract for claim/validation) or to
15
+ // display a decoded result.
16
+ //
17
+ // The respond output is UNBOUNDED: this module never pads or clamps it. The
18
+ // protocol attests a hash of the bytes, clients fetch the full output off
19
+ // chain and recompute; any fixed event-field width is the caller's concern.
20
+ //
21
+ // Schemas are the ABI-style JSON carried on chain (NUL-padded fixed-width
22
+ // bytes). Both functions accept the schema in any form: already-parsed
23
+ // fields, a JSON string, or the raw on-chain bytes.
24
+ //
25
+ // Validation is split exactly the way the MPC splits it:
26
+ // - decode side: the type grammar is left FULLY to the ABI library
27
+ // (ethers), the same way the MPC delegates to alloy's DynSolType parser.
28
+ // This module only checks the schema's shape (a non-empty array of
29
+ // uniquely, non-emptily named fields).
30
+ // - respond side: the restricted Compact-carrier vocabulary below is the
31
+ // law, strictly enforced: unknown types, missing capacities, duplicate
32
+ // names and malformed JSON all throw with the offending field named.
33
+ //
34
+ // The respond byte layout is Compact's builtin serialize<T, N> /
35
+ // deserialize<T, N> (via @sig-net/midnight-serde, pinned against compiled
36
+ // circuits), so a consumer contract reads the payload with ONE
37
+ // deserialize<T, N> call. Per-type mapping (Compact struct field on the
38
+ // right):
39
+ // bool 1 byte Boolean
40
+ // uint8..uint248 bits / 8 bytes LE Uint<bits>
41
+ // (whole-byte widths only: multiples of 8, others are rejected)
42
+ // uint256, field 32 bytes LE, below Fr Field
43
+ // address 32 bytes LE (numeric) Field
44
+ // bytes1..bytes32 N raw bytes Bytes<N>
45
+ // string, bytes 8-byte LE length + payload zero-padded to maxBytes
46
+ // struct { len: Uint<64>; data: Bytes<maxBytes>; }
47
+ // T[] 8-byte LE count + maxItems elements at T's width
48
+ // struct { len: Uint<64>; items: Vector<maxItems, T>; }
49
+ // intN rejected: Compact has no signed integers
50
+ //
51
+ // RANGE TRAP: uint256, address and field all map to Compact `Field`, whose
52
+ // values must lie strictly below the BLS12-381 Fr modulus (just under
53
+ // 2^255). An EVM uint256 at or above Fr therefore cannot be
54
+ // respond-serialised, and `serializeRespondOutput` throws at respond time.
55
+ // The max-uint256 allowance readback is the everyday case that hits this.
56
+ // Schema authors who need the full 256-bit range should carry the value as
57
+ // bytes32 instead.
58
+ import { ethers } from "ethers";
59
+ import { compactSerialize, } from "@sig-net/midnight-serde";
60
+ // ---------------------------------------------------------------------------
61
+ // 1. EVM call result -> decoded values (outputDeserializationSchema)
62
+ // ---------------------------------------------------------------------------
63
+ /**
64
+ * Decode a raw EVM call result (eth_call return data / debug_trace output)
65
+ * into named values, driven by the request's outputDeserializationSchema.
66
+ *
67
+ * Type validation is FULLY delegated to ethers (the canonical ABI grammar,
68
+ * mirroring the MPC's delegation to alloy): this function only checks the
69
+ * schema's shape, then hands the type strings straight to the ABI coder.
70
+ *
71
+ * Returns a plain object keyed by field name (never an ethers `Result`, so it
72
+ * survives JSON round-trips and structural comparison), with nested ethers
73
+ * Results flattened to plain arrays.
74
+ *
75
+ * @param schema - The outputDeserializationSchema: parsed, JSON text, or the raw NUL-padded on-chain bytes.
76
+ * @param callResult - The ABI-encoded return data (hex string or bytes).
77
+ * @returns The decoded values keyed by schema field name.
78
+ */
79
+ export function deserializeEvmOutput(schema, callResult) {
80
+ const fields = parseSchemaShape(schema);
81
+ const decoded = ethers.AbiCoder.defaultAbiCoder().decode(fields.map((field) => field.type), callResult);
82
+ const output = {};
83
+ fields.forEach((field, i) => {
84
+ output[field.name] = toPlainValue(decoded[i], field.name);
85
+ });
86
+ return output;
87
+ }
88
+ // ---------------------------------------------------------------------------
89
+ // 2. decoded values -> respond bytes (respondSerializationSchema)
90
+ // ---------------------------------------------------------------------------
91
+ /**
92
+ * Encode decoded output values into the respond payload, driven by the
93
+ * request's respondSerializationSchema. The bytes are exactly what a consumer
94
+ * contract reads with `deserialize<T, N>` and what the MPC attests, so
95
+ * clients can recompute and verify them independently.
96
+ *
97
+ * The result is the PACKED value, unpadded and unbounded: its length follows
98
+ * entirely from the schema. Padding to any fixed container width is the
99
+ * caller's concern.
100
+ *
101
+ * Strict: values are range-checked (Uint widths, the Field modulus, the
102
+ * 2^160 address bound), dynamic payloads must fit their capacity (no silent
103
+ * truncation), and signed integer types are rejected outright.
104
+ *
105
+ * @param schema - The respondSerializationSchema: parsed, JSON text, or the raw NUL-padded on-chain bytes.
106
+ * @param output - Decoded values keyed by field name (from {@link deserializeEvmOutput} or any source using the same forms).
107
+ * @returns The packed respond bytes.
108
+ */
109
+ export function serializeRespondOutput(schema, output) {
110
+ const fields = normalizeRespondSchema(schema);
111
+ const descriptor = respondSchemaToCompactType(fields);
112
+ const value = {};
113
+ for (const field of fields) {
114
+ const raw = output[field.name];
115
+ if (raw === undefined) {
116
+ throw new Error(`respond output: missing value for '${field.name}'`);
117
+ }
118
+ value[field.name] = toCompactValue(raw, field);
119
+ }
120
+ return compactSerialize(descriptor, value);
121
+ }
122
+ // ===========================================================================
123
+ // Helpers from here down. The two functions above are the whole public
124
+ // surface; everything below serves them.
125
+ // ===========================================================================
126
+ // ---------------------------------------------------------------------------
127
+ // Field-kind guards
128
+ // ---------------------------------------------------------------------------
129
+ export function isAbiDynamicField(field) {
130
+ return field.type === "string" || field.type === "bytes";
131
+ }
132
+ export function isAbiArrayField(field) {
133
+ return field.type.endsWith("[]");
134
+ }
135
+ // ---------------------------------------------------------------------------
136
+ // Decode-side value flattening
137
+ // ---------------------------------------------------------------------------
138
+ /** Flatten ethers `Result` arrays into plain arrays, pass scalars through. */
139
+ function toPlainValue(value, label) {
140
+ if (value instanceof ethers.Result) {
141
+ return value.toArray().map((v, i) => toPlainValue(v, `${label}[${i}]`));
142
+ }
143
+ if (Array.isArray(value)) {
144
+ return value.map((v, i) => toPlainValue(v, `${label}[${i}]`));
145
+ }
146
+ if (typeof value === "bigint" ||
147
+ typeof value === "boolean" ||
148
+ typeof value === "number" ||
149
+ typeof value === "string" ||
150
+ value instanceof Uint8Array) {
151
+ return value;
152
+ }
153
+ throw new Error(`${label}: un-decodable ABI value of type ${typeof value}`);
154
+ }
155
+ // ---------------------------------------------------------------------------
156
+ // Schema parsing + validation
157
+ // ---------------------------------------------------------------------------
158
+ const ADDRESS_BOUND = 1n << 160n;
159
+ const MAX_UINT_BITS = 248;
160
+ /** Length-prefix width of the dynamic string/bytes/array convention (Uint<64>). */
161
+ const DYN_LEN_BYTES = 8;
162
+ /**
163
+ * Parse a schema in any input form and check its SHAPE only: a non-empty
164
+ * array of fields with non-empty, unique names and non-empty type strings.
165
+ * The type grammar is deliberately not checked here: the decode side leaves
166
+ * it fully to the ABI library, the respond side runs
167
+ * {@link normalizeRespondSchema} on top.
168
+ */
169
+ function parseSchemaShape(schema) {
170
+ const parsed = typeof schema === "string" || schema instanceof Uint8Array
171
+ ? JSON.parse(schemaText(schema))
172
+ : schema;
173
+ if (!Array.isArray(parsed) || parsed.length === 0) {
174
+ throw new Error("schema must be a non-empty JSON array of fields");
175
+ }
176
+ const seen = new Set();
177
+ return parsed.map((raw, i) => {
178
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
179
+ throw new Error(`schema field ${i} is not an object`);
180
+ }
181
+ const { name, type, maxBytes, maxItems } = raw;
182
+ if (typeof name !== "string" || name.length === 0) {
183
+ throw new Error(`schema field ${i} needs a non-empty name`);
184
+ }
185
+ if (seen.has(name)) {
186
+ throw new Error(`schema: duplicate field name '${name}'`);
187
+ }
188
+ seen.add(name);
189
+ if (typeof type !== "string" || type.length === 0) {
190
+ throw new Error(`schema: '${name}' needs a type`);
191
+ }
192
+ return { name, type, maxBytes, maxItems };
193
+ });
194
+ }
195
+ /**
196
+ * Enforce the respond-side Compact-carrier vocabulary on a shape-checked
197
+ * schema: every type needs a Compact carrier (no signed ints, uint widths of
198
+ * at most 248 bits or exactly 256, bytesN at most 32) and every dynamic field
199
+ * needs its fixed capacity.
200
+ */
201
+ function normalizeRespondSchema(schema) {
202
+ return parseSchemaShape(schema).map(({ name, type, maxBytes, maxItems }) => {
203
+ if (type === "string" || type === "bytes") {
204
+ assertCapacity(maxBytes, `'${name}' (${type}) maxBytes`);
205
+ return { name, type, maxBytes };
206
+ }
207
+ if (type.endsWith("[]")) {
208
+ classifyFixedType(type.slice(0, -2), name);
209
+ assertCapacity(maxItems, `'${name}' (${type}) maxItems`);
210
+ return { name, type: type, maxItems };
211
+ }
212
+ classifyFixedType(type, name);
213
+ return { name, type: type };
214
+ });
215
+ }
216
+ /** Cut a NUL-padded on-chain schema at the first NUL and decode to text. */
217
+ function schemaText(schema) {
218
+ const raw = typeof schema === "string" ? schema : new TextDecoder().decode(schema);
219
+ const nul = raw.indexOf("\0");
220
+ return nul === -1 ? raw : raw.slice(0, nul);
221
+ }
222
+ function assertCapacity(value, label) {
223
+ if (value === undefined) {
224
+ throw new Error(`schema: ${label} is required: Compact types are fixed-size`);
225
+ }
226
+ if (typeof value !== "number" || !Number.isInteger(value) || value < 1) {
227
+ throw new Error(`schema: ${label} must be a positive integer`);
228
+ }
229
+ }
230
+ /**
231
+ * Classify a fixed-width respond type into its Compact carrier, validating
232
+ * the respond-side vocabulary in one place: both the schema check
233
+ * ({@link normalizeRespondSchema}) and the descriptor build
234
+ * ({@link respondSchemaToCompactType}) call this, so the grammar cannot
235
+ * drift between them. Respond-side uint widths are restricted to whole-byte
236
+ * widths (multiples of 8 from 8 to 248, packing to bits / 8 bytes), plus
237
+ * uint256 which maps to Field. Throws with the offending field named.
238
+ */
239
+ function classifyFixedType(type, fieldName) {
240
+ if (type === "bool")
241
+ return { kind: "boolean" };
242
+ if (type === "field" || type === "uint256" || type === "address") {
243
+ return { kind: "field" };
244
+ }
245
+ if (/^int\d+$/.test(type)) {
246
+ throw new Error(`schema: '${fieldName}' (${type}) is unsupported: Compact has no signed integers`);
247
+ }
248
+ const uintMatch = type.match(/^uint(\d+)$/);
249
+ if (uintMatch) {
250
+ const bits = Number(uintMatch[1]);
251
+ const wholeByteWidth = bits >= 8 && bits <= MAX_UINT_BITS && bits % 8 === 0;
252
+ if (!wholeByteWidth) {
253
+ throw new Error(`schema: '${fieldName}' (${type}) has no respond carrier: uint widths ` +
254
+ `must be multiples of 8 from 8 to ${MAX_UINT_BITS}, or uint256 (maps to Field)`);
255
+ }
256
+ return { kind: "uint", bits };
257
+ }
258
+ const bytesMatch = type.match(/^bytes(\d+)$/);
259
+ if (bytesMatch) {
260
+ const n = Number(bytesMatch[1]);
261
+ if (n < 1 || n > 32) {
262
+ throw new Error(`schema: '${fieldName}' (${type}) is not a valid bytesN type`);
263
+ }
264
+ return { kind: "bytes", length: n };
265
+ }
266
+ throw new Error(`schema: '${fieldName}' has unsupported type '${type}'`);
267
+ }
268
+ // ---------------------------------------------------------------------------
269
+ // Schema -> CompactType descriptor + value coercion
270
+ // ---------------------------------------------------------------------------
271
+ function respondSchemaToCompactType(fields) {
272
+ return {
273
+ kind: "struct",
274
+ fields: fields.map((field) => {
275
+ if (isAbiDynamicField(field)) {
276
+ return {
277
+ name: field.name,
278
+ type: {
279
+ kind: "struct",
280
+ fields: [
281
+ { name: "len", type: { kind: "uint", bits: DYN_LEN_BYTES * 8 } },
282
+ { name: "data", type: { kind: "bytes", length: field.maxBytes } },
283
+ ],
284
+ },
285
+ };
286
+ }
287
+ if (isAbiArrayField(field)) {
288
+ return {
289
+ name: field.name,
290
+ type: {
291
+ kind: "struct",
292
+ fields: [
293
+ { name: "len", type: { kind: "uint", bits: DYN_LEN_BYTES * 8 } },
294
+ {
295
+ name: "items",
296
+ type: {
297
+ kind: "vector",
298
+ length: field.maxItems,
299
+ element: classifyFixedType(field.type.slice(0, -2), field.name),
300
+ },
301
+ },
302
+ ],
303
+ },
304
+ };
305
+ }
306
+ return { name: field.name, type: classifyFixedType(field.type, field.name) };
307
+ }),
308
+ };
309
+ }
310
+ function toCompactValue(value, field) {
311
+ const { name } = field;
312
+ if (isAbiDynamicField(field)) {
313
+ const payload = field.type === "string"
314
+ ? new TextEncoder().encode(asString(value, name))
315
+ : asBytes(value, name);
316
+ if (payload.length > field.maxBytes) {
317
+ throw new Error(`'${name}': payload is ${payload.length} bytes, maxBytes is ${field.maxBytes}`);
318
+ }
319
+ const data = new Uint8Array(field.maxBytes);
320
+ data.set(payload);
321
+ return { len: BigInt(payload.length), data };
322
+ }
323
+ if (isAbiArrayField(field)) {
324
+ if (!Array.isArray(value)) {
325
+ throw new Error(`'${name}' (${field.type}) expects an array`);
326
+ }
327
+ if (value.length > field.maxItems) {
328
+ throw new Error(`'${name}': ${value.length} elements, maxItems is ${field.maxItems}`);
329
+ }
330
+ const elementType = field.type.slice(0, -2);
331
+ const items = value.map((element, i) => fixedCompactValue(element, elementType, `${name}[${i}]`));
332
+ // Unused capacity encodes as zero values of the element type.
333
+ while (items.length < field.maxItems)
334
+ items.push(zeroOf(elementType));
335
+ return { len: BigInt(value.length), items };
336
+ }
337
+ return fixedCompactValue(value, field.type, name);
338
+ }
339
+ function fixedCompactValue(value, type, label) {
340
+ if (type === "bool") {
341
+ if (typeof value !== "boolean") {
342
+ throw new Error(`'${label}' (bool) expects a boolean`);
343
+ }
344
+ return value;
345
+ }
346
+ if (/^bytes\d+$/.test(type)) {
347
+ const raw = asBytes(value, label);
348
+ const expected = Number(type.slice(5));
349
+ if (raw.length !== expected) {
350
+ throw new Error(`'${label}' (${type}) expects exactly ${expected} bytes, got ${raw.length}`);
351
+ }
352
+ return raw;
353
+ }
354
+ // Numeric carriers: uintN, uint256/field and address.
355
+ const n = asBigint(value, label);
356
+ if (type === "address" && n >= ADDRESS_BOUND) {
357
+ throw new Error(`'${label}': value ${n} exceeds an address`);
358
+ }
359
+ // Uint width and Field modulus bounds are enforced by @sig-net/midnight-serde.
360
+ return n;
361
+ }
362
+ function zeroOf(type) {
363
+ if (type === "bool")
364
+ return false;
365
+ if (/^bytes\d+$/.test(type))
366
+ return new Uint8Array(Number(type.slice(5)));
367
+ return 0n;
368
+ }
369
+ // ---------------------------------------------------------------------------
370
+ // Value-form coercions
371
+ // ---------------------------------------------------------------------------
372
+ function asBigint(value, label) {
373
+ if (typeof value === "bigint")
374
+ return value;
375
+ if (typeof value === "number" && Number.isSafeInteger(value))
376
+ return BigInt(value);
377
+ if (typeof value === "string") {
378
+ try {
379
+ return BigInt(value);
380
+ }
381
+ catch {
382
+ throw new Error(`'${label}': cannot parse '${value}' as an integer`);
383
+ }
384
+ }
385
+ throw new Error(`'${label}': expected an integer-like value`);
386
+ }
387
+ function asBytes(value, label) {
388
+ if (value instanceof Uint8Array)
389
+ return value;
390
+ if (typeof value === "string")
391
+ return ethers.getBytes(value);
392
+ throw new Error(`'${label}': expected bytes (Uint8Array or hex string)`);
393
+ }
394
+ function asString(value, label) {
395
+ if (typeof value !== "string") {
396
+ throw new Error(`'${label}': expected a string`);
397
+ }
398
+ return value;
399
+ }
400
+ //# sourceMappingURL=abi-serde.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abi-serde.js","sourceRoot":"","sources":["../src/abi-serde.ts"],"names":[],"mappings":"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"}