@aztec/foundation 0.55.1 → 0.57.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 +13 -0
- package/dest/abi/abi.d.ts.map +1 -1
- package/dest/abi/abi.js +1 -1
- package/dest/abi/decoder.d.ts +6 -6
- package/dest/abi/decoder.d.ts.map +1 -1
- package/dest/abi/decoder.js +23 -24
- package/dest/buffer/buffer32.d.ts +9 -0
- package/dest/buffer/buffer32.d.ts.map +1 -1
- package/dest/buffer/buffer32.js +18 -1
- package/dest/collection/array.d.ts +4 -0
- package/dest/collection/array.d.ts.map +1 -1
- package/dest/collection/array.js +15 -1
- package/dest/config/env_var.d.ts +1 -1
- package/dest/config/env_var.d.ts.map +1 -1
- package/dest/config/index.d.ts +6 -0
- package/dest/config/index.d.ts.map +1 -1
- package/dest/config/index.js +12 -1
- package/dest/crypto/index.d.ts +1 -0
- package/dest/crypto/index.d.ts.map +1 -1
- package/dest/crypto/index.js +2 -1
- package/dest/crypto/keccak/index.d.ts +2 -1
- package/dest/crypto/keccak/index.d.ts.map +1 -1
- package/dest/crypto/keccak/index.js +5 -1
- package/dest/crypto/secp256k1-signer/index.d.ts +3 -0
- package/dest/crypto/secp256k1-signer/index.d.ts.map +1 -0
- package/dest/crypto/secp256k1-signer/index.js +3 -0
- package/dest/crypto/secp256k1-signer/secp256k1_signer.d.ts +24 -0
- package/dest/crypto/secp256k1-signer/secp256k1_signer.d.ts.map +1 -0
- package/dest/crypto/secp256k1-signer/secp256k1_signer.js +31 -0
- package/dest/crypto/secp256k1-signer/utils.d.ts +39 -0
- package/dest/crypto/secp256k1-signer/utils.d.ts.map +1 -0
- package/dest/crypto/secp256k1-signer/utils.js +89 -0
- package/dest/crypto/sha256/index.d.ts +15 -3
- package/dest/crypto/sha256/index.d.ts.map +1 -1
- package/dest/crypto/sha256/index.js +110 -5
- package/dest/decorators/index.d.ts +2 -0
- package/dest/decorators/index.d.ts.map +1 -0
- package/dest/decorators/index.js +2 -0
- package/dest/decorators/memoize.d.ts +2 -0
- package/dest/decorators/memoize.d.ts.map +1 -0
- package/dest/decorators/memoize.js +12 -0
- package/dest/eth-signature/eth_signature.d.ts +55 -0
- package/dest/eth-signature/eth_signature.d.ts.map +1 -0
- package/dest/eth-signature/eth_signature.js +72 -0
- package/dest/eth-signature/index.d.ts +2 -0
- package/dest/eth-signature/index.d.ts.map +1 -0
- package/dest/eth-signature/index.js +2 -0
- package/dest/fields/point.d.ts.map +1 -1
- package/dest/fields/point.js +3 -2
- package/dest/index.d.ts +1 -0
- package/dest/index.d.ts.map +1 -1
- package/dest/index.js +2 -1
- package/dest/serialize/buffer_reader.d.ts +9 -0
- package/dest/serialize/buffer_reader.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.js +18 -1
- package/dest/serialize/serialize.js +2 -2
- package/dest/serialize/types.d.ts +1 -1
- package/dest/serialize/types.d.ts.map +1 -1
- package/dest/serialize/types.js +1 -1
- package/dest/testing/index.d.ts +1 -0
- package/dest/testing/index.d.ts.map +1 -1
- package/dest/testing/index.js +2 -1
- package/dest/testing/port_allocator.d.ts +10 -0
- package/dest/testing/port_allocator.d.ts.map +1 -0
- package/dest/testing/port_allocator.js +32 -0
- package/dest/testing/test_data.js +2 -2
- package/dest/trees/index.d.ts +1 -0
- package/dest/trees/index.d.ts.map +1 -1
- package/dest/trees/index.js +2 -2
- package/dest/trees/unbalanced_merkle_root.d.ts +12 -0
- package/dest/trees/unbalanced_merkle_root.d.ts.map +1 -0
- package/dest/trees/unbalanced_merkle_root.js +52 -0
- package/dest/types/index.d.ts +2 -0
- package/dest/types/index.d.ts.map +1 -1
- package/dest/types/index.js +5 -2
- package/package.json +9 -3
- package/src/abi/abi.ts +14 -0
- package/src/abi/decoder.ts +24 -25
- package/src/buffer/buffer32.ts +18 -0
- package/src/collection/array.ts +15 -0
- package/src/config/env_var.ts +116 -107
- package/src/config/index.ts +12 -0
- package/src/crypto/index.ts +1 -0
- package/src/crypto/keccak/index.ts +6 -1
- package/src/crypto/secp256k1-signer/index.ts +2 -0
- package/src/crypto/secp256k1-signer/secp256k1_signer.ts +38 -0
- package/src/crypto/secp256k1-signer/utils.ts +99 -0
- package/src/crypto/sha256/index.ts +137 -4
- package/src/decorators/index.ts +1 -0
- package/src/decorators/memoize.ts +11 -0
- package/src/eth-signature/eth_signature.ts +94 -0
- package/src/eth-signature/index.ts +1 -0
- package/src/fields/point.ts +2 -1
- package/src/index.ts +1 -0
- package/src/serialize/buffer_reader.ts +20 -0
- package/src/serialize/serialize.ts +1 -1
- package/src/serialize/types.ts +1 -1
- package/src/testing/index.ts +1 -0
- package/src/testing/port_allocator.ts +31 -0
- package/src/testing/test_data.ts +1 -1
- package/src/trees/index.ts +2 -0
- package/src/trees/unbalanced_merkle_root.ts +52 -0
- package/src/types/index.ts +5 -0
|
@@ -1,14 +1,147 @@
|
|
|
1
|
+
/* eslint-disable camelcase */
|
|
1
2
|
import { default as hash } from 'hash.js';
|
|
2
3
|
|
|
3
4
|
import { Fr } from '../../fields/fields.js';
|
|
4
5
|
import { truncateAndPad } from '../../serialize/free_funcs.js';
|
|
5
6
|
import { type Bufferable, serializeToBuffer } from '../../serialize/serialize.js';
|
|
6
7
|
|
|
7
|
-
export
|
|
8
|
+
export function sha256(data: Buffer) {
|
|
9
|
+
return Buffer.from(hash.sha256().update(data).digest());
|
|
10
|
+
}
|
|
8
11
|
|
|
9
|
-
export
|
|
12
|
+
export function sha256Trunc(data: Buffer) {
|
|
13
|
+
return truncateAndPad(sha256(data));
|
|
14
|
+
}
|
|
10
15
|
|
|
11
|
-
export
|
|
16
|
+
export function sha256ToField(data: Bufferable[]) {
|
|
12
17
|
const buffer = serializeToBuffer(data);
|
|
13
18
|
return Fr.fromBuffer(sha256Trunc(buffer));
|
|
14
|
-
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The "SHA256 Compression" operation (component operation of SHA256 "Hash").
|
|
23
|
+
* WARNING: modifies `state` in place (and also returns it)
|
|
24
|
+
*
|
|
25
|
+
* This algorithm is extracted from the hash.js package
|
|
26
|
+
* and modified to take in an initial state to operate on.
|
|
27
|
+
*
|
|
28
|
+
* @param state - The initial state to operate on (modified in-place). 8 u32s.
|
|
29
|
+
* @param inputs - The inputs to compress into the state. 16 u32s.
|
|
30
|
+
* @returns The modified state. 8 u32s.
|
|
31
|
+
*/
|
|
32
|
+
export function sha256Compression(state: Uint32Array, inputs: Uint32Array): Uint32Array {
|
|
33
|
+
if (state.length !== 8) {
|
|
34
|
+
throw new Error('`state` argument to SHA256 compression must be of length 8');
|
|
35
|
+
}
|
|
36
|
+
if (inputs.length !== 16) {
|
|
37
|
+
throw new Error('`inputs` argument to SHA256 compression must be of length 16');
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const W = new Array(64);
|
|
41
|
+
const k = [
|
|
42
|
+
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98,
|
|
43
|
+
0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
|
44
|
+
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8,
|
|
45
|
+
0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
|
46
|
+
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
|
|
47
|
+
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
|
48
|
+
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7,
|
|
49
|
+
0xc67178f2,
|
|
50
|
+
];
|
|
51
|
+
let i = 0;
|
|
52
|
+
for (i = 0; i < 16; i++) {
|
|
53
|
+
W[i] = inputs[i];
|
|
54
|
+
}
|
|
55
|
+
for (i = 16; i < W.length; i++) {
|
|
56
|
+
W[i] = sum32_4(
|
|
57
|
+
W[i - 16],
|
|
58
|
+
W[i - 7],
|
|
59
|
+
g0_256(W[i - 15]), // Rot17, Rot18, Sh3
|
|
60
|
+
g1_256(W[i - 2]), //ROt17, Rot19, Sh10
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let a = state[0];
|
|
65
|
+
let b = state[1];
|
|
66
|
+
let c = state[2];
|
|
67
|
+
let d = state[3];
|
|
68
|
+
let e = state[4];
|
|
69
|
+
let f = state[5];
|
|
70
|
+
let g = state[6];
|
|
71
|
+
let h = state[7];
|
|
72
|
+
|
|
73
|
+
for (let i = 0; i < 64; i++) {
|
|
74
|
+
const T1 = sum32_5(
|
|
75
|
+
h,
|
|
76
|
+
s1_256(e), // Rot6, Rot11, Rot25
|
|
77
|
+
ch32(e, f, g),
|
|
78
|
+
k[i],
|
|
79
|
+
W[i],
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
const T2 = sum32(
|
|
83
|
+
s0_256(a), // Rot2, Rot13, Rot22
|
|
84
|
+
maj32(a, b, c),
|
|
85
|
+
);
|
|
86
|
+
h = g;
|
|
87
|
+
g = f;
|
|
88
|
+
f = e;
|
|
89
|
+
e = sum32(d, T1);
|
|
90
|
+
d = c;
|
|
91
|
+
c = b;
|
|
92
|
+
b = a;
|
|
93
|
+
a = sum32(T1, T2);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
state[0] = sum32(state[0], a);
|
|
97
|
+
state[1] = sum32(state[1], b);
|
|
98
|
+
state[2] = sum32(state[2], c);
|
|
99
|
+
state[3] = sum32(state[3], d);
|
|
100
|
+
state[4] = sum32(state[4], e);
|
|
101
|
+
state[5] = sum32(state[5], f);
|
|
102
|
+
state[6] = sum32(state[6], g);
|
|
103
|
+
state[7] = sum32(state[7], h);
|
|
104
|
+
return state;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// SHA256 HELPER FUNCTIONS (from hash.js package)
|
|
108
|
+
|
|
109
|
+
function rotr32(w: number, b: number) {
|
|
110
|
+
return (w >>> b) | (w << (32 - b));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function sum32(a: number, b: number) {
|
|
114
|
+
return (a + b) >>> 0;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function sum32_4(a: number, b: number, c: number, d: number) {
|
|
118
|
+
return (a + b + c + d) >>> 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function sum32_5(a: number, b: number, c: number, d: number, e: number) {
|
|
122
|
+
return (a + b + c + d + e) >>> 0;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function ch32(x: number, y: number, z: number) {
|
|
126
|
+
return (x & y) ^ (~x & z);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function maj32(x: number, y: number, z: number) {
|
|
130
|
+
return (x & y) ^ (x & z) ^ (y & z);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function s0_256(x: number) {
|
|
134
|
+
return rotr32(x, 2) ^ rotr32(x, 13) ^ rotr32(x, 22);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function s1_256(x: number) {
|
|
138
|
+
return rotr32(x, 6) ^ rotr32(x, 11) ^ rotr32(x, 25);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function g0_256(x: number) {
|
|
142
|
+
return rotr32(x, 7) ^ rotr32(x, 18) ^ (x >>> 3);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function g1_256(x: number) {
|
|
146
|
+
return rotr32(x, 17) ^ rotr32(x, 19) ^ (x >>> 10);
|
|
147
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './memoize.js';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export function memoize<This extends object, Result>(fn: () => Result, context: ClassMethodDecoratorContext) {
|
|
2
|
+
return function (this: This) {
|
|
3
|
+
const key = `__${String(context.name)}_value`;
|
|
4
|
+
const thisWithKey = this as { [key: string]: Result };
|
|
5
|
+
if (!(key in this)) {
|
|
6
|
+
const result = fn.call(this);
|
|
7
|
+
thisWithKey[key] = result;
|
|
8
|
+
}
|
|
9
|
+
return thisWithKey[key];
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Buffer32 } from '@aztec/foundation/buffer';
|
|
2
|
+
import { BufferReader, serializeToBuffer } from '@aztec/foundation/serialize';
|
|
3
|
+
|
|
4
|
+
/**Viem Signature
|
|
5
|
+
*
|
|
6
|
+
* A version of the Signature class that uses `0x${string}` values for r and s rather than
|
|
7
|
+
* Buffer32s
|
|
8
|
+
*/
|
|
9
|
+
export type ViemSignature = {
|
|
10
|
+
r: `0x${string}`;
|
|
11
|
+
s: `0x${string}`;
|
|
12
|
+
v: number;
|
|
13
|
+
isEmpty: boolean;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Signature
|
|
18
|
+
*
|
|
19
|
+
* Contains a signature split into it's primary components (r,s,v)
|
|
20
|
+
*/
|
|
21
|
+
export class Signature {
|
|
22
|
+
constructor(
|
|
23
|
+
/** The r value of the signature */
|
|
24
|
+
public readonly r: Buffer32,
|
|
25
|
+
/** The s value of the signature */
|
|
26
|
+
public readonly s: Buffer32,
|
|
27
|
+
/** The v value of the signature */
|
|
28
|
+
public readonly v: number,
|
|
29
|
+
/** Does this struct store an empty signature */
|
|
30
|
+
public readonly isEmpty: boolean = false,
|
|
31
|
+
) {}
|
|
32
|
+
|
|
33
|
+
static fromBuffer(buf: Buffer | BufferReader): Signature {
|
|
34
|
+
const reader = BufferReader.asReader(buf);
|
|
35
|
+
|
|
36
|
+
const r = reader.readObject(Buffer32);
|
|
37
|
+
const s = reader.readObject(Buffer32);
|
|
38
|
+
const v = reader.readNumber();
|
|
39
|
+
|
|
40
|
+
const isEmpty = r.isZero() && s.isZero();
|
|
41
|
+
|
|
42
|
+
return new Signature(r, s, v, isEmpty);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A seperate method exists for this as when signing locally with viem, as when
|
|
47
|
+
* parsing from viem, we can expect the v value to be a u8, rather than our
|
|
48
|
+
* default serialization of u32
|
|
49
|
+
*/
|
|
50
|
+
static from0xString(sig: `0x${string}`): Signature {
|
|
51
|
+
const buf = Buffer.from(sig.slice(2), 'hex');
|
|
52
|
+
const reader = BufferReader.asReader(buf);
|
|
53
|
+
|
|
54
|
+
const r = reader.readObject(Buffer32);
|
|
55
|
+
const s = reader.readObject(Buffer32);
|
|
56
|
+
const v = parseInt(sig.slice(2 + 64 * 2), 16);
|
|
57
|
+
|
|
58
|
+
const isEmpty = r.isZero() && s.isZero();
|
|
59
|
+
|
|
60
|
+
return new Signature(r, s, v, isEmpty);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
static random(): Signature {
|
|
64
|
+
return new Signature(Buffer32.random(), Buffer32.random(), Math.floor(Math.random() * 2), false);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
static empty(): Signature {
|
|
68
|
+
return new Signature(Buffer32.ZERO, Buffer32.ZERO, 0, true);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
equals(other: Signature): boolean {
|
|
72
|
+
return this.r.equals(other.r) && this.s.equals(other.s) && this.v === other.v && this.isEmpty === other.isEmpty;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
toBuffer(): Buffer {
|
|
76
|
+
return serializeToBuffer([this.r, this.s, this.v]);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
to0xString(): `0x${string}` {
|
|
80
|
+
return `0x${this.r.toString()}${this.s.toString()}${this.v.toString(16)}`;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Return the signature with `0x${string}` encodings for r and s
|
|
85
|
+
*/
|
|
86
|
+
toViemSignature(): ViemSignature {
|
|
87
|
+
return {
|
|
88
|
+
r: this.r.to0xString(),
|
|
89
|
+
s: this.s.to0xString(),
|
|
90
|
+
v: this.v,
|
|
91
|
+
isEmpty: this.isEmpty,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './eth_signature.js';
|
package/src/fields/point.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { toBigIntBE } from '../bigint-buffer/index.js';
|
|
2
|
-
import { poseidon2Hash
|
|
2
|
+
import { poseidon2Hash } from '../crypto/poseidon/index.js';
|
|
3
|
+
import { randomBoolean } from '../crypto/random/index.js';
|
|
3
4
|
import { BufferReader, FieldReader, serializeToBuffer } from '../serialize/index.js';
|
|
4
5
|
import { Fr } from './fields.js';
|
|
5
6
|
|
package/src/index.ts
CHANGED
|
@@ -70,6 +70,26 @@ export class BufferReader {
|
|
|
70
70
|
return result as Tuple<number, N>;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Reads a 256-bit unsigned integer from the buffer at the current index position.
|
|
75
|
+
* Updates the index position by 32 bytes after reading the number.
|
|
76
|
+
*
|
|
77
|
+
* Assumes the number is stored in big-endian format.
|
|
78
|
+
*
|
|
79
|
+
* @returns The read 256 bit value as a bigint.
|
|
80
|
+
*/
|
|
81
|
+
public readUInt256(): bigint {
|
|
82
|
+
this.#rangeCheck(32);
|
|
83
|
+
|
|
84
|
+
let result = BigInt(0);
|
|
85
|
+
for (let i = 0; i < 32; i++) {
|
|
86
|
+
result = (result << BigInt(8)) | BigInt(this.buffer[this.index + i]);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
this.index += 32;
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
|
|
73
93
|
/**
|
|
74
94
|
* Reads a 16-bit unsigned integer from the buffer at the current index position.
|
|
75
95
|
* Updates the index position by 2 bytes after reading the number.
|
|
@@ -242,7 +242,7 @@ export function toFriendlyJSON(obj: object): string {
|
|
|
242
242
|
).toFriendlyJSON
|
|
243
243
|
) {
|
|
244
244
|
return value.toFriendlyJSON();
|
|
245
|
-
} else if (value && value.type && ['Fr', 'Fq', 'AztecAddress'].includes(value.type)) {
|
|
245
|
+
} else if (value && value.type && ['Fr', 'Fq', 'AztecAddress', 'EthAddress'].includes(value.type)) {
|
|
246
246
|
return value.value;
|
|
247
247
|
} else {
|
|
248
248
|
return value;
|
package/src/serialize/types.ts
CHANGED
|
@@ -35,6 +35,6 @@ type MapTuple<T extends any[], F extends (item: any) => any> = {
|
|
|
35
35
|
* @see https://github.com/microsoft/TypeScript/issues/29841.
|
|
36
36
|
* @param array - A tuple array.
|
|
37
37
|
*/
|
|
38
|
-
export function mapTuple<T extends any[], F extends (item:
|
|
38
|
+
export function mapTuple<T extends any[], F extends (item: T[number]) => any>(tuple: T, fn: F): MapTuple<T, F> {
|
|
39
39
|
return tuple.map(fn) as MapTuple<T, F>;
|
|
40
40
|
}
|
package/src/testing/index.ts
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import net from 'net';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Get a random port that is free to use.
|
|
5
|
+
* Returns undefined if it fails to get a port.
|
|
6
|
+
*
|
|
7
|
+
* @attribution: adapted from https://stackoverflow.com/a/71178451
|
|
8
|
+
*
|
|
9
|
+
* @returns a random port that is free to use.
|
|
10
|
+
*/
|
|
11
|
+
export function getRandomPort(): Promise<number | undefined> {
|
|
12
|
+
return new Promise(resolve => {
|
|
13
|
+
const server = net.createServer();
|
|
14
|
+
server.listen(0, () => {
|
|
15
|
+
const address = server.address();
|
|
16
|
+
if (address && typeof address === 'object' && 'port' in address) {
|
|
17
|
+
const port = address.port;
|
|
18
|
+
server.close(() => {
|
|
19
|
+
resolve(port);
|
|
20
|
+
});
|
|
21
|
+
} else {
|
|
22
|
+
server.close(() => {
|
|
23
|
+
resolve(undefined);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
server.on('error', () => {
|
|
28
|
+
resolve(undefined);
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
package/src/testing/test_data.ts
CHANGED
|
@@ -8,7 +8,7 @@ const testData: { [key: string]: unknown[] } = {};
|
|
|
8
8
|
|
|
9
9
|
/** Returns whether test data generation is enabled */
|
|
10
10
|
export function isGenerateTestDataEnabled() {
|
|
11
|
-
return process.env.AZTEC_GENERATE_TEST_DATA
|
|
11
|
+
return ['1', 'true'].includes(process.env.AZTEC_GENERATE_TEST_DATA ?? '') && typeof expect !== 'undefined';
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/** Pushes test data with the given name, only if test data generation is enabled. */
|
package/src/trees/index.ts
CHANGED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
2
|
+
import { sha256Trunc } from '@aztec/foundation/crypto';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Computes the merkle root for an unbalanced tree.
|
|
6
|
+
*
|
|
7
|
+
* @dev Adapted from proving-state.ts -> findMergeLevel and unbalanced_tree.ts.
|
|
8
|
+
* Calculates the tree upwards layer by layer until we reach the root.
|
|
9
|
+
* The L1 calculation instead computes the tree from right to left (slightly cheaper gas).
|
|
10
|
+
* TODO: A more thorough investigation of which method is cheaper, then use that method everywhere.
|
|
11
|
+
*/
|
|
12
|
+
export function computeUnbalancedMerkleRoot(leaves: Buffer[], emptyLeaf?: Buffer, hasher = sha256Trunc): Buffer {
|
|
13
|
+
// Pad leaves to 2
|
|
14
|
+
if (leaves.length < 2) {
|
|
15
|
+
if (emptyLeaf === undefined) {
|
|
16
|
+
throw new Error('Cannot compute a Merkle root with less than 2 leaves');
|
|
17
|
+
} else {
|
|
18
|
+
leaves = padArrayEnd(leaves, emptyLeaf, 2);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const depth = Math.ceil(Math.log2(leaves.length));
|
|
23
|
+
let [layerWidth, nodeToShift] =
|
|
24
|
+
leaves.length & 1 ? [leaves.length - 1, leaves[leaves.length - 1]] : [leaves.length, Buffer.alloc(0)];
|
|
25
|
+
// Allocate this layer's leaves and init the next layer up
|
|
26
|
+
let thisLayer = leaves.slice(0, layerWidth);
|
|
27
|
+
let nextLayer = [];
|
|
28
|
+
for (let i = 0; i < depth; i++) {
|
|
29
|
+
for (let j = 0; j < layerWidth; j += 2) {
|
|
30
|
+
// Store the hash of each pair one layer up
|
|
31
|
+
nextLayer[j / 2] = hasher(Buffer.concat([thisLayer[j], thisLayer[j + 1]]));
|
|
32
|
+
}
|
|
33
|
+
layerWidth /= 2;
|
|
34
|
+
if (layerWidth & 1) {
|
|
35
|
+
if (nodeToShift.length) {
|
|
36
|
+
// If the next layer has odd length, and we have a node that needs to be shifted up, add it here
|
|
37
|
+
nextLayer.push(nodeToShift);
|
|
38
|
+
layerWidth += 1;
|
|
39
|
+
nodeToShift = Buffer.alloc(0);
|
|
40
|
+
} else {
|
|
41
|
+
// If we don't have a node waiting to be shifted, store the next layer's final node to be shifted
|
|
42
|
+
layerWidth -= 1;
|
|
43
|
+
nodeToShift = nextLayer[layerWidth];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// reset the layers
|
|
47
|
+
thisLayer = nextLayer;
|
|
48
|
+
nextLayer = [];
|
|
49
|
+
}
|
|
50
|
+
// return the root
|
|
51
|
+
return thisLayer[0];
|
|
52
|
+
}
|
package/src/types/index.ts
CHANGED
|
@@ -15,3 +15,8 @@ export type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
|
|
|
15
15
|
|
|
16
16
|
/** Removes readonly modifiers for a type. */
|
|
17
17
|
export type Writeable<T> = { -readonly [P in keyof T]: T[P] };
|
|
18
|
+
|
|
19
|
+
/** Removes readonly modifiers for an object. */
|
|
20
|
+
export function unfreeze<T>(obj: T): Writeable<T> {
|
|
21
|
+
return obj as Writeable<T>;
|
|
22
|
+
}
|