@aztec-labs/simulator 6.0.0-nightly.20260829
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +57 -0
- package/dest/client.d.ts +6 -0
- package/dest/client.d.ts.map +1 -0
- package/dest/client.js +3 -0
- package/dest/common/errors.d.ts +51 -0
- package/dest/common/errors.d.ts.map +1 -0
- package/dest/common/errors.js +154 -0
- package/dest/common/index.d.ts +3 -0
- package/dest/common/index.d.ts.map +1 -0
- package/dest/common/index.js +2 -0
- package/dest/common/stats/index.d.ts +2 -0
- package/dest/common/stats/index.d.ts.map +1 -0
- package/dest/common/stats/index.js +1 -0
- package/dest/common/stats/stats.d.ts +4 -0
- package/dest/common/stats/stats.d.ts.map +1 -0
- package/dest/common/stats/stats.js +10 -0
- package/dest/private/acvm/acvm.d.ts +43 -0
- package/dest/private/acvm/acvm.d.ts.map +1 -0
- package/dest/private/acvm/acvm.js +65 -0
- package/dest/private/acvm/acvm_types.d.ts +10 -0
- package/dest/private/acvm/acvm_types.d.ts.map +1 -0
- package/dest/private/acvm/acvm_types.js +3 -0
- package/dest/private/acvm/deserialize.d.ts +35 -0
- package/dest/private/acvm/deserialize.d.ts.map +1 -0
- package/dest/private/acvm/deserialize.js +50 -0
- package/dest/private/acvm/index.d.ts +5 -0
- package/dest/private/acvm/index.d.ts.map +1 -0
- package/dest/private/acvm/index.js +4 -0
- package/dest/private/acvm/serialize.d.ts +41 -0
- package/dest/private/acvm/serialize.d.ts.map +1 -0
- package/dest/private/acvm/serialize.js +99 -0
- package/dest/private/acvm_native.d.ts +41 -0
- package/dest/private/acvm_native.d.ts.map +1 -0
- package/dest/private/acvm_native.js +147 -0
- package/dest/private/acvm_wasm.d.ts +16 -0
- package/dest/private/acvm_wasm.d.ts.map +1 -0
- package/dest/private/acvm_wasm.js +67 -0
- package/dest/private/acvm_wasm_with_blobs.d.ts +20 -0
- package/dest/private/acvm_wasm_with_blobs.d.ts.map +1 -0
- package/dest/private/acvm_wasm_with_blobs.js +35 -0
- package/dest/private/circuit_simulator.d.ts +35 -0
- package/dest/private/circuit_simulator.d.ts.map +1 -0
- package/dest/private/circuit_simulator.js +43 -0
- package/dest/private/factory.d.ts +12 -0
- package/dest/private/factory.d.ts.map +1 -0
- package/dest/private/factory.js +30 -0
- package/dest/public/avm/testing/account_proof_fetcher.d.ts +2 -0
- package/dest/public/avm/testing/account_proof_fetcher.d.ts.map +1 -0
- package/dest/public/avm/testing/account_proof_fetcher.js +152 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.d.ts +39 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.d.ts.map +1 -0
- package/dest/public/avm/testing/base_avm_simulation_tester.js +121 -0
- package/dest/public/avm/testing/utils.d.ts +32 -0
- package/dest/public/avm/testing/utils.d.ts.map +1 -0
- package/dest/public/avm/testing/utils.js +66 -0
- package/dest/public/avm_simulator.d.ts +28 -0
- package/dest/public/avm_simulator.d.ts.map +1 -0
- package/dest/public/avm_simulator.js +4 -0
- package/dest/public/avm_simulator_pool.d.ts +84 -0
- package/dest/public/avm_simulator_pool.d.ts.map +1 -0
- package/dest/public/avm_simulator_pool.js +311 -0
- package/dest/public/cdb_ipc_server.d.ts +40 -0
- package/dest/public/cdb_ipc_server.d.ts.map +1 -0
- package/dest/public/cdb_ipc_server.js +153 -0
- package/dest/public/contracts_db_checkpoint.d.ts +16 -0
- package/dest/public/contracts_db_checkpoint.d.ts.map +1 -0
- package/dest/public/contracts_db_checkpoint.js +30 -0
- package/dest/public/db_interfaces.d.ts +68 -0
- package/dest/public/db_interfaces.d.ts.map +1 -0
- package/dest/public/db_interfaces.js +3 -0
- package/dest/public/executor_metrics.d.ts +21 -0
- package/dest/public/executor_metrics.d.ts.map +1 -0
- package/dest/public/executor_metrics.js +64 -0
- package/dest/public/executor_metrics_interface.d.ts +10 -0
- package/dest/public/executor_metrics_interface.d.ts.map +1 -0
- package/dest/public/executor_metrics_interface.js +1 -0
- package/dest/public/fixtures/amm_test.d.ts +10 -0
- package/dest/public/fixtures/amm_test.d.ts.map +1 -0
- package/dest/public/fixtures/amm_test.js +213 -0
- package/dest/public/fixtures/bulk_test.d.ts +6 -0
- package/dest/public/fixtures/bulk_test.d.ts.map +1 -0
- package/dest/public/fixtures/bulk_test.js +289 -0
- package/dest/public/fixtures/custom_bytecode_tester.d.ts +34 -0
- package/dest/public/fixtures/custom_bytecode_tester.d.ts.map +1 -0
- package/dest/public/fixtures/custom_bytecode_tester.js +53 -0
- package/dest/public/fixtures/index.d.ts +10 -0
- package/dest/public/fixtures/index.d.ts.map +1 -0
- package/dest/public/fixtures/index.js +9 -0
- package/dest/public/fixtures/public_processor_test_env.d.ts +30 -0
- package/dest/public/fixtures/public_processor_test_env.d.ts.map +1 -0
- package/dest/public/fixtures/public_processor_test_env.js +73 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +77 -0
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -0
- package/dest/public/fixtures/public_tx_simulation_tester.js +176 -0
- package/dest/public/fixtures/simple_contract_data_source.d.ts +36 -0
- package/dest/public/fixtures/simple_contract_data_source.d.ts.map +1 -0
- package/dest/public/fixtures/simple_contract_data_source.js +95 -0
- package/dest/public/fixtures/token_test.d.ts +12 -0
- package/dest/public/fixtures/token_test.d.ts.map +1 -0
- package/dest/public/fixtures/token_test.js +96 -0
- package/dest/public/fixtures/utils.d.ts +26 -0
- package/dest/public/fixtures/utils.d.ts.map +1 -0
- package/dest/public/fixtures/utils.js +170 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts +65 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.d.ts.map +1 -0
- package/dest/public/fuzzing/avm_fuzzer_simulator.js +181 -0
- package/dest/public/fuzzing/avm_simulator_bin.d.ts +2 -0
- package/dest/public/fuzzing/avm_simulator_bin.d.ts.map +1 -0
- package/dest/public/fuzzing/avm_simulator_bin.js +108 -0
- package/dest/public/index.d.ts +10 -0
- package/dest/public/index.d.ts.map +1 -0
- package/dest/public/index.js +6 -0
- package/dest/public/public_db_sources.d.ts +83 -0
- package/dest/public/public_db_sources.d.ts.map +1 -0
- package/dest/public/public_db_sources.js +297 -0
- package/dest/public/public_errors.d.ts +12 -0
- package/dest/public/public_errors.d.ts.map +1 -0
- package/dest/public/public_errors.js +13 -0
- package/dest/public/public_processor/guarded_merkle_tree.d.ts +52 -0
- package/dest/public/public_processor/guarded_merkle_tree.d.ts.map +1 -0
- package/dest/public/public_processor/guarded_merkle_tree.js +116 -0
- package/dest/public/public_processor/public_processor.d.ts +71 -0
- package/dest/public/public_processor/public_processor.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor.js +858 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts +30 -0
- package/dest/public/public_processor/public_processor_metrics.d.ts.map +1 -0
- package/dest/public/public_processor/public_processor_metrics.js +116 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts +17 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/dumping_public_tx_simulator.js +39 -0
- package/dest/public/public_tx_simulator/factories.d.ts +14 -0
- package/dest/public/public_tx_simulator/factories.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/factories.js +28 -0
- package/dest/public/public_tx_simulator/index.d.ts +6 -0
- package/dest/public/public_tx_simulator/index.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/index.js +3 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +53 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator.js +127 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts +24 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_base.js +31 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts +32 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.d.ts.map +1 -0
- package/dest/public/public_tx_simulator/public_tx_simulator_interface.js +1 -0
- package/dest/public/side_effect_errors.d.ts +44 -0
- package/dest/public/side_effect_errors.d.ts.map +1 -0
- package/dest/public/side_effect_errors.js +75 -0
- package/dest/public/test_executor_metrics.d.ts +56 -0
- package/dest/public/test_executor_metrics.d.ts.map +1 -0
- package/dest/public/test_executor_metrics.js +305 -0
- package/dest/public/unique_class_ids.d.ts +37 -0
- package/dest/public/unique_class_ids.d.ts.map +1 -0
- package/dest/public/unique_class_ids.js +61 -0
- package/dest/public/utils.d.ts +3 -0
- package/dest/public/utils.d.ts.map +1 -0
- package/dest/public/utils.js +18 -0
- package/dest/server.d.ts +7 -0
- package/dest/server.d.ts.map +1 -0
- package/dest/server.js +5 -0
- package/package.json +109 -0
- package/src/client.ts +5 -0
- package/src/common/errors.ts +219 -0
- package/src/common/index.ts +2 -0
- package/src/common/stats/index.ts +1 -0
- package/src/common/stats/stats.ts +20 -0
- package/src/private/acvm/acvm.ts +114 -0
- package/src/private/acvm/acvm_types.ts +11 -0
- package/src/private/acvm/deserialize.ts +58 -0
- package/src/private/acvm/index.ts +4 -0
- package/src/private/acvm/serialize.ts +123 -0
- package/src/private/acvm_native.ts +200 -0
- package/src/private/acvm_wasm.ts +80 -0
- package/src/private/acvm_wasm_with_blobs.ts +55 -0
- package/src/private/circuit_simulator.ts +91 -0
- package/src/private/factory.ts +40 -0
- package/src/public/avm/testing/account_proof.json +553 -0
- package/src/public/avm/testing/account_proof_fetcher.ts +166 -0
- package/src/public/avm/testing/base_avm_simulation_tester.ts +162 -0
- package/src/public/avm/testing/utils.ts +114 -0
- package/src/public/avm_simulator.ts +29 -0
- package/src/public/avm_simulator_pool.ts +355 -0
- package/src/public/cdb_ipc_server.ts +198 -0
- package/src/public/contracts_db_checkpoint.ts +41 -0
- package/src/public/db_interfaces.ts +76 -0
- package/src/public/executor_metrics.ts +102 -0
- package/src/public/executor_metrics_interface.ts +20 -0
- package/src/public/fixtures/amm_test.ts +331 -0
- package/src/public/fixtures/bulk_test.ts +194 -0
- package/src/public/fixtures/custom_bytecode_tester.ts +83 -0
- package/src/public/fixtures/index.ts +13 -0
- package/src/public/fixtures/public_processor_test_env.ts +88 -0
- package/src/public/fixtures/public_tx_simulation_tester.ts +315 -0
- package/src/public/fixtures/simple_contract_data_source.ts +122 -0
- package/src/public/fixtures/token_test.ts +148 -0
- package/src/public/fixtures/utils.ts +269 -0
- package/src/public/fuzzing/avm_fuzzer_simulator.ts +302 -0
- package/src/public/fuzzing/avm_simulator_bin.ts +156 -0
- package/src/public/index.ts +16 -0
- package/src/public/public_db_sources.ts +405 -0
- package/src/public/public_errors.ts +14 -0
- package/src/public/public_processor/guarded_merkle_tree.ts +161 -0
- package/src/public/public_processor/public_processor.ts +657 -0
- package/src/public/public_processor/public_processor_metrics.ts +138 -0
- package/src/public/public_tx_simulator/dumping_public_tx_simulator.ts +66 -0
- package/src/public/public_tx_simulator/factories.ts +61 -0
- package/src/public/public_tx_simulator/index.ts +8 -0
- package/src/public/public_tx_simulator/public_tx_simulator.ts +190 -0
- package/src/public/public_tx_simulator/public_tx_simulator_base.ts +37 -0
- package/src/public/public_tx_simulator/public_tx_simulator_interface.ts +33 -0
- package/src/public/side_effect_errors.ts +96 -0
- package/src/public/test_executor_metrics.ts +399 -0
- package/src/public/unique_class_ids.ts +79 -0
- package/src/public/utils.ts +16 -0
- package/src/server.ts +6 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches an account proof from the Ethereum mainnet and saves it as account_proof.json.
|
|
3
|
+
* This script is not using any Aztec library code, so it's easily portable.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'fs';
|
|
6
|
+
import { dirname, join } from 'path';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
import { createPublicClient, fromRlp, hexToBytes, http } from 'viem';
|
|
9
|
+
import { mainnet } from 'viem/chains';
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
|
|
13
|
+
const RPC_URL = process.env.RPC_URL;
|
|
14
|
+
const ADDRESS = (process.env.ADDRESS || '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045') as `0x${string}`;
|
|
15
|
+
const BLOCK_TAG = process.env.BLOCK_NUMBER ? BigInt(process.env.BLOCK_NUMBER) : 'latest';
|
|
16
|
+
const MAX_ACCOUNT_PATH = 15;
|
|
17
|
+
|
|
18
|
+
function padTo(arr: number[], len: number) {
|
|
19
|
+
return [...arr, ...Array(len - arr.length).fill(0)].slice(0, len);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function toBytes(hex: `0x${string}`) {
|
|
23
|
+
return Array.from(hexToBytes(hex));
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function bytesToU64s(bytes: number[]) {
|
|
27
|
+
const paddedBytes = padTo(bytes, 32);
|
|
28
|
+
return Array.from({ length: 4 }, (_, i) => {
|
|
29
|
+
let val = 0n;
|
|
30
|
+
for (let j = 0; j < 8; j++) {
|
|
31
|
+
val += BigInt(paddedBytes[i * 8 + j]) << BigInt(j * 8);
|
|
32
|
+
}
|
|
33
|
+
return val.toString();
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function toBytesAndLen(val: bigint | number) {
|
|
38
|
+
if (val === 0n || val === 0) {
|
|
39
|
+
return { bytes: [0], length: 0 };
|
|
40
|
+
}
|
|
41
|
+
let hex = val.toString(16);
|
|
42
|
+
if (hex.length % 2) {
|
|
43
|
+
hex = '0' + hex;
|
|
44
|
+
}
|
|
45
|
+
const bytes = toBytes(`0x${hex}`);
|
|
46
|
+
return { bytes, length: bytes.length };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function parseNode(rlp: `0x${string}`) {
|
|
50
|
+
// Should be safe when working with branches and extensions without embedded children.
|
|
51
|
+
const decoded = fromRlp(rlp) as `0x${string}`[];
|
|
52
|
+
const node = {
|
|
53
|
+
rows: Array(16)
|
|
54
|
+
.fill(0)
|
|
55
|
+
.map(() => Array(32).fill(0)),
|
|
56
|
+
row_exist: Array(16).fill(false),
|
|
57
|
+
node_type: 0,
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
if (decoded.length === 17) {
|
|
61
|
+
for (let i = 0; i < 16; i++) {
|
|
62
|
+
if (decoded[i] !== '0x') {
|
|
63
|
+
node.row_exist[i] = true;
|
|
64
|
+
node.rows[i] = padTo(toBytes(decoded[i]), 32);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
} else if (decoded.length === 2) {
|
|
68
|
+
const keyBytes = toBytes(decoded[0]);
|
|
69
|
+
const prefix = keyBytes[0];
|
|
70
|
+
if (prefix >> 4 >= 2) {
|
|
71
|
+
throw new Error('Unsupported: leaf node in proof path');
|
|
72
|
+
}
|
|
73
|
+
node.node_type = 1;
|
|
74
|
+
// Extension header format expected by the noir code: check out storage_proof types.nr.
|
|
75
|
+
node.rows[0][0] = prefix >> 4;
|
|
76
|
+
node.rows[0][8] = prefix & 0x0f;
|
|
77
|
+
node.rows[0][16] = keyBytes.length - 1;
|
|
78
|
+
|
|
79
|
+
for (let i = 1; i < keyBytes.length && i < 32; i++) {
|
|
80
|
+
node.rows[1][i - 1] = keyBytes[i];
|
|
81
|
+
}
|
|
82
|
+
node.rows[2] = padTo(toBytes(decoded[1]), 32);
|
|
83
|
+
node.row_exist[0] = node.row_exist[1] = node.row_exist[2] = true;
|
|
84
|
+
}
|
|
85
|
+
return node;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function parseProof(proof: `0x${string}`[], maxLen: number) {
|
|
89
|
+
const nodes = proof.slice(0, -1).slice(0, maxLen).map(parseNode);
|
|
90
|
+
while (nodes.length < maxLen) {
|
|
91
|
+
nodes.push({
|
|
92
|
+
rows: Array(16)
|
|
93
|
+
.fill(0)
|
|
94
|
+
.map(() => Array(32).fill(0)),
|
|
95
|
+
row_exist: Array(16).fill(false),
|
|
96
|
+
node_type: 0,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return nodes;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function nodeToLibFormat(node: { rows: number[][]; row_exist: boolean[]; node_type: number }) {
|
|
103
|
+
return {
|
|
104
|
+
rows: node.rows.map(bytesToU64s),
|
|
105
|
+
row_exist: node.row_exist,
|
|
106
|
+
node_type: String(node.node_type),
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async function main() {
|
|
111
|
+
if (!RPC_URL) {
|
|
112
|
+
throw new Error('RPC_URL is not set');
|
|
113
|
+
}
|
|
114
|
+
console.log(`Fetching account proof for ${ADDRESS}`);
|
|
115
|
+
|
|
116
|
+
const client = createPublicClient({
|
|
117
|
+
chain: mainnet,
|
|
118
|
+
transport: http(RPC_URL),
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const [blockNumber, proof, block] = await Promise.all([
|
|
122
|
+
client.getBlockNumber(),
|
|
123
|
+
client.getProof({
|
|
124
|
+
address: ADDRESS,
|
|
125
|
+
storageKeys: [],
|
|
126
|
+
blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
|
|
127
|
+
}),
|
|
128
|
+
client.getBlock({
|
|
129
|
+
blockNumber: BLOCK_TAG === 'latest' ? undefined : BLOCK_TAG,
|
|
130
|
+
}),
|
|
131
|
+
]);
|
|
132
|
+
|
|
133
|
+
console.log(`Block: ${blockNumber}, Account nodes: ${proof.accountProof.length}`);
|
|
134
|
+
|
|
135
|
+
// The -1 is because the last node in the proof is the leaf, which is excluded from path verification.
|
|
136
|
+
const accountPathLen = proof.accountProof.length - 1;
|
|
137
|
+
if (accountPathLen > MAX_ACCOUNT_PATH) {
|
|
138
|
+
throw new Error(
|
|
139
|
+
`Account proof path length ${accountPathLen} exceeds MAX_ACCOUNT_PATH ${MAX_ACCOUNT_PATH}. Increase the limit.`,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const nonce = toBytesAndLen(proof.nonce);
|
|
144
|
+
const balance = toBytesAndLen(proof.balance);
|
|
145
|
+
|
|
146
|
+
const data = {
|
|
147
|
+
block_number: String(blockNumber),
|
|
148
|
+
node_length: String(accountPathLen),
|
|
149
|
+
root: bytesToU64s(toBytes(block.stateRoot)),
|
|
150
|
+
nodes: parseProof(proof.accountProof, MAX_ACCOUNT_PATH).map(nodeToLibFormat),
|
|
151
|
+
account: {
|
|
152
|
+
address: toBytes(ADDRESS).map(String),
|
|
153
|
+
balance: padTo(balance.bytes, 32).map(String),
|
|
154
|
+
balance_length: String(balance.length),
|
|
155
|
+
code_hash: bytesToU64s(toBytes(proof.codeHash)),
|
|
156
|
+
nonce: padTo(nonce.bytes, 8).map(String),
|
|
157
|
+
nonce_length: String(nonce.length),
|
|
158
|
+
storage_hash: bytesToU64s(toBytes(proof.storageHash)),
|
|
159
|
+
},
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
fs.writeFileSync(join(__dirname, 'account_proof.json'), JSON.stringify(data, null, 2));
|
|
163
|
+
console.log('account_proof.json generated');
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
main().catch(console.error);
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS } from '@aztec-labs/constants';
|
|
2
|
+
import { Fr } from '@aztec-labs/foundation/curves/bn254';
|
|
3
|
+
import { createLogger } from '@aztec-labs/foundation/log';
|
|
4
|
+
import { ProtocolContractAddress } from '@aztec-labs/protocol-contracts';
|
|
5
|
+
import { getCanonicalClassRegistry } from '@aztec-labs/protocol-contracts/class-registry';
|
|
6
|
+
import { computeFeePayerBalanceStorageSlot, getCanonicalFeeJuice } from '@aztec-labs/protocol-contracts/fee-juice';
|
|
7
|
+
import { getCanonicalInstanceRegistry } from '@aztec-labs/protocol-contracts/instance-registry';
|
|
8
|
+
import { getStandardAuthRegistry } from '@aztec-labs/standard-contracts/auth-registry';
|
|
9
|
+
import type { ContractArtifact } from '@aztec-labs/stdlib/abi';
|
|
10
|
+
import { PublicDataWrite } from '@aztec-labs/stdlib/avm';
|
|
11
|
+
import { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
12
|
+
import type { ContractInstanceWithAddress } from '@aztec-labs/stdlib/contract';
|
|
13
|
+
import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec-labs/stdlib/hash';
|
|
14
|
+
import type { MerkleTreeWriteOperations } from '@aztec-labs/stdlib/interfaces/server';
|
|
15
|
+
import { MerkleTreeId } from '@aztec-labs/stdlib/trees';
|
|
16
|
+
|
|
17
|
+
import type { SimpleContractDataSource } from '../../fixtures/simple_contract_data_source.js';
|
|
18
|
+
import { createContractClassAndInstance } from './utils.js';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* An abstract test class that enables tests of real apps in the AVM without requiring e2e tests.
|
|
22
|
+
* It enables this by letting us (1) perform pseudo-contract-deployments (and registrations)
|
|
23
|
+
* that trigger merkle tree operations and (2) maintain a contract data source to store
|
|
24
|
+
* and retrieve contract classes and instances.
|
|
25
|
+
*
|
|
26
|
+
* This class is meant to be extended when writing tests for a specific simulation interface.
|
|
27
|
+
* For example, has been extended for testing of the core AvmSimulator, and again for the PublicTxSimulator,
|
|
28
|
+
* both of which benefit from such pseudo-deployments by populating merkle trees and a contract data source
|
|
29
|
+
* with contract information.
|
|
30
|
+
*/
|
|
31
|
+
export abstract class BaseAvmSimulationTester {
|
|
32
|
+
public logger = createLogger('avm-simulation-tester');
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
public contractDataSource: SimpleContractDataSource,
|
|
36
|
+
public merkleTrees: MerkleTreeWriteOperations,
|
|
37
|
+
private initialFeePayerBalance = new Fr(10 ** 10),
|
|
38
|
+
) {}
|
|
39
|
+
|
|
40
|
+
async setFeePayerBalance(feePayer: AztecAddress, balance = this.initialFeePayerBalance) {
|
|
41
|
+
const feeJuiceAddress = ProtocolContractAddress.FeeJuice;
|
|
42
|
+
const balanceSlot = await computeFeePayerBalanceStorageSlot(feePayer);
|
|
43
|
+
await this.setPublicStorage(feeJuiceAddress, balanceSlot, balance);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async setPublicStorage(address: AztecAddress, slot: Fr, value: Fr) {
|
|
47
|
+
const leafSlot = await computePublicDataTreeLeafSlot(address, slot);
|
|
48
|
+
// get existing preimage
|
|
49
|
+
const publicDataWrite = new PublicDataWrite(leafSlot, value);
|
|
50
|
+
await this.merkleTrees.sequentialInsert(MerkleTreeId.PUBLIC_DATA_TREE, [publicDataWrite.toBuffer()]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Derive the contract class and instance with some seed.
|
|
55
|
+
* Add both to the contract data source along with the contract artifact.
|
|
56
|
+
*/
|
|
57
|
+
async registerAndDeployContract(
|
|
58
|
+
constructorArgs: any[],
|
|
59
|
+
deployer: AztecAddress,
|
|
60
|
+
contractArtifact: ContractArtifact,
|
|
61
|
+
skipNullifierInsertion = false,
|
|
62
|
+
seed = 0,
|
|
63
|
+
contractClassSeed = seed,
|
|
64
|
+
originalContractClassId?: Fr, // if previously upgraded
|
|
65
|
+
): Promise<ContractInstanceWithAddress> {
|
|
66
|
+
const { contractClass, contractInstance } = await createContractClassAndInstance(
|
|
67
|
+
constructorArgs,
|
|
68
|
+
deployer,
|
|
69
|
+
contractArtifact,
|
|
70
|
+
seed,
|
|
71
|
+
contractClassSeed,
|
|
72
|
+
originalContractClassId,
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
await this.contractDataSource.addNewContract(contractArtifact, contractClass, contractInstance);
|
|
76
|
+
|
|
77
|
+
if (!skipNullifierInsertion) {
|
|
78
|
+
await this.insertContractAddressNullifier(contractInstance.address);
|
|
79
|
+
}
|
|
80
|
+
return contractInstance;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async registerFeeJuiceContract(): Promise<ContractInstanceWithAddress> {
|
|
84
|
+
const feeJuice = await getCanonicalFeeJuice();
|
|
85
|
+
const feeJuiceContractClassPublic = {
|
|
86
|
+
...feeJuice.contractClass,
|
|
87
|
+
privateFunctions: [],
|
|
88
|
+
utilityFunctions: [],
|
|
89
|
+
};
|
|
90
|
+
await this.contractDataSource.addNewContract(feeJuice.artifact, feeJuiceContractClassPublic, feeJuice.instance);
|
|
91
|
+
return feeJuice.instance;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async registerAuthContract(): Promise<ContractInstanceWithAddress> {
|
|
95
|
+
const authRegistry = await getStandardAuthRegistry();
|
|
96
|
+
const authRegistryContractClassPublic = {
|
|
97
|
+
...authRegistry.contractClass,
|
|
98
|
+
privateFunctions: [],
|
|
99
|
+
utilityFunctions: [],
|
|
100
|
+
};
|
|
101
|
+
await this.contractDataSource.addNewContract(
|
|
102
|
+
authRegistry.artifact,
|
|
103
|
+
authRegistryContractClassPublic,
|
|
104
|
+
authRegistry.instance,
|
|
105
|
+
);
|
|
106
|
+
// AuthRegistry is a standard contract (not a protocol contract), so the AVM enforces a
|
|
107
|
+
// deployment-nullifier check on every instance retrieval. Insert the nullifier here so
|
|
108
|
+
// calls to AuthRegistry don't EXCEPTIONAL_HALT during simulation.
|
|
109
|
+
await this.insertContractAddressNullifier(authRegistry.instance.address);
|
|
110
|
+
return authRegistry.instance;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async registerClassRegistryContract(): Promise<ContractInstanceWithAddress> {
|
|
114
|
+
const classRegistry = await getCanonicalClassRegistry();
|
|
115
|
+
const classRegistryContractClassPublic = {
|
|
116
|
+
...classRegistry.contractClass,
|
|
117
|
+
privateFunctions: [],
|
|
118
|
+
utilityFunctions: [],
|
|
119
|
+
};
|
|
120
|
+
await this.contractDataSource.addNewContract(
|
|
121
|
+
classRegistry.artifact,
|
|
122
|
+
classRegistryContractClassPublic,
|
|
123
|
+
classRegistry.instance,
|
|
124
|
+
);
|
|
125
|
+
return classRegistry.instance;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async registerInstanceRegistryContract(): Promise<ContractInstanceWithAddress> {
|
|
129
|
+
const instanceRegistry = await getCanonicalInstanceRegistry();
|
|
130
|
+
const instanceRegistryContractClassPublic = {
|
|
131
|
+
...instanceRegistry.contractClass,
|
|
132
|
+
privateFunctions: [],
|
|
133
|
+
utilityFunctions: [],
|
|
134
|
+
};
|
|
135
|
+
await this.contractDataSource.addNewContract(
|
|
136
|
+
instanceRegistry.artifact,
|
|
137
|
+
instanceRegistryContractClassPublic,
|
|
138
|
+
instanceRegistry.instance,
|
|
139
|
+
);
|
|
140
|
+
return instanceRegistry.instance;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
async addContractInstance(contractInstance: ContractInstanceWithAddress, skipNullifierInsertion = false) {
|
|
144
|
+
if (!skipNullifierInsertion) {
|
|
145
|
+
await this.insertContractAddressNullifier(contractInstance.address);
|
|
146
|
+
}
|
|
147
|
+
await this.contractDataSource.addContractInstance(contractInstance);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
private async insertContractAddressNullifier(contractAddress: AztecAddress) {
|
|
151
|
+
const contractAddressNullifier = await siloNullifier(
|
|
152
|
+
AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
|
|
153
|
+
contractAddress.toField(),
|
|
154
|
+
);
|
|
155
|
+
await this.merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()]);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
async insertNullifier(contractThatEmitted: AztecAddress, nullifier: Fr) {
|
|
159
|
+
const siloedNullifier = await siloNullifier(contractThatEmitted, nullifier);
|
|
160
|
+
await this.merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [siloedNullifier.toBuffer()]);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS } from '@aztec-labs/constants';
|
|
2
|
+
import { BlockNumber } from '@aztec-labs/foundation/branded-types';
|
|
3
|
+
import { Fr } from '@aztec-labs/foundation/curves/bn254';
|
|
4
|
+
import {
|
|
5
|
+
type ContractArtifact,
|
|
6
|
+
type FunctionAbi,
|
|
7
|
+
type FunctionArtifact,
|
|
8
|
+
FunctionSelector,
|
|
9
|
+
getAllFunctionAbis,
|
|
10
|
+
} from '@aztec-labs/stdlib/abi';
|
|
11
|
+
import { AztecAddress } from '@aztec-labs/stdlib/aztec-address';
|
|
12
|
+
import {
|
|
13
|
+
type ContractClassPublic,
|
|
14
|
+
type ContractInstanceWithAddress,
|
|
15
|
+
computeInitializationHash,
|
|
16
|
+
} from '@aztec-labs/stdlib/contract';
|
|
17
|
+
import { siloNullifier } from '@aztec-labs/stdlib/hash';
|
|
18
|
+
import { deriveKeys } from '@aztec-labs/stdlib/keys';
|
|
19
|
+
import { makeContractClassPublic, makeContractInstanceFromClassId } from '@aztec-labs/stdlib/testing';
|
|
20
|
+
import type { UInt64 } from '@aztec-labs/stdlib/types';
|
|
21
|
+
import { strict as assert } from 'assert';
|
|
22
|
+
import merge from 'lodash.merge';
|
|
23
|
+
|
|
24
|
+
export const PUBLIC_DISPATCH_FN_NAME = 'public_dispatch';
|
|
25
|
+
export const DEFAULT_TIMESTAMP: UInt64 = 99833n;
|
|
26
|
+
export const DEFAULT_BLOCK_NUMBER = BlockNumber(42);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Create a new object with all the same properties as the original, except for the ones in the overrides object.
|
|
30
|
+
*/
|
|
31
|
+
export function allSameExcept(original: any, overrides: any): any {
|
|
32
|
+
return merge({}, original, overrides);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getFunctionSelector(
|
|
36
|
+
functionName: string,
|
|
37
|
+
contractArtifact: ContractArtifact,
|
|
38
|
+
): Promise<FunctionSelector> {
|
|
39
|
+
const fnArtifact = getAllFunctionAbis(contractArtifact).find(f => f.name === functionName)!;
|
|
40
|
+
assert(!!fnArtifact, `Function ${functionName} not found in ${contractArtifact.name}`);
|
|
41
|
+
const params = fnArtifact.parameters;
|
|
42
|
+
return FunctionSelector.fromNameAndParameters(fnArtifact.name, params);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function getContractFunctionArtifact(
|
|
46
|
+
functionName: string,
|
|
47
|
+
contractArtifact: ContractArtifact,
|
|
48
|
+
): FunctionArtifact | undefined {
|
|
49
|
+
return contractArtifact.functions.find(f => f.name === functionName);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function getContractFunctionAbi(
|
|
53
|
+
functionName: string,
|
|
54
|
+
contractArtifact: ContractArtifact,
|
|
55
|
+
): FunctionAbi | undefined {
|
|
56
|
+
return (
|
|
57
|
+
contractArtifact.functions.find(f => f.name === functionName) ??
|
|
58
|
+
contractArtifact.nonDispatchPublicFunctions.find(f => f.name === functionName)
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Create a contract class and instance given constructor args, artifact, etc.
|
|
64
|
+
* NOTE: This is useful for testing real-ish contract class registration and instance deployment TXs (via logs)
|
|
65
|
+
* @param constructorArgs - The constructor arguments for the contract.
|
|
66
|
+
* @param deployer - The deployer of the contract.
|
|
67
|
+
* @param contractArtifact - The contract artifact for the contract.
|
|
68
|
+
* @param seed - The seed for the contract.
|
|
69
|
+
* @param originalContractClassId - The original contract class ID (if upgraded)
|
|
70
|
+
* @returns The contract class, instance, and contract address nullifier.
|
|
71
|
+
*/
|
|
72
|
+
export async function createContractClassAndInstance(
|
|
73
|
+
constructorArgs: any[],
|
|
74
|
+
deployer: AztecAddress,
|
|
75
|
+
contractArtifact: ContractArtifact,
|
|
76
|
+
seed = 0,
|
|
77
|
+
contractClassSeed = seed,
|
|
78
|
+
originalContractClassId?: Fr, // if previously upgraded
|
|
79
|
+
): Promise<{
|
|
80
|
+
contractClass: ContractClassPublic;
|
|
81
|
+
contractInstance: ContractInstanceWithAddress;
|
|
82
|
+
contractAddressNullifier: Fr;
|
|
83
|
+
}> {
|
|
84
|
+
const bytecode = (getContractFunctionArtifact(PUBLIC_DISPATCH_FN_NAME, contractArtifact) as FunctionArtifact)!
|
|
85
|
+
.bytecode;
|
|
86
|
+
const contractClass = await makeContractClassPublic(contractClassSeed, bytecode);
|
|
87
|
+
|
|
88
|
+
const constructorAbi = getContractFunctionAbi('constructor', contractArtifact);
|
|
89
|
+
const { publicKeys } = await deriveKeys(new Fr(seed));
|
|
90
|
+
const initializationHash = await computeInitializationHash(constructorAbi, constructorArgs);
|
|
91
|
+
const immutablesHash = new Fr(seed + 1);
|
|
92
|
+
const contractInstance =
|
|
93
|
+
originalContractClassId === undefined
|
|
94
|
+
? await makeContractInstanceFromClassId(contractClass.id, seed, {
|
|
95
|
+
deployer,
|
|
96
|
+
initializationHash,
|
|
97
|
+
immutablesHash,
|
|
98
|
+
publicKeys,
|
|
99
|
+
})
|
|
100
|
+
: await makeContractInstanceFromClassId(originalContractClassId, seed, {
|
|
101
|
+
deployer,
|
|
102
|
+
initializationHash,
|
|
103
|
+
currentClassId: contractClass.id,
|
|
104
|
+
immutablesHash,
|
|
105
|
+
publicKeys,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const contractAddressNullifier = await siloNullifier(
|
|
109
|
+
AztecAddress.fromNumberUnsafe(CONTRACT_INSTANCE_REGISTRY_CONTRACT_ADDRESS),
|
|
110
|
+
contractInstance.address.toField(),
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return { contractClass, contractInstance, contractAddressNullifier };
|
|
114
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PublicContractsDB } from './public_db_sources.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Identifies the contract data a single simulation reads. The AVM's contract-data lookups during a
|
|
5
|
+
* `simulate` call are answered from `contractsDB`; `forkId` and `timestamp` scope those lookups to the
|
|
6
|
+
* world-state fork being simulated against. How this reaches the AVM (in-process call, IPC callback
|
|
7
|
+
* server, ...) is the implementation's concern — callers only supply the context.
|
|
8
|
+
*/
|
|
9
|
+
export interface AvmContractsDBContext {
|
|
10
|
+
contractsDB: PublicContractsDB;
|
|
11
|
+
forkId: number;
|
|
12
|
+
timestamp: bigint;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Something that can run AVM simulations, independent of how the work is dispatched (a single external
|
|
17
|
+
* process, a pool of them, or an in-process stub). Callers hold this and never see the underlying transport.
|
|
18
|
+
*/
|
|
19
|
+
export interface AvmSimulator {
|
|
20
|
+
/**
|
|
21
|
+
* Run a fast simulation and return the msgpack-encoded result. `context` supplies the contracts DB whose
|
|
22
|
+
* data the simulation reads. If `signal` aborts, the simulation stops at the next cancellation checkpoint.
|
|
23
|
+
*/
|
|
24
|
+
simulate(inputBuffer: Uint8Array, context: AvmContractsDBContext, signal?: AbortSignal): Promise<Uint8Array>;
|
|
25
|
+
/** Run a simulation collecting proving hints and return the msgpack-encoded result. */
|
|
26
|
+
simulateWithHints(inputBuffer: Uint8Array): Promise<Uint8Array>;
|
|
27
|
+
/** Release any resources held by the underlying implementation. */
|
|
28
|
+
destroy?(): Promise<void>;
|
|
29
|
+
}
|