@aztec/foundation 0.0.1-commit.ff7989d6c → 0.0.1-commit.fff30aa
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/dest/branded-types/slot.d.ts +4 -1
- package/dest/branded-types/slot.d.ts.map +1 -1
- package/dest/branded-types/slot.js +3 -0
- package/dest/buffer/index.d.ts +2 -1
- package/dest/buffer/index.d.ts.map +1 -1
- package/dest/buffer/index.js +1 -0
- package/dest/buffer/utils.d.ts +3 -0
- package/dest/buffer/utils.d.ts.map +1 -0
- package/dest/buffer/utils.js +7 -0
- package/dest/collection/array.d.ts +3 -1
- package/dest/collection/array.d.ts.map +1 -1
- package/dest/collection/array.js +15 -0
- package/dest/config/env_var.d.ts +2 -2
- package/dest/config/env_var.d.ts.map +1 -1
- package/dest/config/index.d.ts +1 -1
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +15 -0
- package/dest/config/network_config.d.ts +19 -1
- package/dest/config/network_config.d.ts.map +1 -1
- package/dest/config/network_config.js +4 -1
- package/dest/config/network_name.d.ts +2 -2
- package/dest/config/network_name.d.ts.map +1 -1
- package/dest/config/network_name.js +0 -2
- package/dest/crypto/poseidon/index.d.ts +1 -1
- package/dest/crypto/poseidon/index.d.ts.map +1 -1
- package/dest/crypto/poseidon/index.js +40 -33
- package/dest/crypto/secp256k1-signer/utils.d.ts +12 -1
- package/dest/crypto/secp256k1-signer/utils.d.ts.map +1 -1
- package/dest/crypto/secp256k1-signer/utils.js +26 -0
- package/dest/curves/bn254/field.d.ts +2 -1
- package/dest/curves/bn254/field.d.ts.map +1 -1
- package/dest/curves/bn254/field.js +5 -2
- package/dest/curves/grumpkin/point.d.ts +4 -4
- package/dest/curves/grumpkin/point.d.ts.map +1 -1
- package/dest/curves/grumpkin/point.js +7 -4
- package/dest/eth-signature/eth_signature.d.ts +2 -1
- package/dest/eth-signature/eth_signature.d.ts.map +1 -1
- package/dest/eth-signature/eth_signature.js +7 -2
- package/dest/log/bigint-utils.d.ts +1 -1
- package/dest/log/bigint-utils.d.ts.map +1 -1
- package/dest/log/bigint-utils.js +3 -0
- package/dest/schemas/api.d.ts +2 -2
- package/dest/schemas/api.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.d.ts +20 -7
- package/dest/serialize/buffer_reader.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.js +18 -5
- package/dest/serialize/field_reader.d.ts +13 -5
- package/dest/serialize/field_reader.d.ts.map +1 -1
- package/dest/serialize/field_reader.js +13 -0
- package/dest/timer/date.d.ts +1 -3
- package/dest/timer/date.d.ts.map +1 -1
- package/dest/timer/date.js +0 -4
- package/dest/transport/transport_client.js +2 -2
- package/package.json +2 -2
- package/src/branded-types/slot.ts +5 -0
- package/src/buffer/index.ts +1 -0
- package/src/buffer/utils.ts +8 -0
- package/src/collection/array.ts +14 -0
- package/src/config/env_var.ts +14 -4
- package/src/config/index.ts +15 -0
- package/src/config/network_config.ts +3 -0
- package/src/config/network_name.ts +1 -4
- package/src/crypto/poseidon/index.ts +42 -34
- package/src/crypto/secp256k1-signer/utils.ts +32 -0
- package/src/curves/bn254/field.ts +6 -2
- package/src/curves/grumpkin/point.ts +6 -3
- package/src/eth-signature/eth_signature.ts +7 -1
- package/src/log/bigint-utils.ts +3 -0
- package/src/schemas/api.ts +4 -1
- package/src/serialize/buffer_reader.ts +29 -6
- package/src/serialize/field_reader.ts +22 -4
- package/src/timer/date.ts +0 -6
- package/src/transport/transport_client.ts +2 -2
- package/src/trees/membership_witness.ts +2 -2
package/src/collection/array.ts
CHANGED
|
@@ -315,3 +315,17 @@ export function partition<T>(items: T[], predicate: (item: T) => boolean): [T[],
|
|
|
315
315
|
}
|
|
316
316
|
return [pass, fail];
|
|
317
317
|
}
|
|
318
|
+
|
|
319
|
+
/** Partitions the given iterable into two arrays based on the predicate. */
|
|
320
|
+
export async function partitionAsync<T>(items: T[], predicate: (item: T) => Promise<boolean>): Promise<[T[], T[]]> {
|
|
321
|
+
const pass: T[] = [];
|
|
322
|
+
const fail: T[] = [];
|
|
323
|
+
for (const item of items) {
|
|
324
|
+
if (await predicate(item)) {
|
|
325
|
+
pass.push(item);
|
|
326
|
+
} else {
|
|
327
|
+
fail.push(item);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
return [pass, fail];
|
|
331
|
+
}
|
package/src/config/env_var.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type EnvVar =
|
|
|
12
12
|
| 'ARCHIVER_VIEM_POLLING_INTERVAL_MS'
|
|
13
13
|
| 'ARCHIVER_BATCH_SIZE'
|
|
14
14
|
| 'AZTEC_ADMIN_PORT'
|
|
15
|
+
| 'AZTEC_NODE_DEBUG'
|
|
15
16
|
| 'AZTEC_ADMIN_API_KEY_HASH'
|
|
16
17
|
| 'AZTEC_DISABLE_ADMIN_API_KEY'
|
|
17
18
|
| 'AZTEC_RESET_ADMIN_API_KEY'
|
|
@@ -80,6 +81,7 @@ export type EnvVar =
|
|
|
80
81
|
| 'KEY_STORE_DIRECTORY'
|
|
81
82
|
| 'L1_CHAIN_ID'
|
|
82
83
|
| 'L1_CONSENSUS_HOST_URLS'
|
|
84
|
+
| 'ETHEREUM_HTTP_TIMEOUT_MS'
|
|
83
85
|
| 'L1_CONSENSUS_HOST_API_KEYS'
|
|
84
86
|
| 'L1_CONSENSUS_HOST_API_KEY_HEADERS'
|
|
85
87
|
| 'LOG_JSON'
|
|
@@ -89,7 +91,6 @@ export type EnvVar =
|
|
|
89
91
|
| 'MNEMONIC'
|
|
90
92
|
| 'NETWORK'
|
|
91
93
|
| 'NETWORK_CONFIG_LOCATION'
|
|
92
|
-
| 'NO_PXE'
|
|
93
94
|
| 'USE_GCLOUD_LOGGING'
|
|
94
95
|
| 'OTEL_EXPORTER_OTLP_METRICS_ENDPOINT'
|
|
95
96
|
| 'OTEL_EXPORTER_OTLP_TRACES_ENDPOINT'
|
|
@@ -148,9 +149,11 @@ export type EnvVar =
|
|
|
148
149
|
| 'P2P_PREFERRED_PEERS'
|
|
149
150
|
| 'P2P_MAX_PENDING_TX_COUNT'
|
|
150
151
|
| 'P2P_SEEN_MSG_CACHE_SIZE'
|
|
152
|
+
| 'P2P_DROP_TX'
|
|
151
153
|
| 'P2P_DROP_TX_CHANCE'
|
|
152
154
|
| 'P2P_TX_POOL_DELETE_TXS_AFTER_REORG'
|
|
153
155
|
| 'P2P_MIN_TX_POOL_AGE_MS'
|
|
156
|
+
| 'P2P_RPC_PRICE_BUMP_PERCENTAGE'
|
|
154
157
|
| 'DEBUG_P2P_INSTRUMENT_MESSAGES'
|
|
155
158
|
| 'PEER_ID_PRIVATE_KEY'
|
|
156
159
|
| 'PEER_ID_PRIVATE_KEY_PATH'
|
|
@@ -166,6 +169,7 @@ export type EnvVar =
|
|
|
166
169
|
| 'PROVER_BROKER_MAX_EPOCHS_TO_KEEP_RESULTS_FOR'
|
|
167
170
|
| 'PROVER_BROKER_DEBUG_REPLAY_ENABLED'
|
|
168
171
|
| 'PROVER_CANCEL_JOBS_ON_STOP'
|
|
172
|
+
| 'PROVER_ENQUEUE_CONCURRENCY'
|
|
169
173
|
| 'PROVER_COORDINATION_NODE_URLS'
|
|
170
174
|
| 'PROVER_PROOF_STORE'
|
|
171
175
|
| 'PROVER_FAILED_PROOF_STORE'
|
|
@@ -199,12 +203,14 @@ export type EnvVar =
|
|
|
199
203
|
| 'SENTINEL_ENABLED'
|
|
200
204
|
| 'SENTINEL_HISTORY_LENGTH_IN_EPOCHS'
|
|
201
205
|
| 'SENTINEL_HISTORIC_PROVEN_PERFORMANCE_LENGTH_IN_EPOCHS'
|
|
202
|
-
| 'SEQ_MAX_BLOCK_SIZE_IN_BYTES'
|
|
203
206
|
| 'SEQ_MAX_TX_PER_BLOCK'
|
|
207
|
+
| 'SEQ_MAX_TX_PER_CHECKPOINT'
|
|
204
208
|
| 'SEQ_MIN_TX_PER_BLOCK'
|
|
205
209
|
| 'SEQ_PUBLISH_TXS_WITH_PROPOSALS'
|
|
206
210
|
| 'SEQ_MAX_DA_BLOCK_GAS'
|
|
207
211
|
| 'SEQ_MAX_L2_BLOCK_GAS'
|
|
212
|
+
| 'SEQ_PER_BLOCK_ALLOCATION_MULTIPLIER'
|
|
213
|
+
| 'SEQ_REDISTRIBUTE_CHECKPOINT_BUDGET'
|
|
208
214
|
| 'SEQ_PUBLISHER_PRIVATE_KEY'
|
|
209
215
|
| 'SEQ_PUBLISHER_PRIVATE_KEYS'
|
|
210
216
|
| 'SEQ_PUBLISHER_ADDRESSES'
|
|
@@ -246,6 +252,7 @@ export type EnvVar =
|
|
|
246
252
|
| 'TELEMETRY'
|
|
247
253
|
| 'TEST_ACCOUNTS'
|
|
248
254
|
| 'SPONSORED_FPC'
|
|
255
|
+
| 'PREFUND_ADDRESSES'
|
|
249
256
|
| 'TX_COLLECTION_FAST_NODES_TIMEOUT_BEFORE_REQ_RESP_MS'
|
|
250
257
|
| 'TX_COLLECTION_SLOW_NODES_INTERVAL_MS'
|
|
251
258
|
| 'TX_COLLECTION_SLOW_REQ_RESP_INTERVAL_MS'
|
|
@@ -275,6 +282,10 @@ export type EnvVar =
|
|
|
275
282
|
| 'TRANSACTIONS_DISABLED'
|
|
276
283
|
| 'VALIDATOR_ATTESTATIONS_POLLING_INTERVAL_MS'
|
|
277
284
|
| 'VALIDATOR_DISABLED'
|
|
285
|
+
| 'VALIDATOR_MAX_DA_BLOCK_GAS'
|
|
286
|
+
| 'VALIDATOR_MAX_L2_BLOCK_GAS'
|
|
287
|
+
| 'VALIDATOR_MAX_TX_PER_BLOCK'
|
|
288
|
+
| 'VALIDATOR_MAX_TX_PER_CHECKPOINT'
|
|
278
289
|
| 'VALIDATOR_PRIVATE_KEYS'
|
|
279
290
|
| 'VALIDATOR_PRIVATE_KEY'
|
|
280
291
|
| 'VALIDATOR_REEXECUTE'
|
|
@@ -339,9 +350,8 @@ export type EnvVar =
|
|
|
339
350
|
| 'K8S_POD_NAME'
|
|
340
351
|
| 'K8S_POD_UID'
|
|
341
352
|
| 'K8S_NAMESPACE_NAME'
|
|
353
|
+
| 'ENABLE_VERSION_CHECK'
|
|
342
354
|
| 'VALIDATOR_REEXECUTE_DEADLINE_MS'
|
|
343
|
-
| 'AUTO_UPDATE'
|
|
344
|
-
| 'AUTO_UPDATE_URL'
|
|
345
355
|
| 'WEB3_SIGNER_URL'
|
|
346
356
|
| 'SKIP_ARCHIVER_INITIAL_SYNC'
|
|
347
357
|
| 'BLOB_ALLOW_EMPTY_SOURCES'
|
package/src/config/index.ts
CHANGED
|
@@ -177,6 +177,21 @@ export function bigintConfigHelper(defaultVal?: bigint): Pick<ConfigMapping, 'pa
|
|
|
177
177
|
if (val === '') {
|
|
178
178
|
return defaultVal;
|
|
179
179
|
}
|
|
180
|
+
// Handle scientific notation (e.g. "1e+23", "2E23") which BigInt() doesn't accept directly.
|
|
181
|
+
// We parse it losslessly using bigint arithmetic instead of going through float64.
|
|
182
|
+
if (/[eE]/.test(val)) {
|
|
183
|
+
const match = val.match(/^(-?\d+(?:\.(\d+))?)[eE]([+-]?\d+)$/);
|
|
184
|
+
if (!match) {
|
|
185
|
+
throw new Error(`Cannot convert '${val}' to a BigInt`);
|
|
186
|
+
}
|
|
187
|
+
const digits = match[1].replace('.', '');
|
|
188
|
+
const decimalPlaces = match[2]?.length ?? 0;
|
|
189
|
+
const exponent = parseInt(match[3], 10) - decimalPlaces;
|
|
190
|
+
if (exponent < 0) {
|
|
191
|
+
throw new Error(`Cannot convert '${val}' to a BigInt: result is not an integer`);
|
|
192
|
+
}
|
|
193
|
+
return BigInt(digits) * 10n ** BigInt(exponent);
|
|
194
|
+
}
|
|
180
195
|
return BigInt(val);
|
|
181
196
|
},
|
|
182
197
|
defaultValue: defaultVal,
|
|
@@ -5,10 +5,13 @@ export const NetworkConfigSchema = z
|
|
|
5
5
|
bootnodes: z.array(z.string()),
|
|
6
6
|
snapshots: z.array(z.string()),
|
|
7
7
|
blobFileStoreUrls: z.array(z.string()).optional(),
|
|
8
|
+
txCollectionFileStoreUrls: z.array(z.string()).optional(),
|
|
8
9
|
registryAddress: z.string(),
|
|
9
10
|
feeAssetHandlerAddress: z.string().optional(),
|
|
10
11
|
l1ChainId: z.number(),
|
|
11
12
|
blockDurationMs: z.number().positive().optional(),
|
|
13
|
+
nodeVersion: z.string().optional(),
|
|
14
|
+
txPublicSetupAllowListExtend: z.string().optional(),
|
|
12
15
|
})
|
|
13
16
|
.passthrough(); // Allow additional unknown fields to pass through
|
|
14
17
|
|
|
@@ -5,8 +5,7 @@ export type NetworkNames =
|
|
|
5
5
|
| 'testnet'
|
|
6
6
|
| 'mainnet'
|
|
7
7
|
| 'next-net'
|
|
8
|
-
| 'devnet'
|
|
9
|
-
| `v${number}-devnet-${number}`;
|
|
8
|
+
| 'devnet';
|
|
10
9
|
|
|
11
10
|
export function getActiveNetworkName(name?: string): NetworkNames {
|
|
12
11
|
const network = name || process.env.NETWORK;
|
|
@@ -24,8 +23,6 @@ export function getActiveNetworkName(name?: string): NetworkNames {
|
|
|
24
23
|
return 'next-net';
|
|
25
24
|
} else if (network === 'devnet') {
|
|
26
25
|
return 'devnet';
|
|
27
|
-
} else if (/^v\d+-devnet-\d+$/.test(network)) {
|
|
28
|
-
return network as `v${number}-devnet-${number}`;
|
|
29
26
|
}
|
|
30
27
|
throw new Error(`Unknown network: ${network}`);
|
|
31
28
|
}
|
|
@@ -1,21 +1,35 @@
|
|
|
1
|
-
import { BarretenbergSync } from '@aztec/bb.js';
|
|
1
|
+
import { Barretenberg, BarretenbergSync } from '@aztec/bb.js';
|
|
2
2
|
|
|
3
3
|
import { Fr } from '../../curves/bn254/field.js';
|
|
4
4
|
import { type Fieldable, serializeToFields } from '../../serialize/serialize.js';
|
|
5
5
|
|
|
6
|
+
const IS_BROWSER = typeof self !== 'undefined';
|
|
7
|
+
|
|
8
|
+
async function poseidon2HashFields(inputFields: Fr[]): Promise<Fr> {
|
|
9
|
+
if (IS_BROWSER) {
|
|
10
|
+
await BarretenbergSync.initSingleton();
|
|
11
|
+
const api = BarretenbergSync.getSingleton();
|
|
12
|
+
const response = api.poseidon2Hash({
|
|
13
|
+
inputs: inputFields.map(i => i.toBuffer()),
|
|
14
|
+
});
|
|
15
|
+
return Fr.fromBuffer(Buffer.from(response.hash));
|
|
16
|
+
} else {
|
|
17
|
+
await Barretenberg.initSingleton();
|
|
18
|
+
const api = Barretenberg.getSingleton();
|
|
19
|
+
const response = await api.poseidon2Hash({
|
|
20
|
+
inputs: inputFields.map(i => i.toBuffer()),
|
|
21
|
+
});
|
|
22
|
+
return Fr.fromBuffer(Buffer.from(response.hash));
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
6
26
|
/**
|
|
7
27
|
* Create a poseidon hash (field) from an array of input fields.
|
|
8
28
|
* @param input - The input fields to hash.
|
|
9
29
|
* @returns The poseidon hash.
|
|
10
30
|
*/
|
|
11
|
-
export
|
|
12
|
-
|
|
13
|
-
await BarretenbergSync.initSingleton();
|
|
14
|
-
const api = BarretenbergSync.getSingleton();
|
|
15
|
-
const response = api.poseidon2Hash({
|
|
16
|
-
inputs: inputFields.map(i => i.toBuffer()),
|
|
17
|
-
});
|
|
18
|
-
return Fr.fromBuffer(Buffer.from(response.hash));
|
|
31
|
+
export function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
|
|
32
|
+
return poseidon2HashFields(serializeToFields(input));
|
|
19
33
|
}
|
|
20
34
|
|
|
21
35
|
/**
|
|
@@ -24,15 +38,10 @@ export async function poseidon2Hash(input: Fieldable[]): Promise<Fr> {
|
|
|
24
38
|
* @param separator - The domain separator.
|
|
25
39
|
* @returns The poseidon hash.
|
|
26
40
|
*/
|
|
27
|
-
export
|
|
41
|
+
export function poseidon2HashWithSeparator(input: Fieldable[], separator: number): Promise<Fr> {
|
|
28
42
|
const inputFields = serializeToFields(input);
|
|
29
43
|
inputFields.unshift(new Fr(separator));
|
|
30
|
-
|
|
31
|
-
const api = BarretenbergSync.getSingleton();
|
|
32
|
-
const response = api.poseidon2Hash({
|
|
33
|
-
inputs: inputFields.map(i => i.toBuffer()),
|
|
34
|
-
});
|
|
35
|
-
return Fr.fromBuffer(Buffer.from(response.hash));
|
|
44
|
+
return poseidon2HashFields(inputFields);
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
/**
|
|
@@ -42,19 +51,24 @@ export async function poseidon2HashWithSeparator(input: Fieldable[], separator:
|
|
|
42
51
|
*/
|
|
43
52
|
export async function poseidon2Permutation(input: Fieldable[]): Promise<Fr[]> {
|
|
44
53
|
const inputFields = serializeToFields(input);
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
if (IS_BROWSER) {
|
|
55
|
+
await BarretenbergSync.initSingleton();
|
|
56
|
+
const api = BarretenbergSync.getSingleton();
|
|
57
|
+
const response = api.poseidon2Permutation({
|
|
58
|
+
inputs: inputFields.map(i => i.toBuffer()),
|
|
59
|
+
});
|
|
60
|
+
return response.outputs.map(o => Fr.fromBuffer(Buffer.from(o)));
|
|
61
|
+
} else {
|
|
62
|
+
await Barretenberg.initSingleton();
|
|
63
|
+
const api = Barretenberg.getSingleton();
|
|
64
|
+
const response = await api.poseidon2Permutation({
|
|
65
|
+
inputs: inputFields.map(i => i.toBuffer()),
|
|
66
|
+
});
|
|
67
|
+
return response.outputs.map(o => Fr.fromBuffer(Buffer.from(o)));
|
|
68
|
+
}
|
|
55
69
|
}
|
|
56
70
|
|
|
57
|
-
export
|
|
71
|
+
export function poseidon2HashBytes(input: Buffer): Promise<Fr> {
|
|
58
72
|
const inputFields = [];
|
|
59
73
|
for (let i = 0; i < input.length; i += 31) {
|
|
60
74
|
const fieldBytes = Buffer.alloc(32, 0);
|
|
@@ -65,11 +79,5 @@ export async function poseidon2HashBytes(input: Buffer): Promise<Fr> {
|
|
|
65
79
|
inputFields.push(Fr.fromBuffer(fieldBytes));
|
|
66
80
|
}
|
|
67
81
|
|
|
68
|
-
|
|
69
|
-
const api = BarretenbergSync.getSingleton();
|
|
70
|
-
const response = api.poseidon2Hash({
|
|
71
|
-
inputs: inputFields.map(i => i.toBuffer()),
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
return Fr.fromBuffer(Buffer.from(response.hash));
|
|
82
|
+
return poseidon2HashFields(inputFields);
|
|
75
83
|
}
|
|
@@ -210,3 +210,35 @@ export function recoverPublicKey(hash: Buffer32, signature: Signature, opts: Rec
|
|
|
210
210
|
const publicKey = sig.recoverPublicKey(hash.buffer).toHex(false);
|
|
211
211
|
return Buffer.from(publicKey, 'hex');
|
|
212
212
|
}
|
|
213
|
+
|
|
214
|
+
/** Arbitrary hash used for testing signature recoverability. */
|
|
215
|
+
const PROBE_HASH = Buffer32.fromBuffer(keccak256(Buffer.from('signature-recoverability-probe')));
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Generates a random valid ECDSA signature that is recoverable to some address.
|
|
219
|
+
* Since Signature.random() produces real signatures via secp256k1 signing, the result is always
|
|
220
|
+
* recoverable, but we verify defensively by checking tryRecoverAddress.
|
|
221
|
+
*/
|
|
222
|
+
export function generateRecoverableSignature(): Signature {
|
|
223
|
+
for (let i = 0; i < 100; i++) {
|
|
224
|
+
const sig = Signature.random();
|
|
225
|
+
if (tryRecoverAddress(PROBE_HASH, sig) !== undefined) {
|
|
226
|
+
return sig;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
throw new Secp256k1Error('Failed to generate a recoverable signature after 100 attempts');
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/**
|
|
233
|
+
* Generates a random signature where ECDSA address recovery fails.
|
|
234
|
+
* Uses random r/s values (not from real signing) so that r is unlikely to be a valid secp256k1 x-coordinate.
|
|
235
|
+
*/
|
|
236
|
+
export function generateUnrecoverableSignature(): Signature {
|
|
237
|
+
for (let i = 0; i < 100; i++) {
|
|
238
|
+
const sig = new Signature(Buffer32.random(), Buffer32.random(), 27);
|
|
239
|
+
if (tryRecoverAddress(PROBE_HASH, sig) === undefined) {
|
|
240
|
+
return sig;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
throw new Secp256k1Error('Failed to generate an unrecoverable signature after 100 attempts');
|
|
244
|
+
}
|
|
@@ -118,14 +118,18 @@ abstract class BaseField {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
cmp(rhs: BaseField): -1 | 0 | 1 {
|
|
121
|
-
|
|
122
|
-
return this.asBigInt === rhsBigInt ? 0 : this.asBigInt < rhsBigInt ? -1 : 1;
|
|
121
|
+
return BaseField.cmpAsBigInt(this.asBigInt, rhs.asBigInt);
|
|
123
122
|
}
|
|
124
123
|
|
|
125
124
|
static cmp(lhs: BaseField, rhs: BaseField): -1 | 0 | 1 {
|
|
126
125
|
return lhs.cmp(rhs);
|
|
127
126
|
}
|
|
128
127
|
|
|
128
|
+
// Actual bigint comparison. Arguments must have been validated previously.
|
|
129
|
+
static cmpAsBigInt(lhs: bigint, rhs: bigint): -1 | 0 | 1 {
|
|
130
|
+
return lhs === rhs ? 0 : lhs < rhs ? -1 : 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
129
133
|
isZero(): boolean {
|
|
130
134
|
return this.asBigInt === 0n;
|
|
131
135
|
}
|
|
@@ -65,7 +65,7 @@ export class Point {
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
/**
|
|
68
|
-
* Generate a random Point instance.
|
|
68
|
+
* Generate a random Point instance that is on the curve.
|
|
69
69
|
*
|
|
70
70
|
* @returns A randomly generated Point instance.
|
|
71
71
|
*/
|
|
@@ -125,9 +125,12 @@ export class Point {
|
|
|
125
125
|
}
|
|
126
126
|
|
|
127
127
|
/**
|
|
128
|
-
* Returns the contents of the point as an array of
|
|
129
|
-
* @returns The point as an array of
|
|
128
|
+
* Returns the contents of the point as an array of 3 fields.
|
|
129
|
+
* @returns The point as an array of 3 fields
|
|
130
130
|
*/
|
|
131
|
+
// TODO(F-553): Once we take the breaking change and drop the custom Noir `Point` wrapper in
|
|
132
|
+
// `noir-projects/noir-protocol-circuits/crates/types/src/point.nr`, revert this to serialize as `[x, y]` (2 fields)
|
|
133
|
+
// and drop the `is_infinite` flag from `fromFields` / `toNoirStruct` below.
|
|
131
134
|
toFields() {
|
|
132
135
|
return [this.x, this.y, new Fr(this.isInfinite)];
|
|
133
136
|
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
2
|
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
3
|
|
|
4
|
+
import { secp256k1 } from '@noble/curves/secp256k1';
|
|
4
5
|
import { z } from 'zod';
|
|
5
6
|
|
|
7
|
+
import { randomBytes } from '../crypto/random/index.js';
|
|
6
8
|
import { hasHexPrefix, hexToBuffer } from '../string/index.js';
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -77,8 +79,12 @@ export class Signature {
|
|
|
77
79
|
return new Signature(Buffer32.fromBuffer(hexToBuffer(sig.r)), Buffer32.fromBuffer(hexToBuffer(sig.s)), sig.yParity);
|
|
78
80
|
}
|
|
79
81
|
|
|
82
|
+
/** Generates a random valid ECDSA signature with a low s-value by signing a random message with a random key. */
|
|
80
83
|
static random(): Signature {
|
|
81
|
-
|
|
84
|
+
const privateKey = randomBytes(32);
|
|
85
|
+
const message = randomBytes(32);
|
|
86
|
+
const { r, s, recovery } = secp256k1.sign(message, privateKey);
|
|
87
|
+
return new Signature(Buffer32.fromBigInt(r), Buffer32.fromBigInt(s), recovery ? 28 : 27);
|
|
82
88
|
}
|
|
83
89
|
|
|
84
90
|
static empty(): Signature {
|
package/src/log/bigint-utils.ts
CHANGED
|
@@ -11,6 +11,9 @@ export function convertBigintsToStrings(obj: unknown): unknown {
|
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
if (obj !== null && typeof obj === 'object') {
|
|
14
|
+
if (typeof (obj as any).toJSON === 'function') {
|
|
15
|
+
return convertBigintsToStrings((obj as any).toJSON());
|
|
16
|
+
}
|
|
14
17
|
const result: Record<string, unknown> = {};
|
|
15
18
|
for (const key in obj) {
|
|
16
19
|
result[key] = convertBigintsToStrings((obj as Record<string, unknown>)[key]);
|
package/src/schemas/api.ts
CHANGED
|
@@ -37,7 +37,10 @@ export type ApiSchema = {
|
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
/** Return whether an API schema defines a valid function schema for a given method name. */
|
|
40
|
-
export function schemaHasMethod
|
|
40
|
+
export function schemaHasMethod<T extends ApiSchema>(
|
|
41
|
+
schema: T,
|
|
42
|
+
methodName: string,
|
|
43
|
+
): methodName is Extract<keyof T, string> {
|
|
41
44
|
return (
|
|
42
45
|
typeof methodName === 'string' &&
|
|
43
46
|
Object.hasOwn(schema, methodName) &&
|
|
@@ -286,16 +286,39 @@ export class BufferReader {
|
|
|
286
286
|
}
|
|
287
287
|
|
|
288
288
|
/**
|
|
289
|
-
* Read an array
|
|
290
|
-
*
|
|
291
|
-
* and returns an instance of the desired deserialized data type T.
|
|
292
|
-
* This method will call the 'fromBuffer' method for each element in the array and return the resulting array.
|
|
289
|
+
* Read an array from the buffer using lazy allocation (new Array + loop).
|
|
290
|
+
* Safe for use with untrusted sizes — does not pre-allocate memory proportional to size.
|
|
293
291
|
*
|
|
294
|
-
* @param size - The
|
|
292
|
+
* @param size - The number of elements to read.
|
|
295
293
|
* @param itemDeserializer - An object with a 'fromBuffer' method to deserialize individual elements of type T.
|
|
296
294
|
* @returns An array of instances of type T.
|
|
297
295
|
*/
|
|
298
|
-
public readArray<T
|
|
296
|
+
public readArray<T>(
|
|
297
|
+
size: number,
|
|
298
|
+
itemDeserializer: {
|
|
299
|
+
/**
|
|
300
|
+
* A function for deserializing data from a BufferReader instance.
|
|
301
|
+
*/
|
|
302
|
+
fromBuffer: (reader: BufferReader) => T;
|
|
303
|
+
},
|
|
304
|
+
): T[] {
|
|
305
|
+
const result = new Array<T>(size);
|
|
306
|
+
for (let i = 0; i < size; i++) {
|
|
307
|
+
result[i] = itemDeserializer.fromBuffer(this);
|
|
308
|
+
}
|
|
309
|
+
return result;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Read a fixed-size tuple from the buffer using dense allocation (Array.from).
|
|
314
|
+
* Only use with compile-time constant sizes — the size parameter MUST NOT come from untrusted input
|
|
315
|
+
* as Array.from pre-allocates memory proportional to size.
|
|
316
|
+
*
|
|
317
|
+
* @param size - The fixed number of elements (must be a compile-time constant).
|
|
318
|
+
* @param itemDeserializer - An object with a 'fromBuffer' method to deserialize individual elements of type T.
|
|
319
|
+
* @returns A densely-allocated tuple of instances of type T.
|
|
320
|
+
*/
|
|
321
|
+
public readTuple<T, N extends number>(
|
|
299
322
|
size: N,
|
|
300
323
|
itemDeserializer: {
|
|
301
324
|
/**
|
|
@@ -169,12 +169,30 @@ export class FieldReader {
|
|
|
169
169
|
* @param itemDeserializer - An object with a 'fromFields' method to deserialize individual elements of type T.
|
|
170
170
|
* @returns An array of instances of type T.
|
|
171
171
|
*/
|
|
172
|
-
|
|
172
|
+
/**
|
|
173
|
+
* Read an array from the field array using lazy allocation (new Array + loop).
|
|
174
|
+
* Safe for use with untrusted sizes.
|
|
175
|
+
*/
|
|
176
|
+
public readArray<T>(
|
|
177
|
+
size: number,
|
|
178
|
+
itemDeserializer: {
|
|
179
|
+
fromFields: (reader: FieldReader) => T;
|
|
180
|
+
},
|
|
181
|
+
): T[] {
|
|
182
|
+
const result = new Array<T>(size);
|
|
183
|
+
for (let i = 0; i < size; i++) {
|
|
184
|
+
result[i] = itemDeserializer.fromFields(this);
|
|
185
|
+
}
|
|
186
|
+
return result;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Read a fixed-size tuple from the field array using dense allocation (Array.from).
|
|
191
|
+
* Only use with compile-time constant sizes — the size parameter MUST NOT come from untrusted input.
|
|
192
|
+
*/
|
|
193
|
+
public readTuple<T, N extends number>(
|
|
173
194
|
size: N,
|
|
174
195
|
itemDeserializer: {
|
|
175
|
-
/**
|
|
176
|
-
* A function for deserializing data from a FieldReader instance.
|
|
177
|
-
*/
|
|
178
196
|
fromFields: (reader: FieldReader) => T;
|
|
179
197
|
},
|
|
180
198
|
): Tuple<T, N> {
|
package/src/timer/date.ts
CHANGED
|
@@ -32,12 +32,6 @@ export class TestDateProvider extends DateProvider {
|
|
|
32
32
|
this.logger.warn(`Time set to ${new Date(timeMs).toISOString()}`, { offset: this.offset, timeMs });
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
/** Resets the time back to real time (offset = 0). */
|
|
36
|
-
public reset() {
|
|
37
|
-
this.offset = 0;
|
|
38
|
-
this.logger.warn('Time reset to real time');
|
|
39
|
-
}
|
|
40
|
-
|
|
41
35
|
/** Advances the time by the given number of seconds. */
|
|
42
36
|
public advanceTime(seconds: number) {
|
|
43
37
|
this.offset += seconds * 1000;
|
|
@@ -91,7 +91,7 @@ export class TransportClient<Payload> extends EventEmitter {
|
|
|
91
91
|
}
|
|
92
92
|
const msgId = this.msgId++;
|
|
93
93
|
const msg = { msgId, payload };
|
|
94
|
-
log.
|
|
94
|
+
log.trace(format(`->`, msg));
|
|
95
95
|
return new Promise<any>((resolve, reject) => {
|
|
96
96
|
this.pendingRequests.push({ resolve, reject, msgId });
|
|
97
97
|
this.socket!.send(msg, transfer).catch(reject);
|
|
@@ -111,7 +111,7 @@ export class TransportClient<Payload> extends EventEmitter {
|
|
|
111
111
|
this.close();
|
|
112
112
|
return;
|
|
113
113
|
}
|
|
114
|
-
log.
|
|
114
|
+
log.trace(format(`<-`, msg));
|
|
115
115
|
if (isEventMessage(msg)) {
|
|
116
116
|
this.emit('event_msg', msg.payload);
|
|
117
117
|
return;
|
|
@@ -94,7 +94,7 @@ export class MembershipWitness<N extends number> {
|
|
|
94
94
|
static fromBuffer<N extends number>(buffer: Buffer | BufferReader, size: N): MembershipWitness<N> {
|
|
95
95
|
const reader = BufferReader.asReader(buffer);
|
|
96
96
|
const leafIndex = toBigIntBE(reader.readBytes(32));
|
|
97
|
-
const siblingPath = reader.readArray(size, Fr)
|
|
97
|
+
const siblingPath = reader.readArray(size, Fr) as Tuple<Fr, N>;
|
|
98
98
|
return new MembershipWitness(size, leafIndex, siblingPath);
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -108,7 +108,7 @@ export class MembershipWitness<N extends number> {
|
|
|
108
108
|
fromBuffer: (buffer: Buffer | BufferReader) => {
|
|
109
109
|
const reader = BufferReader.asReader(buffer);
|
|
110
110
|
const leafIndex = toBigIntBE(reader.readBytes(32));
|
|
111
|
-
const siblingPath = reader.readArray(size, Fr)
|
|
111
|
+
const siblingPath = reader.readArray(size, Fr) as Tuple<Fr, N>;
|
|
112
112
|
return new MembershipWitness(size, leafIndex, siblingPath);
|
|
113
113
|
},
|
|
114
114
|
};
|