@sig-net/midnight 0.13.0 → 0.15.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 (31) hide show
  1. package/README.md +39 -12
  2. package/dist/ecdsa-attestation.d.ts +29 -1
  3. package/dist/ecdsa-attestation.d.ts.map +1 -1
  4. package/dist/ecdsa-attestation.js +55 -0
  5. package/dist/ecdsa-attestation.js.map +1 -1
  6. package/dist/managed/compiler/contract-info.json +12 -8
  7. package/dist/managed/compiler/contract-manifest.json +8 -8
  8. package/dist/managed/contract/index.d.ts +10 -10
  9. package/dist/managed/contract/index.js +92 -84
  10. package/dist/managed/contract/index.js.map +1 -1
  11. package/dist/signature-requests-state-reader.d.ts +6 -5
  12. package/dist/signature-requests-state-reader.d.ts.map +1 -1
  13. package/dist/signature-requests-state-reader.js +17 -16
  14. package/dist/signature-requests-state-reader.js.map +1 -1
  15. package/dist/signature-state-reading.d.ts +17 -25
  16. package/dist/signature-state-reading.d.ts.map +1 -1
  17. package/dist/signature-state-reading.js +37 -57
  18. package/dist/signature-state-reading.js.map +1 -1
  19. package/dist/signet-contract-state-reader.d.ts +24 -18
  20. package/dist/signet-contract-state-reader.d.ts.map +1 -1
  21. package/dist/signet-contract-state-reader.js +42 -32
  22. package/dist/signet-contract-state-reader.js.map +1 -1
  23. package/dist/signet-request-resolver.d.ts +1 -1
  24. package/dist/signet-request-resolver.js +2 -2
  25. package/dist/signet-request-resolver.js.map +1 -1
  26. package/dist/signet-request-response-reader.d.ts +39 -14
  27. package/dist/signet-request-response-reader.d.ts.map +1 -1
  28. package/dist/signet-request-response-reader.js +38 -10
  29. package/dist/signet-request-response-reader.js.map +1 -1
  30. package/package.json +2 -2
  31. package/src/Signet.compact +102 -70
