@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.
- package/README.md +39 -12
- package/dist/ecdsa-attestation.d.ts +29 -1
- package/dist/ecdsa-attestation.d.ts.map +1 -1
- package/dist/ecdsa-attestation.js +55 -0
- package/dist/ecdsa-attestation.js.map +1 -1
- package/dist/managed/compiler/contract-info.json +12 -8
- package/dist/managed/compiler/contract-manifest.json +8 -8
- package/dist/managed/contract/index.d.ts +10 -10
- package/dist/managed/contract/index.js +92 -84
- package/dist/managed/contract/index.js.map +1 -1
- package/dist/signature-requests-state-reader.d.ts +6 -5
- package/dist/signature-requests-state-reader.d.ts.map +1 -1
- package/dist/signature-requests-state-reader.js +17 -16
- package/dist/signature-requests-state-reader.js.map +1 -1
- package/dist/signature-state-reading.d.ts +17 -25
- package/dist/signature-state-reading.d.ts.map +1 -1
- package/dist/signature-state-reading.js +37 -57
- package/dist/signature-state-reading.js.map +1 -1
- package/dist/signet-contract-state-reader.d.ts +24 -18
- package/dist/signet-contract-state-reader.d.ts.map +1 -1
- package/dist/signet-contract-state-reader.js +42 -32
- package/dist/signet-contract-state-reader.js.map +1 -1
- package/dist/signet-request-resolver.d.ts +1 -1
- package/dist/signet-request-resolver.js +2 -2
- package/dist/signet-request-resolver.js.map +1 -1
- package/dist/signet-request-response-reader.d.ts +39 -14
- package/dist/signet-request-response-reader.d.ts.map +1 -1
- package/dist/signet-request-response-reader.js +38 -10
- package/dist/signet-request-response-reader.js.map +1 -1
- package/package.json +2 -2
- 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,
|
|
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
|
|
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
|
-
*
|
|
30
|
-
* same
|
|
31
|
-
*
|
|
32
|
-
* the reader cannot
|
|
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
|
|
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 `
|
|
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
|
|
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.
|
|
157
|
-
*
|
|
158
|
-
*
|
|
159
|
-
*
|
|
160
|
-
*
|
|
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,
|
|
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 `
|
|
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
|
|
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.
|
|
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
|
|
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.
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
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":"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;
|
|
1
|
+
{"version":3,"file":"signet-request-response-reader.js","sourceRoot":"","sources":["../src/signet-request-response-reader.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sig-net/midnight",
|
|
3
|
-
"version": "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.
|
|
43
|
+
"@sig-net/midnight-serde": "^0.15.0",
|
|
44
44
|
"ethers": "^6.17.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
package/src/Signet.compact
CHANGED
|
@@ -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
|
|
33
|
-
// digest of the request id and serialised output
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
//
|
|
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
|
-
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
|
|
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 +
|
|
223
|
-
payload: Bytes[
|
|
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
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
//
|
|
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
|
|
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
|
-
//
|
|
292
|
-
// keccak256
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
//
|
|
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
|
-
//
|
|
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
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
362
|
+
// Verification steps:
|
|
363
|
+
// 1. Recompute digest: digest = keccak256(requestId + serializedOutput)
|
|
364
|
+
// 2. Verify signature: secp256k1EcdsaVerify(digest, signature, mpcResponseKey) == true
|
|
336
365
|
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
//
|
|
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
|
-
|
|
351
|
-
|
|
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
|