@aztec/foundation 0.42.0 → 0.44.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/dest/abi/abi.d.ts +2 -5
- package/dest/abi/abi.d.ts.map +1 -1
- package/dest/abi/abi.js +1 -1
- package/dest/abi/index.d.ts +2 -1
- package/dest/abi/index.d.ts.map +1 -1
- package/dest/abi/index.js +3 -2
- package/dest/abi/note_selector.d.ts +41 -0
- package/dest/abi/note_selector.d.ts.map +1 -0
- package/dest/abi/note_selector.js +57 -0
- package/dest/collection/array.d.ts +13 -0
- package/dest/collection/array.d.ts.map +1 -1
- package/dest/collection/array.js +12 -1
- package/dest/crypto/random/randomness_singleton.js +3 -3
- package/dest/error/index.d.ts +1 -1
- package/dest/error/index.d.ts.map +1 -1
- package/dest/error/index.js +2 -2
- package/dest/fields/fields.d.ts +4 -3
- package/dest/fields/fields.d.ts.map +1 -1
- package/dest/fields/fields.js +29 -11
- package/dest/fields/point.d.ts +7 -0
- package/dest/fields/point.d.ts.map +1 -1
- package/dest/fields/point.js +24 -2
- package/dest/fs/run_in_dir.d.ts +1 -1
- package/dest/fs/run_in_dir.d.ts.map +1 -1
- package/dest/fs/run_in_dir.js +7 -6
- package/dest/json-rpc/server/json_rpc_server.d.ts.map +1 -1
- package/dest/json-rpc/server/json_rpc_server.js +3 -3
- package/dest/log/logger.d.ts.map +1 -1
- package/dest/log/logger.js +5 -38
- package/dest/promise/running-promise.d.ts +1 -1
- package/dest/promise/running-promise.d.ts.map +1 -1
- package/dest/promise/running-promise.js +1 -1
- package/dest/serialize/buffer_reader.d.ts +1 -0
- package/dest/serialize/buffer_reader.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.js +17 -1
- package/dest/serialize/free_funcs.d.ts +1 -0
- package/dest/serialize/free_funcs.d.ts.map +1 -1
- package/dest/serialize/free_funcs.js +8 -1
- package/package.json +11 -3
- package/src/abi/abi.ts +2 -5
- package/src/abi/index.ts +2 -1
- package/src/abi/note_selector.ts +73 -0
- package/src/collection/array.ts +14 -0
- package/src/crypto/random/randomness_singleton.ts +2 -2
- package/src/error/index.ts +1 -1
- package/src/fields/fields.ts +32 -11
- package/src/fields/point.ts +28 -2
- package/src/fs/run_in_dir.ts +10 -5
- package/src/json-rpc/server/json_rpc_server.ts +2 -2
- package/src/log/logger.ts +5 -38
- package/src/promise/running-promise.ts +1 -1
- package/src/serialize/buffer_reader.ts +16 -0
- package/src/serialize/free_funcs.ts +8 -0
package/src/fields/fields.ts
CHANGED
|
@@ -25,9 +25,6 @@ type DerivedField<T extends BaseField> = {
|
|
|
25
25
|
* Conversions from Buffer to BigInt and vice-versa are not cheap.
|
|
26
26
|
* We allow construction with either form and lazily convert to other as needed.
|
|
27
27
|
* We only check we are within the field modulus when initializing with bigint.
|
|
28
|
-
* If NODE_ENV === 'test', we will always initialize both types to check the modulus.
|
|
29
|
-
* This is also necessary in test environment as a lot of tests just use deep equality to check equality.
|
|
30
|
-
* WARNING: This could lead to a bugs in production that don't reveal in tests, but it's low risk.
|
|
31
28
|
*/
|
|
32
29
|
abstract class BaseField {
|
|
33
30
|
static SIZE_IN_BYTES = 32;
|
|
@@ -42,6 +39,11 @@ abstract class BaseField {
|
|
|
42
39
|
return this.toBigInt();
|
|
43
40
|
}
|
|
44
41
|
|
|
42
|
+
/** Returns the size in bytes. */
|
|
43
|
+
get size(): number {
|
|
44
|
+
return BaseField.SIZE_IN_BYTES;
|
|
45
|
+
}
|
|
46
|
+
|
|
45
47
|
protected constructor(value: number | bigint | boolean | BaseField | Buffer) {
|
|
46
48
|
if (value instanceof Buffer) {
|
|
47
49
|
if (value.length > BaseField.SIZE_IN_BYTES) {
|
|
@@ -62,14 +64,6 @@ abstract class BaseField {
|
|
|
62
64
|
} else {
|
|
63
65
|
throw new Error(`Type '${typeof value}' with value '${value}' passed to BaseField ctor.`);
|
|
64
66
|
}
|
|
65
|
-
|
|
66
|
-
// Loads of our tests are just doing deep equality rather than calling e.g. toBigInt() first.
|
|
67
|
-
// This ensures the deep equality passes regardless of the internal representation.
|
|
68
|
-
// It also ensures the value range is checked even when initializing as a buffer.
|
|
69
|
-
if (process.env.NODE_ENV === 'test') {
|
|
70
|
-
this.toBuffer();
|
|
71
|
-
this.toBigInt();
|
|
72
|
-
}
|
|
73
67
|
}
|
|
74
68
|
|
|
75
69
|
protected abstract modulus(): bigint;
|
|
@@ -243,6 +237,14 @@ export class Fr extends BaseField {
|
|
|
243
237
|
return new Fr((this.toBigInt() + rhs.toBigInt()) % Fr.MODULUS);
|
|
244
238
|
}
|
|
245
239
|
|
|
240
|
+
square() {
|
|
241
|
+
return new Fr((this.toBigInt() * this.toBigInt()) % Fr.MODULUS);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
negate() {
|
|
245
|
+
return new Fr(Fr.MODULUS - this.toBigInt());
|
|
246
|
+
}
|
|
247
|
+
|
|
246
248
|
sub(rhs: Fr) {
|
|
247
249
|
const result = this.toBigInt() - rhs.toBigInt();
|
|
248
250
|
return new Fr(result < 0 ? result + Fr.MODULUS : result);
|
|
@@ -392,3 +394,22 @@ export const GrumpkinScalar = Fq;
|
|
|
392
394
|
export function reduceFn<TInput, TField extends BaseField>(fn: (input: TInput) => Buffer, field: DerivedField<TField>) {
|
|
393
395
|
return (input: TInput) => fromBufferReduce(fn(input), field);
|
|
394
396
|
}
|
|
397
|
+
|
|
398
|
+
/** If we are in test mode, we register a special equality for fields. */
|
|
399
|
+
if (process.env.NODE_ENV === 'test') {
|
|
400
|
+
const areFieldsEqual = (a: unknown, b: unknown): boolean | undefined => {
|
|
401
|
+
const isAField = a instanceof BaseField;
|
|
402
|
+
const isBField = b instanceof BaseField;
|
|
403
|
+
|
|
404
|
+
if (isAField && isBField) {
|
|
405
|
+
return a.equals(b);
|
|
406
|
+
} else if (isAField === isBField) {
|
|
407
|
+
return undefined;
|
|
408
|
+
} else {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
};
|
|
412
|
+
|
|
413
|
+
// `addEqualityTesters` doesn't seem to be in the types yet.
|
|
414
|
+
(expect as any).addEqualityTesters([areFieldsEqual]);
|
|
415
|
+
}
|
package/src/fields/point.ts
CHANGED
|
@@ -23,7 +23,9 @@ export class Point {
|
|
|
23
23
|
* The point's y coordinate
|
|
24
24
|
*/
|
|
25
25
|
public readonly y: Fr,
|
|
26
|
-
) {
|
|
26
|
+
) {
|
|
27
|
+
// TODO: Do we want to check if the point is on the curve here?
|
|
28
|
+
}
|
|
27
29
|
|
|
28
30
|
/**
|
|
29
31
|
* Generate a random Point instance.
|
|
@@ -44,7 +46,7 @@ export class Point {
|
|
|
44
46
|
*/
|
|
45
47
|
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
46
48
|
const reader = BufferReader.asReader(buffer);
|
|
47
|
-
return new this(Fr.fromBuffer(reader
|
|
49
|
+
return new this(Fr.fromBuffer(reader), Fr.fromBuffer(reader));
|
|
48
50
|
}
|
|
49
51
|
|
|
50
52
|
/**
|
|
@@ -134,6 +136,30 @@ export class Point {
|
|
|
134
136
|
hash() {
|
|
135
137
|
return poseidon2Hash(this.toFields());
|
|
136
138
|
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Check if this is point at infinity.
|
|
142
|
+
* Check this is consistent with how bb is encoding the point at infinity
|
|
143
|
+
*/
|
|
144
|
+
public get inf() {
|
|
145
|
+
return this.x == Fr.ZERO;
|
|
146
|
+
}
|
|
147
|
+
public toFieldsWithInf() {
|
|
148
|
+
return [this.x, this.y, new Fr(this.inf)];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
isOnGrumpkin() {
|
|
152
|
+
// TODO: Check this against how bb handles curve check and infinity point check
|
|
153
|
+
if (this.inf) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// p.y * p.y == p.x * p.x * p.x - 17
|
|
158
|
+
const A = new Fr(17);
|
|
159
|
+
const lhs = this.y.square();
|
|
160
|
+
const rhs = this.x.square().mul(this.x).sub(A);
|
|
161
|
+
return lhs.equals(rhs);
|
|
162
|
+
}
|
|
137
163
|
}
|
|
138
164
|
|
|
139
165
|
/**
|
package/src/fs/run_in_dir.ts
CHANGED
|
@@ -1,18 +1,23 @@
|
|
|
1
|
-
import { randomBytes } from 'crypto';
|
|
2
1
|
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
3
|
|
|
4
4
|
// Create a random directory underneath a 'base' directory
|
|
5
5
|
// Calls a provided method, ensures the random directory is cleaned up afterwards
|
|
6
|
-
export async function runInDirectory<T>(
|
|
6
|
+
export async function runInDirectory<T>(
|
|
7
|
+
workingDirBase: string,
|
|
8
|
+
fn: (dir: string) => Promise<T>,
|
|
9
|
+
cleanup: boolean = true,
|
|
10
|
+
): Promise<T> {
|
|
7
11
|
// Create random directory to be used for temp files
|
|
8
|
-
const workingDirectory =
|
|
9
|
-
await fs.mkdir(workingDirectory, { recursive: true });
|
|
12
|
+
const workingDirectory = await fs.mkdtemp(path.join(workingDirBase, 'tmp-'));
|
|
10
13
|
|
|
11
14
|
await fs.access(workingDirectory);
|
|
12
15
|
|
|
13
16
|
try {
|
|
14
17
|
return await fn(workingDirectory);
|
|
15
18
|
} finally {
|
|
16
|
-
|
|
19
|
+
if (cleanup) {
|
|
20
|
+
await fs.rm(workingDirectory, { recursive: true, force: true });
|
|
21
|
+
}
|
|
17
22
|
}
|
|
18
23
|
}
|
|
@@ -25,7 +25,7 @@ export class JsonRpcServer {
|
|
|
25
25
|
private objectClassMap: JsonClassConverterInput,
|
|
26
26
|
/** List of methods to disallow from calling remotely */
|
|
27
27
|
public readonly disallowedMethods: string[] = [],
|
|
28
|
-
private log = createDebugLogger('
|
|
28
|
+
private log = createDebugLogger('json-rpc:server'),
|
|
29
29
|
) {
|
|
30
30
|
this.proxy = new JsonProxy(handler, stringClassMap, objectClassMap);
|
|
31
31
|
}
|
|
@@ -226,7 +226,7 @@ export type ServerList = {
|
|
|
226
226
|
*/
|
|
227
227
|
export function createNamespacedJsonRpcServer(
|
|
228
228
|
servers: ServerList,
|
|
229
|
-
log = createDebugLogger('
|
|
229
|
+
log = createDebugLogger('json-rpc:multi-server'),
|
|
230
230
|
): JsonRpcServer {
|
|
231
231
|
const handler = {} as any;
|
|
232
232
|
const disallowedMethods: string[] = [];
|
package/src/log/logger.ts
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import debug from 'debug';
|
|
2
|
-
import isNode from 'detect-node';
|
|
3
|
-
import { isatty } from 'tty';
|
|
4
2
|
|
|
5
3
|
import { type LogData, type LogFn } from './log_fn.js';
|
|
6
4
|
|
|
@@ -15,6 +13,9 @@ export type LogLevel = (typeof LogLevels)[number];
|
|
|
15
13
|
const envLogLevel = process.env.LOG_LEVEL?.toLowerCase() as LogLevel;
|
|
16
14
|
const currentLevel = LogLevels.includes(envLogLevel) ? envLogLevel : DefaultLogLevel;
|
|
17
15
|
|
|
16
|
+
const namespaces = process.env.DEBUG ?? 'aztec:*';
|
|
17
|
+
debug.enable(namespaces);
|
|
18
|
+
|
|
18
19
|
/** Log function that accepts an exception object */
|
|
19
20
|
type ErrorLogFn = (msg: string, err?: Error | unknown, data?: LogData) => void;
|
|
20
21
|
|
|
@@ -38,9 +39,6 @@ export type DebugLogger = Logger;
|
|
|
38
39
|
*/
|
|
39
40
|
export function createDebugLogger(name: string): DebugLogger {
|
|
40
41
|
const debugLogger = debug(name);
|
|
41
|
-
if (currentLevel === 'debug') {
|
|
42
|
-
debugLogger.enabled = true;
|
|
43
|
-
}
|
|
44
42
|
|
|
45
43
|
const logger = {
|
|
46
44
|
silent: () => {},
|
|
@@ -78,42 +76,11 @@ function logWithDebug(debug: debug.Debugger, level: LogLevel, msg: string, data?
|
|
|
78
76
|
}
|
|
79
77
|
|
|
80
78
|
msg = data ? `${msg} ${fmtLogData(data)}` : msg;
|
|
81
|
-
if (debug.enabled) {
|
|
82
|
-
|
|
83
|
-
msg = `${level.toUpperCase()} ${msg}`;
|
|
84
|
-
}
|
|
85
|
-
debug(msg);
|
|
86
|
-
} else if (LogLevels.indexOf(level) <= LogLevels.indexOf(currentLevel)) {
|
|
87
|
-
printLog(`${getPrefix(debug, level)} ${msg}`);
|
|
79
|
+
if (debug.enabled && LogLevels.indexOf(level) <= LogLevels.indexOf(currentLevel)) {
|
|
80
|
+
debug('[%s] %s', level.toUpperCase(), msg);
|
|
88
81
|
}
|
|
89
82
|
}
|
|
90
83
|
|
|
91
|
-
/**
|
|
92
|
-
* Returns a log prefix that emulates that of npm debug. Uses colors if in node and in a tty.
|
|
93
|
-
* @param debugLogger - Instance of npm debug logger.
|
|
94
|
-
* @param level - Intended log level (printed out if strictly above current log level).
|
|
95
|
-
* @returns Log prefix.
|
|
96
|
-
*/
|
|
97
|
-
function getPrefix(debugLogger: debug.Debugger, level: LogLevel) {
|
|
98
|
-
const levelLabel = currentLevel !== level ? ` ${level.toUpperCase()}` : '';
|
|
99
|
-
const prefix = `${debugLogger.namespace.replace(/^aztec:/, '')}${levelLabel}`;
|
|
100
|
-
if ((!isNode || !isatty(process.stderr.fd)) && !process.env.DEBUG_COLORS) {
|
|
101
|
-
return prefix;
|
|
102
|
-
}
|
|
103
|
-
const colorIndex = debug.selectColor(debugLogger.namespace) as number;
|
|
104
|
-
const colorCode = '\u001B[3' + (colorIndex < 8 ? colorIndex : '8;5;' + colorIndex);
|
|
105
|
-
return ` ${colorCode};1m${prefix}\u001B[0m`;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Outputs to console error.
|
|
110
|
-
* @param msg - What to log.
|
|
111
|
-
*/
|
|
112
|
-
function printLog(msg: string) {
|
|
113
|
-
// eslint-disable-next-line no-console
|
|
114
|
-
isNode ? process.stderr.write(msg + '\n') : console.error(msg);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
84
|
/**
|
|
118
85
|
* Concatenates a log message and an exception.
|
|
119
86
|
* @param msg - Log message
|
|
@@ -10,7 +10,7 @@ export class RunningPromise {
|
|
|
10
10
|
private runningPromise = Promise.resolve();
|
|
11
11
|
private interruptibleSleep = new InterruptibleSleep();
|
|
12
12
|
|
|
13
|
-
constructor(private fn: () => Promise<void>, private pollingIntervalMS = 10000) {}
|
|
13
|
+
constructor(private fn: () => void | Promise<void>, private pollingIntervalMS = 10000) {}
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Starts the running promise.
|
|
@@ -55,6 +55,7 @@ export class BufferReader {
|
|
|
55
55
|
* @returns The read 32-bit unsigned integer value.
|
|
56
56
|
*/
|
|
57
57
|
public readNumber(): number {
|
|
58
|
+
this.#rangeCheck(4);
|
|
58
59
|
this.index += 4;
|
|
59
60
|
return this.buffer.readUint32BE(this.index - 4);
|
|
60
61
|
}
|
|
@@ -76,6 +77,7 @@ export class BufferReader {
|
|
|
76
77
|
* @returns The read 16 bit value.
|
|
77
78
|
*/
|
|
78
79
|
public readUInt16(): number {
|
|
80
|
+
this.#rangeCheck(2);
|
|
79
81
|
this.index += 2;
|
|
80
82
|
return this.buffer.readUInt16BE(this.index - 2);
|
|
81
83
|
}
|
|
@@ -87,6 +89,7 @@ export class BufferReader {
|
|
|
87
89
|
* @returns The read 8 bit value.
|
|
88
90
|
*/
|
|
89
91
|
public readUInt8(): number {
|
|
92
|
+
this.#rangeCheck(1);
|
|
90
93
|
this.index += 1;
|
|
91
94
|
return this.buffer.readUInt8(this.index - 1);
|
|
92
95
|
}
|
|
@@ -99,6 +102,7 @@ export class BufferReader {
|
|
|
99
102
|
* @returns A boolean value representing the byte at the current index.
|
|
100
103
|
*/
|
|
101
104
|
public readBoolean(): boolean {
|
|
105
|
+
this.#rangeCheck(1);
|
|
102
106
|
this.index += 1;
|
|
103
107
|
return Boolean(this.buffer.at(this.index - 1));
|
|
104
108
|
}
|
|
@@ -112,6 +116,7 @@ export class BufferReader {
|
|
|
112
116
|
* @returns A new Buffer containing the read bytes.
|
|
113
117
|
*/
|
|
114
118
|
public readBytes(n: number): Buffer {
|
|
119
|
+
this.#rangeCheck(n);
|
|
115
120
|
this.index += n;
|
|
116
121
|
return Buffer.from(this.buffer.subarray(this.index - n, this.index));
|
|
117
122
|
}
|
|
@@ -215,6 +220,7 @@ export class BufferReader {
|
|
|
215
220
|
public readBufferArray(size = -1): Buffer[] {
|
|
216
221
|
const result: Buffer[] = [];
|
|
217
222
|
const end = size >= 0 ? this.index + size : this.buffer.length;
|
|
223
|
+
this.#rangeCheck(end - this.index);
|
|
218
224
|
while (this.index < end) {
|
|
219
225
|
const item = this.readBuffer();
|
|
220
226
|
result.push(item);
|
|
@@ -252,6 +258,7 @@ export class BufferReader {
|
|
|
252
258
|
* @returns A Buffer with the next n bytes or the remaining bytes if n is not provided or exceeds the buffer length.
|
|
253
259
|
*/
|
|
254
260
|
public peekBytes(n?: number): Buffer {
|
|
261
|
+
this.#rangeCheck(n || 0);
|
|
255
262
|
return this.buffer.subarray(this.index, n ? this.index + n : undefined);
|
|
256
263
|
}
|
|
257
264
|
|
|
@@ -276,6 +283,7 @@ export class BufferReader {
|
|
|
276
283
|
*/
|
|
277
284
|
public readBuffer(): Buffer {
|
|
278
285
|
const size = this.readNumber();
|
|
286
|
+
this.#rangeCheck(size);
|
|
279
287
|
return this.readBytes(size);
|
|
280
288
|
}
|
|
281
289
|
|
|
@@ -311,6 +319,14 @@ export class BufferReader {
|
|
|
311
319
|
public getLength(): number {
|
|
312
320
|
return this.buffer.length;
|
|
313
321
|
}
|
|
322
|
+
|
|
323
|
+
#rangeCheck(numBytes: number) {
|
|
324
|
+
if (this.index + numBytes > this.buffer.length) {
|
|
325
|
+
throw new Error(
|
|
326
|
+
`Attempted to read beyond buffer length. Start index: ${this.index}, Num bytes to read: ${numBytes}, Buffer length: ${this.buffer.length}`,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
}
|
|
314
330
|
}
|
|
315
331
|
|
|
316
332
|
/**
|
|
@@ -194,3 +194,11 @@ export function fromTruncField(field: Fr): Buffer {
|
|
|
194
194
|
export function fromFieldsTuple(fields: Tuple<Fr, 2>): Buffer {
|
|
195
195
|
return from2Fields(fields[0], fields[1]);
|
|
196
196
|
}
|
|
197
|
+
|
|
198
|
+
export function toHumanReadable(buf: Buffer, maxLen?: number): string {
|
|
199
|
+
const result = buf.every(byte => byte >= 32 && byte <= 126) ? buf.toString('ascii') : `0x${buf.toString('hex')}`;
|
|
200
|
+
if (maxLen && result.length > maxLen) {
|
|
201
|
+
return result.slice(0, maxLen) + '...';
|
|
202
|
+
}
|
|
203
|
+
return result;
|
|
204
|
+
}
|