Skip to content

Commit

Permalink
chore(avm-simulator): avm's nested calls now stay and properly track …
Browse files Browse the repository at this point in the history
…PublicExecutionResult
  • Loading branch information
dbanks12 committed May 2, 2024
1 parent 5fb052e commit 3307777
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 16 deletions.
3 changes: 1 addition & 2 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,7 @@ describe('e2e_avm_simulator', () => {
expect(tx.status).toEqual(TxStatus.MINED);
});

// TODO(4293): this should work! Fails in public kernel because both nullifiers are incorrectly being siloed by same address
it.skip('Should be able to emit the same unsiloed nullifier from two different contracts', async () => {
it('Should be able to emit the same unsiloed nullifier from two different contracts', async () => {
const nullifier = new Fr(1);
const tx = await avmContract.methods
.create_same_nullifier_in_nested_call(secondAvmContract.address, nullifier)
Expand Down
16 changes: 11 additions & 5 deletions yarn-project/simulator/src/avm/opcodes/external_calls.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { padArrayEnd } from '@aztec/foundation/collection';

import { executePublicFunction } from '../../public/executor.js';
import {
convertAvmResultsToPxResult,
convertPublicExecutionResult,
createPublicExecutionContext,
updateAvmContextFromPublicExecutionResult,
Expand All @@ -14,6 +15,7 @@ import { type AvmContractCallResults } from '../avm_message_call_result.js';
import { Opcode, OperandType } from '../serialization/instruction_serialization.js';
import { Addressing } from './addressing_mode.js';
import { Instruction } from './instruction.js';
import { AvmSimulator } from '../avm_simulator.js';

abstract class ExternalCall extends Instruction {
// Informs (de)serialization. See Instruction.deserialize.
Expand Down Expand Up @@ -69,21 +71,25 @@ abstract class ExternalCall extends Instruction {
const totalGas = sumGas(this.gasCost(memoryOperations), allocatedGas);
context.machineState.consumeGas(totalGas);

// TRANSITIONAL: This should be removed once the AVM is fully operational and the public executor is gone.
// TRANSITIONAL: This should be removed once the kernel handles and entire enqueued call per circuit
const nestedContext = context.createNestedContractCallContext(
callAddress.toFr(),
calldata,
allocatedGas,
this.type,
FunctionSelector.fromField(functionSelector),
);
const pxContext = createPublicExecutionContext(nestedContext, calldata);
const pxResults = await executePublicFunction(pxContext, /*nested=*/ true);

const startPxContext = createPublicExecutionContext(nestedContext, calldata);
const startSideEffectCounter = nestedContext.persistableState.trace.accessCounter;
const nestedCallResults: AvmContractCallResults = await new AvmSimulator(nestedContext).execute();

const pxResults = convertAvmResultsToPxResult(nestedCallResults, startSideEffectCounter, startPxContext, nestedContext);
// store the old PublicExecutionResult object to maintain a recursive data structure for the old kernel
context.persistableState.transitionalExecutionResult.nestedExecutions.push(pxResults);
const nestedCallResults: AvmContractCallResults = convertPublicExecutionResult(pxResults);
updateAvmContextFromPublicExecutionResult(nestedContext, pxResults);
const nestedPersistableState = nestedContext.persistableState;
// END TRANSITIONAL

// const nestedContext = context.createNestedContractCallContext(
// callAddress.toFr(),
// calldata,
Expand Down
15 changes: 8 additions & 7 deletions yarn-project/simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import { PackedValuesCache } from '../common/packed_values_cache.js';
import { type CommitmentsDB, type PublicContractsDB, type PublicStateDB } from './db.js';
import { type PublicExecution, type PublicExecutionResult, checkValidStaticCall } from './execution.js';
import { PublicExecutionContext } from './public_execution_context.js';
import { convertAvmResults, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';
import { convertAvmResults, convertAvmResultsToPxResult, createAvmExecutionEnvironment, isAvmBytecode } from './transitional_adaptors.js';

/**
* Execute a public function and return the execution result.
Expand Down Expand Up @@ -66,6 +66,8 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
executionContext.commitmentsDb,
);
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
const startSideEffectCounter = executionContext.execution.callContext.sideEffectCounter;
worldStateJournal.trace.accessCounter = startSideEffectCounter;

const executionEnv = createAvmExecutionEnvironment(
executionContext.execution,
Expand All @@ -76,17 +78,16 @@ async function executePublicFunctionAvm(executionContext: PublicExecutionContext
);

const machineState = new AvmMachineState(executionContext.availableGas);
const context = new AvmContext(worldStateJournal, executionEnv, machineState);
const simulator = new AvmSimulator(context);
const avmContext = new AvmContext(worldStateJournal, executionEnv, machineState);
const simulator = new AvmSimulator(avmContext);

const result = await simulator.execute();
const newWorldState = context.persistableState.flush();
const avmResult = await simulator.execute();

log.verbose(
`[AVM] ${address.toString()}:${selector} returned, reverted: ${result.reverted}, reason: ${result.revertReason}.`,
`[AVM] ${address.toString()}:${selector} returned, reverted: ${avmResult.reverted}, reason: ${avmResult.revertReason}.`,
);

return await convertAvmResults(executionContext, newWorldState, result, machineState);
return Promise.resolve(convertAvmResultsToPxResult(avmResult, startSideEffectCounter, executionContext, avmContext));
}

async function executePublicFunctionAcvm(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ export class PublicExecutionContext extends TypedOracle {
public readonly header: Header,
public readonly globalVariables: GlobalVariables,
private readonly packedValuesCache: PackedValuesCache,
private readonly sideEffectCounter: SideEffectCounter,
// TRANSITIONAL: once AVM-ACVM interoperability is removed (fully functional AVM), sideEffectCounter can be made private
public readonly sideEffectCounter: SideEffectCounter,
public readonly stateDb: PublicStateDB,
public readonly contractsDb: PublicContractsDB,
public readonly commitmentsDb: CommitmentsDB,
Expand Down
21 changes: 20 additions & 1 deletion yarn-project/simulator/src/public/transitional_adaptors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { type AvmContext } from '../avm/avm_context.js';
import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
import { type AvmMachineState } from '../avm/avm_machine_state.js';
import { AvmContractCallResults } from '../avm/avm_message_call_result.js';
import { type JournalData } from '../avm/journal/journal.js';
import { AvmPersistableStateManager, type JournalData } from '../avm/journal/journal.js';
import { Mov } from '../avm/opcodes/memory.js';
import { createSimulationError } from '../common/errors.js';
import { PackedValuesCache, SideEffectCounter } from '../index.js';
Expand Down Expand Up @@ -96,6 +96,25 @@ export function createPublicExecutionContext(avmContext: AvmContext, calldata: F
return context;
}

export function convertAvmResultsToPxResult(avmResult: AvmContractCallResults, startSideEffectCounter: number, startPxContext: PublicExecutionContext, endAvmContext: AvmContext): PublicExecutionResult {
const endPersistableState = endAvmContext.persistableState;
const endMachineState = endAvmContext.machineState;
return {
...endPersistableState.transitionalExecutionResult, // includes nestedExecutions
execution: startPxContext.execution,
returnValues: avmResult.output,
startSideEffectCounter: new Fr(startSideEffectCounter),
endSideEffectCounter: new Fr(endPersistableState.trace.accessCounter),
unencryptedLogs: new UnencryptedFunctionL2Logs(endPersistableState.transitionalExecutionResult.unencryptedLogs),
reverted: avmResult.reverted,
revertReason: avmResult.revertReason ? createSimulationError(avmResult.revertReason) : undefined,
startGasLeft: startPxContext.availableGas,
endGasLeft: endMachineState.gasLeft,
transactionFee: startPxContext.transactionFee,
};
}


/**
* Convert the result of an AVM contract call to a PublicExecutionResult for the public kernel
*
Expand Down

0 comments on commit 3307777

Please sign in to comment.