@aztec/simulator 0.80.0 → 0.82.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/db_interfaces.d.ts +30 -17
- package/dest/common/db_interfaces.d.ts.map +1 -1
- package/dest/common/db_interfaces.js +1 -1
- package/dest/common/debug_fn_name.d.ts +2 -2
- package/dest/common/debug_fn_name.d.ts.map +1 -1
- package/dest/common/message_load_oracle_inputs.d.ts +4 -0
- package/dest/common/message_load_oracle_inputs.d.ts.map +1 -1
- package/dest/common/message_load_oracle_inputs.js +9 -0
- package/dest/private/acvm/acvm.d.ts +6 -1
- package/dest/private/acvm/acvm.d.ts.map +1 -1
- package/dest/private/acvm/acvm.js +7 -13
- package/dest/private/acvm/deserialize.d.ts +19 -18
- package/dest/private/acvm/deserialize.d.ts.map +1 -1
- package/dest/private/acvm/deserialize.js +31 -23
- package/dest/private/acvm/oracle/oracle.d.ts +36 -34
- package/dest/private/acvm/oracle/oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/oracle.js +134 -79
- package/dest/private/acvm/oracle/typed_oracle.d.ts +3 -2
- package/dest/private/acvm/oracle/typed_oracle.d.ts.map +1 -1
- package/dest/private/acvm/oracle/typed_oracle.js +5 -2
- package/dest/private/acvm/serialize.d.ts +11 -0
- package/dest/private/acvm/serialize.d.ts.map +1 -1
- package/dest/private/acvm/serialize.js +27 -0
- package/dest/private/execution_data_provider.d.ts +15 -13
- package/dest/private/execution_data_provider.d.ts.map +1 -1
- package/dest/private/private_execution.d.ts +2 -2
- package/dest/private/private_execution.d.ts.map +1 -1
- package/dest/private/private_execution.js +4 -5
- package/dest/private/private_execution_oracle.d.ts.map +1 -1
- package/dest/private/private_execution_oracle.js +1 -1
- package/dest/private/providers/acvm_native.d.ts +6 -4
- package/dest/private/providers/acvm_native.d.ts.map +1 -1
- package/dest/private/providers/acvm_native.js +6 -3
- package/dest/private/providers/acvm_wasm.d.ts +6 -7
- package/dest/private/providers/acvm_wasm.d.ts.map +1 -1
- package/dest/private/providers/acvm_wasm.js +13 -15
- package/dest/private/providers/acvm_wasm_with_blobs.d.ts +5 -5
- package/dest/private/providers/acvm_wasm_with_blobs.d.ts.map +1 -1
- package/dest/private/providers/acvm_wasm_with_blobs.js +7 -9
- package/dest/private/providers/circuit_recording/circuit_recorder.d.ts +90 -0
- package/dest/private/providers/circuit_recording/circuit_recorder.d.ts.map +1 -0
- package/dest/private/providers/circuit_recording/circuit_recorder.js +246 -0
- package/dest/private/providers/circuit_recording/simulation_provider_recorder_wrapper.d.ts +18 -0
- package/dest/private/providers/circuit_recording/simulation_provider_recorder_wrapper.d.ts.map +1 -0
- package/dest/private/providers/circuit_recording/simulation_provider_recorder_wrapper.js +39 -0
- package/dest/private/providers/simulation_provider.d.ts +21 -7
- package/dest/private/providers/simulation_provider.d.ts.map +1 -1
- package/dest/private/simulator.d.ts +3 -2
- package/dest/private/simulator.d.ts.map +1 -1
- package/dest/private/simulator.js +2 -2
- package/dest/private/unconstrained_execution.d.ts +2 -2
- package/dest/private/unconstrained_execution.d.ts.map +1 -1
- package/dest/private/unconstrained_execution.js +1 -2
- package/dest/private/unconstrained_execution_oracle.d.ts +5 -3
- package/dest/private/unconstrained_execution_oracle.d.ts.map +1 -1
- package/dest/private/unconstrained_execution_oracle.js +9 -5
- package/dest/public/avm/avm_simulator.d.ts.map +1 -1
- package/dest/public/avm/avm_simulator.js +0 -2
- package/dest/public/avm/fixtures/avm_simulation_tester.d.ts.map +1 -1
- package/dest/public/avm/fixtures/avm_simulation_tester.js +5 -5
- package/dest/public/avm/fixtures/index.d.ts +4 -4
- package/dest/public/avm/fixtures/index.d.ts.map +1 -1
- package/dest/public/avm/fixtures/index.js +9 -6
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts +1 -2
- package/dest/public/avm/fixtures/simple_contract_data_source.d.ts.map +1 -1
- package/dest/public/avm/fixtures/simple_contract_data_source.js +0 -3
- package/dest/public/avm/journal/journal.d.ts +16 -70
- package/dest/public/avm/journal/journal.d.ts.map +1 -1
- package/dest/public/avm/journal/journal.js +88 -210
- package/dest/public/avm/journal/nullifiers.d.ts +2 -2
- package/dest/public/avm/journal/nullifiers.d.ts.map +1 -1
- package/dest/public/avm/journal/public_storage.d.ts +2 -2
- package/dest/public/avm/journal/public_storage.d.ts.map +1 -1
- package/dest/public/avm/test_utils.d.ts +10 -13
- package/dest/public/avm/test_utils.d.ts.map +1 -1
- package/dest/public/avm/test_utils.js +8 -13
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts +3 -3
- package/dest/public/fixtures/public_tx_simulation_tester.d.ts.map +1 -1
- package/dest/public/fixtures/public_tx_simulation_tester.js +10 -9
- package/dest/public/hinting_db_sources.d.ts +19 -0
- package/dest/public/hinting_db_sources.d.ts.map +1 -0
- package/dest/public/hinting_db_sources.js +36 -0
- package/dest/public/public_db_sources.d.ts +46 -22
- package/dest/public/public_db_sources.d.ts.map +1 -1
- package/dest/public/public_db_sources.js +82 -27
- package/dest/public/public_processor/public_processor.d.ts +5 -5
- package/dest/public/public_processor/public_processor.d.ts.map +1 -1
- package/dest/public/public_processor/public_processor.js +21 -20
- package/dest/public/public_tx_simulator/public_tx_context.d.ts +9 -14
- package/dest/public/public_tx_simulator/public_tx_context.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_context.js +15 -19
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts +9 -6
- package/dest/public/public_tx_simulator/public_tx_simulator.d.ts.map +1 -1
- package/dest/public/public_tx_simulator/public_tx_simulator.js +28 -14
- package/dest/public/side_effect_trace.d.ts +6 -22
- package/dest/public/side_effect_trace.d.ts.map +1 -1
- package/dest/public/side_effect_trace.js +11 -70
- package/dest/public/side_effect_trace_interface.d.ts +5 -19
- package/dest/public/side_effect_trace_interface.d.ts.map +1 -1
- package/dest/testing.d.ts +2 -0
- package/dest/testing.d.ts.map +1 -0
- package/dest/testing.js +1 -0
- package/package.json +15 -14
- package/src/common/db_interfaces.ts +32 -18
- package/src/common/debug_fn_name.ts +2 -2
- package/src/common/message_load_oracle_inputs.ts +8 -0
- package/src/private/acvm/acvm.ts +8 -24
- package/src/private/acvm/deserialize.ts +35 -29
- package/src/private/acvm/oracle/oracle.ts +171 -129
- package/src/private/acvm/oracle/typed_oracle.ts +7 -3
- package/src/private/acvm/serialize.ts +28 -0
- package/src/private/execution_data_provider.ts +19 -14
- package/src/private/private_execution.ts +11 -7
- package/src/private/private_execution_oracle.ts +5 -1
- package/src/private/providers/acvm_native.ts +17 -6
- package/src/private/providers/acvm_wasm.ts +27 -20
- package/src/private/providers/acvm_wasm_with_blobs.ts +15 -12
- package/src/private/providers/circuit_recording/circuit_recorder.ts +283 -0
- package/src/private/providers/circuit_recording/simulation_provider_recorder_wrapper.ts +82 -0
- package/src/private/providers/simulation_provider.ts +30 -5
- package/src/private/simulator.ts +5 -3
- package/src/private/unconstrained_execution.ts +8 -4
- package/src/private/unconstrained_execution_oracle.ts +15 -9
- package/src/public/avm/avm_simulator.ts +0 -2
- package/src/public/avm/fixtures/avm_simulation_tester.ts +8 -5
- package/src/public/avm/fixtures/index.ts +16 -10
- package/src/public/avm/fixtures/simple_contract_data_source.ts +1 -10
- package/src/public/avm/journal/journal.ts +119 -353
- package/src/public/avm/journal/nullifiers.ts +2 -2
- package/src/public/avm/journal/public_storage.ts +2 -2
- package/src/public/avm/test_utils.ts +20 -29
- package/src/public/fixtures/public_tx_simulation_tester.ts +9 -12
- package/src/public/hinting_db_sources.ts +71 -0
- package/src/public/public_db_sources.ts +134 -32
- package/src/public/public_processor/public_processor.ts +22 -21
- package/src/public/public_tx_simulator/public_tx_context.ts +30 -38
- package/src/public/public_tx_simulator/public_tx_simulator.ts +47 -17
- package/src/public/side_effect_trace.ts +8 -172
- package/src/public/side_effect_trace_interface.ts +4 -55
- package/src/testing.ts +1 -0
- package/dest/public/avm/bytecode_utils.d.ts +0 -5
- package/dest/public/avm/bytecode_utils.d.ts.map +0 -1
- package/dest/public/avm/bytecode_utils.js +0 -17
- package/src/public/avm/bytecode_utils.ts +0 -17
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { PublicTreesDB } from '../../public_db_sources.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* A class to manage new nullifier staging and existence checks during a contract call's AVM simulation.
|
|
@@ -10,7 +10,7 @@ import type { WorldStateDB } from '../../public_db_sources.js';
|
|
|
10
10
|
export class NullifierManager {
|
|
11
11
|
constructor(
|
|
12
12
|
/** Reference to node storage. Checked on parent cache-miss. */
|
|
13
|
-
private readonly hostNullifiers:
|
|
13
|
+
private readonly hostNullifiers: PublicTreesDB,
|
|
14
14
|
/** Cache of siloed nullifiers. */
|
|
15
15
|
private cache: Set<bigint> = new Set(),
|
|
16
16
|
/** Parent nullifier manager to fall back on */
|
|
@@ -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 {
|
|
4
|
+
import type { PublicStateDBInterface } from '../../../common/db_interfaces.js';
|
|
5
5
|
|
|
6
6
|
type PublicStorageReadResult = {
|
|
7
7
|
value: Fr;
|
|
@@ -19,7 +19,7 @@ export class PublicStorage {
|
|
|
19
19
|
|
|
20
20
|
constructor(
|
|
21
21
|
/** Reference to node storage. Checked on parent cache-miss. */
|
|
22
|
-
private readonly hostPublicStorage:
|
|
22
|
+
private readonly hostPublicStorage: PublicStateDBInterface,
|
|
23
23
|
/** Parent's storage. Checked on this' cache-miss. */
|
|
24
24
|
private readonly parent?: PublicStorage,
|
|
25
25
|
) {
|
|
@@ -1,47 +1,34 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
|
-
import {
|
|
3
|
-
type ContractClassPublic,
|
|
4
|
-
type ContractInstanceWithAddress,
|
|
5
|
-
computePublicBytecodeCommitment,
|
|
6
|
-
} from '@aztec/stdlib/contract';
|
|
2
|
+
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
7
3
|
|
|
8
4
|
import type { jest } from '@jest/globals';
|
|
9
5
|
import { mock } from 'jest-mock-extended';
|
|
10
6
|
|
|
11
|
-
import type {
|
|
7
|
+
import type { PublicContractsDB, PublicTreesDB } from '../../public/public_db_sources.js';
|
|
12
8
|
import type { PublicSideEffectTraceInterface } from '../side_effect_trace_interface.js';
|
|
13
9
|
|
|
14
|
-
export async function mockGetBytecode(worldStateDB: WorldStateDB, bytecode: Buffer) {
|
|
15
|
-
const commitment = await computePublicBytecodeCommitment(bytecode);
|
|
16
|
-
(worldStateDB as jest.Mocked<WorldStateDB>).getBytecodeCommitment.mockResolvedValue(commitment);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
10
|
export function mockTraceFork(trace: PublicSideEffectTraceInterface, nestedTrace?: PublicSideEffectTraceInterface) {
|
|
20
11
|
(trace as jest.Mocked<PublicSideEffectTraceInterface>).fork.mockReturnValue(
|
|
21
12
|
nestedTrace ?? mock<PublicSideEffectTraceInterface>(),
|
|
22
13
|
);
|
|
23
14
|
}
|
|
24
15
|
|
|
25
|
-
export function mockStorageRead(worldStateDB:
|
|
26
|
-
(worldStateDB as jest.Mocked<
|
|
16
|
+
export function mockStorageRead(worldStateDB: PublicTreesDB, value: Fr) {
|
|
17
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).storageRead.mockResolvedValue(value);
|
|
27
18
|
}
|
|
28
19
|
|
|
29
20
|
export function mockNoteHashCount(mockedTrace: PublicSideEffectTraceInterface, count: number) {
|
|
30
21
|
(mockedTrace as jest.Mocked<PublicSideEffectTraceInterface>).getNoteHashCount.mockReturnValue(count);
|
|
31
22
|
}
|
|
32
23
|
|
|
33
|
-
export function mockStorageReadWithMap(worldStateDB:
|
|
34
|
-
(worldStateDB as jest.Mocked<
|
|
24
|
+
export function mockStorageReadWithMap(worldStateDB: PublicTreesDB, mockedStorage: Map<bigint, Fr>) {
|
|
25
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).storageRead.mockImplementation((_address, slot) =>
|
|
35
26
|
Promise.resolve(mockedStorage.get(slot.toBigInt()) ?? Fr.ZERO),
|
|
36
27
|
);
|
|
37
28
|
}
|
|
38
29
|
|
|
39
|
-
export function
|
|
40
|
-
(worldStateDB as jest.Mocked<
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
export function mockNoteHashExists(worldStateDB: WorldStateDB, _leafIndex: Fr, value?: Fr) {
|
|
44
|
-
(worldStateDB as jest.Mocked<WorldStateDB>).getCommitmentValue.mockImplementation((index: bigint) => {
|
|
30
|
+
export function mockNoteHashExists(worldStateDB: PublicTreesDB, _leafIndex: Fr, value?: Fr) {
|
|
31
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).getNoteHash.mockImplementation((index: bigint) => {
|
|
45
32
|
if (index == _leafIndex.toBigInt()) {
|
|
46
33
|
return Promise.resolve(value);
|
|
47
34
|
} else {
|
|
@@ -51,17 +38,17 @@ export function mockNoteHashExists(worldStateDB: WorldStateDB, _leafIndex: Fr, v
|
|
|
51
38
|
});
|
|
52
39
|
}
|
|
53
40
|
|
|
54
|
-
export function mockGetNullifierIndex(worldStateDB:
|
|
55
|
-
(worldStateDB as jest.Mocked<
|
|
41
|
+
export function mockGetNullifierIndex(worldStateDB: PublicTreesDB, leafIndex: Fr, _ignoredValue?: Fr) {
|
|
42
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).getNullifierIndex.mockResolvedValue(leafIndex.toBigInt());
|
|
56
43
|
}
|
|
57
44
|
|
|
58
45
|
export function mockL1ToL2MessageExists(
|
|
59
|
-
worldStateDB:
|
|
46
|
+
worldStateDB: PublicTreesDB,
|
|
60
47
|
leafIndex: Fr,
|
|
61
48
|
value: Fr,
|
|
62
49
|
valueAtOtherIndices?: Fr,
|
|
63
50
|
) {
|
|
64
|
-
(worldStateDB as jest.Mocked<
|
|
51
|
+
(worldStateDB as jest.Mocked<PublicTreesDB>).getL1ToL2LeafValue.mockImplementation((index: bigint) => {
|
|
65
52
|
if (index == leafIndex.toBigInt()) {
|
|
66
53
|
return Promise.resolve(value);
|
|
67
54
|
} else {
|
|
@@ -72,10 +59,14 @@ export function mockL1ToL2MessageExists(
|
|
|
72
59
|
});
|
|
73
60
|
}
|
|
74
61
|
|
|
75
|
-
export function mockGetContractInstance(
|
|
76
|
-
(
|
|
62
|
+
export function mockGetContractInstance(contractsDB: PublicContractsDB, contractInstance: ContractInstanceWithAddress) {
|
|
63
|
+
(contractsDB as jest.Mocked<PublicContractsDB>).getContractInstance.mockResolvedValue(contractInstance);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function mockGetContractClass(contractsDB: PublicContractsDB, contractClass: ContractClassPublic) {
|
|
67
|
+
(contractsDB as jest.Mocked<PublicContractsDB>).getContractClass.mockResolvedValue(contractClass);
|
|
77
68
|
}
|
|
78
69
|
|
|
79
|
-
export function
|
|
80
|
-
(
|
|
70
|
+
export function mockGetBytecodeCommitment(contractsDB: PublicContractsDB, commitment: Fr) {
|
|
71
|
+
(contractsDB as jest.Mocked<PublicContractsDB>).getBytecodeCommitment.mockResolvedValue(commitment);
|
|
81
72
|
}
|
|
@@ -11,7 +11,7 @@ import { NativeWorldStateService } from '@aztec/world-state';
|
|
|
11
11
|
import { BaseAvmSimulationTester } from '../avm/fixtures/base_avm_simulation_tester.js';
|
|
12
12
|
import { getContractFunctionArtifact, getFunctionSelector } from '../avm/fixtures/index.js';
|
|
13
13
|
import { SimpleContractDataSource } from '../avm/fixtures/simple_contract_data_source.js';
|
|
14
|
-
import {
|
|
14
|
+
import { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
15
15
|
import { type PublicTxResult, PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
|
|
16
16
|
import { createTxForPublicCalls } from './index.js';
|
|
17
17
|
|
|
@@ -35,19 +35,14 @@ export type TestEnqueuedCall = {
|
|
|
35
35
|
export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
36
36
|
private txCount = 0;
|
|
37
37
|
|
|
38
|
-
constructor(
|
|
39
|
-
|
|
40
|
-
contractDataSource: SimpleContractDataSource,
|
|
41
|
-
merkleTrees: MerkleTreeWriteOperations,
|
|
42
|
-
) {
|
|
43
|
-
super(contractDataSource, merkleTrees);
|
|
38
|
+
constructor(private merkleTree: MerkleTreeWriteOperations, contractDataSource: SimpleContractDataSource) {
|
|
39
|
+
super(contractDataSource, merkleTree);
|
|
44
40
|
}
|
|
45
41
|
|
|
46
42
|
public static async create(): Promise<PublicTxSimulationTester> {
|
|
47
43
|
const contractDataSource = new SimpleContractDataSource();
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
return new PublicTxSimulationTester(worldStateDB, contractDataSource, merkleTrees);
|
|
44
|
+
const merkleTree = await (await NativeWorldStateService.tmp()).fork();
|
|
45
|
+
return new PublicTxSimulationTester(merkleTree, contractDataSource);
|
|
51
46
|
}
|
|
52
47
|
|
|
53
48
|
public async createTx(
|
|
@@ -137,7 +132,9 @@ export class PublicTxSimulationTester extends BaseAvmSimulationTester {
|
|
|
137
132
|
|
|
138
133
|
await this.setFeePayerBalance(feePayer);
|
|
139
134
|
|
|
140
|
-
const
|
|
135
|
+
const treesDB = new PublicTreesDB(this.merkleTree);
|
|
136
|
+
const contractsDB = new PublicContractsDB(this.contractDataSource);
|
|
137
|
+
const simulator = new PublicTxSimulator(treesDB, contractsDB, globals, /*doMerkleOperations=*/ true);
|
|
141
138
|
|
|
142
139
|
const startTime = performance.now();
|
|
143
140
|
const avmResult = await simulator.simulate(tx);
|
|
@@ -170,7 +167,7 @@ async function executionRequestForCall(
|
|
|
170
167
|
return new PublicExecutionRequest(callContext, calldata);
|
|
171
168
|
}
|
|
172
169
|
|
|
173
|
-
function defaultGlobals() {
|
|
170
|
+
export function defaultGlobals() {
|
|
174
171
|
const globals = GlobalVariables.empty();
|
|
175
172
|
globals.timestamp = TIMESTAMP;
|
|
176
173
|
globals.gasFees = DEFAULT_GAS_FEES; // apply some nonzero default gas fees
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import type { Fr } from '@aztec/foundation/fields';
|
|
2
|
+
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
3
|
+
import {
|
|
4
|
+
AvmBytecodeCommitmentHint,
|
|
5
|
+
AvmContractClassHint,
|
|
6
|
+
AvmContractInstanceHint,
|
|
7
|
+
type AvmExecutionHints,
|
|
8
|
+
} from '@aztec/stdlib/avm';
|
|
9
|
+
import type { AztecAddress } from '@aztec/stdlib/aztec-address';
|
|
10
|
+
import type { ContractClassPublic, ContractInstanceWithAddress } from '@aztec/stdlib/contract';
|
|
11
|
+
|
|
12
|
+
import type { PublicContractsDBInterface } from '../server.js';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* A public contracts database that forwards requests and collects AVM hints.
|
|
16
|
+
*/
|
|
17
|
+
export class HintingPublicContractsDB implements PublicContractsDBInterface {
|
|
18
|
+
constructor(private readonly db: PublicContractsDBInterface, public readonly hints: AvmExecutionHints) {}
|
|
19
|
+
|
|
20
|
+
public async getContractInstance(
|
|
21
|
+
address: AztecAddress,
|
|
22
|
+
blockNumber: number,
|
|
23
|
+
): Promise<ContractInstanceWithAddress | undefined> {
|
|
24
|
+
const instance = await this.db.getContractInstance(address, blockNumber);
|
|
25
|
+
if (instance) {
|
|
26
|
+
// We don't need to hint the block number because it doesn't change.
|
|
27
|
+
this.hints.contractInstances.push(
|
|
28
|
+
new AvmContractInstanceHint(
|
|
29
|
+
instance.address,
|
|
30
|
+
instance.salt,
|
|
31
|
+
instance.deployer,
|
|
32
|
+
instance.currentContractClassId,
|
|
33
|
+
instance.originalContractClassId,
|
|
34
|
+
instance.initializationHash,
|
|
35
|
+
instance.publicKeys,
|
|
36
|
+
),
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
return instance;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public async getContractClass(contractClassId: Fr): Promise<ContractClassPublic | undefined> {
|
|
43
|
+
const contractClass = await this.db.getContractClass(contractClassId);
|
|
44
|
+
if (contractClass) {
|
|
45
|
+
this.hints.contractClasses.push(
|
|
46
|
+
new AvmContractClassHint(
|
|
47
|
+
contractClass.id,
|
|
48
|
+
contractClass.artifactHash,
|
|
49
|
+
contractClass.privateFunctionsRoot,
|
|
50
|
+
contractClass.packedBytecode,
|
|
51
|
+
),
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return contractClass;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
public async getBytecodeCommitment(contractClassId: Fr): Promise<Fr | undefined> {
|
|
58
|
+
const commitment = await this.db.getBytecodeCommitment(contractClassId);
|
|
59
|
+
if (commitment) {
|
|
60
|
+
this.hints.bytecodeCommitments.push(new AvmBytecodeCommitmentHint(contractClassId, commitment));
|
|
61
|
+
}
|
|
62
|
+
return commitment;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
public async getDebugFunctionName(
|
|
66
|
+
contractAddress: AztecAddress,
|
|
67
|
+
selector: FunctionSelector,
|
|
68
|
+
): Promise<string | undefined> {
|
|
69
|
+
return await this.db.getDebugFunctionName(contractAddress, selector);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Fr } from '@aztec/foundation/fields';
|
|
2
2
|
import { createLogger } from '@aztec/foundation/log';
|
|
3
3
|
import { Timer } from '@aztec/foundation/timer';
|
|
4
|
+
import type { IndexedTreeLeafPreimage, SiblingPath } from '@aztec/foundation/trees';
|
|
4
5
|
import { ContractClassRegisteredEvent } from '@aztec/protocol-contracts/class-registerer';
|
|
5
6
|
import { ContractInstanceDeployedEvent } from '@aztec/protocol-contracts/instance-deployer';
|
|
6
7
|
import type { FunctionSelector } from '@aztec/stdlib/abi';
|
|
@@ -14,25 +15,29 @@ import {
|
|
|
14
15
|
} from '@aztec/stdlib/contract';
|
|
15
16
|
import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
|
|
16
17
|
import type {
|
|
17
|
-
|
|
18
|
+
BatchInsertionResult,
|
|
19
|
+
IndexedTreeId,
|
|
20
|
+
MerkleTreeLeafType,
|
|
18
21
|
MerkleTreeReadOperations,
|
|
19
22
|
MerkleTreeWriteOperations,
|
|
23
|
+
SequentialInsertionResult,
|
|
24
|
+
TreeInfo,
|
|
20
25
|
} from '@aztec/stdlib/interfaces/server';
|
|
21
26
|
import { ContractClassLog, PrivateLog } from '@aztec/stdlib/logs';
|
|
22
27
|
import type { PublicDBAccessStats } from '@aztec/stdlib/stats';
|
|
23
28
|
import { MerkleTreeId, type PublicDataTreeLeafPreimage } from '@aztec/stdlib/trees';
|
|
24
|
-
import type { Tx } from '@aztec/stdlib/tx';
|
|
29
|
+
import type { BlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
|
|
25
30
|
|
|
26
|
-
import type {
|
|
31
|
+
import type { PublicContractsDBInterface, PublicStateDBInterface } from '../common/db_interfaces.js';
|
|
27
32
|
import { TxContractCache } from './tx_contract_cache.js';
|
|
28
33
|
|
|
29
34
|
/**
|
|
30
|
-
* Implements the
|
|
35
|
+
* Implements the PublicContractsDBInterface using a ContractDataSource.
|
|
31
36
|
* Progressively records contracts in transaction as they are processed in a block.
|
|
32
37
|
* Separates block-level contract information (from processed/included txs) from the
|
|
33
38
|
* current tx's contract information (which may be cleared on tx revert/death).
|
|
34
39
|
*/
|
|
35
|
-
export class
|
|
40
|
+
export class PublicContractsDB implements PublicContractsDBInterface {
|
|
36
41
|
// Two caching layers for contract classes and instances.
|
|
37
42
|
// Tx-level cache:
|
|
38
43
|
// - The current tx's new contract information is cached
|
|
@@ -210,13 +215,23 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
|
|
|
210
215
|
this.currentTxRevertibleCache.clear();
|
|
211
216
|
}
|
|
212
217
|
|
|
213
|
-
|
|
218
|
+
// TODO(fcarreiro/alvaro): This method currently needs a blockNumber. Since this class
|
|
219
|
+
// is only ever used for a given block, it should be possible to construct it with the
|
|
220
|
+
// block number and then forget about it. However, since this class (and interface) is
|
|
221
|
+
// currently more externally exposed than we'd want to, Facundo preferred to not add it
|
|
222
|
+
// to the constructor right now. If we can make this class more private, we should
|
|
223
|
+
// reconsider this. A litmus test is in how many places we need to initialize with a
|
|
224
|
+
// dummy block number (tests or not) and pass block numbers to `super`.
|
|
225
|
+
public async getContractInstance(
|
|
226
|
+
address: AztecAddress,
|
|
227
|
+
blockNumber: number,
|
|
228
|
+
): Promise<ContractInstanceWithAddress | undefined> {
|
|
214
229
|
// Check caches in order: tx revertible -> tx non-revertible -> block -> data source
|
|
215
230
|
return (
|
|
216
231
|
this.currentTxRevertibleCache.getInstance(address) ??
|
|
217
232
|
this.currentTxNonRevertibleCache.getInstance(address) ??
|
|
218
233
|
this.blockCache.getInstance(address) ??
|
|
219
|
-
(await this.dataSource.getContract(address))
|
|
234
|
+
(await this.dataSource.getContract(address, blockNumber))
|
|
220
235
|
);
|
|
221
236
|
}
|
|
222
237
|
|
|
@@ -261,38 +276,125 @@ export class ContractsDataSourcePublicDB implements PublicContractsDB {
|
|
|
261
276
|
}
|
|
262
277
|
|
|
263
278
|
/**
|
|
264
|
-
*
|
|
279
|
+
* Proxy class that forwards all merkle tree operations to the underlying object.
|
|
280
|
+
*
|
|
281
|
+
* NOTE: It might be possible to prune this to just the methods used in public.
|
|
282
|
+
* Then we'd need to define a new interface, instead of MerkleTreeWriteOperations,
|
|
283
|
+
* to be used by all our classes (that could be PublicStateDBInterface).
|
|
265
284
|
*/
|
|
266
|
-
|
|
267
|
-
private
|
|
285
|
+
class ForwardMerkleTree implements MerkleTreeWriteOperations {
|
|
286
|
+
constructor(private readonly operations: MerkleTreeWriteOperations) {}
|
|
268
287
|
|
|
269
|
-
|
|
270
|
-
|
|
288
|
+
getTreeInfo(treeId: MerkleTreeId): Promise<TreeInfo> {
|
|
289
|
+
return this.operations.getTreeInfo(treeId);
|
|
271
290
|
}
|
|
272
291
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
*/
|
|
276
|
-
public async createCheckpoint() {
|
|
277
|
-
await this.db.createCheckpoint();
|
|
292
|
+
getStateReference(): Promise<StateReference> {
|
|
293
|
+
return this.operations.getStateReference();
|
|
278
294
|
}
|
|
279
295
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
*/
|
|
283
|
-
public async commitCheckpoint() {
|
|
284
|
-
await this.db.commitCheckpoint();
|
|
296
|
+
getInitialHeader(): BlockHeader {
|
|
297
|
+
return this.operations.getInitialHeader();
|
|
285
298
|
}
|
|
286
299
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
300
|
+
getSiblingPath<N extends number>(treeId: MerkleTreeId, index: bigint): Promise<SiblingPath<N>> {
|
|
301
|
+
return this.operations.getSiblingPath(treeId, index);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
getPreviousValueIndex<ID extends IndexedTreeId>(
|
|
305
|
+
treeId: ID,
|
|
306
|
+
value: bigint,
|
|
307
|
+
): Promise<
|
|
308
|
+
| {
|
|
309
|
+
index: bigint;
|
|
310
|
+
alreadyPresent: boolean;
|
|
311
|
+
}
|
|
312
|
+
| undefined
|
|
313
|
+
> {
|
|
314
|
+
return this.operations.getPreviousValueIndex(treeId, value);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
getLeafPreimage<ID extends IndexedTreeId>(treeId: ID, index: bigint): Promise<IndexedTreeLeafPreimage | undefined> {
|
|
318
|
+
return this.operations.getLeafPreimage(treeId, index);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
findLeafIndices<ID extends MerkleTreeId>(
|
|
322
|
+
treeId: ID,
|
|
323
|
+
values: MerkleTreeLeafType<ID>[],
|
|
324
|
+
): Promise<(bigint | undefined)[]> {
|
|
325
|
+
return this.operations.findLeafIndices(treeId, values);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
findLeafIndicesAfter<ID extends MerkleTreeId>(
|
|
329
|
+
treeId: ID,
|
|
330
|
+
values: MerkleTreeLeafType<ID>[],
|
|
331
|
+
startIndex: bigint,
|
|
332
|
+
): Promise<(bigint | undefined)[]> {
|
|
333
|
+
return this.operations.findLeafIndicesAfter(treeId, values, startIndex);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
getLeafValue<ID extends MerkleTreeId>(
|
|
337
|
+
treeId: ID,
|
|
338
|
+
index: bigint,
|
|
339
|
+
): Promise<MerkleTreeLeafType<typeof treeId> | undefined> {
|
|
340
|
+
return this.operations.getLeafValue(treeId, index);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
getBlockNumbersForLeafIndices<ID extends MerkleTreeId>(
|
|
344
|
+
treeId: ID,
|
|
345
|
+
leafIndices: bigint[],
|
|
346
|
+
): Promise<(bigint | undefined)[]> {
|
|
347
|
+
return this.operations.getBlockNumbersForLeafIndices(treeId, leafIndices);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
createCheckpoint(): Promise<void> {
|
|
351
|
+
return this.operations.createCheckpoint();
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
commitCheckpoint(): Promise<void> {
|
|
355
|
+
return this.operations.commitCheckpoint();
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
revertCheckpoint(): Promise<void> {
|
|
359
|
+
return this.operations.revertCheckpoint();
|
|
292
360
|
}
|
|
293
361
|
|
|
294
|
-
|
|
295
|
-
return this.
|
|
362
|
+
appendLeaves<ID extends MerkleTreeId>(treeId: ID, leaves: MerkleTreeLeafType<ID>[]): Promise<void> {
|
|
363
|
+
return this.operations.appendLeaves(treeId, leaves);
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
updateArchive(header: BlockHeader): Promise<void> {
|
|
367
|
+
return this.operations.updateArchive(header);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
batchInsert<TreeHeight extends number, SubtreeSiblingPathHeight extends number, ID extends IndexedTreeId>(
|
|
371
|
+
treeId: ID,
|
|
372
|
+
leaves: Buffer[],
|
|
373
|
+
subtreeHeight: number,
|
|
374
|
+
): Promise<BatchInsertionResult<TreeHeight, SubtreeSiblingPathHeight>> {
|
|
375
|
+
return this.operations.batchInsert(treeId, leaves, subtreeHeight);
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
sequentialInsert<TreeHeight extends number, ID extends IndexedTreeId>(
|
|
379
|
+
treeId: ID,
|
|
380
|
+
leaves: Buffer[],
|
|
381
|
+
): Promise<SequentialInsertionResult<TreeHeight>> {
|
|
382
|
+
return this.operations.sequentialInsert(treeId, leaves);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
close(): Promise<void> {
|
|
386
|
+
return this.operations.close();
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
/**
|
|
391
|
+
* A class that provides access to the merkle trees, and other helper methods.
|
|
392
|
+
*/
|
|
393
|
+
export class PublicTreesDB extends ForwardMerkleTree implements PublicStateDBInterface {
|
|
394
|
+
private logger = createLogger('simulator:public-trees-db');
|
|
395
|
+
|
|
396
|
+
constructor(public db: MerkleTreeWriteOperations) {
|
|
397
|
+
super(db);
|
|
296
398
|
}
|
|
297
399
|
|
|
298
400
|
/**
|
|
@@ -329,13 +431,13 @@ export class WorldStateDB extends ContractsDataSourcePublicDB implements PublicS
|
|
|
329
431
|
return leafValue;
|
|
330
432
|
}
|
|
331
433
|
|
|
332
|
-
public async
|
|
434
|
+
public async getNoteHash(leafIndex: bigint): Promise<Fr | undefined> {
|
|
333
435
|
const timer = new Timer();
|
|
334
436
|
const leafValue = await this.db.getLeafValue(MerkleTreeId.NOTE_HASH_TREE, leafIndex);
|
|
335
|
-
this.logger.debug(`[DB] Fetched
|
|
437
|
+
this.logger.debug(`[DB] Fetched note hash leaf value`, {
|
|
336
438
|
eventName: 'public-db-access',
|
|
337
439
|
duration: timer.ms(),
|
|
338
|
-
operation: 'get-
|
|
440
|
+
operation: 'get-note-hash',
|
|
339
441
|
} satisfies PublicDBAccessStats);
|
|
340
442
|
return leafValue;
|
|
341
443
|
}
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
} from '@aztec/telemetry-client';
|
|
34
34
|
import { ForkCheckpoint } from '@aztec/world-state/native';
|
|
35
35
|
|
|
36
|
-
import {
|
|
36
|
+
import { PublicContractsDB, PublicTreesDB } from '../public_db_sources.js';
|
|
37
37
|
import { PublicTxSimulator } from '../public_tx_simulator/public_tx_simulator.js';
|
|
38
38
|
import { PublicProcessorMetrics } from './public_processor_metrics.js';
|
|
39
39
|
|
|
@@ -59,10 +59,11 @@ export class PublicProcessorFactory {
|
|
|
59
59
|
globalVariables: GlobalVariables,
|
|
60
60
|
skipFeeEnforcement: boolean,
|
|
61
61
|
): PublicProcessor {
|
|
62
|
-
const
|
|
62
|
+
const treesDB = new PublicTreesDB(merkleTree);
|
|
63
|
+
const contractsDB = new PublicContractsDB(this.contractDataSource);
|
|
63
64
|
const publicTxSimulator = this.createPublicTxSimulator(
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
treesDB,
|
|
66
|
+
contractsDB,
|
|
66
67
|
globalVariables,
|
|
67
68
|
/*doMerkleOperations=*/ true,
|
|
68
69
|
skipFeeEnforcement,
|
|
@@ -70,9 +71,9 @@ export class PublicProcessorFactory {
|
|
|
70
71
|
);
|
|
71
72
|
|
|
72
73
|
return new PublicProcessor(
|
|
73
|
-
merkleTree,
|
|
74
74
|
globalVariables,
|
|
75
|
-
|
|
75
|
+
treesDB,
|
|
76
|
+
contractsDB,
|
|
76
77
|
publicTxSimulator,
|
|
77
78
|
this.dateProvider,
|
|
78
79
|
this.telemetryClient,
|
|
@@ -80,16 +81,16 @@ export class PublicProcessorFactory {
|
|
|
80
81
|
}
|
|
81
82
|
|
|
82
83
|
protected createPublicTxSimulator(
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
treesDB: PublicTreesDB,
|
|
85
|
+
contractsDB: PublicContractsDB,
|
|
85
86
|
globalVariables: GlobalVariables,
|
|
86
87
|
doMerkleOperations: boolean,
|
|
87
88
|
skipFeeEnforcement: boolean,
|
|
88
89
|
telemetryClient: TelemetryClient,
|
|
89
90
|
) {
|
|
90
91
|
return new PublicTxSimulator(
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
treesDB,
|
|
93
|
+
contractsDB,
|
|
93
94
|
globalVariables,
|
|
94
95
|
doMerkleOperations,
|
|
95
96
|
skipFeeEnforcement,
|
|
@@ -112,9 +113,9 @@ class PublicProcessorTimeoutError extends Error {
|
|
|
112
113
|
export class PublicProcessor implements Traceable {
|
|
113
114
|
private metrics: PublicProcessorMetrics;
|
|
114
115
|
constructor(
|
|
115
|
-
protected db: MerkleTreeWriteOperations,
|
|
116
116
|
protected globalVariables: GlobalVariables,
|
|
117
|
-
protected
|
|
117
|
+
protected treesDB: PublicTreesDB,
|
|
118
|
+
protected contractsDB: PublicContractsDB,
|
|
118
119
|
protected publicTxSimulator: PublicTxSimulator,
|
|
119
120
|
private dateProvider: DateProvider,
|
|
120
121
|
telemetryClient: TelemetryClient = getTelemetryClient(),
|
|
@@ -222,7 +223,7 @@ export class PublicProcessor implements Traceable {
|
|
|
222
223
|
// We checkpoint the transaction here, then within the try/catch we
|
|
223
224
|
// 1. Revert the checkpoint if the tx fails or needs to be discarded for any reason
|
|
224
225
|
// 2. Commit the transaction in the finally block. Note that by using the ForkCheckpoint lifecycle only the first commit/revert takes effect
|
|
225
|
-
const checkpoint = await ForkCheckpoint.new(this.
|
|
226
|
+
const checkpoint = await ForkCheckpoint.new(this.treesDB);
|
|
226
227
|
|
|
227
228
|
try {
|
|
228
229
|
const [processedTx, returnValues] = await this.processTx(tx, deadline);
|
|
@@ -267,8 +268,8 @@ export class PublicProcessor implements Traceable {
|
|
|
267
268
|
await this.doTreeInsertionsForPrivateOnlyTx(processedTx);
|
|
268
269
|
// Add any contracts registered/deployed in this private-only tx to the block-level cache
|
|
269
270
|
// (add to tx-level cache and then commit to block-level cache)
|
|
270
|
-
await this.
|
|
271
|
-
this.
|
|
271
|
+
await this.contractsDB.addNewContracts(tx);
|
|
272
|
+
this.contractsDB.commitContractsForTx();
|
|
272
273
|
}
|
|
273
274
|
|
|
274
275
|
nullifierCache?.addNullifiers(processedTx.txEffect.nullifiers.map(n => n.toBuffer()));
|
|
@@ -294,7 +295,7 @@ export class PublicProcessor implements Traceable {
|
|
|
294
295
|
// Base case is we always commit the checkpoint. Using the ForkCheckpoint means this has no effect if the tx was reverted
|
|
295
296
|
await checkpoint.commit();
|
|
296
297
|
// The tx-level contracts cache should not live on to the next tx
|
|
297
|
-
this.
|
|
298
|
+
this.contractsDB.clearContractsForTx();
|
|
298
299
|
}
|
|
299
300
|
}
|
|
300
301
|
|
|
@@ -353,12 +354,12 @@ export class PublicProcessor implements Traceable {
|
|
|
353
354
|
// b) always had a txHandler with the same db passed to it as this.db, which updated the db in buildBaseRollupHints in this loop
|
|
354
355
|
// To see how this ^ happens, move back to one shared db in test_context and run orchestrator_multi_public_functions.test.ts
|
|
355
356
|
// The below is taken from buildBaseRollupHints:
|
|
356
|
-
await this.
|
|
357
|
+
await this.treesDB.appendLeaves(
|
|
357
358
|
MerkleTreeId.NOTE_HASH_TREE,
|
|
358
359
|
padArrayEnd(processedTx.txEffect.noteHashes, Fr.ZERO, MAX_NOTE_HASHES_PER_TX),
|
|
359
360
|
);
|
|
360
361
|
try {
|
|
361
|
-
await this.
|
|
362
|
+
await this.treesDB.batchInsert(
|
|
362
363
|
MerkleTreeId.NULLIFIER_TREE,
|
|
363
364
|
padArrayEnd(processedTx.txEffect.nullifiers, Fr.ZERO, MAX_NULLIFIERS_PER_TX).map(n => n.toBuffer()),
|
|
364
365
|
NULLIFIER_SUBTREE_HEIGHT,
|
|
@@ -374,7 +375,7 @@ export class PublicProcessor implements Traceable {
|
|
|
374
375
|
}
|
|
375
376
|
|
|
376
377
|
// The only public data write should be for fee payment
|
|
377
|
-
await this.
|
|
378
|
+
await this.treesDB.sequentialInsert(
|
|
378
379
|
MerkleTreeId.PUBLIC_DATA_TREE,
|
|
379
380
|
processedTx.txEffect.publicDataWrites.map(x => x.toBuffer()),
|
|
380
381
|
);
|
|
@@ -426,7 +427,7 @@ export class PublicProcessor implements Traceable {
|
|
|
426
427
|
|
|
427
428
|
this.log.debug(`Deducting ${txFee.toBigInt()} balance in Fee Juice for ${feePayer}`);
|
|
428
429
|
|
|
429
|
-
const balance = await this.
|
|
430
|
+
const balance = await this.treesDB.storageRead(feeJuiceAddress, balanceSlot);
|
|
430
431
|
|
|
431
432
|
if (balance.lt(txFee)) {
|
|
432
433
|
throw new Error(
|
|
@@ -435,7 +436,7 @@ export class PublicProcessor implements Traceable {
|
|
|
435
436
|
}
|
|
436
437
|
|
|
437
438
|
const updatedBalance = balance.sub(txFee);
|
|
438
|
-
await this.
|
|
439
|
+
await this.treesDB.storageWrite(feeJuiceAddress, balanceSlot, updatedBalance);
|
|
439
440
|
|
|
440
441
|
return new PublicDataWrite(leafSlot, updatedBalance);
|
|
441
442
|
}
|