Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
fcarreiro committed Apr 8, 2024
1 parent 31337c0 commit d347c1b
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 29 deletions.
1 change: 0 additions & 1 deletion avm-transpiler/src/instructions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ pub const ALL_DIRECT: u8 = 0b00000000;
pub const ZEROTH_OPERAND_INDIRECT: u8 = 0b00000001;
pub const FIRST_OPERAND_INDIRECT: u8 = 0b00000010;
pub const SECOND_OPERAND_INDIRECT: u8 = 0b00000100;
pub const ZEROTH_FIRST_OPERANDS_INDIRECT: u8 = ZEROTH_OPERAND_INDIRECT | FIRST_OPERAND_INDIRECT;

/// A simple representation of an AVM instruction for the purpose
/// of generating an AVM bytecode from Brillig.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,39 @@ contract AvmTest {
dep::std::hash::pedersen_hash_with_separator(data, 20)
}

/************************************************************************
* ACVM interoperability
************************************************************************/
#[aztec(public)]
fn constant_field_acvm() -> pub Field {
123456
}

#[aztec(public-vm)]
fn constant_field_avm() -> pub Field {
123456
}

#[aztec(public-vm)]
fn call_acvm_from_avm() -> pub Field {
let data_to_return: [Field; RETURN_VALUES_LENGTH] = context.call_public_function(
context.this_address(),
FunctionSelector::from_signature("constant_field_acvm()"),
[]
);
data_to_return[0]
}

#[aztec(public)]
fn call_avm_from_acvm() -> pub Field {
let data_to_return: [Field; RETURN_VALUES_LENGTH] = context.call_public_function(
context.this_address(),
FunctionSelector::from_signature("constant_field_avm()"),
[]
);
data_to_return[0]
}

/************************************************************************
* Contract instance
************************************************************************/
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/end-to-end/src/e2e_avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,4 +79,10 @@ describe('e2e_avm_simulator', () => {
});
});
});