@@ -1 +1 @@
1
- {"version":3,"file":"signet-request-resolver.js","sourceRoot":"","sources":["../src/signet-request-resolver.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,uDAAuD;AACvD,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,6DAA6D;AAC7D,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;AACzE,qCAAqC;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAiC7E;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,qBAAqB;IACf,MAAM,CAA0B;IAEjD,8EAA8E;IAC9E,4DAA4D;IAC3C,aAAa,GAAG,IAAI,GAAG,EAAuC,CAAC;IAEhF;;OAEG;IACH,YAAY,MAAmC;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,OAAO,CACX,SAAuB,EACvB,YAA2C;QAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,KAAwC,CAAC;QAC7C,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC,CAAC,uDAAuD;QAC3E,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;YACjB,OAAO,SAAS,CAAC,CAAC,qDAAqD;QACzE,CAAC;QACD,MAAM,OAAO,GAAG,qBAAqB,CACnC,KAAK,CAAC,IAAI,EACV,YAAY,CAAC,kBAAkB,EAC/B,SAAS,CACV,CAAC;QACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC,CAAC,kDAAkD;QACtE,CAAC;QACD,MAAM,QAAQ,GAA0B;YACtC,aAAa,EAAE,YAAY,CAAC,aAAa;YACzC,SAAS;YACT,OAAO;SACR,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC5C,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
1
+ {"version":3,"file":"signet-request-resolver.js","sourceRoot":"","sources":["../src/signet-request-resolver.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,uDAAuD;AACvD,6EAA6E;AAC7E,yEAAyE;AACzE,4EAA4E;AAC5E,6EAA6E;AAC7E,0EAA0E;AAC1E,6DAA6D;AAC7D,EAAE;AACF,4EAA4E;AAC5E,yEAAyE;AACzE,qCAAqC;AAErC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAiC7E;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,qBAAqB;IACf,MAAM,CAA0B;IAEjD,8EAA8E;IAC9E,4DAA4D;IAC3C,aAAa,GAAG,IAAI,GAAG,EAAuC,CAAC;IAEhF;;OAEG;IACH,YAAY,MAAmC;QAC7C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IAC9B,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,OAAO,CACX,SAAuB,EACvB,YAA2C;QAE3C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,IAAI,KAAwC,CAAC;QAC7C,IAAI,CAAC;YACH,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAC,CAAC,uDAAuD;QAC3E,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;YACjB,OAAO,SAAS,CAAC,CAAC,qDAAqD;QACzE,CAAC;QACD,MAAM,OAAO,GAAG,qBAAqB,CACnC,KAAK,CAAC,IAAI,EACV,YAAY,CAAC,YAAY,EACzB,SAAS,CACV,CAAC;QACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,SAAS,CAAC,CAAC,kDAAkD;QACtE,CAAC;QACD,MAAM,QAAQ,GAA0B;YACtC,aAAa,EAAE,YAAY,CAAC,aAAa;YACzC,SAAS;YACT,OAAO;SACR,CAAC;QACF,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC5C,OAAO,QAAQ,CAAC;IAClB,CAAC;CACF"}
@@ -1,8 +1,9 @@
1
1
  import type { PublicDataProvider } from "@midnight-ntwrk/midnight-js-types";
2
2
  import type { Transaction } from "ethers";
3
3
  import { type SignatureRespondedEvent, type RespondBidirectionalEvent } from "./signet-contract-state-reader.ts";
4
+ import { type Secp256k1Point } from "./ecdsa-attestation.ts";
4
5
  import type { RawContractState } from "./signature-state-reading.ts";
5
- import type { SignBidirectionalEvent, RequestIdHex } from "./signet-requests.ts";
6
+ import { type SignBidirectionalEvent, type RequestIdHex } from "./signet-requests.ts";
6
7
  /**
7
8
  * The least of midnight-js's `PublicDataProvider` the reader needs: raw
8
9
  * contract state by address. Declared structurally so tests can satisfy it
@@ -26,12 +27,13 @@ export interface SignetRequestResponseReaderConfig {
26
27
  /** Address of the signet-compliant requester contract (e.g. the vault). */
27
28
  readonly requesterContractAddress: string;
28
29
  /**
29
- * Ledger field position of the requester contract's request index: the
30
- * same position the contract passes as `requestsIndexField` in its
31
- * notifications. A contract is free to declare the index at any field, so
32
- * the reader cannot assume one.
30
+ * Resolved ledger-tree path of the requester contract's request index: the
31
+ * same path the contract packs as `requestsPath` in its notifications
32
+ * (`[4]` for a flat contract's field 4, longer once chunking applies). A
33
+ * contract is free to declare the index at any field, so the reader cannot
34
+ * assume one.
33
35
  */
34
- readonly requesterRequestsIndexField: number;
36
+ readonly requesterRequestsPath: readonly number[];
35
37
  /** Address of the central signet contract. */
36
38
  readonly signetContractAddress: string;
37
39
  /** Source of raw contract state, e.g. midnight-js's `indexerPublicDataProvider`. */
@@ -85,13 +87,13 @@ export declare class SignetRequestResponseReader {
85
87
  private queryRawState;
86
88
  /**
87
89
  * Fetch the request record for `requestId` from the requester contract's
88
- * request index (at the configured `requesterRequestsIndexField`). Cached
90
+ * request index (at the configured `requesterRequestsPath`). Cached
89
91
  * after the first fetch.
90
92
  *
91
93
  * @param requestId - The request id to look up.
92
94
  * @returns The stored request record.
93
95
  * @throws Error when the requester contract has no state or holds no
94
- * request under `requestId` at the configured index field.
96
+ * request under `requestId` at the configured index path.
95
97
  */
96
98
  getSignatureRequest(requestId: RequestIdHex): Promise<SignBidirectionalEvent>;
97
99
  /**
@@ -153,12 +155,11 @@ export declare class SignetRequestResponseReader {
153
155
  /**
154
156
  * Fetch every respond-bidirectional response posted for `requestId`, in
155
157
  * post (count) order. UNVERIFIED: the signet contract stores posts without
156
- * checking them, so any entry may be garbage. Verify each candidate before
157
- * trusting it (in-circuit at claim time, or off-chain: recompute the digest
158
- * with the TS twin `calculateSignetAttestationDigest`, match it against the
159
- * event's `attestationDigest`, and verify the ECDSA signature against the
160
- * MPC response key you expect). An empty array simply means none posted
161
- * yet: poll again.
158
+ * checking them, so any entry may be garbage. Each post carries a signature
159
+ * and nothing else, so verifying it against the MPC response key you expect
160
+ * is the only way to pick the genuine one: in-circuit at claim time, or off
161
+ * chain with {@link verifyRespondBidirectionalSignature} over the output you
162
+ * fetched. An empty array simply means none posted yet: poll again.
162
163
  *
163
164
  * @param requestId - The request id whose responses to enumerate.
164
165
  * @returns The posted records, index = count, empty when none yet.
@@ -166,5 +167,29 @@ export declare class SignetRequestResponseReader {
166
167
  * disagrees with the log (inconsistent ledger).
167
168
  */
168
169
  getRespondBidirectionalEvents(requestId: RequestIdHex): Promise<RespondBidirectionalEvent[]>;
170
+ /**
171
+ * Fetch the respond-bidirectional posts for `requestId` and return the
172
+ * first (lowest count) one whose signature verifies over
173
+ * `serializedOutput` against `mpcResponseKey`: the off-chain twin of the
174
+ * check the client contract runs in-circuit, and the only way to pick a
175
+ * genuine post out of an unauthenticated log now that posts carry nothing
176
+ * but a signature.
177
+ *
178
+ * The output must be the exact unpadded bytes the attestation commits to
179
+ * (the packed respond payload, recomputed from the execution output the
180
+ * client fetched), so a post that verifies here is the post that proves at
181
+ * claim time.
182
+ *
183
+ * @param requestId - The request id to fetch a verified attestation for.
184
+ * @param serializedOutput - The serialised execution output the attestation
185
+ * must commit to, exact unpadded bytes.
186
+ * @param mpcResponseKey - The MPC response key the requesting contract
187
+ * pinned at deploy (see `deriveMidnightResponseKey`).
188
+ * @returns The first verifying post, or `undefined` when none has been
189
+ * posted yet (poll again) or none attests this output.
190
+ * @throws Error when the signet contract has no state, or its counter
191
+ * disagrees with the log (inconsistent ledger).
192
+ */
193
+ getVerifiedRespondBidirectionalEvent(requestId: RequestIdHex, serializedOutput: Uint8Array, mpcResponseKey: Secp256k1Point): Promise<RespondBidirectionalEvent | undefined>;
169
194
  }
170
195
  //# sourceMappingURL=signet-request-response-reader.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signet-request-response-reader.d.ts","sourceRoot":"","sources":["../src/signet-request-response-reader.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,mCAAmC,CAAC;AAC5E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAGL,KAAK,uBAAuB,EAC5B,KAAK,yBAAyB,EAC/B,MAAM,mCAAmC,CAAC;AAE3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAKrE,OAAO,KAAK,EACV,sBAAsB,EACtB,YAAY,EACb,MAAM,sBAAsB,CAAC;AAE9B;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;OAMG;IACH,kBAAkB,CAChB,eAAe,EAAE,UAAU,CAAC,kBAAkB,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,GACvE,OAAO,CAAC;QAAE,IAAI,EAAE,gBAAgB,CAAA;KAAE,GAAG,IAAI,CAAC,CAAC;CAC/C;AAED,yEAAyE;AACzE,MAAM,WAAW,iCAAiC;IAChD,2EAA2E;IAC3E,QAAQ,CAAC,wBAAwB,EAAE,MAAM,CAAC;IAC1C;;;;;OAKG;IACH,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,8CAA8C;IAC9C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACvC,oFAAoF;IACpF,QAAQ,CAAC,kBAAkB,EAAE,uBAAuB,CAAC;CACtD;AAED,4DAA4D;AAC5D,MAAM,WAAW,wBAAwB;IACvC,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,6CAA6C;IAC7C,QAAQ,EAAE,uBAAuB,CAAC;IAClC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,2FAA2F;AAC3F,MAAM,WAAW,+BAA+B;IAC9C;;;OAGG;IACH,QAAQ,CAAC,EAAE,uBAAuB,CAAC;IACnC;;;OAGG;IACH,QAAQ,EAAE,wBAAwB,EAAE,CAAC;CACtC;AAED;;;;;GAKG;AACH,qBAAa,2BAA2B;IACtC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAoC;IAG3D,OAAO,CAAC,QAAQ,CAAC,YAAY,CAGzB;IAEJ;;OAEG;gBACS,MAAM,EAAE,iCAAiC;IAIrD;;;;;;;OAOG;YACW,aAAa;IAc3B;;;;;;;;;OASG;IACG,mBAAmB,CACvB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,sBAAsB,CAAC;IAwBlC;;;;;;;;;OASG;IACG,qBAAqB,CACzB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,uBAAuB,EAAE,CAAC;IAwBrC;;;;;;;;;;;;;OAaG;IACG,kCAAkC,CACtC,SAAS,EAAE,YAAY,EACvB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,+BAA+B,CAAC;IAiC3C;;;;;;;;;;;OAWG;IACG,yBAAyB,CAC7B,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,WAAW,CAAC;IAMvB;;;;;;;;;;;;;;;OAeG;IACG,uBAAuB,CAC3B,SAAS,EAAE,YAAY,EACvB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC;IAcnC;;;;;;;;;;;;;;OAcG;IACG,6BAA6B,CACjC,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,yBAAyB,EAAE,CAAC;CAuBxC"}
1
+ {"version":3,"file":"signet-request-response-reader.d.ts","sourceRoot":"","sources":["../src/signet-request-response-reader.ts"],"names":[],"mappings":"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"}
@@ -11,7 +11,9 @@
11
11
  import { lookupSignetRequestAt } from "./signature-requests-state-reader.js";
12
12
  import { readSignetContractLedgerFromState, signetMapEntryKey, } from "./signet-contract-state-reader.js";
13
13
  import { recoverSignatureResponseSigner } from "./signature-response-verification.js";
14
+ import { verifyRespondBidirectionalSignature, } from "./ecdsa-attestation.js";
14
15
  import { signBidirectionalEventToSignedEvmTransaction, signBidirectionalEventToUnsignedEvmTransaction, } from "./signet-evtype2tx-requests.js";
16
+ import { requestIdBytes, } from "./signet-requests.js";
15
17
  /**
16
18
  * Reader over one requester contract / signet contract pair.
17
19
  * Construct once per pair and reuse: fetched request records are cached (they
@@ -45,13 +47,13 @@ export class SignetRequestResponseReader {
45
47
  }
46
48
  /**
47
49
  * Fetch the request record for `requestId` from the requester contract's
48
- * request index (at the configured `requesterRequestsIndexField`). Cached
50
+ * request index (at the configured `requesterRequestsPath`). Cached
49
51
  * after the first fetch.
50
52
  *
51
53
  * @param requestId - The request id to look up.
52
54
  * @returns The stored request record.
53
55
  * @throws Error when the requester contract has no state or holds no
54
- * request under `requestId` at the configured index field.
56
+ * request under `requestId` at the configured index path.
55
57
  */
56
58
  async getSignatureRequest(requestId) {
57
59
  const cached = this.requestCache.get(requestId);
@@ -59,10 +61,10 @@ export class SignetRequestResponseReader {
59
61
  return cached;
60
62
  }
61
63
  const raw = await this.queryRawState(this.config.requesterContractAddress, "requester");
62
- const request = lookupSignetRequestAt(raw, this.config.requesterRequestsIndexField, requestId);
64
+ const request = lookupSignetRequestAt(raw, this.config.requesterRequestsPath, requestId);
63
65
  if (request === undefined) {
64
66
  throw new Error(`request ${requestId} is not on the requester contract's ledger ` +
65
- `(request index at field ${this.config.requesterRequestsIndexField}): was it submitted?`);
67
+ `(request index at path ${JSON.stringify(this.config.requesterRequestsPath)}): was it submitted?`);
66
68
  }
67
69
  this.requestCache.set(requestId, request);
68
70
  return request;
@@ -181,12 +183,11 @@ export class SignetRequestResponseReader {
181
183
  /**
182
184
  * Fetch every respond-bidirectional response posted for `requestId`, in
183
185
  * post (count) order. UNVERIFIED: the signet contract stores posts without
184
- * checking them, so any entry may be garbage. Verify each candidate before
185
- * trusting it (in-circuit at claim time, or off-chain: recompute the digest
186
- * with the TS twin `calculateSignetAttestationDigest`, match it against the
187
- * event's `attestationDigest`, and verify the ECDSA signature against the
188
- * MPC response key you expect). An empty array simply means none posted
189
- * yet: poll again.
186
+ * checking them, so any entry may be garbage. Each post carries a signature
187
+ * and nothing else, so verifying it against the MPC response key you expect
188
+ * is the only way to pick the genuine one: in-circuit at claim time, or off
189
+ * chain with {@link verifyRespondBidirectionalSignature} over the output you
190
+ * fetched. An empty array simply means none posted yet: poll again.
190
191
  *
191
192
  * @param requestId - The request id whose responses to enumerate.
192
193
  * @returns The posted records, index = count, empty when none yet.
@@ -208,5 +209,32 @@ export class SignetRequestResponseReader {
208
209
  }
209
210
  return responses;
210
211
  }
212
+ /**
213
+ * Fetch the respond-bidirectional posts for `requestId` and return the
214
+ * first (lowest count) one whose signature verifies over
215
+ * `serializedOutput` against `mpcResponseKey`: the off-chain twin of the
216
+ * check the client contract runs in-circuit, and the only way to pick a
217
+ * genuine post out of an unauthenticated log now that posts carry nothing
218
+ * but a signature.
219
+ *
220
+ * The output must be the exact unpadded bytes the attestation commits to
221
+ * (the packed respond payload, recomputed from the execution output the
222
+ * client fetched), so a post that verifies here is the post that proves at
223
+ * claim time.
224
+ *
225
+ * @param requestId - The request id to fetch a verified attestation for.
226
+ * @param serializedOutput - The serialised execution output the attestation
227
+ * must commit to, exact unpadded bytes.
228
+ * @param mpcResponseKey - The MPC response key the requesting contract
229
+ * pinned at deploy (see `deriveMidnightResponseKey`).
230
+ * @returns The first verifying post, or `undefined` when none has been
231
+ * posted yet (poll again) or none attests this output.
232
+ * @throws Error when the signet contract has no state, or its counter
233
+ * disagrees with the log (inconsistent ledger).
234
+ */
235
+ async getVerifiedRespondBidirectionalEvent(requestId, serializedOutput, mpcResponseKey) {
236
+ const events = await this.getRespondBidirectionalEvents(requestId);
237
+ return events.find((event) => verifyRespondBidirectionalSignature(requestIdBytes(requestId), serializedOutput, event, mpcResponseKey));
238
+ }
211
239
  }
212
240
  //# sourceMappingURL=signet-request-response-reader.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"signet-request-response-reader.js","sourceRoot":"","sources":["../src/signet-request-response-reader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signet-request-response-reader.js","sourceRoot":"","sources":["../src/signet-request-response-reader.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,8EAA8E;AAC9E,0EAA0E;AAC1E,uBAAuB;AACvB,yEAAyE;AACzE,2EAA2E;AAC3E,uEAAuE;AACvE,mEAAmE;AACnE,2EAA2E;AAC3E,iCAAiC;AAKjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EACL,iCAAiC,EACjC,iBAAiB,GAGlB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,8BAA8B,EAAE,MAAM,sCAAsC,CAAC;AACtF,OAAO,EACL,mCAAmC,GAEpC,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,4CAA4C,EAC5C,8CAA8C,GAC/C,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,cAAc,GAGf,MAAM,sBAAsB,CAAC;AAiE9B;;;;;GAKG;AACH,MAAM,OAAO,2BAA2B;IACrB,MAAM,CAAoC;IAE3D,wEAAwE;IACvD,YAAY,GAAG,IAAI,GAAG,EAGpC,CAAC;IAEJ;;OAEG;IACH,YAAY,MAAyC;QACnD,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;;;;;;OAOG;IACK,KAAK,CAAC,aAAa,CACzB,eAAuB,EACvB,IAAY;QAEZ,MAAM,KAAK,GACT,MAAM,IAAI,CAAC,MAAM,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,eAAe,CAAC,CAAC;QAC3E,IAAI,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CACb,2BAA2B,IAAI,cAAc,eAAe,qBAAqB,CAClF,CAAC;QACJ,CAAC;QACD,OAAO,KAAK,CAAC,IAAI,CAAC;IACpB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,mBAAmB,CACvB,SAAuB;QAEvB,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAChD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAClC,IAAI,CAAC,MAAM,CAAC,wBAAwB,EACpC,WAAW,CACZ,CAAC;QACF,MAAM,OAAO,GAAG,qBAAqB,CACnC,GAAG,EACH,IAAI,CAAC,MAAM,CAAC,qBAAqB,EACjC,SAAS,CACV,CAAC;QACF,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,WAAW,SAAS,6CAA6C;gBAC/D,0BAA0B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,qBAAqB,CAAC,sBAAsB,CACpG,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QAC1C,OAAO,OAAO,CAAC;IACjB,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,qBAAqB,CACzB,SAAuB;QAEvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAClC,IAAI,CAAC,MAAM,CAAC,qBAAqB,EACjC,iBAAiB,CAClB,CAAC;QACF,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,GACrC,iCAAiC,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC1D,MAAM,SAAS,GAA8B,EAAE,CAAC;QAChD,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,CAC7B,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CACpC,CAAC;YACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,gBAAgB,SAAS,GAAG;oBAC5D,+BAA+B,UAAU,gCAAgC,CAC5E,CAAC;YACJ,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,kCAAkC,CACtC,SAAuB,EACvB,cAAsB;QAEtB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,SAAS,CAAC,CAAC;QAC9D,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAC5B,CAAC,QAAQ,EAAE,KAAK,EAA4B,EAAE;YAC5C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC5B,IAAI,MAAc,CAAC;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,8BAA8B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;YAC7D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO;oBACL,KAAK;oBACL,QAAQ;oBACR,cAAc,EAAE,8BAA8B,MAAM,CAAC,KAAK,CAAC,GAAG;iBAC/D,CAAC;YACJ,CAAC;YACD,IAAI,MAAM,CAAC,WAAW,EAAE,KAAK,cAAc,CAAC,WAAW,EAAE,EAAE,CAAC;gBAC1D,OAAO;oBACL,KAAK;oBACL,QAAQ;oBACR,MAAM;oBACN,cAAc,EAAE,aAAa,MAAM,cAAc,cAAc,EAAE;iBAClE,CAAC;YACJ,CAAC;YACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QACrC,CAAC,CACF,CAAC;QACF,OAAO;YACL,QAAQ,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,KAAK,SAAS,CAAC,EAAE,QAAQ;YACxE,QAAQ;SACT,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,yBAAyB,CAC7B,SAAuB;QAEvB,OAAO,8CAA8C,CACnD,MAAM,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAC1C,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;;;;;OAeG;IACH,KAAK,CAAC,uBAAuB,CAC3B,SAAuB,EACvB,cAAsB;QAEtB,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,IAAI,CAAC,kCAAkC,CAChE,SAAS,EACT,cAAc,CACf,CAAC;QACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3B,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,4EAA4E;QAC5E,wCAAwC;QACxC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;QAC1D,OAAO,4CAA4C,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IACzE,CAAC;IAED;;;;;;;;;;;;;OAaG;IACH,KAAK,CAAC,6BAA6B,CACjC,SAAuB;QAEvB,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,aAAa,CAClC,IAAI,CAAC,MAAM,CAAC,qBAAqB,EACjC,iBAAiB,CAClB,CAAC;QACF,MAAM,EAAE,8BAA8B,EAAE,uBAAuB,EAAE,GAC/D,iCAAiC,CAAC,GAAG,CAAC,CAAC;QACzC,MAAM,UAAU,GAAG,8BAA8B,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACvE,MAAM,SAAS,GAAgC,EAAE,CAAC;QAClD,KAAK,IAAI,KAAK,GAAG,EAAE,EAAE,KAAK,GAAG,UAAU,EAAE,KAAK,EAAE,EAAE,CAAC;YACjD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,GAAG,CAC1C,iBAAiB,CAAC,SAAS,EAAE,KAAK,CAAC,CACpC,CAAC;YACF,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CACb,0CAA0C,KAAK,gBAAgB,SAAS,GAAG;oBACzE,+BAA+B,UAAU,gCAAgC,CAC5E,CAAC;YACJ,CAAC;YACD,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC3B,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,KAAK,CAAC,oCAAoC,CACxC,SAAuB,EACvB,gBAA4B,EAC5B,cAA8B;QAE9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,6BAA6B,CAAC,SAAS,CAAC,CAAC;QACnE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC3B,mCAAmC,CACjC,cAAc,CAAC,SAAS,CAAC,EACzB,gBAAgB,EAChB,KAAK,EACL,cAAc,CACf,CACF,CAAC;IACJ,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sig-net/midnight",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/sig-net/midnight-integration",
@@ -40,7 +40,7 @@
40
40
  "@midnight-ntwrk/compact-runtime": "0.18.0-rc.1",
41
41
  "@midnight-ntwrk/midnight-js-types": "5.0.0-beta.4",
42
42
  "@noble/curves": "^2.2.0",
43
- "@sig-net/midnight-serde": "^0.13.0",
43
+ "@sig-net/midnight-serde": "^0.15.0",
44
44
  "ethers": "^6.17.0"
45
45
  },
46
46
  "devDependencies": {
@@ -29,12 +29,12 @@
29
29
  // (via SignetSigner interface) to notify the MPC of a SignBidirectionalEvent.
30
30
  // - SignatureRespondedEvent: Counterpart to SignBidirectionalEvent containing MPC generated signature requested by a SignBidirectionalEvent.
31
31
  // Posted by MPC back to Signet singleton for clients to extract to build a signed transaction.
32
- // - RespondBidirectionalEvent: Attestation of a transaction executed on a foreign blockchain: the attestation
33
- // digest of the request id and serialised output (see calculateSignetAttestationDigest)
34
- // plus the MPC's ECDSA signature over that digest, signed with the MPC's RESPONSE
35
- // key for the requesting contract: the key derived from the client contract's
36
- // address + the fixed path "midnight response key". The output itself travels
37
- // off chain. Posted by MPC back to Signet singleton for clients to extract,
32
+ // - RespondBidirectionalEvent: Attestation of a transaction executed on a foreign blockchain: the MPC's ECDSA
33
+ // signature over the attestation digest of the request id and serialised output
34
+ // (see calculateSignetAttestationDigest), signed with the MPC's RESPONSE key for
35
+ // the requesting contract: the key derived from the client contract's address +
36
+ // the fixed path "midnight response key". Both the digest and the output itself
37
+ // travel off chain. Posted by MPC back to Signet singleton for clients to extract,
38
38
  // verify (see verifyRespondBidirectionalEvent) and deliver back to the client
39
39
  // contract.
40
40
  //
@@ -50,6 +50,10 @@
50
50
  // verifies the posted SignatureRespondedEvent and broadcasts txn to destination chain.
51
51
  // 4. MPC observes txn execution on destination chain, posts a RespondBidirectionalEvent
52
52
  // attestation to the central Signet contract, and the client polls it by RequestId.
53
+ // The client recovers the execution output itself off chain (for EVM: the mined
54
+ // call's return data via debug_traceTransaction, also served by the fakenet
55
+ // responder's /responses/{requestId} helper API) and hands output plus attestation
56
+ // to its verify circuit. See "Output recovery" in this package's README.
53
57
  //
54
58
  // Read more:
55
59
  // - For full integration examples (such as an ERC20 cross chain vault example) see
@@ -205,22 +209,62 @@ module Signet {
205
209
  // Notification delivered by client contracts via cross contract call to Signet singleton
206
210
  // (via SignetSigner interface) to notify the MPC of a SignBidirectionalEvent.
207
211
  export struct SignBidirectionalEventNotification {
208
- version: Uint<8>; // payload layout tag; 1 = the V1 layout:
209
- // callerAddress (32) ++ requestsIndexField (1) ++ zero padding (95)
210
- payload: Bytes<128>;
212
+ // Notification payload layout version.
213
+ // Curent Layout Version: 1 (see constructSignBidirectionalEventNotificationV1)
214
+ version: Uint<8>;
215
+ // Payload containing serialised notification payload.
216
+ payload: Bytes<128>;
211
217
  }
212
218
 
213
- // Construction helper for the V1 SignBidirectionalEventNotification
219
+ // Construction helper for the V1 SignBidirectionalEventNotification.
220
+ //
221
+ // The payload is a pointer for the MPC. It names the contract that holds the
222
+ // SignBidirectionalEventMap (callerAddress) and the position of that map in the
223
+ // contract's raw on-chain state (requestsPathDepth + requestsPath). The MPC
224
+ // follows the path through the raw state tree to read the authenticated
225
+ // request, without the caller's compiled contract.
226
+ //
227
+ // Why a path: compactc packs a contract's public ledger fields into a tree of
228
+ // state values whose array nodes hold at most 15 entries (the compiler's
229
+ // maximum-ledger-segment-length). A contract with 15 or fewer ledger fields
230
+ // keeps each field directly in the root array, so field N sits at path [N]
231
+ // (depth 1). Past 15 fields the compiler splits the declaration list into
232
+ // segments of at most 15, remainder segment first, and the root array holds
233
+ // the segments. Each split adds one level to the tree and one entry to every
234
+ // field's path. Example: 20 fields split into segments of 5 and 15, so
235
+ // fields 0..4 sit at [0, 0]..[0, 4] and fields 5..19 sit at
236
+ // [1, 0]..[1, 14] (depth 2).
237
+ //
238
+ // How to determine the values: read the path from your contract's compiled
239
+ // artifacts, do not derive it by hand. The compiler records each field's
240
+ // resolved path as its "index" in managed/<contract>/compiler/contract-info.json
241
+ // (a bare number N means path [N]). The generated
242
+ // managed/<contract>/contract/index.js accessors walk the same indices, for
243
+ // example state.asArray()[1].asArray()[14] for a map recorded at [1, 14].
244
+ // Set requestsPathDepth to the number of path entries and requestsPath to
245
+ // the path itself, zero padded to 4 entries: [1, 14] becomes depth 2 and
246
+ // path [1, 14, 0, 0].
214
247
  export pure circuit constructSignBidirectionalEventNotificationV1(
215
248
  // Address of the client contract that stores and notifies of this SignBidirectionalEvent.
216
249
  // Set with kernel.self(). MUST match sender in associated SignBidirectionalEvent.
217
250
  callerAddress: ContractAddress,
218
- requestsIndexField: Uint<8>
251
+ // Number of meaningful entries in requestsPath: 1 for a flat (15 or fewer
252
+ // field) contract, one more per chunk level after that (max 4).
253
+ requestsPathDepth: Uint<8>,
254
+ // Resolved ledger-tree path of the caller's SignBidirectionalEventMap, from
255
+ // its contract-info.json "index". Entries at and beyond requestsPathDepth
256
+ // are zero.
257
+ requestsPath: Vector<4, Uint<8>>
219
258
  ): SignBidirectionalEventNotification {
220
259
  return SignBidirectionalEventNotification {
221
260
  version: 1,
222
- // 128 = 32 + 1 + 95
223
- payload: Bytes[...callerAddress.bytes, requestsIndexField, ...default<Bytes<95>>]
261
+ // 128 = 32 + 1 + 4 + 91
262
+ payload: Bytes[
263
+ ...callerAddress.bytes,
264
+ requestsPathDepth,
265
+ requestsPath[0], requestsPath[1], requestsPath[2], requestsPath[3],
266
+ ...default<Bytes<91>>
267
+ ]
224
268
  };
225
269
  }
226
270
 
@@ -254,30 +298,30 @@ module Signet {
254
298
  signature: Signature;
255
299
  }
256
300
 
257
- // Attestation of a transaction executed on a foreign blockchain: the 32-byte
258
- // attestation digest of the request id and serialised output (see
259
- // calculateSignetAttestationDigest) plus the MPC's ECDSA (secp256k1) signature
260
- // over that digest, signed with the MPC's RESPONSE key for the requesting contract:
261
- // mpcResponseKey = f(mpcRootKey[keyVersion], sender, "midnight response key")
262
- // i.e. the same derivation as request-signing keys but with the FIXED
263
- // respond-bidirectional path, so it is per-client-contract yet independent of any
264
- // request's own path (mirrors the MPC's per-chain "<chain> response key" convention).
265
- // The execution output itself is unbounded, so it travels off chain. Posted by MPC
266
- // back to Signet singleton for clients to extract, verify and deliver back to the
267
- // client contract. Clients fetch the full output off chain, recompute the digest
268
- // and verify via verifyRespondBidirectionalEvent. The singleton stores posts
269
- // UNVERIFIED: client contracts must verify the signature themselves against their
270
- // MPC response key.
301
+ // RespondBidirectionalEvent is the final step of the Sig Network Sign Bidirectional flow.
302
+ // It holds an MPC ECDSA signature of an attestation digest verifying foreign chain execution output.
303
+ //
304
+ // The attestation digest is a keccak256 hash of the request id concatenated with the serialised foreign
305
+ // transaction execution output:
306
+ // attestationDigest = keccak256(requestId + serialisedOutput)
307
+ //
308
+ // The signature is the ECDSA secp256k1 signature over the attestation digest by the MPC with the
309
+ // client contract's MPC response key:
310
+ // signature = signSECP256k1(mpcResponseKey, attestationDigest)
311
+ //
312
+ // Where the MPC response key is a per-client-contract key derived using the same derivation function
313
+ // as request signing keys, with the path set to the fixed "midnight response key":
314
+ // mpcResponseKey = f(mpcRootKey[keyVersion], sender, "midnight response key")
315
+ //
316
+ // Storage & Verification:
317
+ // The execution output is of variable size, so it travels off chain, and the digest
318
+ // over it is recomputed rather than stored. The client fetches the output, recomputes
319
+ // the attestation digest and verifies the signature in-circuit via
320
+ // verifyRespondBidirectionalEvent against its derived MPC response key. The signature
321
+ // is the ONLY thing that distinguishes a genuine post from garbage: the Signet
322
+ // singleton is an unauthenticated log and stores every post unverified.
271
323
  export struct RespondBidirectionalEvent {
272
- // The attestation digest the signature signs: keccak256 of the request id
273
- // concatenated with the serialised output (see calculateSignetAttestationDigest).
274
- // A checkpoint for off-chain readers: match a fetched output against the
275
- // attestation (and check the signature) without any other inputs.
276
- // verifyRespondBidirectionalEvent binds it to the actual output bytes in-circuit.
277
- attestationDigest: Bytes<32>;
278
-
279
- // The MPC's ECDSA signature over attestationDigest above. The verify
280
- // circuit's r is this signature's bigR.x mod the curve order.
324
+ // The MPC's ECDSA signature over the attestation digest.
281
325
  signature: Signature;
282
326
  }
283
327
 
@@ -288,20 +332,13 @@ module Signet {
288
332
  requestId: RequestId;
289
333
  };
290
334
 
291
- // The 32-byte attestation digest the MPC ECDSA-signs to attest a remote execution:
292
- // keccak256 over the request id concatenated with the serialised output, exactly
293
- // the MPC's respond-bidirectional construction (hash(request_id || serialized_output):
294
- // one flat concatenation, one hash). The output is hashed AS GIVEN, at its exact
295
- // width: no padding and no length binding. The width is a generic parameter, fixed
296
- // by each client contract from its own respond serialisation schema. The digest
297
- // commits to the output byte-for-byte: the keccak preimage of the
298
- // [RequestId, Bytes<N>] pair is the raw concatenated bytes.
299
- // secp256k1EcdsaVerify interprets the digest as a BIG-ENDIAN integer reduced mod
300
- // the curve order (RFC 6979 convention). ONE implementation for everyone: client
301
- // contracts call this in-circuit. The compiler cannot export a size-generic circuit
302
- // top-level, so off-chain code uses the TS twin (calculateSignetAttestationDigest
303
- // in ecdsa-attestation.ts), pinned byte-for-byte against the fixed-width
304
- // instantiations circuits.compact exports as test oracles.
335
+ // Calculates the 32-byte attestation digest for a remote execution output:
336
+ // attestationDigest = keccak256(requestId + serializedOutput)
337
+ //
338
+ // Inputs are concatenated raw with no padding or length prefixes. The output digest is
339
+ // interpreted as a big-endian integer during ECDSA signature verification.
340
+ //
341
+ // Note: Off-chain code should use the matching TypeScript twin in `ecdsa-attestation.ts`.
305
342
  export pure circuit calculateSignetAttestationDigest<#serializedOutputLength>(
306
343
  requestId: RequestId,
307
344
  serializedOutput: Bytes<serializedOutputLength>,
@@ -320,23 +357,21 @@ module Signet {
320
357
  v[7], v[6], v[5], v[4], v[3], v[2], v[1], v[0]];
321
358
  }
322
359
 
323
- // Verify a RespondBidirectionalEvent against the serialised output it attests and
324
- // a secp256k1 public key: the event's digest checkpoint must equal the recomputed
325
- // attestation digest of (requestId, serializedOutput), and the event's ECDSA
326
- // signature must sign that digest. This is the check client contracts run before
327
- // accepting a response (the Signet singleton stores posts unverified). Pass the
328
- // contract's MPC RESPONSE key (derived off-chain from the contract's address + the
329
- // fixed path "midnight response key", typically hash-pinned in the contract's
330
- // ledger at deploy time). The caller supplies serializedOutput at its exact
331
- // unpadded width, per calculateSignetAttestationDigest.
360
+ // Verifies a RespondBidirectionalEvent against its execution output and MPC response key.
332
361
  //
333
- // Takes the event as stored: the caller hands over the record it read, and the
334
- // big-endian-to-little-endian re-encoding happens here, in one place for every
335
- // integrator.
362
+ // Verification steps:
363
+ // 1. Recompute digest: digest = keccak256(requestId + serializedOutput)
364
+ // 2. Verify signature: secp256k1EcdsaVerify(digest, signature, mpcResponseKey) == true
336
365
  //
337
- // ECDSA's r is bigR.x reduced mod the curve order. bigR.x is taken as-is: it is
338
- // already below the order for all but a ~2^-128 fraction of signatures, and one
339
- // that is not simply fails to verify.
366
+ // The caller supplies serializedOutput at its exact unpadded width, per
367
+ // calculateSignetAttestationDigest, and hands over the event record as stored: the
368
+ // big-endian-to-little-endian re-encoding of the signature scalars happens here, in one
369
+ // place for every integrator. ECDSA's r is bigR.x reduced mod the curve order; bigR.x is
370
+ // taken as-is, as it is already below the order for all but a ~2^-128 fraction of
371
+ // signatures, and one that is not simply fails to verify.
372
+ //
373
+ // Note: Client contracts must run this check before consuming outputs, as the Signet
374
+ // singleton stores responses unverified.
340
375
  export pure circuit verifyRespondBidirectionalEvent<#serializedOutputLength>(
341
376
  requestId: RequestId,
342
377
  serializedOutput: Bytes<serializedOutputLength>,
@@ -347,10 +382,8 @@ module Signet {
347
382
  requestId,
348
383
  serializedOutput,
349
384
  );
350
- // Two consts rather than one `&&` expression: compactc 0.33 ICEs when the
351
- // secp256k1EcdsaVerify call (its scalar casts) sits inside a subexpression.
352
- const checkpointMatches = digest == respondBidirectionalEvent.attestationDigest;
353
- const signatureValid = secp256k1EcdsaVerify(
385
+
386
+ return secp256k1EcdsaVerify(
354
387
  digest,
355
388
  Secp256k1EcdsaSignature {
356
389
  r: reverseBytes32(respondBidirectionalEvent.signature.bigR.x) as Secp256k1Scalar,
@@ -358,7 +391,6 @@ module Signet {
358
391
  },
359
392
  mpcResponseKey
360
393
  );
361
- return checkpointMatches && signatureValid;
362
394
  }
363
395
 
364
396
  // Hash a secp256k1 public key exactly as client contracts pin it at deploy time