@aztec/foundation 0.23.0 → 0.26.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/dest/abi/abi.d.ts +1 -1
- package/dest/abi/abi.d.ts.map +1 -1
- package/dest/abi/event_selector.d.ts +45 -0
- package/dest/abi/event_selector.d.ts.map +1 -0
- package/dest/abi/event_selector.js +60 -0
- package/dest/abi/function_selector.d.ts +69 -0
- package/dest/abi/function_selector.d.ts.map +1 -0
- package/dest/abi/function_selector.js +86 -0
- 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/selector.d.ts +4 -106
- package/dest/abi/selector.d.ts.map +1 -1
- package/dest/abi/selector.js +8 -143
- package/dest/abi/utils.js +3 -3
- package/dest/array/array.d.ts +8 -0
- package/dest/array/array.d.ts.map +1 -1
- package/dest/array/array.js +26 -1
- package/dest/aztec-address/index.d.ts +8 -1
- package/dest/aztec-address/index.d.ts.map +1 -1
- package/dest/aztec-address/index.js +16 -2
- 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/pedersen/pedersen.wasm.d.ts +2 -1
- package/dest/crypto/pedersen/pedersen.wasm.d.ts.map +1 -1
- package/dest/crypto/pedersen/pedersen.wasm.js +7 -6
- package/dest/crypto/poseidon/index.d.ts +8 -0
- package/dest/crypto/poseidon/index.d.ts.map +1 -0
- package/dest/crypto/poseidon/index.js +12 -0
- package/dest/eth-address/index.d.ts +3 -0
- package/dest/eth-address/index.d.ts.map +1 -1
- package/dest/eth-address/index.js +5 -2
- package/dest/fields/fields.d.ts +19 -0
- package/dest/fields/fields.d.ts.map +1 -1
- package/dest/fields/fields.js +11 -4
- package/dest/json-rpc/client/json_rpc_client.js +2 -2
- package/dest/serialize/buffer_reader.d.ts +15 -0
- package/dest/serialize/buffer_reader.d.ts.map +1 -1
- package/dest/serialize/buffer_reader.js +18 -1
- package/dest/serialize/serialize.d.ts +3 -5
- package/dest/serialize/serialize.d.ts.map +1 -1
- package/dest/serialize/serialize.js +17 -8
- package/package.json +2 -2
- package/src/abi/abi.ts +337 -0
- package/src/abi/buffer.ts +36 -0
- package/src/abi/decoder.ts +176 -0
- package/src/abi/encoder.ts +143 -0
- package/src/abi/event_selector.ts +73 -0
- package/src/abi/function_selector.ts +122 -0
- package/src/abi/index.ts +7 -0
- package/src/abi/selector.ts +63 -0
- package/src/abi/utils.ts +50 -0
- package/src/array/array.ts +119 -0
- package/src/array/index.ts +1 -0
- package/src/async-map/index.ts +18 -0
- package/src/aztec-address/index.ts +56 -0
- package/src/bigint-buffer/index.ts +87 -0
- package/src/collection/array.ts +64 -0
- package/src/collection/index.ts +1 -0
- package/src/committable/committable.ts +46 -0
- package/src/committable/index.ts +1 -0
- package/src/crypto/index.ts +17 -0
- package/src/crypto/keccak/index.ts +33 -0
- package/src/crypto/pedersen/index.ts +1 -0
- package/src/crypto/pedersen/pedersen.elliptic.ts +584 -0
- package/src/crypto/pedersen/pedersen.noble.ts +573 -0
- package/src/crypto/pedersen/pedersen.wasm.ts +46 -0
- package/src/crypto/poseidon/index.ts +17 -0
- package/src/crypto/random/index.ts +42 -0
- package/src/crypto/sha256/index.ts +3 -0
- package/src/errors/index.ts +6 -0
- package/src/eth-address/index.ts +239 -0
- package/src/fields/coordinate.ts +104 -0
- package/src/fields/fields.ts +338 -0
- package/src/fields/index.ts +3 -0
- package/src/fields/point.ts +145 -0
- package/src/fifo/bounded_serial_queue.ts +100 -0
- package/src/fifo/index.ts +4 -0
- package/src/fifo/memory_fifo.ts +118 -0
- package/src/fifo/semaphore.ts +33 -0
- package/src/fifo/serial_queue.ts +81 -0
- package/src/index.ts +29 -0
- package/src/json-rpc/README.md +55 -0
- package/src/json-rpc/class_converter.ts +213 -0
- package/src/json-rpc/client/index.ts +1 -0
- package/src/json-rpc/client/json_rpc_client.ts +147 -0
- package/src/json-rpc/convert.ts +163 -0
- package/src/json-rpc/fixtures/class_a.ts +15 -0
- package/src/json-rpc/fixtures/class_b.ts +15 -0
- package/src/json-rpc/fixtures/test_state.ts +59 -0
- package/src/json-rpc/index.ts +8 -0
- package/src/json-rpc/js_utils.ts +20 -0
- package/src/json-rpc/server/index.ts +2 -0
- package/src/json-rpc/server/json_proxy.ts +60 -0
- package/src/json-rpc/server/json_rpc_server.ts +269 -0
- package/src/log/console.ts +39 -0
- package/src/log/debug.ts +83 -0
- package/src/log/index.ts +5 -0
- package/src/log/log_fn.ts +5 -0
- package/src/log/log_history.ts +44 -0
- package/src/log/logger.ts +137 -0
- package/src/mutex/index.ts +83 -0
- package/src/mutex/mutex_database.ts +12 -0
- package/src/noir/index.ts +1 -0
- package/src/noir/noir_package_config.ts +54 -0
- package/src/retry/index.ts +99 -0
- package/src/running-promise/index.ts +60 -0
- package/src/serialize/buffer_reader.ts +309 -0
- package/src/serialize/field_reader.ts +143 -0
- package/src/serialize/free_funcs.ts +147 -0
- package/src/serialize/index.ts +5 -0
- package/src/serialize/serialize.ts +310 -0
- package/src/serialize/types.ts +40 -0
- package/src/sleep/index.ts +71 -0
- package/src/testing/index.ts +1 -0
- package/src/testing/test_data.ts +36 -0
- package/src/timer/elapsed.ts +23 -0
- package/src/timer/index.ts +3 -0
- package/src/timer/timeout.ts +64 -0
- package/src/timer/timer.ts +48 -0
- package/src/transport/browser/index.ts +4 -0
- package/src/transport/browser/message_port_socket.ts +48 -0
- package/src/transport/browser/shared_worker_connector.ts +21 -0
- package/src/transport/browser/shared_worker_listener.ts +53 -0
- package/src/transport/browser/worker_connector.ts +30 -0
- package/src/transport/browser/worker_listener.ts +54 -0
- package/src/transport/dispatch/create_dispatch_fn.ts +35 -0
- package/src/transport/dispatch/create_dispatch_proxy.ts +141 -0
- package/src/transport/dispatch/messages.ts +58 -0
- package/src/transport/index.ts +11 -0
- package/src/transport/interface/connector.ts +9 -0
- package/src/transport/interface/listener.ts +16 -0
- package/src/transport/interface/socket.ts +15 -0
- package/src/transport/interface/transferable.ts +125 -0
- package/src/transport/node/index.ts +2 -0
- package/src/transport/node/node_connector.ts +30 -0
- package/src/transport/node/node_connector_socket.ts +52 -0
- package/src/transport/node/node_listener.ts +34 -0
- package/src/transport/node/node_listener_socket.ts +48 -0
- package/src/transport/transport_client.ts +131 -0
- package/src/transport/transport_server.ts +108 -0
- package/src/trees/index.ts +54 -0
- package/src/types/index.ts +8 -0
- package/src/url/index.ts +73 -0
- package/src/wasm/README.md +6 -0
- package/src/wasm/empty_wasi_sdk.ts +166 -0
- package/src/wasm/fixtures/gcd.wasm +0 -0
- package/src/wasm/fixtures/gcd.wat +27 -0
- package/src/wasm/index.ts +1 -0
- package/src/wasm/wasm_module.ts +260 -0
- package/src/worker/browser/index.ts +2 -0
- package/src/worker/browser/start_web_module.ts +23 -0
- package/src/worker/browser/web_data_store.ts +38 -0
- package/src/worker/browser/web_worker.ts +24 -0
- package/src/worker/data_store.ts +19 -0
- package/src/worker/index.ts +2 -0
- package/src/worker/node/index.ts +2 -0
- package/src/worker/node/node_data_store.ts +27 -0
- package/src/worker/node/node_worker.ts +22 -0
- package/src/worker/node/start_node_module.ts +29 -0
- package/src/worker/wasm_worker.ts +7 -0
- package/src/worker/worker_pool.ts +73 -0
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { AztecAddress } from '../aztec-address/index.js';
|
|
2
|
+
import { Fr } from '../fields/index.js';
|
|
3
|
+
import { ABIParameter, type ABIType, ABIVariable, FunctionArtifact } from './abi.js';
|
|
4
|
+
import { isAztecAddressStruct } from './utils.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The type of our decoded ABI.
|
|
8
|
+
*/
|
|
9
|
+
export type DecodedReturn = bigint | boolean | AztecAddress | DecodedReturn[] | { [key: string]: DecodedReturn };
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Decodes return values from a function call.
|
|
13
|
+
* Missing support for integer and string.
|
|
14
|
+
*/
|
|
15
|
+
class ReturnValuesDecoder {
|
|
16
|
+
constructor(private artifact: FunctionArtifact, private flattened: Fr[]) {}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Decodes a single return value from field to the given type.
|
|
20
|
+
* @param abiType - The type of the return value.
|
|
21
|
+
* @returns The decoded return value.
|
|
22
|
+
*/
|
|
23
|
+
private decodeReturn(abiType: ABIType): DecodedReturn {
|
|
24
|
+
switch (abiType.kind) {
|
|
25
|
+
case 'field':
|
|
26
|
+
return this.getNextField().toBigInt();
|
|
27
|
+
case 'integer':
|
|
28
|
+
if (abiType.sign === 'signed') {
|
|
29
|
+
throw new Error('Unsupported type: signed integer');
|
|
30
|
+
}
|
|
31
|
+
return this.getNextField().toBigInt();
|
|
32
|
+
case 'boolean':
|
|
33
|
+
return !this.getNextField().isZero();
|
|
34
|
+
case 'array': {
|
|
35
|
+
const array = [];
|
|
36
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
37
|
+
array.push(this.decodeReturn(abiType.type));
|
|
38
|
+
}
|
|
39
|
+
return array;
|
|
40
|
+
}
|
|
41
|
+
case 'struct': {
|
|
42
|
+
const struct: { [key: string]: DecodedReturn } = {};
|
|
43
|
+
if (isAztecAddressStruct(abiType)) {
|
|
44
|
+
return new AztecAddress(this.getNextField().toBuffer());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
for (const field of abiType.fields) {
|
|
48
|
+
struct[field.name] = this.decodeReturn(field.type);
|
|
49
|
+
}
|
|
50
|
+
return struct;
|
|
51
|
+
}
|
|
52
|
+
case 'string': {
|
|
53
|
+
const array = [];
|
|
54
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
55
|
+
array.push(this.getNextField().toBigInt());
|
|
56
|
+
}
|
|
57
|
+
return array;
|
|
58
|
+
}
|
|
59
|
+
default:
|
|
60
|
+
throw new Error(`Unsupported type: ${abiType}`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Gets the next field in the flattened return values.
|
|
66
|
+
* @returns The next field in the flattened return values.
|
|
67
|
+
*/
|
|
68
|
+
private getNextField(): Fr {
|
|
69
|
+
const field = this.flattened.shift();
|
|
70
|
+
if (!field) {
|
|
71
|
+
throw new Error('Not enough return values');
|
|
72
|
+
}
|
|
73
|
+
return field;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Decodes all the return values for the given function ABI.
|
|
78
|
+
* Aztec.nr support only single return value
|
|
79
|
+
* The return value can however be simple types, structs or arrays
|
|
80
|
+
* @returns The decoded return values.
|
|
81
|
+
*/
|
|
82
|
+
public decode(): DecodedReturn {
|
|
83
|
+
if (this.artifact.returnTypes.length > 1) {
|
|
84
|
+
throw new Error('Multiple return values not supported');
|
|
85
|
+
}
|
|
86
|
+
if (this.artifact.returnTypes.length === 0) {
|
|
87
|
+
return [];
|
|
88
|
+
}
|
|
89
|
+
return this.decodeReturn(this.artifact.returnTypes[0]);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Decodes return values from a function call.
|
|
95
|
+
* @param abi - The ABI entry of the function.
|
|
96
|
+
* @param returnValues - The decoded return values.
|
|
97
|
+
* @returns
|
|
98
|
+
*/
|
|
99
|
+
export function decodeReturnValues(abi: FunctionArtifact, returnValues: Fr[]) {
|
|
100
|
+
return new ReturnValuesDecoder(abi, returnValues.slice()).decode();
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Decodes the signature of a function from the name and parameters.
|
|
105
|
+
*/
|
|
106
|
+
export class FunctionSignatureDecoder {
|
|
107
|
+
private separator: string;
|
|
108
|
+
constructor(private name: string, private parameters: ABIParameter[], private includeNames = false) {
|
|
109
|
+
this.separator = includeNames ? ', ' : ',';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Decodes a single function parameter type for the function signature.
|
|
114
|
+
* @param param - The parameter type to decode.
|
|
115
|
+
* @returns A string representing the parameter type.
|
|
116
|
+
*/
|
|
117
|
+
private getParameterType(param: ABIType): string {
|
|
118
|
+
switch (param.kind) {
|
|
119
|
+
case 'field':
|
|
120
|
+
return 'Field';
|
|
121
|
+
case 'integer':
|
|
122
|
+
if (param.sign === 'signed') {
|
|
123
|
+
throw new Error('Unsupported type: signed integer');
|
|
124
|
+
}
|
|
125
|
+
return `u${param.width}`;
|
|
126
|
+
case 'boolean':
|
|
127
|
+
return 'bool';
|
|
128
|
+
case 'array':
|
|
129
|
+
return `[${this.getParameterType(param.type)};${param.length}]`;
|
|
130
|
+
case 'string':
|
|
131
|
+
return `str<${param.length}>`;
|
|
132
|
+
case 'struct':
|
|
133
|
+
return `(${param.fields.map(field => `${this.decodeParameter(field)}`).join(this.separator)})`;
|
|
134
|
+
default:
|
|
135
|
+
throw new Error(`Unsupported type: ${param}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Decodes a single function parameter for the function signature.
|
|
141
|
+
* @param param - The parameter to decode.
|
|
142
|
+
* @returns A string representing the parameter type and optionally its name.
|
|
143
|
+
*/
|
|
144
|
+
private decodeParameter(param: ABIVariable): string {
|
|
145
|
+
const type = this.getParameterType(param.type);
|
|
146
|
+
return this.includeNames ? `${param.name}: ${type}` : type;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Decodes all the parameters and build the function signature
|
|
151
|
+
* @returns The function signature.
|
|
152
|
+
*/
|
|
153
|
+
public decode(): string {
|
|
154
|
+
return `${this.name}(${this.parameters.map(param => this.decodeParameter(param)).join(this.separator)})`;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Decodes a function signature from the name and parameters.
|
|
160
|
+
* @param name - The name of the function.
|
|
161
|
+
* @param parameters - The parameters of the function.
|
|
162
|
+
* @returns - The function signature.
|
|
163
|
+
*/
|
|
164
|
+
export function decodeFunctionSignature(name: string, parameters: ABIParameter[]) {
|
|
165
|
+
return new FunctionSignatureDecoder(name, parameters).decode();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Decodes a function signature from the name and parameters including parameter names.
|
|
170
|
+
* @param name - The name of the function.
|
|
171
|
+
* @param parameters - The parameters of the function.
|
|
172
|
+
* @returns - The user-friendly function signature.
|
|
173
|
+
*/
|
|
174
|
+
export function decodeFunctionSignatureWithParameterNames(name: string, parameters: ABIParameter[]) {
|
|
175
|
+
return new FunctionSignatureDecoder(name, parameters, true).decode();
|
|
176
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Fr } from '../fields/index.js';
|
|
2
|
+
import { ABIType, FunctionAbi } from './abi.js';
|
|
3
|
+
import { isAddressStruct, isFunctionSelectorStruct, isWrappedFieldStruct } from './utils.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Encodes arguments for a function call.
|
|
7
|
+
* Missing support for integer and string.
|
|
8
|
+
*/
|
|
9
|
+
class ArgumentEncoder {
|
|
10
|
+
private flattened: Fr[] = [];
|
|
11
|
+
|
|
12
|
+
constructor(private abi: FunctionAbi, private args: any[]) {}
|
|
13
|
+
|
|
14
|
+
static typeSize(abiType: ABIType): number {
|
|
15
|
+
switch (abiType.kind) {
|
|
16
|
+
case 'field':
|
|
17
|
+
case 'boolean':
|
|
18
|
+
case 'integer':
|
|
19
|
+
return 1;
|
|
20
|
+
case 'string':
|
|
21
|
+
return abiType.length;
|
|
22
|
+
case 'array':
|
|
23
|
+
return abiType.length * ArgumentEncoder.typeSize(abiType.type);
|
|
24
|
+
case 'struct':
|
|
25
|
+
return abiType.fields.reduce((acc, field) => acc + ArgumentEncoder.typeSize(field.type), 0);
|
|
26
|
+
default: {
|
|
27
|
+
const exhaustiveCheck: never = abiType;
|
|
28
|
+
throw new Error(`Unhandled abi type: ${exhaustiveCheck}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Encodes a single argument from the given type to field.
|
|
35
|
+
* @param abiType - The abi type of the argument.
|
|
36
|
+
* @param arg - The value to encode.
|
|
37
|
+
* @param name - Name.
|
|
38
|
+
*/
|
|
39
|
+
private encodeArgument(abiType: ABIType, arg: any, name?: string) {
|
|
40
|
+
if (arg === undefined || arg == null) {
|
|
41
|
+
throw new Error(`Undefined argument ${name ?? 'unnamed'} of type ${abiType.kind}`);
|
|
42
|
+
}
|
|
43
|
+
switch (abiType.kind) {
|
|
44
|
+
case 'field':
|
|
45
|
+
if (typeof arg === 'number') {
|
|
46
|
+
this.flattened.push(new Fr(BigInt(arg)));
|
|
47
|
+
} else if (typeof arg === 'bigint') {
|
|
48
|
+
this.flattened.push(new Fr(arg));
|
|
49
|
+
} else if (typeof arg === 'boolean') {
|
|
50
|
+
this.flattened.push(new Fr(arg ? 1n : 0n));
|
|
51
|
+
} else if (typeof arg === 'object') {
|
|
52
|
+
if (Buffer.isBuffer(arg)) {
|
|
53
|
+
this.flattened.push(Fr.fromBuffer(arg));
|
|
54
|
+
} else if (typeof arg.toField === 'function') {
|
|
55
|
+
this.flattened.push(arg.toField());
|
|
56
|
+
} else {
|
|
57
|
+
throw new Error(`Argument for ${name} cannot be serialized to a field`);
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
throw new Error(`Invalid argument "${arg}" of type ${abiType.kind}`);
|
|
61
|
+
}
|
|
62
|
+
break;
|
|
63
|
+
case 'boolean':
|
|
64
|
+
this.flattened.push(new Fr(arg ? 1n : 0n));
|
|
65
|
+
break;
|
|
66
|
+
case 'array':
|
|
67
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
68
|
+
this.encodeArgument(abiType.type, arg[i], `${name}[${i}]`);
|
|
69
|
+
}
|
|
70
|
+
break;
|
|
71
|
+
case 'string':
|
|
72
|
+
for (let i = 0; i < abiType.length; i += 1) {
|
|
73
|
+
// If the string is shorter than the defined length, pad it with 0s.
|
|
74
|
+
const toInsert = i < arg.length ? BigInt((arg as string).charCodeAt(i)) : 0n;
|
|
75
|
+
this.flattened.push(new Fr(toInsert));
|
|
76
|
+
}
|
|
77
|
+
break;
|
|
78
|
+
case 'struct': {
|
|
79
|
+
// If the abi expects a struct like { address: Field } and the supplied arg does not have
|
|
80
|
+
// an address field in it, we try to encode it as if it were a field directly.
|
|
81
|
+
const isAddress = isAddressStruct(abiType);
|
|
82
|
+
if (isAddress && typeof arg.address === 'undefined' && typeof arg.inner === 'undefined') {
|
|
83
|
+
this.encodeArgument({ kind: 'field' }, arg, `${name}.inner`);
|
|
84
|
+
break;
|
|
85
|
+
}
|
|
86
|
+
// Or if the supplied argument does have an address field in it, like a CompleteAddress,
|
|
87
|
+
// we encode it directly as a field.
|
|
88
|
+
if (isAddress && typeof arg.address !== 'undefined') {
|
|
89
|
+
this.encodeArgument({ kind: 'field' }, arg.address, `${name}.address`);
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
if (isFunctionSelectorStruct(abiType)) {
|
|
93
|
+
this.encodeArgument({ kind: 'integer', sign: 'unsigned', width: 32 }, arg.value ?? arg, `${name}.inner`);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
if (isWrappedFieldStruct(abiType)) {
|
|
97
|
+
this.encodeArgument({ kind: 'field' }, arg.inner ?? arg, `${name}.inner`);
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
for (const field of abiType.fields) {
|
|
101
|
+
this.encodeArgument(field.type, arg[field.name], `${name}.${field.name}`);
|
|
102
|
+
}
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
case 'integer':
|
|
106
|
+
this.flattened.push(new Fr(arg));
|
|
107
|
+
break;
|
|
108
|
+
default:
|
|
109
|
+
throw new Error(`Unsupported type: ${abiType}`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Encodes all the arguments for the given function ABI.
|
|
115
|
+
* @returns The encoded arguments.
|
|
116
|
+
*/
|
|
117
|
+
public encode() {
|
|
118
|
+
for (let i = 0; i < this.abi.parameters.length; i += 1) {
|
|
119
|
+
const parameterAbi = this.abi.parameters[i];
|
|
120
|
+
this.encodeArgument(parameterAbi.type, this.args[i], parameterAbi.name);
|
|
121
|
+
}
|
|
122
|
+
return this.flattened;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Encodes all the arguments for a function call.
|
|
128
|
+
* @param abi - The function ABI entry.
|
|
129
|
+
* @param args - The arguments to encode.
|
|
130
|
+
* @returns The encoded arguments.
|
|
131
|
+
*/
|
|
132
|
+
export function encodeArguments(abi: FunctionAbi, args: any[]) {
|
|
133
|
+
return new ArgumentEncoder(abi, args).encode();
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Returns the size of the arguments for a function ABI.
|
|
138
|
+
* @param abi - The function ABI entry.
|
|
139
|
+
* @returns The size of the arguments.
|
|
140
|
+
*/
|
|
141
|
+
export function countArgumentsSize(abi: FunctionAbi) {
|
|
142
|
+
return abi.parameters.reduce((acc, parameter) => acc + ArgumentEncoder.typeSize(parameter.type), 0);
|
|
143
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { fromHex, toBigIntBE } from '../bigint-buffer/index.js';
|
|
2
|
+
import { keccak } from '../crypto/index.js';
|
|
3
|
+
import { Fr } from '../fields/fields.js';
|
|
4
|
+
import { BufferReader } from '../serialize/buffer_reader.js';
|
|
5
|
+
import { Selector } from './selector.js';
|
|
6
|
+
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
|
|
8
|
+
|
|
9
|
+
/** Event selector branding */
|
|
10
|
+
export interface EventSelector {
|
|
11
|
+
/** Brand. */
|
|
12
|
+
_branding: 'EventSelector';
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** An event selector is the first 4 bytes of the hash of an event signature. */
|
|
16
|
+
export class EventSelector extends Selector {
|
|
17
|
+
/**
|
|
18
|
+
* Deserializes from a buffer or reader, corresponding to a write in cpp.
|
|
19
|
+
* @param buffer - Buffer or BufferReader to read from.
|
|
20
|
+
* @returns The Selector.
|
|
21
|
+
*/
|
|
22
|
+
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
23
|
+
const reader = BufferReader.asReader(buffer);
|
|
24
|
+
const value = Number(toBigIntBE(reader.readBytes(Selector.SIZE)));
|
|
25
|
+
return new EventSelector(value);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Converts a field to selector.
|
|
30
|
+
* @param fr - The field to convert.
|
|
31
|
+
* @returns The selector.
|
|
32
|
+
*/
|
|
33
|
+
static fromField(fr: Fr) {
|
|
34
|
+
return new EventSelector(Number(fr.toBigInt()));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Creates a selector from a signature.
|
|
39
|
+
* @param signature - Signature to generate the selector for (e.g. "transfer(field,field)").
|
|
40
|
+
* @returns selector.
|
|
41
|
+
*/
|
|
42
|
+
static fromSignature(signature: string) {
|
|
43
|
+
// throw if signature contains whitespace
|
|
44
|
+
if (/\s/.test(signature)) {
|
|
45
|
+
throw new Error('Signature cannot contain whitespace');
|
|
46
|
+
}
|
|
47
|
+
return EventSelector.fromBuffer(keccak(Buffer.from(signature)).subarray(0, Selector.SIZE));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Create a Selector instance from a hex-encoded string.
|
|
52
|
+
* The input 'address' should be prefixed with '0x' or not, and have exactly 64 hex characters.
|
|
53
|
+
* Throws an error if the input length is invalid or address value is out of range.
|
|
54
|
+
*
|
|
55
|
+
* @param selector - The hex-encoded string representing the Selector.
|
|
56
|
+
* @returns An Selector instance.
|
|
57
|
+
*/
|
|
58
|
+
static fromString(selector: string) {
|
|
59
|
+
const buf = fromHex(selector);
|
|
60
|
+
if (buf.length !== Selector.SIZE) {
|
|
61
|
+
throw new Error(`Invalid Selector length ${buf.length} (expected ${Selector.SIZE}).`);
|
|
62
|
+
}
|
|
63
|
+
return EventSelector.fromBuffer(buf);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Creates an empty selector.
|
|
68
|
+
* @returns An empty selector.
|
|
69
|
+
*/
|
|
70
|
+
static empty() {
|
|
71
|
+
return new EventSelector(0);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { fromHex, toBigIntBE } from '../bigint-buffer/index.js';
|
|
2
|
+
import { keccak, randomBytes } from '../crypto/index.js';
|
|
3
|
+
import { Fr } from '../fields/fields.js';
|
|
4
|
+
import { BufferReader } from '../serialize/buffer_reader.js';
|
|
5
|
+
import { FieldReader } from '../serialize/field_reader.js';
|
|
6
|
+
import { ABIParameter } from './abi.js';
|
|
7
|
+
import { decodeFunctionSignature } from './decoder.js';
|
|
8
|
+
import { Selector } from './selector.js';
|
|
9
|
+
|
|
10
|
+
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
|
|
11
|
+
|
|
12
|
+
/** Function selector branding */
|
|
13
|
+
export interface FunctionSelector {
|
|
14
|
+
/** Brand. */
|
|
15
|
+
_branding: 'FunctionSelector';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** A function selector is the first 4 bytes of the hash of a function signature. */
|
|
19
|
+
export class FunctionSelector extends Selector {
|
|
20
|
+
/**
|
|
21
|
+
* Checks if this function selector is equal to another.
|
|
22
|
+
* @returns True if the function selectors are equal.
|
|
23
|
+
*/
|
|
24
|
+
equals(otherName: string, otherParams: ABIParameter[]): boolean;
|
|
25
|
+
equals(other: FunctionSelector): boolean;
|
|
26
|
+
equals(other: FunctionSelector | string, otherParams?: ABIParameter[]): boolean {
|
|
27
|
+
if (typeof other === 'string') {
|
|
28
|
+
return this.equals(FunctionSelector.fromNameAndParameters(other, otherParams!));
|
|
29
|
+
}
|
|
30
|
+
return this.value === other.value;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Deserializes from a buffer or reader, corresponding to a write in cpp.
|
|
35
|
+
* @param buffer - Buffer or BufferReader to read from.
|
|
36
|
+
* @returns The Selector.
|
|
37
|
+
*/
|
|
38
|
+
static fromBuffer(buffer: Buffer | BufferReader) {
|
|
39
|
+
const reader = BufferReader.asReader(buffer);
|
|
40
|
+
const value = Number(toBigIntBE(reader.readBytes(Selector.SIZE)));
|
|
41
|
+
return new FunctionSelector(value);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Converts a field to selector.
|
|
46
|
+
* @param fr - The field to convert.
|
|
47
|
+
* @returns The selector.
|
|
48
|
+
*/
|
|
49
|
+
static fromField(fr: Fr) {
|
|
50
|
+
return new FunctionSelector(Number(fr.toBigInt()));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static fromFields(fields: Fr[] | FieldReader) {
|
|
54
|
+
const reader = FieldReader.asReader(fields);
|
|
55
|
+
return FunctionSelector.fromField(reader.readField());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Creates a selector from a signature.
|
|
60
|
+
* @param signature - Signature to generate the selector for (e.g. "transfer(field,field)").
|
|
61
|
+
* @returns selector.
|
|
62
|
+
*/
|
|
63
|
+
static fromSignature(signature: string) {
|
|
64
|
+
// throw if signature contains whitespace
|
|
65
|
+
if (/\s/.test(signature)) {
|
|
66
|
+
throw new Error('Signature cannot contain whitespace');
|
|
67
|
+
}
|
|
68
|
+
return FunctionSelector.fromBuffer(keccak(Buffer.from(signature)).subarray(0, Selector.SIZE));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Create a Selector instance from a hex-encoded string.
|
|
73
|
+
* The input 'address' should be prefixed with '0x' or not, and have exactly 64 hex characters.
|
|
74
|
+
* Throws an error if the input length is invalid or address value is out of range.
|
|
75
|
+
*
|
|
76
|
+
* @param selector - The hex-encoded string representing the Selector.
|
|
77
|
+
* @returns An Selector instance.
|
|
78
|
+
*/
|
|
79
|
+
static fromString(selector: string) {
|
|
80
|
+
const buf = fromHex(selector);
|
|
81
|
+
if (buf.length !== Selector.SIZE) {
|
|
82
|
+
throw new Error(`Invalid Selector length ${buf.length} (expected ${Selector.SIZE}).`);
|
|
83
|
+
}
|
|
84
|
+
return FunctionSelector.fromBuffer(buf);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Creates an empty selector.
|
|
89
|
+
* @returns An empty selector.
|
|
90
|
+
*/
|
|
91
|
+
static empty() {
|
|
92
|
+
return new FunctionSelector(0);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Creates a function selector for a given function name and parameters.
|
|
97
|
+
* @param name - The name of the function.
|
|
98
|
+
* @param parameters - An array of ABIParameter objects, each containing the type information of a function parameter.
|
|
99
|
+
* @returns A Buffer containing the 4-byte selector.
|
|
100
|
+
*/
|
|
101
|
+
static fromNameAndParameters(args: { name: string; parameters: ABIParameter[] }): FunctionSelector;
|
|
102
|
+
static fromNameAndParameters(name: string, parameters: ABIParameter[]): FunctionSelector;
|
|
103
|
+
static fromNameAndParameters(
|
|
104
|
+
nameOrArgs: string | { name: string; parameters: ABIParameter[] },
|
|
105
|
+
maybeParameters?: ABIParameter[],
|
|
106
|
+
): FunctionSelector {
|
|
107
|
+
const { name, parameters } =
|
|
108
|
+
typeof nameOrArgs === 'string' ? { name: nameOrArgs, parameters: maybeParameters! } : nameOrArgs;
|
|
109
|
+
const signature = decodeFunctionSignature(name, parameters);
|
|
110
|
+
const selector = this.fromSignature(signature);
|
|
111
|
+
// If using the debug logger here it kill the typing in the `server_world_state_synchronizer` and jest tests.
|
|
112
|
+
// console.log(`selector for ${signature} is ${selector}`);
|
|
113
|
+
return selector;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Creates a random instance.
|
|
118
|
+
*/
|
|
119
|
+
static random() {
|
|
120
|
+
return FunctionSelector.fromBuffer(randomBytes(Selector.SIZE));
|
|
121
|
+
}
|
|
122
|
+
}
|
package/src/abi/index.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { inspect } from 'util';
|
|
2
|
+
|
|
3
|
+
import { toBufferBE } from '../bigint-buffer/index.js';
|
|
4
|
+
import { Fr } from '../fields/index.js';
|
|
5
|
+
|
|
6
|
+
/** A selector is the first 4 bytes of the hash of a signature. */
|
|
7
|
+
export abstract class Selector {
|
|
8
|
+
/** The size of the selector in bytes. */
|
|
9
|
+
public static SIZE = 4;
|
|
10
|
+
|
|
11
|
+
constructor(/** Value of the selector */ public value: number) {
|
|
12
|
+
if (value > 2 ** (Selector.SIZE * 8) - 1) {
|
|
13
|
+
throw new Error(`Selector must fit in ${Selector.SIZE} bytes (got value ${value}).`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Checks if the selector is empty (all bytes are 0).
|
|
19
|
+
* @returns True if the selector is empty (all bytes are 0).
|
|
20
|
+
*/
|
|
21
|
+
public isEmpty(): boolean {
|
|
22
|
+
return this.value === 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Serialize as a buffer.
|
|
27
|
+
* @param bufferSize - The buffer size.
|
|
28
|
+
* @returns The buffer.
|
|
29
|
+
*/
|
|
30
|
+
toBuffer(bufferSize = Selector.SIZE): Buffer {
|
|
31
|
+
return toBufferBE(BigInt(this.value), bufferSize);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Serialize as a hex string.
|
|
36
|
+
* @returns The string.
|
|
37
|
+
*/
|
|
38
|
+
toString(): string {
|
|
39
|
+
return '0x' + this.toBuffer().toString('hex');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[inspect.custom]() {
|
|
43
|
+
return `Selector<${this.toString()}>`;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Checks if this selector is equal to another.
|
|
48
|
+
* @param other - The other selector.
|
|
49
|
+
* @returns True if the selectors are equal.
|
|
50
|
+
*/
|
|
51
|
+
equals(other: Selector): boolean {
|
|
52
|
+
return this.value === other.value;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Returns a new field with the same contents as this EthAddress.
|
|
57
|
+
*
|
|
58
|
+
* @returns An Fr instance.
|
|
59
|
+
*/
|
|
60
|
+
public toField() {
|
|
61
|
+
return new Fr(BigInt(this.value));
|
|
62
|
+
}
|
|
63
|
+
}
|
package/src/abi/utils.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type ABIType } from './abi.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns whether the ABI type is an Aztec or Ethereum Address defined in Aztec.nr.
|
|
5
|
+
* @param abiType - Type to check.
|
|
6
|
+
* @returns Boolean.
|
|
7
|
+
*/
|
|
8
|
+
export function isAddressStruct(abiType: ABIType) {
|
|
9
|
+
return isEthAddressStruct(abiType) || isAztecAddressStruct(abiType);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* Returns whether the ABI type is an Ethereum Address defined in Aztec.nr.
|
|
14
|
+
* @param abiType - Type to check.
|
|
15
|
+
* @returns Boolean.
|
|
16
|
+
*/
|
|
17
|
+
export function isEthAddressStruct(abiType: ABIType) {
|
|
18
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('address::EthAddress');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Returns whether the ABI type is an Aztec Address defined in Aztec.nr.
|
|
23
|
+
* @param abiType - Type to check.
|
|
24
|
+
* @returns Boolean.
|
|
25
|
+
*/
|
|
26
|
+
export function isAztecAddressStruct(abiType: ABIType) {
|
|
27
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('address::AztecAddress');
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Returns whether the ABI type is an Function Selector defined in Aztec.nr.
|
|
32
|
+
* @param abiType - Type to check.
|
|
33
|
+
* @returns Boolean.
|
|
34
|
+
*/
|
|
35
|
+
export function isFunctionSelectorStruct(abiType: ABIType) {
|
|
36
|
+
return abiType.kind === 'struct' && abiType.path.endsWith('types::abis::function_selector::FunctionSelector');
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Returns whether the ABI type is a struct with a single `inner` field.
|
|
41
|
+
* @param abiType - Type to check.
|
|
42
|
+
*/
|
|
43
|
+
export function isWrappedFieldStruct(abiType: ABIType) {
|
|
44
|
+
return (
|
|
45
|
+
abiType.kind === 'struct' &&
|
|
46
|
+
abiType.fields.length === 1 &&
|
|
47
|
+
abiType.fields[0].name === 'inner' &&
|
|
48
|
+
abiType.fields[0].type.kind === 'field'
|
|
49
|
+
);
|
|
50
|
+
}
|