describe('ACVM interoperability', () => {
it('Can execute ACVM function among AVM functions', async () => {
expect(await avmContact.methods.constant_field_acvm().simulate()).toEqual(123456n);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ export abstract class AbstractPhaseManager {
while (executionStack.length) {
const current = executionStack.pop()!;
const isExecutionRequest = !isPublicExecutionResult(current);

const sideEffectCounter = lastSideEffectCounter(tx) + 1;

const result = isExecutionRequest
? await this.publicExecutor.simulate(current, this.globalVariables, sideEffectCounter)
: current;
Expand Down
61 changes: 53 additions & 8 deletions yarn-project/simulator/src/public/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,67 @@ import { PackedArgsCache } from '../common/packed_args_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 {
isAvmBytecode,
temporaryConvertAvmResults,
temporaryCreateAvmExecutionEnvironment,
} from './transitional_migration.js';

/**
* Execute a public function and return the execution result.
*/
export async function executePublicFunction(
context: PublicExecutionContext,
nested: boolean,
): Promise<PublicExecutionResult> {
const bytecode = await context.contractsDb.getBytecode(
context.execution.contractAddress,
context.execution.functionData.selector,
);
if (!bytecode) {
throw new Error(
`Bytecode not found for ${context.execution.contractAddress}:${context.execution.functionData.selector}`,
);
}

if (isAvmBytecode(bytecode)) {
return await executePublicFunctionAvm(context);
} else {
return await executePublicFunctionAcvm(context, bytecode, nested);
}
}

async function executePublicFunctionAvm(executionContext: PublicExecutionContext): Promise<PublicExecutionResult> {
// Temporary code to construct the AVM context
// These data structures will permeate across the simulator when the public executor is phased out
const hostStorage = new HostStorage(
executionContext.stateDb,
executionContext.contractsDb,
executionContext.commitmentsDb,
);
const worldStateJournal = new AvmPersistableStateManager(hostStorage);
const executionEnv = temporaryCreateAvmExecutionEnvironment(
executionContext.execution,
executionContext.globalVariables,
);
// TODO(@spalladino) Load initial gas from the public execution request
const machineState = new AvmMachineState(100_000, 100_000, 100_000);

const context = new AvmContext(worldStateJournal, executionEnv, machineState);
const simulator = new AvmSimulator(context);

const result = await simulator.execute();
const newWorldState = context.persistableState.flush();
// TODO(@spalladino) Read gas left from machineState and return it
return temporaryConvertAvmResults(executionContext.execution, newWorldState, result);
}

async function executePublicFunctionAcvm(
context: PublicExecutionContext,
acir: Buffer,
nested: boolean,
log = createDebugLogger('aztec:simulator:public_execution'),
): Promise<PublicExecutionResult> {
const log = createDebugLogger('aztec:simulator:public_execution');
const execution = context.execution;
const { contractAddress, functionData } = execution;
const selector = functionData.selector;
Expand Down Expand Up @@ -203,12 +254,6 @@ export class PublicExecutor {
globalVariables: GlobalVariables,
sideEffectCounter: number = 0,
): Promise<PublicExecutionResult> {
const selector = execution.functionData.selector;
const acir = await this.contractsDb.getBytecode(execution.contractAddress, selector);
if (!acir) {
throw new Error(`Bytecode not found for ${execution.contractAddress}:${selector}`);
}

// Functions can request to pack arguments before calling other functions.
// We use this cache to hold the packed arguments.
const packedArgs = PackedArgsCache.create([]);
Expand All @@ -224,7 +269,7 @@ export class PublicExecutor {
this.commitmentsDb,
);

const executionResult = await executePublicFunction(context, acir, false /** nested */);
const executionResult = await executePublicFunction(context, /*nested=*/ false);

if (executionResult.execution.callContext.isStaticCall) {
checkValidStaticCall(
Expand Down
19 changes: 6 additions & 13 deletions yarn-project/simulator/src/public/public_execution_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,12 @@ export class PublicExecutionContext extends TypedOracle {
*/
public readonly execution: PublicExecution,
private readonly header: Header,
private readonly globalVariables: GlobalVariables,
public readonly globalVariables: GlobalVariables,
private readonly packedArgsCache: PackedArgsCache,
private readonly sideEffectCounter: SideEffectCounter,
private readonly stateDb: PublicStateDB,
private readonly contractsDb: PublicContractsDB,
private readonly commitmentsDb: CommitmentsDB,
public readonly stateDb: PublicStateDB,
public readonly contractsDb: PublicContractsDB,
public readonly commitmentsDb: CommitmentsDB,
private log = createDebugLogger('aztec:simulator:public_execution_context'),
) {
super();
Expand Down Expand Up @@ -190,14 +190,7 @@ export class PublicExecutionContext extends TypedOracle {
this.log(`Public function call: addr=${targetContractAddress} selector=${functionSelector} args=${args.join(',')}`);

const portalAddress = (await this.contractsDb.getPortalContractAddress(targetContractAddress)) ?? EthAddress.ZERO;

const acir = await this.contractsDb.getBytecode(targetContractAddress, functionSelector);
if (!acir) {
throw new Error(`Bytecode not found for ${targetContractAddress}:${functionSelector}`);
}

const functionData = new FunctionData(functionSelector, false);

const functionData = new FunctionData(functionSelector, /*isPrivate=*/ false);
const callContext = CallContext.from({
msgSender: isDelegateCall ? this.execution.callContext.msgSender : this.execution.contractAddress,
storageContractAddress: isDelegateCall ? this.execution.contractAddress : targetContractAddress,
Expand Down Expand Up @@ -227,7 +220,7 @@ export class PublicExecutionContext extends TypedOracle {
this.log,
);

const childExecutionResult = await executePublicFunction(context, acir, true /** nested */);
const childExecutionResult = await executePublicFunction(context, /*nested=*/ true);

if (isStaticCall) {
checkValidStaticCall(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// All code in this file needs to die once the public executor is phased out.
// All code in this file needs to die once the public executor is phased out in favor of the AVM.
import { UnencryptedFunctionL2Logs } from '@aztec/circuit-types';
import {
ContractStorageRead,
Expand All @@ -12,12 +12,12 @@ import {
} from '@aztec/circuits.js';
import { Fr } from '@aztec/foundation/fields';

import { AvmExecutionEnvironment } from '../avm/avm_execution_environment.js';
import { type AvmContractCallResults } from '../avm/avm_message_call_result.js';
import { type JournalData } from '../avm/journal/journal.js';
import { Mov } from '../avm/opcodes/memory.js';
import { createSimulationError } from '../common/errors.js';
import { type PublicExecution, type PublicExecutionResult } from '../public/execution.js';
import { AvmExecutionEnvironment } from './avm_execution_environment.js';
import { type AvmContractCallResults } from './avm_message_call_result.js';
import { type JournalData } from './journal/journal.js';
import { Mov } from './opcodes/memory.js';
import { type PublicExecution, type PublicExecutionResult } from './execution.js';

/** Temporary Method
*
Expand Down

0 comments on commit d347c1b

Please sign in to comment.