@sig-net/midnight 0.0.1
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 +20 -0
- package/dist/constants.d.ts +62 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +83 -0
- package/dist/constants.js.map +1 -0
- package/dist/epsilon-derivation.d.ts +32 -0
- package/dist/epsilon-derivation.d.ts.map +1 -0
- package/dist/epsilon-derivation.js +54 -0
- package/dist/epsilon-derivation.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/managed/compiler/contract-info.json +165 -0
- package/dist/managed/compiler/contract-manifest.json +32 -0
- package/dist/managed/contract/index.d.ts +65 -0
- package/dist/managed/contract/index.js +611 -0
- package/dist/managed/contract/index.js.map +8 -0
- package/dist/schnorr.d.ts +100 -0
- package/dist/schnorr.d.ts.map +1 -0
- package/dist/schnorr.js +144 -0
- package/dist/schnorr.js.map +1 -0
- package/dist/signature-requests-state-reader.d.ts +74 -0
- package/dist/signature-requests-state-reader.d.ts.map +1 -0
- package/dist/signature-requests-state-reader.js +167 -0
- package/dist/signature-requests-state-reader.js.map +1 -0
- package/dist/signature-response-verification.d.ts +27 -0
- package/dist/signature-response-verification.d.ts.map +1 -0
- package/dist/signature-response-verification.js +45 -0
- package/dist/signature-response-verification.js.map +1 -0
- package/dist/signature-state-reading.d.ts +36 -0
- package/dist/signature-state-reading.d.ts.map +1 -0
- package/dist/signature-state-reading.js +62 -0
- package/dist/signature-state-reading.js.map +1 -0
- package/dist/signet-contract-state-reader.d.ts +146 -0
- package/dist/signet-contract-state-reader.d.ts.map +1 -0
- package/dist/signet-contract-state-reader.js +226 -0
- package/dist/signet-contract-state-reader.js.map +1 -0
- package/dist/signet-event-observer.d.ts +102 -0
- package/dist/signet-event-observer.d.ts.map +1 -0
- package/dist/signet-event-observer.js +127 -0
- package/dist/signet-event-observer.js.map +1 -0
- package/dist/signet-events.d.ts +175 -0
- package/dist/signet-events.d.ts.map +1 -0
- package/dist/signet-events.js +210 -0
- package/dist/signet-events.js.map +1 -0
- package/dist/signet-request-feed.d.ts +78 -0
- package/dist/signet-request-feed.d.ts.map +1 -0
- package/dist/signet-request-feed.js +116 -0
- package/dist/signet-request-feed.js.map +1 -0
- package/dist/signet-request-resolver.d.ts +58 -0
- package/dist/signet-request-resolver.d.ts.map +1 -0
- package/dist/signet-request-resolver.js +76 -0
- package/dist/signet-request-resolver.js.map +1 -0
- package/dist/signet-request-response-reader.d.ts +160 -0
- package/dist/signet-request-response-reader.d.ts.map +1 -0
- package/dist/signet-request-response-reader.js +198 -0
- package/dist/signet-request-response-reader.js.map +1 -0
- package/dist/signet-requests.d.ts +363 -0
- package/dist/signet-requests.d.ts.map +1 -0
- package/dist/signet-requests.js +497 -0
- package/dist/signet-requests.js.map +1 -0
- package/dist/signet-response-feed.d.ts +161 -0
- package/dist/signet-response-feed.d.ts.map +1 -0
- package/dist/signet-response-feed.js +234 -0
- package/dist/signet-response-feed.js.map +1 -0
- package/package.json +47 -0
- package/src/Schnorr.compact +63 -0
- package/src/Signet.compact +529 -0
- package/src/circuits.compact +36 -0
- package/src/constants.ts +97 -0
- package/src/epsilon-derivation.ts +62 -0
- package/src/index.ts +31 -0
- package/src/managed/compiler/contract-info.json +165 -0
- package/src/managed/compiler/contract-manifest.json +32 -0
- package/src/managed/contract/index.d.ts +65 -0
- package/src/managed/contract/index.js +611 -0
- package/src/managed/contract/index.js.map +8 -0
- package/src/schnorr.ts +210 -0
- package/src/signature-requests-state-reader.ts +223 -0
- package/src/signature-response-verification.ts +64 -0
- package/src/signature-state-reading.ts +87 -0
- package/src/signet-contract-state-reader.ts +391 -0
- package/src/signet-event-observer.ts +186 -0
- package/src/signet-events.ts +337 -0
- package/src/signet-request-feed.ts +158 -0
- package/src/signet-request-resolver.ts +116 -0
- package/src/signet-request-response-reader.ts +324 -0
- package/src/signet-requests.ts +737 -0
- package/src/signet-response-feed.ts +325 -0
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
// TypeScript twins of the request-side structs in the Compact library
|
|
2
|
+
// `Signet.compact` (same directory). The shapes MUST stay in lockstep with the Compact structs: the
|
|
3
|
+
// compiler inlines struct types anonymously into each contract's generated
|
|
4
|
+
// managed/contract/index.d.ts, and these named types match them structurally,
|
|
5
|
+
// so ledger reads assign to them without casts.
|
|
6
|
+
//
|
|
7
|
+
// The lockstep is enforced by each consuming contract's simulator tests: the
|
|
8
|
+
// "erc20-vault ledger shape" test in packages/vault-contract/tests/
|
|
9
|
+
// contract.test.ts assigns the generated `ledger().signetRequestsIndex` to the
|
|
10
|
+
// named SignBidirectionalRequestLedgerIndex type — the assignment itself is
|
|
11
|
+
// the assertion, so any structural drift between the generated managed types
|
|
12
|
+
// and these twins fails that package's `yarn build` / `yarn test`.
|
|
13
|
+
//
|
|
14
|
+
// Read more: https://docs.sig.network/ (signet protocol) and the module
|
|
15
|
+
// header in Signet.compact (layout convention, path binding).
|
|
16
|
+
import { CompactTypeBoolean, CompactTypeBytes, CompactTypeEnum, CompactTypeUnsignedInteger, CompactTypeVector, persistentHash, } from "@midnight-ntwrk/compact-runtime";
|
|
17
|
+
import { getAddress, getBytes, Signature, Transaction } from "ethers";
|
|
18
|
+
import { asciiPadded } from "./constants.js";
|
|
19
|
+
import { bigintToBytes32, bytesToBigint } from "./schnorr.js";
|
|
20
|
+
/**
|
|
21
|
+
* Which transaction-param decomposition a request carries (Compact:
|
|
22
|
+
* `enum TxParamType`), as the generated code represents enums: a `number`
|
|
23
|
+
* holding the 0-based variant index. Exported as a `const` object (not a TS
|
|
24
|
+
* `enum`) so the values stay structurally `number`.
|
|
25
|
+
*/
|
|
26
|
+
export const TxParamType = {
|
|
27
|
+
/** {@link EVMType2TxParams}: an EIP-1559 EVM transaction. */
|
|
28
|
+
evmType2: 0,
|
|
29
|
+
/**
|
|
30
|
+
* Never emitted — mirrors the Compact-side padding variant that keeps the
|
|
31
|
+
* enum at >= 2 variants (a 1-variant enum is a zero-byte value the proof
|
|
32
|
+
* server cannot parse inside persistentHash preimages).
|
|
33
|
+
*/
|
|
34
|
+
reserved: 1,
|
|
35
|
+
};
|
|
36
|
+
// ---- Request id (TS twin of the Compact circuit) ---------------------------
|
|
37
|
+
//
|
|
38
|
+
// DEVIATION from the "pure circuits are compiled, never re-written in TS"
|
|
39
|
+
// rule (see circuits.compact): `calculateRequestId` is generic over the
|
|
40
|
+
// tx-params type, the Compact compiler cannot export type-parameterized
|
|
41
|
+
// circuits from the top level, and a compiled copy would have to be
|
|
42
|
+
// monomorphized at ONE capacity instantiation — a client contract's choice
|
|
43
|
+
// that never belongs in this client-agnostic package. So the request-id
|
|
44
|
+
// circuit alone gets a TS twin here.
|
|
45
|
+
//
|
|
46
|
+
// It is NOT a hand-port of the hash algorithm: it calls the very
|
|
47
|
+
// `persistentHash` runtime builtin that compiled circuits call, over runtime
|
|
48
|
+
// type descriptors mirroring the ones the compiler generates (compare
|
|
49
|
+
// `_calculateRequestId_0` in any consuming contract's
|
|
50
|
+
// managed/contract/index.js). What must stay in lockstep with Signet.compact
|
|
51
|
+
// is exactly what this file already keeps in lockstep — the struct shapes,
|
|
52
|
+
// field by field, in declaration order. Enforced by vault-contract's
|
|
53
|
+
// "deposit round-trip" test, which asserts the id computed here equals the
|
|
54
|
+
// ledger map key minted by the REAL compiled contract.
|
|
55
|
+
// Runtime descriptors of the Compact base types the request record uses.
|
|
56
|
+
// CompactTypeUnsignedInteger takes (maxValue, byte length) — same literals
|
|
57
|
+
// the compiler emits for Uint<8/32/64/128>. CompactTypeEnum takes
|
|
58
|
+
// (variantCount - 1, byte length); NOTE a 1-variant enum would compile to
|
|
59
|
+
// `CompactTypeEnum(0, 0)` — zero bytes, which the proof server cannot parse
|
|
60
|
+
// inside persistentHash preimages. TxParamType therefore carries a padding
|
|
61
|
+
// `reserved` variant so it stays at (1, 1).
|
|
62
|
+
const BYTES_4 = new CompactTypeBytes(4);
|
|
63
|
+
const BYTES_20 = new CompactTypeBytes(20);
|
|
64
|
+
const BYTES_32 = new CompactTypeBytes(32);
|
|
65
|
+
const BYTES_64 = new CompactTypeBytes(64);
|
|
66
|
+
const BYTES_128 = new CompactTypeBytes(128);
|
|
67
|
+
const BYTES_256 = new CompactTypeBytes(256);
|
|
68
|
+
const UINT_8 = new CompactTypeUnsignedInteger(2n ** 8n - 1n, 1);
|
|
69
|
+
const UINT_16 = new CompactTypeUnsignedInteger(2n ** 16n - 1n, 2);
|
|
70
|
+
const UINT_32 = new CompactTypeUnsignedInteger(2n ** 32n - 1n, 4);
|
|
71
|
+
const UINT_64 = new CompactTypeUnsignedInteger(2n ** 64n - 1n, 8);
|
|
72
|
+
const UINT_128 = new CompactTypeUnsignedInteger(2n ** 128n - 1n, 16);
|
|
73
|
+
const TX_PARAM_TYPE = new CompactTypeEnum(1, 1);
|
|
74
|
+
/**
|
|
75
|
+
* Build the runtime descriptor of a Compact struct from its per-field
|
|
76
|
+
* descriptors — the generic form of the struct descriptor classes the
|
|
77
|
+
* compiler generates (field-by-field concatenation of alignments and values).
|
|
78
|
+
*
|
|
79
|
+
* Field ORDER must match the Compact struct declaration order; object
|
|
80
|
+
* literals preserve insertion order for string keys, so pass fields in
|
|
81
|
+
* declaration order.
|
|
82
|
+
*
|
|
83
|
+
* @param fields - One runtime descriptor per struct field, in declaration order.
|
|
84
|
+
* @returns The composed struct descriptor.
|
|
85
|
+
*/
|
|
86
|
+
function compactStructDescriptor(fields) {
|
|
87
|
+
const entries = Object.entries(fields);
|
|
88
|
+
return {
|
|
89
|
+
alignment: () => entries.flatMap(([, type]) => type.alignment()),
|
|
90
|
+
toValue: (value) => entries.flatMap(([key, type]) => type.toValue(value[key])),
|
|
91
|
+
fromValue: (value) => {
|
|
92
|
+
const result = {};
|
|
93
|
+
for (const [key, type] of entries) {
|
|
94
|
+
result[key] = type.fromValue(value);
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Descriptor of Compact's standard-library `Maybe<T>` — the compiler
|
|
102
|
+
* generates it as the struct `{ is_some: Boolean, value: T }`.
|
|
103
|
+
*
|
|
104
|
+
* @param inner - Descriptor of the wrapped type.
|
|
105
|
+
* @returns The Maybe struct descriptor.
|
|
106
|
+
*/
|
|
107
|
+
function compactMaybeDescriptor(inner) {
|
|
108
|
+
return compactStructDescriptor({
|
|
109
|
+
is_some: CompactTypeBoolean,
|
|
110
|
+
value: inner,
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Descriptor of {@link EVMCalldata} at one word capacity — the TS analogue
|
|
115
|
+
* of instantiating Compact's `EVMCalldata<#maxWords>`.
|
|
116
|
+
*
|
|
117
|
+
* @param maxWords - The contract's calldata word capacity (the vault uses 2).
|
|
118
|
+
* @returns The calldata descriptor.
|
|
119
|
+
*/
|
|
120
|
+
export function evmCalldataDescriptor(maxWords) {
|
|
121
|
+
return compactStructDescriptor({
|
|
122
|
+
selector: BYTES_4,
|
|
123
|
+
noWords: UINT_16,
|
|
124
|
+
words: new CompactTypeVector(maxWords, BYTES_32),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Descriptor of {@link EVMAccessListEntry} at one storage-key capacity
|
|
129
|
+
* (Compact: `EVMAccessListEntry<#maxStorageKeys>`).
|
|
130
|
+
*
|
|
131
|
+
* @param maxStorageKeys - Storage-key capacity per entry.
|
|
132
|
+
* @returns The entry descriptor.
|
|
133
|
+
*/
|
|
134
|
+
export function evmAccessListEntryDescriptor(maxStorageKeys) {
|
|
135
|
+
return compactStructDescriptor({
|
|
136
|
+
address: BYTES_20,
|
|
137
|
+
storageKeyCount: UINT_8,
|
|
138
|
+
storageKeys: new CompactTypeVector(maxStorageKeys, BYTES_32),
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Descriptor of {@link EVMType2TxParams} at one capacity instantiation —
|
|
143
|
+
* the TS analogue of Compact's `EVMType2TxParams<#maxCalldataWords,
|
|
144
|
+
* #maxAccessListEntries, #maxStorageKeysPerEntry>`.
|
|
145
|
+
*
|
|
146
|
+
* @param maxCalldataWords - Calldata word capacity.
|
|
147
|
+
* @param maxAccessListEntries - Access-list entry capacity.
|
|
148
|
+
* @param maxStorageKeysPerEntry - Storage-key capacity per entry.
|
|
149
|
+
* @returns The tx-params descriptor.
|
|
150
|
+
*/
|
|
151
|
+
export function evmType2TxParamsDescriptor(maxCalldataWords, maxAccessListEntries, maxStorageKeysPerEntry) {
|
|
152
|
+
return compactStructDescriptor({
|
|
153
|
+
to: BYTES_20,
|
|
154
|
+
chainId: UINT_64,
|
|
155
|
+
nonce: UINT_64,
|
|
156
|
+
gasLimit: UINT_64,
|
|
157
|
+
maxFeePerGas: UINT_128,
|
|
158
|
+
maxPriorityFeePerGas: UINT_128,
|
|
159
|
+
value: UINT_128,
|
|
160
|
+
accessListEntryCount: UINT_8,
|
|
161
|
+
accessList: new CompactTypeVector(maxAccessListEntries, evmAccessListEntryDescriptor(maxStorageKeysPerEntry)),
|
|
162
|
+
calldata: compactMaybeDescriptor(evmCalldataDescriptor(maxCalldataWords)),
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Descriptor of {@link SignBidirectionalRequest} at one capacity instantiation.
|
|
167
|
+
*
|
|
168
|
+
* @param maxCalldataWords - Calldata word capacity.
|
|
169
|
+
* @param maxAccessListEntries - Access-list entry capacity.
|
|
170
|
+
* @param maxStorageKeysPerEntry - Storage-key capacity per entry.
|
|
171
|
+
* @returns The request record descriptor.
|
|
172
|
+
*/
|
|
173
|
+
export function signBidirectionalRequestDescriptor(maxCalldataWords, maxAccessListEntries, maxStorageKeysPerEntry) {
|
|
174
|
+
return compactStructDescriptor({
|
|
175
|
+
requestNonce: UINT_64,
|
|
176
|
+
txParamType: TX_PARAM_TYPE,
|
|
177
|
+
txParams: evmType2TxParamsDescriptor(maxCalldataWords, maxAccessListEntries, maxStorageKeysPerEntry),
|
|
178
|
+
caip2Id: BYTES_32,
|
|
179
|
+
keyVersion: UINT_32,
|
|
180
|
+
path: BYTES_256,
|
|
181
|
+
algo: BYTES_32,
|
|
182
|
+
dest: BYTES_32,
|
|
183
|
+
params: BYTES_64,
|
|
184
|
+
outputDeserializationSchema: BYTES_128,
|
|
185
|
+
respondSerializationSchema: BYTES_128,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Domain tag partitioning the {@link RequestId} space
|
|
190
|
+
* (Compact: `pad(32, "signet:midnight:request")`).
|
|
191
|
+
*/
|
|
192
|
+
const REQUEST_ID_DOMAIN_TAG = asciiPadded("signet:midnight:request", 32);
|
|
193
|
+
/**
|
|
194
|
+
* Canonical id of a signet request: the domain-separated persistent hash of
|
|
195
|
+
* the entire request record. TS twin of Signet.compact's `calculateRequestId`
|
|
196
|
+
* circuit (see the deviation note atop this section), generic over the
|
|
197
|
+
* capacity instantiation via the record's own array lengths — pass the
|
|
198
|
+
* record exactly as the ledger stores it, unused slots included.
|
|
199
|
+
*
|
|
200
|
+
* @param request - The full request record (contract-shaped, all slots).
|
|
201
|
+
* @returns The 32-byte request id — the record's ledger map key.
|
|
202
|
+
*/
|
|
203
|
+
export function calculateRequestId(request) {
|
|
204
|
+
const { txParams } = request;
|
|
205
|
+
const maxCalldataWords = txParams.calldata.value.words.length;
|
|
206
|
+
const maxAccessListEntries = txParams.accessList.length;
|
|
207
|
+
const maxStorageKeysPerEntry = maxAccessListEntries === 0 ? 0 : txParams.accessList[0].storageKeys.length;
|
|
208
|
+
return persistentHash(new CompactTypeVector(2, BYTES_32), [
|
|
209
|
+
REQUEST_ID_DOMAIN_TAG,
|
|
210
|
+
persistentHash(signBidirectionalRequestDescriptor(maxCalldataWords, maxAccessListEntries, maxStorageKeysPerEntry), request),
|
|
211
|
+
]);
|
|
212
|
+
}
|
|
213
|
+
// ---- Calldata / transaction assembly ----------------------------------------
|
|
214
|
+
/**
|
|
215
|
+
* The 32-byte value of a numeric ABI word: the little-endian field embed of
|
|
216
|
+
* the number, exactly what Compact's `x as Field as Bytes<32>` cast produces
|
|
217
|
+
* in-circuit. Use when building words off-chain (UIs, expected-record
|
|
218
|
+
* builders, tests).
|
|
219
|
+
*
|
|
220
|
+
* @param value - The word's numeric value (e.g. an amount).
|
|
221
|
+
* @returns The 32-byte LE embed to store in an {@link EVMCalldata} word.
|
|
222
|
+
*/
|
|
223
|
+
export function numericAbiWordValue(value) {
|
|
224
|
+
return bigintToBytes32(value);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* The 32-byte staticArg word value for an EVM address: the BIG-ENDIAN
|
|
228
|
+
* numeric reading of its 20 display-order bytes, LE-embedded. TS mirror of
|
|
229
|
+
* Signet.compact's `evmAddressAbiValue` circuit (+ `as Bytes<32>`); see the
|
|
230
|
+
* warning there — embedding the display-order bytes directly would come out
|
|
231
|
+
* byte-reversed in the assembled calldata.
|
|
232
|
+
*
|
|
233
|
+
* @param address - The 20-byte address in display order.
|
|
234
|
+
* @returns The 32-byte word value to store in an {@link EVMCalldata} word.
|
|
235
|
+
*/
|
|
236
|
+
export function evmAddressAbiWord(address) {
|
|
237
|
+
let value = 0n;
|
|
238
|
+
for (const byte of address) {
|
|
239
|
+
value = value * 256n + BigInt(byte);
|
|
240
|
+
}
|
|
241
|
+
return bigintToBytes32(value);
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* Re-assemble the raw calldata a request's words describe:
|
|
245
|
+
* `data = selector || BE(words[0..noWords])`. Each word is a little-endian
|
|
246
|
+
* field embed (the contract's `x as Field as Bytes<32>` cast); the leading
|
|
247
|
+
* `noWords` are re-encoded big-endian into 32-byte ABI words and any remaining
|
|
248
|
+
* capacity slots are dropped. This is THE implementation of the MPC re-assembly
|
|
249
|
+
* documented on `EVMCalldata` in Signet.compact.
|
|
250
|
+
*
|
|
251
|
+
* @param calldata - The request's calldata field.
|
|
252
|
+
* @returns Hex calldata for the transaction (`"0x"` when absent).
|
|
253
|
+
*/
|
|
254
|
+
export function assembleCalldata(calldata) {
|
|
255
|
+
if (!calldata.is_some) {
|
|
256
|
+
return "0x";
|
|
257
|
+
}
|
|
258
|
+
const { selector, noWords, words } = calldata.value;
|
|
259
|
+
let data = `0x${bytesToHex(selector)}`;
|
|
260
|
+
for (let i = 0; i < Number(noWords); i++) {
|
|
261
|
+
data += bytesToHex(bigintToBytes32BE(bytesToBigint(words[i])));
|
|
262
|
+
}
|
|
263
|
+
return data;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Decode the real (count-trimmed) access list of a request into the shape
|
|
267
|
+
* ethers' `Transaction.from` accepts.
|
|
268
|
+
*
|
|
269
|
+
* @param txParams - The request's transaction decomposition.
|
|
270
|
+
* @returns The access list, possibly empty.
|
|
271
|
+
*/
|
|
272
|
+
function decodeAccessList(txParams) {
|
|
273
|
+
return txParams.accessList
|
|
274
|
+
.slice(0, Number(txParams.accessListEntryCount))
|
|
275
|
+
.map((entry) => ({
|
|
276
|
+
address: getAddress(`0x${bytesToHex(entry.address)}`),
|
|
277
|
+
storageKeys: entry.storageKeys
|
|
278
|
+
.slice(0, Number(entry.storageKeyCount))
|
|
279
|
+
.map((key) => `0x${bytesToHex(key)}`),
|
|
280
|
+
}));
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Rebuild the unsigned EIP-1559 transaction a request record describes,
|
|
284
|
+
* byte-identical to the one the MPC assembles and signs: calldata from the
|
|
285
|
+
* tagged words (see {@link assembleCalldata}), the count-trimmed access
|
|
286
|
+
* list, and the stored envelope fields. This is the canonical
|
|
287
|
+
* request→transaction transform; response-side verification
|
|
288
|
+
* (`signature-response-verification.ts`) and the signed-transaction builder
|
|
289
|
+
* below both go through it, so the transaction a client broadcasts is
|
|
290
|
+
* provably the one the MPC put its signature over.
|
|
291
|
+
*
|
|
292
|
+
* @param event - The on-ledger request record.
|
|
293
|
+
* @returns The unsigned ethers transaction (`unsignedHash` is the digest the
|
|
294
|
+
* MPC signs).
|
|
295
|
+
* @throws Error if a calldata word carries an unknown kind.
|
|
296
|
+
*/
|
|
297
|
+
export function signBidirectionalRequestToUnsignedEVMTransaction(event) {
|
|
298
|
+
const { txParams } = event;
|
|
299
|
+
return Transaction.from({
|
|
300
|
+
type: 2,
|
|
301
|
+
chainId: txParams.chainId,
|
|
302
|
+
nonce: Number(txParams.nonce),
|
|
303
|
+
gasLimit: txParams.gasLimit,
|
|
304
|
+
maxFeePerGas: txParams.maxFeePerGas,
|
|
305
|
+
maxPriorityFeePerGas: txParams.maxPriorityFeePerGas,
|
|
306
|
+
to: getAddress(`0x${bytesToHex(txParams.to)}`),
|
|
307
|
+
value: txParams.value,
|
|
308
|
+
accessList: decodeAccessList(txParams),
|
|
309
|
+
data: assembleCalldata(txParams.calldata),
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Decode a response signature record (as posted to the signet contract's
|
|
314
|
+
* signature response log — the canonical MPC `Signature { big_r, s,
|
|
315
|
+
* recovery_id }` shape) into an ethers {@link Signature}: `r` is `bigR`'s x
|
|
316
|
+
* coordinate, `v` the legacy parity derived from the recovery id.
|
|
317
|
+
*
|
|
318
|
+
* @param response - The posted signature record.
|
|
319
|
+
* @returns The ethers signature.
|
|
320
|
+
* @throws Error if the recovery id is not 0 or 1.
|
|
321
|
+
*/
|
|
322
|
+
export function signatureResponseToSignature(response) {
|
|
323
|
+
const recoveryId = Number(response.recoveryId);
|
|
324
|
+
if (recoveryId !== 0 && recoveryId !== 1) {
|
|
325
|
+
throw new Error(`expected a recovery id of 0 or 1, got ${recoveryId}`);
|
|
326
|
+
}
|
|
327
|
+
return Signature.from({
|
|
328
|
+
r: `0x${bytesToHex(response.bigRx)}`,
|
|
329
|
+
s: `0x${bytesToHex(response.s)}`,
|
|
330
|
+
v: recoveryId + 27,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
/** secp256k1 base field prime (2^256 - 2^32 - 977). */
|
|
334
|
+
const SECP256K1_P = 2n ** 256n - 2n ** 32n - 977n;
|
|
335
|
+
/** Modular exponentiation by squaring. */
|
|
336
|
+
function modPow(base, exponent, modulus) {
|
|
337
|
+
let result = 1n;
|
|
338
|
+
let b = base % modulus;
|
|
339
|
+
let e = exponent;
|
|
340
|
+
while (e > 0n) {
|
|
341
|
+
if (e & 1n)
|
|
342
|
+
result = (result * b) % modulus;
|
|
343
|
+
b = (b * b) % modulus;
|
|
344
|
+
e >>= 1n;
|
|
345
|
+
}
|
|
346
|
+
return result;
|
|
347
|
+
}
|
|
348
|
+
/** Encode a bigint as exactly 32 BIG-endian bytes (secp256k1 scalar form). */
|
|
349
|
+
function bigintToBytes32BE(value) {
|
|
350
|
+
const out = new Uint8Array(32);
|
|
351
|
+
let v = value;
|
|
352
|
+
for (let i = 31; i >= 0; i--) {
|
|
353
|
+
out[i] = Number(v & 0xffn);
|
|
354
|
+
v >>= 8n;
|
|
355
|
+
}
|
|
356
|
+
return out;
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Encode an ECDSA signature as the response record posted to the signet
|
|
360
|
+
* contract — the inverse of {@link signatureResponseToSignature},
|
|
361
|
+
* for MPC-side posters (the fakenet signer, tests). The canonical record
|
|
362
|
+
* carries `bigR` as a full affine point but an `r || s || v` signature only
|
|
363
|
+
* has R.x and the parity of R.y, so R.y is recovered by decompressing the
|
|
364
|
+
* point on the curve (y² = x³ + 7 over the secp256k1 base field).
|
|
365
|
+
*
|
|
366
|
+
* The parameter is structural (the r/s/yParity subset of an ethers
|
|
367
|
+
* {@link Signature}) so signatures from ANY ethers instance qualify — posters
|
|
368
|
+
* living in other repos resolve their own ethers install, and nominal class
|
|
369
|
+
* typing would reject it.
|
|
370
|
+
*
|
|
371
|
+
* @param signature - The signature to encode (`r`/`s` as 0x hex, `yParity` 0 or 1).
|
|
372
|
+
* @returns The response record, ready to post.
|
|
373
|
+
* @throws Error if `r` is not the x coordinate of a curve point.
|
|
374
|
+
*/
|
|
375
|
+
export function signatureToSignatureResponse(signature) {
|
|
376
|
+
const x = BigInt(signature.r);
|
|
377
|
+
const ySquared = (modPow(x, 3n, SECP256K1_P) + 7n) % SECP256K1_P;
|
|
378
|
+
// P ≡ 3 (mod 4), so a square root (when one exists) is c^((P+1)/4).
|
|
379
|
+
let y = modPow(ySquared, (SECP256K1_P + 1n) / 4n, SECP256K1_P);
|
|
380
|
+
if ((y * y) % SECP256K1_P !== ySquared) {
|
|
381
|
+
throw new Error("signature r is not the x coordinate of a secp256k1 point");
|
|
382
|
+
}
|
|
383
|
+
if ((y & 1n) !== BigInt(signature.yParity)) {
|
|
384
|
+
y = SECP256K1_P - y;
|
|
385
|
+
}
|
|
386
|
+
return {
|
|
387
|
+
bigRx: getBytes(signature.r),
|
|
388
|
+
bigRy: bigintToBytes32BE(y),
|
|
389
|
+
s: getBytes(signature.s),
|
|
390
|
+
recoveryId: BigInt(signature.yParity),
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Assemble the broadcast-ready signed EIP-1559 transaction for a request from
|
|
395
|
+
* its MPC signature response: rebuild the exact unsigned transaction the MPC
|
|
396
|
+
* signed (see {@link signBidirectionalRequestToUnsignedEVMTransaction}) and
|
|
397
|
+
* attach the signature. Does NOT check that the signature recovers to the
|
|
398
|
+
* requester's derived address — the response log is unauthenticated, so
|
|
399
|
+
* verify first with `verifySignatureResponse`.
|
|
400
|
+
*
|
|
401
|
+
* @param event - The on-ledger request record.
|
|
402
|
+
* @param response - The posted signature record answering it.
|
|
403
|
+
* @returns The signed ethers transaction; `serialized` is the raw payload for
|
|
404
|
+
* `eth_sendRawTransaction`, `hash` its on-chain hash, `from` the recovered
|
|
405
|
+
* sender.
|
|
406
|
+
* @throws Error if the request record is malformed (see
|
|
407
|
+
* {@link signBidirectionalRequestToUnsignedEVMTransaction}) or the response
|
|
408
|
+
* is not a decodable signature.
|
|
409
|
+
*/
|
|
410
|
+
export function signBidirectionalRequestToSignedEVMTransaction(event, response) {
|
|
411
|
+
const transaction = signBidirectionalRequestToUnsignedEVMTransaction(event);
|
|
412
|
+
transaction.signature = signatureResponseToSignature(response);
|
|
413
|
+
return transaction;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Render bytes as a lowercase hex string, no `0x` prefix.
|
|
417
|
+
*
|
|
418
|
+
* @param bytes - The bytes to render.
|
|
419
|
+
* @returns Lowercase hex, two chars per byte.
|
|
420
|
+
*/
|
|
421
|
+
export function bytesToHex(bytes) {
|
|
422
|
+
return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Render a request id in its canonical TS form (see
|
|
426
|
+
* {@link RequestIdHex}) — also usable as a JS `Map` key, which raw
|
|
427
|
+
* `Uint8Array` ids are not (they compare by reference).
|
|
428
|
+
*
|
|
429
|
+
* @param requestId - 32-byte request id.
|
|
430
|
+
* @returns The branded 64-char lowercase hex string, no `0x` prefix.
|
|
431
|
+
*/
|
|
432
|
+
export function requestIdHex(requestId) {
|
|
433
|
+
return bytesToHex(requestId);
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Validate and normalize an untrusted string (CLI argument, config value)
|
|
437
|
+
* into a {@link RequestIdHex}: an optional `0x` prefix is stripped and
|
|
438
|
+
* the digits lowercased before validation.
|
|
439
|
+
*
|
|
440
|
+
* @param value - The candidate request id string.
|
|
441
|
+
* @returns The branded, normalized request id hex.
|
|
442
|
+
* @throws Error if the value is not 64 hex chars after normalization.
|
|
443
|
+
*/
|
|
444
|
+
export function parseRequestIdHex(value) {
|
|
445
|
+
const hex = value.replace(/^0x/i, "").toLowerCase();
|
|
446
|
+
if (!/^[0-9a-f]{64}$/.test(hex)) {
|
|
447
|
+
throw new Error(`not a 32-byte request id in hex: "${value}"`);
|
|
448
|
+
}
|
|
449
|
+
return hex;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Decode a request id back to its 32 raw bytes for the Compact boundary
|
|
453
|
+
* (compiled-circuit calls, ledger lookups).
|
|
454
|
+
*
|
|
455
|
+
* @param id - The request id in canonical hex form.
|
|
456
|
+
* @returns The 32-byte request id.
|
|
457
|
+
*/
|
|
458
|
+
export function requestIdBytes(id) {
|
|
459
|
+
const bytes = new Uint8Array(32);
|
|
460
|
+
for (let i = 0; i < 32; i++) {
|
|
461
|
+
bytes[i] = Number.parseInt(id.slice(2 * i, 2 * i + 2), 16);
|
|
462
|
+
}
|
|
463
|
+
return bytes;
|
|
464
|
+
}
|
|
465
|
+
/** Byte width of the path field (Compact `Bytes<256>`). */
|
|
466
|
+
export const PATH_BYTES = 256;
|
|
467
|
+
/**
|
|
468
|
+
* Build the canonical MPC derivation path for an identity commitment: the
|
|
469
|
+
* lowercase hex of the commitment as ASCII, zero-padded to {@link PATH_BYTES}
|
|
470
|
+
* — exactly what the contract's `assertPathCommitment` accepts. Use this to
|
|
471
|
+
* populate {@link SignBidirectionalRequest.path} when constructing requests.
|
|
472
|
+
*
|
|
473
|
+
* @param commitment - 32-byte identity commitment.
|
|
474
|
+
* @returns The 256-byte path field value.
|
|
475
|
+
*/
|
|
476
|
+
export function signetPathOfCommitment(commitment) {
|
|
477
|
+
const path = new Uint8Array(PATH_BYTES);
|
|
478
|
+
path.set(new TextEncoder().encode(bytesToHex(commitment)));
|
|
479
|
+
return path;
|
|
480
|
+
}
|
|
481
|
+
/**
|
|
482
|
+
* Parse the on-ledger request map into a plain-JS index keyed by hex
|
|
483
|
+
* request id.
|
|
484
|
+
*
|
|
485
|
+
* @param ledgerIndex - Iterable of `[requestId, request]` entries — e.g. a
|
|
486
|
+
* contract's `ledger(state).signetRequestsIndex` (any
|
|
487
|
+
* {@link SignBidirectionalRequestLedgerIndex}).
|
|
488
|
+
* @returns A new `Map` from {@link requestIdHex} key to request record.
|
|
489
|
+
*/
|
|
490
|
+
export function toSignBidirectionalRequestIndex(ledgerIndex) {
|
|
491
|
+
const index = new Map();
|
|
492
|
+
for (const [requestId, request] of ledgerIndex) {
|
|
493
|
+
index.set(requestIdHex(requestId), request);
|
|
494
|
+
}
|
|
495
|
+
return index;
|
|
496
|
+
}
|
|
497
|
+
//# sourceMappingURL=signet-requests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signet-requests.js","sourceRoot":"","sources":["../src/signet-requests.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { type SignetEventSource } from "./signet-event-observer.ts";
|
|
2
|
+
import { type RespondBidirectional } from "./signet-contract-state-reader.ts";
|
|
3
|
+
import { type SignatureResponseVerdict, type SignetPublicStateSource } from "./signet-request-response-reader.ts";
|
|
4
|
+
import type { RequestIdHex, SignBidirectionalRequest } from "./signet-requests.ts";
|
|
5
|
+
/** Default gap between poll cycles of {@link SignetResponseFeed.verdicts}. */
|
|
6
|
+
export declare const DEFAULT_RESPONSE_FEED_POLL_INTERVAL_MS = 3000;
|
|
7
|
+
/** Everything a {@link SignetResponseFeed} needs. */
|
|
8
|
+
export interface SignetResponseFeedConfig {
|
|
9
|
+
/** Address of the central signet contract whose events and response log to watch. */
|
|
10
|
+
readonly signetContractAddress: string;
|
|
11
|
+
/** Address of the signet-compliant requester contract holding the request records (e.g. the vault). */
|
|
12
|
+
readonly requesterContractAddress: string;
|
|
13
|
+
/**
|
|
14
|
+
* Source of BOTH events and raw contract state — a full
|
|
15
|
+
* `indexerPublicDataProvider` satisfies both halves.
|
|
16
|
+
*/
|
|
17
|
+
readonly source: SignetEventSource & SignetPublicStateSource;
|
|
18
|
+
/** Durable resume floor for the underlying observer (see {@link SignetEventObserverConfig.fromEventId}). */
|
|
19
|
+
readonly fromEventId?: number;
|
|
20
|
+
/** Poll cadence for {@link SignetResponseFeed.verdicts}; default {@link DEFAULT_RESPONSE_FEED_POLL_INTERVAL_MS}. */
|
|
21
|
+
readonly pollIntervalMs?: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The event-driven signature response feed. Composes a
|
|
25
|
+
* {@link SignetEventObserver} of {@link SignatureRespondedEvent} notifications
|
|
26
|
+
* (discovery) with a {@link SignetRequestResponseReader} (verification),
|
|
27
|
+
* yielding one {@link SignatureResponseVerdict} per posted response, in count
|
|
28
|
+
* order, each exactly once per feed lifetime. Consumers act on the first
|
|
29
|
+
* valid verdict and surface the rejected ones as they see fit — the feed,
|
|
30
|
+
* like the reader, never logs.
|
|
31
|
+
*/
|
|
32
|
+
export declare class SignetResponseFeed {
|
|
33
|
+
private readonly observer;
|
|
34
|
+
private readonly reader;
|
|
35
|
+
private readonly pollIntervalMs;
|
|
36
|
+
private readonly yielded;
|
|
37
|
+
/**
|
|
38
|
+
* @param config - The contract pair, combined event/state source, and
|
|
39
|
+
* resume floor.
|
|
40
|
+
*/
|
|
41
|
+
constructor(config: SignetResponseFeedConfig);
|
|
42
|
+
/** The yielded-count set for `requestId`, created on first use. */
|
|
43
|
+
private yieldedCounts;
|
|
44
|
+
/**
|
|
45
|
+
* One-shot: the verdicts on every response post for `requestId` not yielded
|
|
46
|
+
* before, in count order. The response log is only read when a currently-
|
|
47
|
+
* visible event announces a post this feed has not yielded yet — no new
|
|
48
|
+
* event, no state query. Ledger posts the read then surfaces beyond the
|
|
49
|
+
* announced ones are yielded too (events are the trigger, the ledger is the
|
|
50
|
+
* source of truth), and a post whose event is visible but whose write has
|
|
51
|
+
* not indexed yet is simply retried next cycle.
|
|
52
|
+
*
|
|
53
|
+
* @param requestId - The request whose response posts to judge.
|
|
54
|
+
* @param expectedSigner - The EVM address (0x hex, any case) the genuine
|
|
55
|
+
* response must be signed by — the requester's MPC-derived address.
|
|
56
|
+
* @returns The newly-judged verdicts this cycle (possibly empty).
|
|
57
|
+
* @throws Error when either contract has no state, the request is not on
|
|
58
|
+
* the requester's ledger, or the responses ledger is inconsistent.
|
|
59
|
+
*/
|
|
60
|
+
poll(requestId: RequestIdHex, expectedSigner: string): Promise<SignatureResponseVerdict[]>;
|
|
61
|
+
/**
|
|
62
|
+
* Live stream: poll + sleep, yielding the verdict on each posted response
|
|
63
|
+
* exactly once, in count order, until `opts.signal` aborts. The natural
|
|
64
|
+
* consumption is to warn on each rejected verdict and act on the first
|
|
65
|
+
* valid one (see the cli's poll-signature-response command).
|
|
66
|
+
*
|
|
67
|
+
* @param requestId - The request whose response posts to judge.
|
|
68
|
+
* @param expectedSigner - The EVM address (0x hex, any case) the genuine
|
|
69
|
+
* response must be signed by — the requester's MPC-derived address.
|
|
70
|
+
* @param opts.signal - Abort to stop the stream.
|
|
71
|
+
* @yields Each post's verdict, in discovery order.
|
|
72
|
+
* @throws Error when either contract has no state, the request is not on
|
|
73
|
+
* the requester's ledger, or the responses ledger is inconsistent.
|
|
74
|
+
*/
|
|
75
|
+
verdicts(requestId: RequestIdHex, expectedSigner: string, opts?: {
|
|
76
|
+
signal?: AbortSignal;
|
|
77
|
+
}): AsyncIterableIterator<SignatureResponseVerdict>;
|
|
78
|
+
/**
|
|
79
|
+
* The request record a verdict's response answers, read through the feed's
|
|
80
|
+
* own reader (cached after the first fetch — free after any {@link poll}
|
|
81
|
+
* that reached verification). What a consumer needs to assemble the signed
|
|
82
|
+
* transaction from a valid verdict via
|
|
83
|
+
* `signBidirectionalRequestToSignedEVMTransaction`.
|
|
84
|
+
*
|
|
85
|
+
* @param requestId - The request id to look up.
|
|
86
|
+
* @returns The stored request record.
|
|
87
|
+
* @throws Error when the requester contract has no state or holds no
|
|
88
|
+
* request under `requestId`.
|
|
89
|
+
*/
|
|
90
|
+
getSignatureRequest(requestId: RequestIdHex): Promise<SignBidirectionalRequest>;
|
|
91
|
+
}
|
|
92
|
+
/** Everything a {@link SignetRespondBidirectionalFeed} needs. */
|
|
93
|
+
export interface SignetRespondBidirectionalFeedConfig {
|
|
94
|
+
/**
|
|
95
|
+
* Address of the central signet contract whose events and
|
|
96
|
+
* respond-bidirectional index to watch. Attestations live entirely on the
|
|
97
|
+
* signet contract, so — unlike {@link SignetResponseFeedConfig} — no
|
|
98
|
+
* requester contract address is needed.
|
|
99
|
+
*/
|
|
100
|
+
readonly signetContractAddress: string;
|
|
101
|
+
/**
|
|
102
|
+
* Source of BOTH events and raw contract state — a full
|
|
103
|
+
* `indexerPublicDataProvider` satisfies both halves.
|
|
104
|
+
*/
|
|
105
|
+
readonly source: SignetEventSource & SignetPublicStateSource;
|
|
106
|
+
/** Durable resume floor for the underlying observer (see {@link SignetEventObserverConfig.fromEventId}). */
|
|
107
|
+
readonly fromEventId?: number;
|
|
108
|
+
/** Poll cadence for {@link SignetRespondBidirectionalFeed.attestation}; default {@link DEFAULT_RESPONSE_FEED_POLL_INTERVAL_MS}. */
|
|
109
|
+
readonly pollIntervalMs?: number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The event-driven respond-bidirectional feed: composes a
|
|
113
|
+
* {@link SignetEventObserver} of {@link RespondBidirectionalEvent}
|
|
114
|
+
* notifications (discovery) with a read of the signet contract's
|
|
115
|
+
* respond-bidirectional index (the source of truth), yielding the MPC's
|
|
116
|
+
* attestation of a request's remote execution. No verdicts and no off-chain
|
|
117
|
+
* verification — the signet contract verified the attestation IN-CIRCUIT at
|
|
118
|
+
* post time (Schnorr over `(requestId, hash(serializedOutput, outputLen))`
|
|
119
|
+
* against its sealed MPC key), so the stored record is authentic by
|
|
120
|
+
* construction and there is exactly one per request (first valid write wins).
|
|
121
|
+
*/
|
|
122
|
+
export declare class SignetRespondBidirectionalFeed {
|
|
123
|
+
private readonly observer;
|
|
124
|
+
private readonly signetContractAddress;
|
|
125
|
+
private readonly source;
|
|
126
|
+
private readonly pollIntervalMs;
|
|
127
|
+
private readonly attestations;
|
|
128
|
+
/**
|
|
129
|
+
* @param config - The signet contract, combined event/state source, and
|
|
130
|
+
* resume floor.
|
|
131
|
+
*/
|
|
132
|
+
constructor(config: SignetRespondBidirectionalFeedConfig);
|
|
133
|
+
/**
|
|
134
|
+
* One-shot: the attestation for `requestId`, or `undefined` while none is
|
|
135
|
+
* discoverable yet. The index is only read when a currently-visible event
|
|
136
|
+
* announces `requestId`'s attestation — no event, no state query. An event
|
|
137
|
+
* whose ledger write has not indexed yet is simply retried next cycle
|
|
138
|
+
* (events are the trigger, the ledger is the source of truth).
|
|
139
|
+
*
|
|
140
|
+
* @param requestId - The request whose attestation to look for.
|
|
141
|
+
* @returns The stored attestation record, or `undefined` when its event is
|
|
142
|
+
* not yet visible or its write not yet indexed.
|
|
143
|
+
* @throws Error when the signet contract has no state on-chain.
|
|
144
|
+
*/
|
|
145
|
+
poll(requestId: RequestIdHex): Promise<RespondBidirectional | undefined>;
|
|
146
|
+
/**
|
|
147
|
+
* Live wait: poll + sleep until `requestId`'s attestation is discoverable,
|
|
148
|
+
* and return it. Runs until `opts.signal` aborts — the caller owns the
|
|
149
|
+
* give-up policy (see the cli's poll-respond-bidirectional command).
|
|
150
|
+
*
|
|
151
|
+
* @param requestId - The request whose attestation to wait for.
|
|
152
|
+
* @param opts.signal - Abort to stop waiting.
|
|
153
|
+
* @returns The stored attestation record, or `undefined` when aborted
|
|
154
|
+
* before one was discovered.
|
|
155
|
+
* @throws Error when the signet contract has no state on-chain.
|
|
156
|
+
*/
|
|
157
|
+
attestation(requestId: RequestIdHex, opts?: {
|
|
158
|
+
signal?: AbortSignal;
|
|
159
|
+
}): Promise<RespondBidirectional | undefined>;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=signet-response-feed.d.ts.map
|