@sig-net/midnight 0.12.0 → 0.14.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 +22 -10
- package/dist/abi-serde.d.ts.map +1 -1
- package/dist/abi-serde.js +35 -28
- package/dist/abi-serde.js.map +1 -1
- package/dist/constants.d.ts +22 -23
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +24 -26
- package/dist/constants.js.map +1 -1
- 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 +0 -7
- package/dist/managed/compiler/contract-manifest.json +8 -8
- package/dist/managed/contract/index.d.ts +2 -4
- package/dist/managed/contract/index.js +46 -54
- package/dist/managed/contract/index.js.map +1 -1
- package/dist/signet-contract-state-reader.d.ts +11 -11
- package/dist/signet-contract-state-reader.d.ts.map +1 -1
- package/dist/signet-contract-state-reader.js +8 -16
- package/dist/signet-contract-state-reader.js.map +1 -1
- package/dist/signet-request-response-reader.d.ts +31 -5
- package/dist/signet-request-response-reader.d.ts.map +1 -1
- package/dist/signet-request-response-reader.js +34 -4
- package/dist/signet-request-response-reader.js.map +1 -1
- package/package.json +2 -2
- package/src/Signet.compact +57 -65
|
@@ -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
|
|
@@ -181,10 +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
|
-
*
|
|
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.
|
|
188
191
|
*
|
|
189
192
|
* @param requestId - The request id whose responses to enumerate.
|
|
190
193
|
* @returns The posted records, index = count, empty when none yet.
|
|
@@ -206,5 +209,32 @@ export class SignetRequestResponseReader {
|
|
|
206
209
|
}
|
|
207
210
|
return responses;
|
|
208
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
|
+
}
|
|
209
239
|
}
|
|
210
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.14.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.14.0",
|
|
44
44
|
"ethers": "^6.17.0"
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
package/src/Signet.compact
CHANGED
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
// - client contract(s): contracts on the Midnight blockchain that integrate with the Signet Distributed MPC
|
|
8
8
|
// to execute arbitrary transactions on foreign blockchains.
|
|
9
9
|
// - Signet singleton: a single contract on the Midnight blockchain holding the Signet registry for transaction
|
|
10
|
-
// signature requests and responses, as well as
|
|
11
|
-
// on foreign blockchains.
|
|
10
|
+
// signature requests and responses, as well as signed attestations of transactions executed
|
|
11
|
+
// on foreign blockchains (the execution outputs themselves travel off chain).
|
|
12
12
|
//
|
|
13
13
|
// Usage:
|
|
14
14
|
// // Import this module at the start of a contract (resolved through node_modules via COMPACT_PATH):
|
|
@@ -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
|
|
@@ -254,30 +258,30 @@ module Signet {
|
|
|
254
258
|
signature: Signature;
|
|
255
259
|
}
|
|
256
260
|
|
|
257
|
-
//
|
|
258
|
-
//
|
|
259
|
-
//
|
|
260
|
-
//
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
//
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
//
|
|
267
|
-
//
|
|
268
|
-
//
|
|
269
|
-
//
|
|
270
|
-
//
|
|
261
|
+
// RespondBidirectionalEvent is the final step of the Sig Network Sign Bidirectional flow.
|
|
262
|
+
// It holds an MPC ECDSA signature of an attestation digest verifying foreign chain execution output.
|
|
263
|
+
//
|
|
264
|
+
// The attestation digest is a keccak256 hash of the request id concatenated with the serialised foreign
|
|
265
|
+
// transaction execution output:
|
|
266
|
+
// attestationDigest = keccak256(requestId + serialisedOutput)
|
|
267
|
+
//
|
|
268
|
+
// The signature is the ECDSA secp256k1 signature over the attestation digest by the MPC with the
|
|
269
|
+
// client contract's MPC response key:
|
|
270
|
+
// signature = signSECP256k1(mpcResponseKey, attestationDigest)
|
|
271
|
+
//
|
|
272
|
+
// Where the MPC response key is a per-client-contract key derived using the same derivation function
|
|
273
|
+
// as request signing keys, with the path set to the fixed "midnight response key":
|
|
274
|
+
// mpcResponseKey = f(mpcRootKey[keyVersion], sender, "midnight response key")
|
|
275
|
+
//
|
|
276
|
+
// Storage & Verification:
|
|
277
|
+
// The execution output is of variable size, so it travels off chain, and the digest
|
|
278
|
+
// over it is recomputed rather than stored. The client fetches the output, recomputes
|
|
279
|
+
// the attestation digest and verifies the signature in-circuit via
|
|
280
|
+
// verifyRespondBidirectionalEvent against its derived MPC response key. The signature
|
|
281
|
+
// is the ONLY thing that distinguishes a genuine post from garbage: the Signet
|
|
282
|
+
// singleton is an unauthenticated log and stores every post unverified.
|
|
271
283
|
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.
|
|
284
|
+
// The MPC's ECDSA signature over the attestation digest.
|
|
281
285
|
signature: Signature;
|
|
282
286
|
}
|
|
283
287
|
|
|
@@ -288,20 +292,13 @@ module Signet {
|
|
|
288
292
|
requestId: RequestId;
|
|
289
293
|
};
|
|
290
294
|
|
|
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.
|
|
295
|
+
// Calculates the 32-byte attestation digest for a remote execution output:
|
|
296
|
+
// attestationDigest = keccak256(requestId + serializedOutput)
|
|
297
|
+
//
|
|
298
|
+
// Inputs are concatenated raw with no padding or length prefixes. The output digest is
|
|
299
|
+
// interpreted as a big-endian integer during ECDSA signature verification.
|
|
300
|
+
//
|
|
301
|
+
// Note: Off-chain code should use the matching TypeScript twin in `ecdsa-attestation.ts`.
|
|
305
302
|
export pure circuit calculateSignetAttestationDigest<#serializedOutputLength>(
|
|
306
303
|
requestId: RequestId,
|
|
307
304
|
serializedOutput: Bytes<serializedOutputLength>,
|
|
@@ -320,23 +317,21 @@ module Signet {
|
|
|
320
317
|
v[7], v[6], v[5], v[4], v[3], v[2], v[1], v[0]];
|
|
321
318
|
}
|
|
322
319
|
|
|
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.
|
|
320
|
+
// Verifies a RespondBidirectionalEvent against its execution output and MPC response key.
|
|
332
321
|
//
|
|
333
|
-
//
|
|
334
|
-
//
|
|
335
|
-
//
|
|
322
|
+
// Verification steps:
|
|
323
|
+
// 1. Recompute digest: digest = keccak256(requestId + serializedOutput)
|
|
324
|
+
// 2. Verify signature: secp256k1EcdsaVerify(digest, signature, mpcResponseKey) == true
|
|
336
325
|
//
|
|
337
|
-
//
|
|
338
|
-
//
|
|
339
|
-
//
|
|
326
|
+
// The caller supplies serializedOutput at its exact unpadded width, per
|
|
327
|
+
// calculateSignetAttestationDigest, and hands over the event record as stored: the
|
|
328
|
+
// big-endian-to-little-endian re-encoding of the signature scalars happens here, in one
|
|
329
|
+
// place for every integrator. ECDSA's r is bigR.x reduced mod the curve order; bigR.x is
|
|
330
|
+
// taken as-is, as it is already below the order for all but a ~2^-128 fraction of
|
|
331
|
+
// signatures, and one that is not simply fails to verify.
|
|
332
|
+
//
|
|
333
|
+
// Note: Client contracts must run this check before consuming outputs, as the Signet
|
|
334
|
+
// singleton stores responses unverified.
|
|
340
335
|
export pure circuit verifyRespondBidirectionalEvent<#serializedOutputLength>(
|
|
341
336
|
requestId: RequestId,
|
|
342
337
|
serializedOutput: Bytes<serializedOutputLength>,
|
|
@@ -347,10 +342,8 @@ module Signet {
|
|
|
347
342
|
requestId,
|
|
348
343
|
serializedOutput,
|
|
349
344
|
);
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const checkpointMatches = digest == respondBidirectionalEvent.attestationDigest;
|
|
353
|
-
const signatureValid = secp256k1EcdsaVerify(
|
|
345
|
+
|
|
346
|
+
return secp256k1EcdsaVerify(
|
|
354
347
|
digest,
|
|
355
348
|
Secp256k1EcdsaSignature {
|
|
356
349
|
r: reverseBytes32(respondBidirectionalEvent.signature.bigR.x) as Secp256k1Scalar,
|
|
@@ -358,7 +351,6 @@ module Signet {
|
|
|
358
351
|
},
|
|
359
352
|
mpcResponseKey
|
|
360
353
|
);
|
|
361
|
-
return checkpointMatches && signatureValid;
|
|
362
354
|
}
|
|
363
355
|
|
|
364
356
|
// Hash a secp256k1 public key exactly as client contracts pin it at deploy time
|