@aztec/simulator 0.84.0 → 0.85.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/common/debug_fn_name.d.ts +1 -1
- package/dest/common/debug_fn_name.d.ts.map +1 -1
- package/dest/common/index.d.ts +0 -1
- package/dest/common/index.d.ts.map +1 -1
- package/dest/common/index.js +0 -1
- package/dest/private/acvm/oracle/oracle.d.ts +1 -1
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +3 -3
- package/dest/private/acvm/oracle/typed_oracle.d.ts +3 -3
- package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/typed_oracle.js +1 -1
- package/dest/private/execution_data_provider.d.ts +39 -5
- package/dest/private/execution_data_provider.d.ts.map +1 -1
- package/dest/private/index.d.ts +1 -0
- package/dest/private/index.d.ts.map +1 -1
- package/dest/private/index.js +1 -0
- package/dest/private/message_load_oracle_inputs.d.ts.map +1 -0
- package/dest/private/simulator.js +1 -1
- package/dest/private/utility_execution_oracle.d.ts +3 -3
- package/dest/private/utility_execution_oracle.d.ts.map +1 -1
- package/dest/private/utility_execution_oracle.js +2 -6
- package/dest/public/avm/fixtures/base_avm_simulation_tester.js +4 -4
- package/dest/public/avm/test_utils.d.ts +1 -1
- package/dest/public/avm/test_utils.d.ts.map +1 -1
- package/dest/public/avm/test_utils.js +2 -2
- package/dest/{common → public}/db_interfaces.d.ts +0 -38
- package/dest/public/db_interfaces.d.ts.map +1 -0
- package/dest/public/db_interfaces.js +3 -0
- package/dest/public/hinting_db_sources.d.ts +11 -1
- package/dest/public/hinting_db_sources.d.ts.map +1 -1
- package/dest/public/hinting_db_sources.js +80 -13
- package/dest/public/index.d.ts +1 -1
- package/dest/public/index.d.ts.map +1 -1
- package/dest/public/index.js +1 -1
- package/dest/public/public_db_sources.d.ts +3 -3
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +27 -9
- package/dest/public/public_processor/public_processor.d.ts +1 -1
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +3 -3
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +6 -4
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +1 -1
- package/dest/public/state_manager/nullifiers.js +2 -2
- package/dest/public/state_manager/public_storage.d.ts +1 -1
- package/dest/public/state_manager/public_storage.d.ts.map +1 -1
- package/dest/public/state_manager/state_manager.js +4 -4
- package/package.json +14 -18
- package/src/common/debug_fn_name.ts +1 -1
- package/src/common/index.ts +0 -1
- package/src/private/acvm/oracle/oracle.ts +6 -4
- package/src/private/acvm/oracle/typed_oracle.ts +3 -2
- package/src/private/execution_data_provider.ts +49 -5
- package/src/private/index.ts +1 -0
- package/src/private/simulator.ts +2 -2
- package/src/private/utility_execution_oracle.ts +5 -7
- package/src/public/avm/fixtures/base_avm_simulation_tester.ts +2 -2
- package/src/public/avm/test_utils.ts +2 -2
- package/src/{common → public}/db_interfaces.ts +0 -48
- package/src/public/hinting_db_sources.ts +121 -19
- package/src/public/index.ts +1 -1
- package/src/public/public_db_sources.ts +36 -8
- package/src/public/public_processor/public_processor.ts +1 -3
- package/src/public/public_tx_simulator/public_tx_context.ts +10 -10
- package/src/public/public_tx_simulator/public_tx_simulator.ts +1 -2
- package/src/public/state_manager/nullifiers.ts +2 -2
- package/src/public/state_manager/public_storage.ts +1 -1
- package/src/public/state_manager/state_manager.ts +4 -4
- package/dest/common/db_interfaces.d.ts.map +0 -1
- package/dest/common/db_interfaces.js +0 -1
- package/dest/common/message_load_oracle_inputs.d.ts.map +0 -1
- /package/dest/{common → private}/message_load_oracle_inputs.d.ts +0 -0
- /package/dest/{common → private}/message_load_oracle_inputs.js +0 -0
- /package/src/{common → private}/message_load_oracle_inputs.ts +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
|
|
1
2
|
import type { Fr, Point } from '@aztec/foundation/fields';
|
|
2
3
|
import type {
|
|
3
4
|
EventSelector,
|
|
@@ -14,8 +15,8 @@ import type { NoteStatus } from '@aztec/stdlib/note';
|
|
|
14
15
|
import { type MerkleTreeId, type NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
|
|
15
16
|
import type { BlockHeader, TxHash } from '@aztec/stdlib/tx';
|
|
16
17
|
|
|
17
|
-
import type { CommitmentsDBInterface } from '../common/db_interfaces.js';
|
|
18
18
|
import type { NoteData } from './acvm/index.js';
|
|
19
|
+
import type { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Error thrown when a contract is not found in the database.
|
|
@@ -38,7 +39,7 @@ export class ContractClassNotFoundError extends Error {
|
|
|
38
39
|
/**
|
|
39
40
|
* The interface for the data layer required to perform private and utility execution.
|
|
40
41
|
*/
|
|
41
|
-
export interface ExecutionDataProvider
|
|
42
|
+
export interface ExecutionDataProvider {
|
|
42
43
|
/**
|
|
43
44
|
* Returns a contract instance associated with an address, if available.
|
|
44
45
|
* @param address - Address.
|
|
@@ -117,6 +118,40 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
|
|
|
117
118
|
*/
|
|
118
119
|
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;
|
|
119
120
|
|
|
121
|
+
/**
|
|
122
|
+
* Gets the index of a nullifier in the nullifier tree.
|
|
123
|
+
* @param nullifier - The nullifier.
|
|
124
|
+
* @returns - The index of the nullifier. Undefined if it does not exist in the tree.
|
|
125
|
+
*/
|
|
126
|
+
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Returns a nullifier membership witness for the given nullifier or undefined if not found.
|
|
130
|
+
* REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
|
|
131
|
+
* @param nullifier - Nullifier we're looking for.
|
|
132
|
+
*/
|
|
133
|
+
getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Fetches a message from the db, given its key.
|
|
137
|
+
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
138
|
+
* @param messageHash - Hash of the message.
|
|
139
|
+
* @param secret - Secret used to compute a nullifier.
|
|
140
|
+
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
141
|
+
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
142
|
+
*/
|
|
143
|
+
getL1ToL2MembershipWitness(
|
|
144
|
+
contractAddress: AztecAddress,
|
|
145
|
+
messageHash: Fr,
|
|
146
|
+
secret: Fr,
|
|
147
|
+
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* @param leafIndex the leaf to look up
|
|
151
|
+
* @returns The l1 to l2 leaf message hash or undefined if not found.
|
|
152
|
+
*/
|
|
153
|
+
getL1ToL2MessageHash(leafIndex: bigint): Promise<Fr | undefined>;
|
|
154
|
+
|
|
120
155
|
/**
|
|
121
156
|
* Retrieve the databases view of the Block Header object.
|
|
122
157
|
* This structure is fed into the circuits simulator and is used to prove against certain historical roots.
|
|
@@ -259,10 +294,17 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
|
|
|
259
294
|
content: Fr[],
|
|
260
295
|
noteHash: Fr,
|
|
261
296
|
nullifier: Fr,
|
|
262
|
-
txHash:
|
|
297
|
+
txHash: TxHash,
|
|
263
298
|
recipient: AztecAddress,
|
|
264
299
|
): Promise<void>;
|
|
265
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Gets note hash in the note hash tree at the given leaf index.
|
|
303
|
+
* @param leafIndex - the leaf to look up.
|
|
304
|
+
* @returns - The note hash at that index. Undefined if leaf index is not found.
|
|
305
|
+
*/
|
|
306
|
+
getNoteHash(leafIndex: bigint): Promise<Fr | undefined>;
|
|
307
|
+
|
|
266
308
|
/**
|
|
267
309
|
* Searches for a log with the corresponding `tag` and returns it along with contextual transaction information.
|
|
268
310
|
* Returns null if no such log exists, and throws if more than one exists.
|
|
@@ -329,16 +371,18 @@ export interface ExecutionDataProvider extends CommitmentsDBInterface {
|
|
|
329
371
|
* @param contractAddress - The address of the contract that emitted the log.
|
|
330
372
|
* @param recipient - The address of the recipient.
|
|
331
373
|
* @param eventSelector - The event selector of the event.
|
|
332
|
-
* @param
|
|
374
|
+
* @param msgContent - The content of the private event message.
|
|
333
375
|
* @param txHash - The hash of the transaction that emitted the log.
|
|
334
376
|
* @param logIndexInTx - The index of the log within the transaction.
|
|
377
|
+
* @param txIndexInBlock - The index of the transaction in which the log was emitted in the block.
|
|
335
378
|
*/
|
|
336
379
|
storePrivateEventLog(
|
|
337
380
|
contractAddress: AztecAddress,
|
|
338
381
|
recipient: AztecAddress,
|
|
339
382
|
eventSelector: EventSelector,
|
|
340
|
-
|
|
383
|
+
msgContent: Fr[],
|
|
341
384
|
txHash: TxHash,
|
|
342
385
|
logIndexInTx: number,
|
|
386
|
+
txIndexInBlock: number,
|
|
343
387
|
): Promise<void>;
|
|
344
388
|
}
|
package/src/private/index.ts
CHANGED
|
@@ -13,3 +13,4 @@ export { extractCallStack } from './acvm/acvm.js';
|
|
|
13
13
|
export { type NoteData, TypedOracle } from './acvm/oracle/typed_oracle.js';
|
|
14
14
|
export { Oracle } from './acvm/oracle/oracle.js';
|
|
15
15
|
export { HashedValuesCache } from './hashed_values_cache.js';
|
|
16
|
+
export { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
|
package/src/private/simulator.ts
CHANGED
|
@@ -115,7 +115,7 @@ export class AcirSimulator {
|
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
// docs:start:
|
|
118
|
+
// docs:start:execute_utility_function
|
|
119
119
|
/**
|
|
120
120
|
* Runs a utility function.
|
|
121
121
|
* @param call - The function call to execute.
|
|
@@ -163,5 +163,5 @@ export class AcirSimulator {
|
|
|
163
163
|
throw createSimulationError(err instanceof Error ? err : new Error('Unknown error during private execution'));
|
|
164
164
|
}
|
|
165
165
|
}
|
|
166
|
-
// docs:end:
|
|
166
|
+
// docs:end:execute_utility_function
|
|
167
167
|
}
|
|
@@ -256,10 +256,6 @@ export class UtilityExecutionOracle extends TypedOracle {
|
|
|
256
256
|
}
|
|
257
257
|
|
|
258
258
|
public override debugLog(message: string, fields: Fr[]): void {
|
|
259
|
-
// TODO(#10558) Remove this check once the debug log is fixed
|
|
260
|
-
if (message.startsWith('Context.note_hashes, after pushing new note hash:')) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
259
|
this.log.verbose(`${applyStringFormatting(message, fields)}`, { module: `${this.log.module}:debug_log` });
|
|
264
260
|
}
|
|
265
261
|
|
|
@@ -291,7 +287,7 @@ export class UtilityExecutionOracle extends TypedOracle {
|
|
|
291
287
|
content: Fr[],
|
|
292
288
|
noteHash: Fr,
|
|
293
289
|
nullifier: Fr,
|
|
294
|
-
txHash:
|
|
290
|
+
txHash: TxHash,
|
|
295
291
|
recipient: AztecAddress,
|
|
296
292
|
) {
|
|
297
293
|
// TODO(#10727): allow other contracts to deliver notes
|
|
@@ -370,17 +366,19 @@ export class UtilityExecutionOracle extends TypedOracle {
|
|
|
370
366
|
contractAddress: AztecAddress,
|
|
371
367
|
recipient: AztecAddress,
|
|
372
368
|
eventSelector: EventSelector,
|
|
373
|
-
|
|
369
|
+
msgContent: Fr[],
|
|
374
370
|
txHash: TxHash,
|
|
375
371
|
logIndexInTx: number,
|
|
372
|
+
txIndexInBlock: number,
|
|
376
373
|
): Promise<void> {
|
|
377
374
|
return this.executionDataProvider.storePrivateEventLog(
|
|
378
375
|
contractAddress,
|
|
379
376
|
recipient,
|
|
380
377
|
eventSelector,
|
|
381
|
-
|
|
378
|
+
msgContent,
|
|
382
379
|
txHash,
|
|
383
380
|
logIndexInTx,
|
|
381
|
+
txIndexInBlock,
|
|
384
382
|
);
|
|
385
383
|
}
|
|
386
384
|
}
|
|
@@ -44,7 +44,7 @@ export abstract class BaseAvmSimulationTester {
|
|
|
44
44
|
const leafSlot = await computePublicDataTreeLeafSlot(address, slot);
|
|
45
45
|
// get existing preimage
|
|
46
46
|
const publicDataWrite = new PublicDataWrite(leafSlot, value);
|
|
47
|
-
await this.merkleTrees.
|
|
47
|
+
await this.merkleTrees.sequentialInsert(MerkleTreeId.PUBLIC_DATA_TREE, [publicDataWrite.toBuffer()]);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -98,6 +98,6 @@ export abstract class BaseAvmSimulationTester {
|
|
|
98
98
|
AztecAddress.fromNumber(DEPLOYER_CONTRACT_ADDRESS),
|
|
99
99
|
contractAddress.toField(),
|
|
100
100
|
);
|
|
101
|
-
await this.merkleTrees.
|
|
101
|
+
await this.merkleTrees.sequentialInsert(MerkleTreeId.NULLIFIER_TREE, [contractAddressNullifier.toBuffer()]);
|
|
102
102
|
}
|
|
103
103
|
}
|
|
@@ -38,8 +38,8 @@ export function mockNoteHashExists(worldStateDB: PublicTreesDB, _leafIndex: Fr,
|
|
|
38
38
|
});
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
export function
|
|
42
|
-
(worldStateDB as jest.Mocked<PublicTreesDB>).
|
|
41
|
+
export function mockCheckNullifierExists(worldStateDB: PublicTreesDB, exists: boolean, _ignoredValue?: Fr) {
|
|
42
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).checkNullifierExists.mockResolvedValue(exists);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export function mockL1ToL2MessageExists(
|
|
@@ -1,11 +1,7 @@
|
|
|
1
|
-
import type { L1_TO_L2_MSG_TREE_HEIGHT } from '@aztec/constants';
|
|
2
1
|
import type { Fr } from '@aztec/foundation/fields';
|
|
3
2
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
4
3
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
5
4
|
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
6
|
-
import type { NullifierMembershipWitness } from '@aztec/stdlib/trees';
|
|
7
|
-
|
|
8
|
-
import type { MessageLoadOracleInputs } from './message_load_oracle_inputs.js';
|
|
9
5
|
|
|
10
6
|
/**
|
|
11
7
|
* Database interface for providing access to public state.
|
|
@@ -62,47 +58,3 @@ export interface PublicContractsDBInterface {
|
|
|
62
58
|
*/
|
|
63
59
|
getDebugFunctionName(contractAddress: AztecAddress, selector: FunctionSelector): Promise<string | undefined>;
|
|
64
60
|
}
|
|
65
|
-
|
|
66
|
-
/** Database interface for providing access to note hash tree, l1 to l2 message tree, and nullifier tree. */
|
|
67
|
-
export interface CommitmentsDBInterface {
|
|
68
|
-
/**
|
|
69
|
-
* Fetches a message from the db, given its key.
|
|
70
|
-
* @param contractAddress - Address of a contract by which the message was emitted.
|
|
71
|
-
* @param messageHash - Hash of the message.
|
|
72
|
-
* @param secret - Secret used to compute a nullifier.
|
|
73
|
-
* @dev Contract address and secret are only used to compute the nullifier to get non-nullified messages
|
|
74
|
-
* @returns The l1 to l2 membership witness (index of message in the tree and sibling path).
|
|
75
|
-
*/
|
|
76
|
-
getL1ToL2MembershipWitness(
|
|
77
|
-
contractAddress: AztecAddress,
|
|
78
|
-
messageHash: Fr,
|
|
79
|
-
secret: Fr,
|
|
80
|
-
): Promise<MessageLoadOracleInputs<typeof L1_TO_L2_MSG_TREE_HEIGHT>>;
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* @param leafIndex the leaf to look up
|
|
84
|
-
* @returns The l1 to l2 leaf message hash or undefined if not found.
|
|
85
|
-
*/
|
|
86
|
-
getL1ToL2MessageHash(leafIndex: bigint): Promise<Fr | undefined>;
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Gets note hash in the note hash tree at the given leaf index.
|
|
90
|
-
* @param leafIndex - the leaf to look up.
|
|
91
|
-
* @returns - The note hash at that index. Undefined if leaf index is not found.
|
|
92
|
-
*/
|
|
93
|
-
getNoteHash(leafIndex: bigint): Promise<Fr | undefined>;
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Gets the index of a nullifier in the nullifier tree.
|
|
97
|
-
* @param nullifier - The nullifier.
|
|
98
|
-
* @returns - The index of the nullifier. Undefined if it does not exist in the tree.
|
|
99
|
-
*/
|
|
100
|
-
getNullifierIndex(nullifier: Fr): Promise<bigint | undefined>;
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Returns a nullifier membership witness for the given nullifier or undefined if not found.
|
|
104
|
-
* REFACTOR: Same as getL1ToL2MembershipWitness, can be combined with aztec-node method that does almost the same thing.
|
|
105
|
-
* @param nullifier - Nullifier we're looking for.
|
|
106
|
-
*/
|
|
107
|
-
getNullifierMembershipWitnessAtLatestBlock(nullifier: Fr): Promise<NullifierMembershipWitness | undefined>;
|
|
108
|
-
}
|
|
@@ -1,17 +1,22 @@
|
|
|
1
|
+
import { sha256Trunc } from '@aztec/foundation/crypto';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { type Logger, createLogger } from '@aztec/foundation/log';
|
|
3
4
|
import type { IndexedTreeLeafPreimage, SiblingPath } from '@aztec/foundation/trees';
|
|
4
5
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
5
6
|
import {
|
|
7
|
+
AvmAppendLeavesHint,
|
|
6
8
|
AvmBytecodeCommitmentHint,
|
|
9
|
+
AvmCommitCheckpointHint,
|
|
7
10
|
AvmContractClassHint,
|
|
8
11
|
AvmContractInstanceHint,
|
|
12
|
+
AvmCreateCheckpointHint,
|
|
9
13
|
type AvmExecutionHints,
|
|
10
14
|
AvmGetLeafPreimageHintNullifierTree,
|
|
11
15
|
AvmGetLeafPreimageHintPublicDataTree,
|
|
12
16
|
AvmGetLeafValueHint,
|
|
13
17
|
AvmGetPreviousValueIndexHint,
|
|
14
18
|
AvmGetSiblingPathHint,
|
|
19
|
+
AvmRevertCheckpointHint,
|
|
15
20
|
AvmSequentialInsertHintNullifierTree,
|
|
16
21
|
AvmSequentialInsertHintPublicDataTree,
|
|
17
22
|
} from '@aztec/stdlib/avm';
|
|
@@ -28,11 +33,12 @@ import {
|
|
|
28
33
|
PublicDataTreeLeafPreimage,
|
|
29
34
|
type SequentialInsertionResult,
|
|
30
35
|
getTreeName,
|
|
36
|
+
merkleTreeIds,
|
|
31
37
|
} from '@aztec/stdlib/trees';
|
|
32
38
|
|
|
33
39
|
import { strict as assert } from 'assert';
|
|
34
40
|
|
|
35
|
-
import type { PublicContractsDBInterface } from '
|
|
41
|
+
import type { PublicContractsDBInterface } from './db_interfaces.js';
|
|
36
42
|
import { PublicTreesDB } from './public_db_sources.js';
|
|
37
43
|
|
|
38
44
|
/**
|
|
@@ -99,6 +105,13 @@ export class HintingPublicContractsDB implements PublicContractsDBInterface {
|
|
|
99
105
|
*/
|
|
100
106
|
export class HintingPublicTreesDB extends PublicTreesDB {
|
|
101
107
|
private static readonly log: Logger = createLogger('HintingPublicTreesDB');
|
|
108
|
+
// This stack is only for debugging purposes.
|
|
109
|
+
// The top of the stack is the current checkpoint id.
|
|
110
|
+
// We need the stack to be non-empty and use 0 as an arbitrary initial checkpoint id.
|
|
111
|
+
// This is not necessarily a checkpoint that happened, but whatever tree state we start with.
|
|
112
|
+
private checkpointStack: number[] = [0];
|
|
113
|
+
private nextCheckpointId: number = 1;
|
|
114
|
+
private checkpointActionCounter: number = 0; // yes, a side-effect counter.
|
|
102
115
|
|
|
103
116
|
constructor(db: PublicTreesDB, private hints: AvmExecutionHints) {
|
|
104
117
|
super(db);
|
|
@@ -200,11 +213,8 @@ export class HintingPublicTreesDB extends PublicTreesDB {
|
|
|
200
213
|
const result = await super.sequentialInsert<TreeHeight, ID>(treeId, leaves);
|
|
201
214
|
|
|
202
215
|
const afterState = await this.getHintKey(treeId);
|
|
203
|
-
HintingPublicTreesDB.log.debug(
|
|
204
|
-
|
|
205
|
-
afterState.root
|
|
206
|
-
}, ${afterState.nextAvailableLeafIndex}.`,
|
|
207
|
-
);
|
|
216
|
+
HintingPublicTreesDB.log.debug('[sequentialInsert] Evolved tree state.');
|
|
217
|
+
HintingPublicTreesDB.logTreeChange(beforeState, afterState, treeId);
|
|
208
218
|
|
|
209
219
|
switch (treeId) {
|
|
210
220
|
case MerkleTreeId.PUBLIC_DATA_TREE:
|
|
@@ -255,12 +265,58 @@ export class HintingPublicTreesDB extends PublicTreesDB {
|
|
|
255
265
|
return result;
|
|
256
266
|
}
|
|
257
267
|
|
|
268
|
+
public override async appendLeaves<ID extends MerkleTreeId>(
|
|
269
|
+
treeId: ID,
|
|
270
|
+
leaves: MerkleTreeLeafType<ID>[],
|
|
271
|
+
): Promise<void> {
|
|
272
|
+
// Use sequentialInsert for PublicDataTree and NullifierTree.
|
|
273
|
+
assert(treeId == MerkleTreeId.NOTE_HASH_TREE || treeId == MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
|
|
274
|
+
|
|
275
|
+
// We need to process each leaf individually because we need the sibling path after insertion, to be able to constraint the insertion.
|
|
276
|
+
// TODO(https://github.com/AztecProtocol/aztec-packages/issues/13380): This can be changed if the world state appendLeaves returns the sibling paths.
|
|
277
|
+
for (const leaf of leaves) {
|
|
278
|
+
await this.appendLeafInternal(treeId, leaf);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
public override async createCheckpoint(): Promise<void> {
|
|
283
|
+
const actionCounter = this.checkpointActionCounter++;
|
|
284
|
+
const oldCheckpointId = this.getCurrentCheckpointId();
|
|
285
|
+
const treesStateHash = await this.getTreesStateHash();
|
|
286
|
+
|
|
287
|
+
await super.createCheckpoint();
|
|
288
|
+
this.checkpointStack.push(this.nextCheckpointId++);
|
|
289
|
+
const newCheckpointId = this.getCurrentCheckpointId();
|
|
290
|
+
|
|
291
|
+
this.hints.createCheckpointHints.push(new AvmCreateCheckpointHint(actionCounter, oldCheckpointId, newCheckpointId));
|
|
292
|
+
|
|
293
|
+
HintingPublicTreesDB.log.debug(
|
|
294
|
+
`[createCheckpoint:${actionCounter}] Checkpoint evolved ${oldCheckpointId} -> ${newCheckpointId} at trees state ${treesStateHash}.`,
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
public override async commitCheckpoint(): Promise<void> {
|
|
299
|
+
const actionCounter = this.checkpointActionCounter++;
|
|
300
|
+
const oldCheckpointId = this.getCurrentCheckpointId();
|
|
301
|
+
const treesStateHash = await this.getTreesStateHash();
|
|
302
|
+
|
|
303
|
+
await super.commitCheckpoint();
|
|
304
|
+
this.checkpointStack.pop();
|
|
305
|
+
const newCheckpointId = this.getCurrentCheckpointId();
|
|
306
|
+
|
|
307
|
+
this.hints.commitCheckpointHints.push(new AvmCommitCheckpointHint(actionCounter, oldCheckpointId, newCheckpointId));
|
|
308
|
+
|
|
309
|
+
HintingPublicTreesDB.log.debug(
|
|
310
|
+
`[commitCheckpoint:${actionCounter}] Checkpoint evolved ${oldCheckpointId} -> ${newCheckpointId} at trees state ${treesStateHash}.`,
|
|
311
|
+
);
|
|
312
|
+
}
|
|
313
|
+
|
|
258
314
|
public override async revertCheckpoint(): Promise<void> {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
const beforeState = {
|
|
315
|
+
const actionCounter = this.checkpointActionCounter++;
|
|
316
|
+
const oldCheckpointId = this.getCurrentCheckpointId();
|
|
317
|
+
const treesStateHash = await this.getTreesStateHash();
|
|
318
|
+
|
|
319
|
+
const beforeState: Record<MerkleTreeId, AppendOnlyTreeSnapshot> = {
|
|
264
320
|
[MerkleTreeId.PUBLIC_DATA_TREE]: await this.getHintKey(MerkleTreeId.PUBLIC_DATA_TREE),
|
|
265
321
|
[MerkleTreeId.NULLIFIER_TREE]: await this.getHintKey(MerkleTreeId.NULLIFIER_TREE),
|
|
266
322
|
[MerkleTreeId.NOTE_HASH_TREE]: await this.getHintKey(MerkleTreeId.NOTE_HASH_TREE),
|
|
@@ -269,8 +325,10 @@ export class HintingPublicTreesDB extends PublicTreesDB {
|
|
|
269
325
|
};
|
|
270
326
|
|
|
271
327
|
await super.revertCheckpoint();
|
|
328
|
+
this.checkpointStack.pop();
|
|
329
|
+
const newCheckpointId = this.getCurrentCheckpointId();
|
|
272
330
|
|
|
273
|
-
const afterState = {
|
|
331
|
+
const afterState: Record<MerkleTreeId, AppendOnlyTreeSnapshot> = {
|
|
274
332
|
[MerkleTreeId.PUBLIC_DATA_TREE]: await this.getHintKey(MerkleTreeId.PUBLIC_DATA_TREE),
|
|
275
333
|
[MerkleTreeId.NULLIFIER_TREE]: await this.getHintKey(MerkleTreeId.NULLIFIER_TREE),
|
|
276
334
|
[MerkleTreeId.NOTE_HASH_TREE]: await this.getHintKey(MerkleTreeId.NOTE_HASH_TREE),
|
|
@@ -278,13 +336,15 @@ export class HintingPublicTreesDB extends PublicTreesDB {
|
|
|
278
336
|
[MerkleTreeId.ARCHIVE]: await this.getHintKey(MerkleTreeId.ARCHIVE),
|
|
279
337
|
};
|
|
280
338
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
339
|
+
this.hints.revertCheckpointHints.push(
|
|
340
|
+
AvmRevertCheckpointHint.create(actionCounter, oldCheckpointId, newCheckpointId, beforeState, afterState),
|
|
341
|
+
);
|
|
342
|
+
|
|
343
|
+
HintingPublicTreesDB.log.debug(
|
|
344
|
+
`[revertCheckpoint:${actionCounter}] Checkpoint evolved ${oldCheckpointId} -> ${newCheckpointId} at trees state ${treesStateHash}.`,
|
|
345
|
+
);
|
|
346
|
+
for (const treeId of merkleTreeIds()) {
|
|
347
|
+
HintingPublicTreesDB.logTreeChange(beforeState[treeId], afterState[treeId], treeId);
|
|
288
348
|
}
|
|
289
349
|
}
|
|
290
350
|
|
|
@@ -293,4 +353,46 @@ export class HintingPublicTreesDB extends PublicTreesDB {
|
|
|
293
353
|
const treeInfo = await super.getTreeInfo(treeId);
|
|
294
354
|
return new AppendOnlyTreeSnapshot(Fr.fromBuffer(treeInfo.root), Number(treeInfo.size));
|
|
295
355
|
}
|
|
356
|
+
|
|
357
|
+
private getCurrentCheckpointId(): number {
|
|
358
|
+
return this.checkpointStack[this.checkpointStack.length - 1];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
// For logging/debugging purposes.
|
|
362
|
+
private async getTreesStateHash(): Promise<Fr> {
|
|
363
|
+
const stateReferenceFields = (await super.getStateReference()).toFields();
|
|
364
|
+
return Fr.fromBuffer(sha256Trunc(Buffer.concat(stateReferenceFields.map(field => field.toBuffer()))));
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
private static logTreeChange(
|
|
368
|
+
beforeState: AppendOnlyTreeSnapshot,
|
|
369
|
+
afterState: AppendOnlyTreeSnapshot,
|
|
370
|
+
treeId: MerkleTreeId,
|
|
371
|
+
) {
|
|
372
|
+
const treeName = getTreeName(treeId);
|
|
373
|
+
HintingPublicTreesDB.log.debug(
|
|
374
|
+
`[${treeName}] Evolved tree state: ${beforeState.root}, ${beforeState.nextAvailableLeafIndex} -> ${afterState.root}, ${afterState.nextAvailableLeafIndex}.`,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
private async appendLeafInternal<ID extends MerkleTreeId, N extends number>(
|
|
379
|
+
treeId: ID,
|
|
380
|
+
leaf: MerkleTreeLeafType<ID>,
|
|
381
|
+
): Promise<SiblingPath<N>> {
|
|
382
|
+
// Use sequentialInsert for PublicDataTree and NullifierTree.
|
|
383
|
+
assert(treeId == MerkleTreeId.NOTE_HASH_TREE || treeId == MerkleTreeId.L1_TO_L2_MESSAGE_TREE);
|
|
384
|
+
|
|
385
|
+
const beforeState = await this.getHintKey(treeId);
|
|
386
|
+
|
|
387
|
+
await super.appendLeaves<ID>(treeId, [leaf]);
|
|
388
|
+
|
|
389
|
+
const afterState = await this.getHintKey(treeId);
|
|
390
|
+
|
|
391
|
+
HintingPublicTreesDB.log.debug('[appendLeaves] Evolved tree state.');
|
|
392
|
+
HintingPublicTreesDB.logTreeChange(beforeState, afterState, treeId);
|
|
393
|
+
|
|
394
|
+
this.hints.appendLeavesHints.push(new AvmAppendLeavesHint(beforeState, afterState, treeId, [leaf as Fr]));
|
|
395
|
+
|
|
396
|
+
return await this.getSiblingPath<N>(treeId, BigInt(beforeState.nextAvailableLeafIndex));
|
|
397
|
+
}
|
|
296
398
|
}
|
package/src/public/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from '
|
|
1
|
+
export * from './db_interfaces.js';
|
|
2
2
|
export * from './public_tx_simulator/index.js';
|
|
3
3
|
export * from './public_db_sources.js';
|
|
4
4
|
export { PublicProcessor, PublicProcessorFactory } from './public_processor/public_processor.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { NULLIFIER_SUBTREE_HEIGHT, PUBLIC_DATA_SUBTREE_HEIGHT } from '@aztec/constants';
|
|
1
2
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
3
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
4
|
import { Timer } from '@aztec/foundation/timer';
|
|
@@ -24,10 +25,10 @@ import type {
|
|
|
24
25
|
} from '@aztec/stdlib/interfaces/server';
|
|
25
26
|
import { ContractClassLog, PrivateLog } from '@aztec/stdlib/logs';
|
|
26
27
|
import type { PublicDBAccessStats } from '@aztec/stdlib/stats';
|
|
27
|
-
import { MerkleTreeId, type PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
|
|
28
|
+
import { MerkleTreeId, NullifierLeaf, PublicDataTreeLeaf, type PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
|
|
28
29
|
import type { BlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
29
30
|
|
|
30
|
-
import type { PublicContractsDBInterface, PublicStateDBInterface } from '
|
|
31
|
+
import type { PublicContractsDBInterface, PublicStateDBInterface } from './db_interfaces.js';
|
|
31
32
|
import { TxContractCache } from './tx_contract_cache.js';
|
|
32
33
|
|
|
33
34
|
/**
|
|
@@ -392,7 +393,7 @@ class ForwardMerkleTree implements MerkleTreeWriteOperations {
|
|
|
392
393
|
export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInterface {
|
|
393
394
|
private logger = createLogger('simulator:public-trees-db');
|
|
394
395
|
|
|
395
|
-
constructor(
|
|
396
|
+
constructor(db: MerkleTreeWriteOperations) {
|
|
396
397
|
super(db);
|
|
397
398
|
}
|
|
398
399
|
|
|
@@ -462,7 +463,7 @@ export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInt
|
|
|
462
463
|
return leafValue;
|
|
463
464
|
}
|
|
464
465
|
|
|
465
|
-
public async
|
|
466
|
+
public async checkNullifierExists(nullifier: Fr): Promise<boolean> {
|
|
466
467
|
const timer = new Timer();
|
|
467
468
|
const lowLeafResult = await this.getPreviousValueIndex(MerkleTreeId.NULLIFIER_TREE, nullifier.toBigInt());
|
|
468
469
|
if (!lowLeafResult) {
|
|
@@ -472,13 +473,40 @@ export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInt
|
|
|
472
473
|
await this.getSiblingPath(MerkleTreeId.NULLIFIER_TREE, lowLeafResult.index);
|
|
473
474
|
// TODO(fcarreiro): We need this for the hints. Might move it to the hinting layer.
|
|
474
475
|
await this.getLeafPreimage(MerkleTreeId.NULLIFIER_TREE, lowLeafResult.index);
|
|
475
|
-
const
|
|
476
|
+
const exists = lowLeafResult.alreadyPresent;
|
|
476
477
|
|
|
477
|
-
this.logger.debug(`[DB]
|
|
478
|
+
this.logger.debug(`[DB] Checked nullifier exists`, {
|
|
478
479
|
eventName: 'public-db-access',
|
|
479
480
|
duration: timer.ms(),
|
|
480
|
-
operation: '
|
|
481
|
+
operation: 'check-nullifier-exists',
|
|
481
482
|
} satisfies PublicDBAccessStats);
|
|
482
|
-
return
|
|
483
|
+
return exists;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
public async padTree(treeId: MerkleTreeId, leavesToInsert: number): Promise<void> {
|
|
487
|
+
switch (treeId) {
|
|
488
|
+
// Indexed trees.
|
|
489
|
+
case MerkleTreeId.NULLIFIER_TREE:
|
|
490
|
+
await this.batchInsert(
|
|
491
|
+
treeId,
|
|
492
|
+
Array(leavesToInsert).fill(NullifierLeaf.empty().toBuffer()),
|
|
493
|
+
NULLIFIER_SUBTREE_HEIGHT,
|
|
494
|
+
);
|
|
495
|
+
break;
|
|
496
|
+
case MerkleTreeId.PUBLIC_DATA_TREE:
|
|
497
|
+
await this.batchInsert(
|
|
498
|
+
treeId,
|
|
499
|
+
Array(leavesToInsert).fill(PublicDataTreeLeaf.empty().toBuffer()),
|
|
500
|
+
PUBLIC_DATA_SUBTREE_HEIGHT,
|
|
501
|
+
);
|
|
502
|
+
break;
|
|
503
|
+
// Non-indexed trees.
|
|
504
|
+
case MerkleTreeId.L1_TO_L2_MESSAGE_TREE:
|
|
505
|
+
case MerkleTreeId.NOTE_HASH_TREE:
|
|
506
|
+
await this.appendLeaves(treeId, Array(leavesToInsert).fill(Fr.ZERO));
|
|
507
|
+
break;
|
|
508
|
+
default:
|
|
509
|
+
throw new Error(`Padding not supported for tree ${treeId}`);
|
|
510
|
+
}
|
|
483
511
|
}
|
|
484
512
|
}
|
|
@@ -67,7 +67,6 @@ export class PublicProcessorFactory {
|
|
|
67
67
|
globalVariables,
|
|
68
68
|
/*doMerkleOperations=*/ true,
|
|
69
69
|
skipFeeEnforcement,
|
|
70
|
-
this.telemetryClient,
|
|
71
70
|
);
|
|
72
71
|
|
|
73
72
|
return new PublicProcessor(
|
|
@@ -86,7 +85,6 @@ export class PublicProcessorFactory {
|
|
|
86
85
|
globalVariables: GlobalVariables,
|
|
87
86
|
doMerkleOperations: boolean,
|
|
88
87
|
skipFeeEnforcement: boolean,
|
|
89
|
-
telemetryClient: TelemetryClient,
|
|
90
88
|
): PublicTxSimulator {
|
|
91
89
|
return new TelemetryPublicTxSimulator(
|
|
92
90
|
treesDB,
|
|
@@ -94,7 +92,7 @@ export class PublicProcessorFactory {
|
|
|
94
92
|
globalVariables,
|
|
95
93
|
doMerkleOperations,
|
|
96
94
|
skipFeeEnforcement,
|
|
97
|
-
telemetryClient,
|
|
95
|
+
this.telemetryClient,
|
|
98
96
|
);
|
|
99
97
|
}
|
|
100
98
|
}
|
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
MAX_NOTE_HASHES_PER_TX,
|
|
5
5
|
MAX_NULLIFIERS_PER_TX,
|
|
6
6
|
MAX_TOTAL_PUBLIC_DATA_UPDATE_REQUESTS_PER_TX,
|
|
7
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
8
7
|
} from '@aztec/constants';
|
|
9
8
|
import { padArrayEnd } from '@aztec/foundation/collection';
|
|
10
9
|
import { Fr } from '@aztec/foundation/fields';
|
|
@@ -111,9 +110,16 @@ export class PublicTxContext {
|
|
|
111
110
|
const firstNullifier = nonRevertibleAccumulatedDataFromPrivate.nullifiers[0];
|
|
112
111
|
|
|
113
112
|
// We wrap the DB to collect AVM hints.
|
|
114
|
-
const hints = new AvmExecutionHints(AvmTxHint.fromTx(tx));
|
|
113
|
+
const hints = new AvmExecutionHints(await AvmTxHint.fromTx(tx));
|
|
115
114
|
const hintingContractsDB = new HintingPublicContractsDB(contractsDB, hints);
|
|
116
115
|
const hintingTreesDB = new HintingPublicTreesDB(treesDB, hints);
|
|
116
|
+
const startStateReference = await treesDB.getStateReference();
|
|
117
|
+
hints.startingTreeRoots = new TreeSnapshots(
|
|
118
|
+
startStateReference.l1ToL2MessageTree,
|
|
119
|
+
startStateReference.partial.noteHashTree,
|
|
120
|
+
startStateReference.partial.nullifierTree,
|
|
121
|
+
startStateReference.partial.publicDataTree,
|
|
122
|
+
);
|
|
117
123
|
|
|
118
124
|
// Transaction level state manager that will be forked for revertible phases.
|
|
119
125
|
const txStateManager = PublicPersistableStateManager.create(
|
|
@@ -394,16 +400,10 @@ export class PublicTxContext {
|
|
|
394
400
|
);
|
|
395
401
|
const numNoteHashesToPad =
|
|
396
402
|
MAX_NOTE_HASHES_PER_TX - countAccumulatedItems(avmCircuitPublicInputs.accumulatedData.noteHashes);
|
|
397
|
-
await stateManager
|
|
398
|
-
.deprecatedGetTreesForPIGeneration()
|
|
399
|
-
.appendLeaves(MerkleTreeId.NOTE_HASH_TREE, padArrayEnd([], Fr.ZERO, numNoteHashesToPad));
|
|
403
|
+
await stateManager.deprecatedGetTreesForPIGeneration().padTree(MerkleTreeId.NOTE_HASH_TREE, numNoteHashesToPad);
|
|
400
404
|
const numNullifiersToPad =
|
|
401
405
|
MAX_NULLIFIERS_PER_TX - countAccumulatedItems(avmCircuitPublicInputs.accumulatedData.nullifiers);
|
|
402
|
-
await stateManager.deprecatedGetTreesForPIGeneration().
|
|
403
|
-
MerkleTreeId.NULLIFIER_TREE,
|
|
404
|
-
padArrayEnd([], Fr.ZERO, numNullifiersToPad).map(nullifier => nullifier.toBuffer()),
|
|
405
|
-
NULLIFIER_SUBTREE_HEIGHT,
|
|
406
|
-
);
|
|
406
|
+
await stateManager.deprecatedGetTreesForPIGeneration().padTree(MerkleTreeId.NULLIFIER_TREE, numNullifiersToPad);
|
|
407
407
|
|
|
408
408
|
const paddedState = await stateManager.deprecatedGetTreesForPIGeneration().getStateReference();
|
|
409
409
|
avmCircuitPublicInputs.endTreeSnapshots = new TreeSnapshots(
|
|
@@ -69,7 +69,6 @@ export class PublicTxSimulator {
|
|
|
69
69
|
public async simulate(tx: Tx): Promise<PublicTxResult> {
|
|
70
70
|
try {
|
|
71
71
|
const txHash = await this.computeTxHash(tx);
|
|
72
|
-
|
|
73
72
|
this.log.debug(`Simulating ${tx.publicFunctionCalldata.length} public calls for tx ${txHash}`, { txHash });
|
|
74
73
|
|
|
75
74
|
const context = await PublicTxContext.create(
|
|
@@ -437,7 +436,7 @@ export class PublicTxSimulator {
|
|
|
437
436
|
): AvmProvingRequest {
|
|
438
437
|
return {
|
|
439
438
|
type: ProvingRequestType.PUBLIC_VM,
|
|
440
|
-
inputs: new AvmCircuitInputs(
|
|
439
|
+
inputs: new AvmCircuitInputs(hints, publicInputs),
|
|
441
440
|
};
|
|
442
441
|
}
|
|
443
442
|
}
|
|
@@ -64,8 +64,8 @@ export class NullifierManager {
|
|
|
64
64
|
// `${MerkleTreeId[MerkleTreeId.NULLIFIER_TREE]} low leaf index should always be found (even if target leaf does not exist)`,
|
|
65
65
|
//);
|
|
66
66
|
//existsInTree = leafOrLowLeafIndex.alreadyPresent;
|
|
67
|
-
const
|
|
68
|
-
existsInTree =
|
|
67
|
+
const exists = await this.hostNullifiers.checkNullifierExists(siloedNullifier);
|
|
68
|
+
existsInTree = exists;
|
|
69
69
|
}
|
|
70
70
|
const exists = cacheHit || existsInTree;
|
|
71
71
|
return Promise.resolve({ exists, cacheHit });
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
3
3
|
|
|
4
|
-
import type { PublicStateDBInterface } from '
|
|
4
|
+
import type { PublicStateDBInterface } from '../db_interfaces.js';
|
|
5
5
|
|
|
6
6
|
type PublicStorageReadResult = {
|
|
7
7
|
value: Fr;
|