-
Notifications
You must be signed in to change notification settings - Fork 606
feat: avm executor - layout and groundwork #3928
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
2b2c97f
init
Maddiaa0 d2e8fab
fix: update missing mul instruction
Maddiaa0 feef224
feat: initial avm scaffold
Maddiaa0 dc8cd76
chore: interpreter test
Maddiaa0 d5629ab
feat: Journal interface
Maddiaa0 34bfbb1
feat: AvmExecutor and state manager interfaces
Maddiaa0 483644c
chore: prettier
Maddiaa0 e812dd5
rm: legacy
Maddiaa0 df233c3
chore: document / silence linter
Maddiaa0 c6ee4b2
Merge branch 'master' into md/public-vm-executor
Maddiaa0 91025fa
fix: linter
Maddiaa0 2a61f28
fix: give todos tags
Maddiaa0 7d25588
fix: add comparators
Maddiaa0 55dd8ce
fix: move shifts to bitwise
Maddiaa0 8eed7d3
fix: update opcodes -> instructions
Maddiaa0 63af797
fix: update multiplication yp text
Maddiaa0 9c81e83
fix: align naming with yellow paper
Maddiaa0 5a9e61f
fix: update interpreter test
Maddiaa0 2c5cce3
chore: formatting fix
Maddiaa0 2989c80
Merge branch 'master' into md/public-vm-executor
Maddiaa0 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,3 +12,5 @@ cmake-build-debug | |
|
|
||
| # Local Netlify folder | ||
| .netlify | ||
|
|
||
| .graphite* | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| describe('Avm', () => { | ||
| it('Executes a simple call', () => {}); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import { Fr } from '@aztec/foundation/fields'; | ||
|
|
||
| import { AvmMachineState } from './avm_machine_state.js'; | ||
| import { AvmMessageCallResult } from './avm_message_call_result.js'; | ||
| import { AvmStateManager } from './avm_state_manager.js'; | ||
| import { AvmInterpreter } from './interpreter/index.js'; | ||
| import { interpretBytecode } from './opcodes/from_bytecode.js'; | ||
| import { Instruction } from './opcodes/index.js'; | ||
|
|
||
| /** | ||
| * Avm Executor manages the execution of the AVM | ||
| * | ||
| * It stores a state manager | ||
| */ | ||
| export class AvmContext { | ||
| private stateManager: AvmStateManager; | ||
|
|
||
| constructor(stateManager: AvmStateManager) { | ||
| this.stateManager = stateManager; | ||
| } | ||
|
|
||
| /** | ||
| * Call a contract with the given calldata | ||
| * | ||
| * - We get the contract from storage | ||
| * - We interpret the bytecode | ||
| * - We run the interpreter | ||
| * | ||
| * @param contractAddress - | ||
| * @param calldata - | ||
| */ | ||
| public call(contractAddress: Fr, calldata: Fr[]): AvmMessageCallResult { | ||
| // NOTE: the following is mocked as getPublicBytecode does not exist yet | ||
| // const bytecode = stateManager.journal.hostStorage.contractsDb.getBytecode(contractAddress); | ||
| const bytecode = Buffer.from('0x01000100020003'); | ||
|
|
||
| const instructions: Instruction[] = interpretBytecode(bytecode); | ||
|
|
||
| const context = new AvmMachineState(calldata); | ||
| const interpreter = new AvmInterpreter(context, this.stateManager, instructions); | ||
|
|
||
| return interpreter.run(); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| import { Fr } from '@aztec/foundation/fields'; | ||
|
|
||
| /** | ||
| * Store's data for an Avm execution frame | ||
| */ | ||
| export class AvmMachineState { | ||
| /** - */ | ||
| public readonly calldata: Fr[]; | ||
| private returnData: Fr[]; | ||
|
|
||
| // TODO: implement tagged memory | ||
| /** - */ | ||
| public memory: Fr[]; | ||
|
|
||
| /** - */ | ||
| public pc: number; | ||
| /** - */ | ||
| public callStack: number[]; | ||
|
|
||
| /** | ||
| * Create a new avm context | ||
| * @param calldata - | ||
| */ | ||
| constructor(calldata: Fr[]) { | ||
| this.calldata = calldata; | ||
| this.returnData = []; | ||
| this.memory = []; | ||
|
|
||
| this.pc = 0; | ||
| this.callStack = []; | ||
| } | ||
|
|
||
| /** | ||
| * Return data must NOT be modified once it is set | ||
| * @param returnData - | ||
| */ | ||
| public setReturnData(returnData: Fr[]) { | ||
| this.returnData = returnData; | ||
| Object.freeze(returnData); | ||
| } | ||
|
|
||
| /** - */ | ||
| public getReturnData(): Fr[] { | ||
| return this.returnData; | ||
| } | ||
|
|
||
| /** - | ||
| * @param offset - | ||
| */ | ||
| public readMemory(offset: number): Fr { | ||
| // TODO: check offset is within bounds | ||
| return this.memory[offset] ?? Fr.ZERO; | ||
| } | ||
|
|
||
| /** - | ||
| * @param offset - | ||
| * @param size - | ||
| */ | ||
| public readMemoryChunk(offset: number, size: number): Fr[] { | ||
| // TODO: bounds -> initialise to 0 | ||
| return this.memory.slice(offset, offset + size); | ||
| } | ||
|
|
||
| /** - | ||
| * @param offset - | ||
| * @param value - | ||
| */ | ||
| public writeMemory(offset: number, value: Fr): void { | ||
| this.memory[offset] = value; | ||
| } | ||
|
|
||
| /** - | ||
| * @param offset - | ||
| * @param values - | ||
| */ | ||
| public writeMemoryChunk(offset: number, values: Fr[]): void { | ||
| this.memory.splice(offset, values.length, ...values); | ||
| } | ||
| } |
34 changes: 34 additions & 0 deletions
34
yarn-project/acir-simulator/src/avm/avm_message_call_result.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| import { Fr } from '@aztec/foundation/fields'; | ||
|
|
||
| /** | ||
| * AVM message call result. | ||
| */ | ||
| export class AvmMessageCallResult { | ||
| /** - */ | ||
| public readonly reverted: boolean; | ||
| /** .- */ | ||
| public readonly output: Fr[]; | ||
|
|
||
| constructor(reverted: boolean, output: Fr[]) { | ||
| this.reverted = reverted; | ||
| this.output = output; | ||
| } | ||
|
|
||
| /** | ||
| * Terminate a call as a success | ||
| * @param output - Return data | ||
| * @returns instance of AvmMessageCallResult | ||
| */ | ||
| public static success(output: Fr[]): AvmMessageCallResult { | ||
| return new AvmMessageCallResult(false, output); | ||
| } | ||
|
|
||
| /** | ||
| * Terminate a call as a revert | ||
| * @param output - Return data ( revert message ) | ||
| * @returns instance of AvmMessageCallResult | ||
| */ | ||
| public static revert(output: Fr[]): AvmMessageCallResult { | ||
| return new AvmMessageCallResult(true, output); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| import { BlockHeader } from '@aztec/circuits.js'; | ||
|
|
||
| import { AvmJournal, HostStorage } from './journal/index.js'; | ||
|
|
||
| /** | ||
| * The Avm State Manager is the interpreter's interface to the node's state | ||
| * It creates revertible views into the node state and manages the current call's journal | ||
| */ | ||
| export class AvmStateManager { | ||
| /** - */ | ||
| public readonly blockHeader: BlockHeader; | ||
|
|
||
| /** | ||
| * Journal keeps track of pending state changes | ||
| */ | ||
| public readonly journal: AvmJournal; | ||
|
|
||
| constructor(blockHeader: BlockHeader, journal: AvmJournal) { | ||
| this.blockHeader = blockHeader; | ||
| this.journal = journal; | ||
| } | ||
|
|
||
| /** | ||
| * Create a base state root manager | ||
| * - this should be created by the highest level item where the state | ||
| * can be reverted | ||
| * @param blockHeader - | ||
| * @param hostStorage - An immutable view into the node db | ||
| * @returns Avm State Manager | ||
| */ | ||
| public static rootStateManager(blockHeader: BlockHeader, hostStorage: HostStorage): AvmStateManager { | ||
| const journal = new AvmJournal(hostStorage); | ||
| return new AvmStateManager(blockHeader, journal); | ||
| } | ||
|
|
||
| /** | ||
| * Avm State | ||
| * @param parent - Avm state manager with a forked journal | ||
| * @returns | ||
| */ | ||
| public static forkStateManager(parent: AvmStateManager): AvmStateManager { | ||
| return new AvmStateManager(parent.blockHeader, parent.journal); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| // Place large AVM text fixtures in here |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| export * from './avm_machine_state.js'; | ||
| export * from './avm_context.js'; | ||
| export * from './avm_state_manager.js'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export * from './interpreter.js'; |
37 changes: 37 additions & 0 deletions
37
yarn-project/acir-simulator/src/avm/interpreter/interpreter.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| import { Fr } from '@aztec/foundation/fields'; | ||
|
|
||
| import { mock } from 'jest-mock-extended'; | ||
|
|
||
| import { AvmMachineState } from '../avm_machine_state.js'; | ||
| import { AvmStateManager } from '../avm_state_manager.js'; | ||
| import { Add } from '../opcodes/arithmetic.js'; | ||
| import { Return } from '../opcodes/control_flow.js'; | ||
| import { Instruction } from '../opcodes/instruction.js'; | ||
| import { CallDataCopy } from '../opcodes/memory.js'; | ||
| import { AvmInterpreter } from './interpreter.js'; | ||
|
|
||
| describe('interpreter', () => { | ||
| it('Should execute a series of instructions', () => { | ||
| const calldata: Fr[] = [new Fr(1), new Fr(2)]; | ||
| const stateManager = mock<AvmStateManager>(); | ||
|
|
||
| const instructions: Instruction[] = [ | ||
| // Copy the first two elements of the calldata to memory regions 0 and 1 | ||
| new CallDataCopy(0, 2, 0), | ||
| // Add the two together and store the result in memory region 2 | ||
| new Add(0, 1, 2), // 1 + 2 | ||
| // Return the result | ||
| new Return(2, 1), // [3] | ||
| ]; | ||
|
|
||
| const context = new AvmMachineState(calldata); | ||
| const interpreter = new AvmInterpreter(context, stateManager, instructions); | ||
| const avmReturnData = interpreter.run(); | ||
|
|
||
| expect(avmReturnData.reverted).toBe(false); | ||
|
|
||
| const returnData = avmReturnData.output; | ||
| expect(returnData.length).toBe(1); | ||
| expect(returnData).toEqual([new Fr(3)]); | ||
| }); | ||
| }); |
54 changes: 54 additions & 0 deletions
54
yarn-project/acir-simulator/src/avm/interpreter/interpreter.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| // import { AvmContext } from "../avm_machineState.js"; | ||
| import { Fr } from '@aztec/foundation/fields'; | ||
|
|
||
| import { AvmMachineState } from '../avm_machine_state.js'; | ||
| import { AvmMessageCallResult } from '../avm_message_call_result.js'; | ||
| import { AvmStateManager } from '../avm_state_manager.js'; | ||
| import { Instruction } from '../opcodes/index.js'; | ||
|
|
||
| /** | ||
| * Avm Interpreter | ||
| * | ||
| * Executes an Avm context | ||
| */ | ||
| export class AvmInterpreter { | ||
| private instructions: Instruction[] = []; | ||
| private machineState: AvmMachineState; | ||
| private stateManager: AvmStateManager; | ||
|
|
||
| constructor(machineState: AvmMachineState, stateManager: AvmStateManager, bytecode: Instruction[]) { | ||
| this.machineState = machineState; | ||
| this.stateManager = stateManager; | ||
| this.instructions = bytecode; | ||
| } | ||
|
|
||
| /** | ||
| * Run the avm | ||
| * @returns bool - successful execution will return true | ||
| * - reverted execution will return false | ||
| * - any other panic will throw | ||
| */ | ||
| run(): AvmMessageCallResult { | ||
| try { | ||
| for (const instruction of this.instructions) { | ||
| instruction.execute(this.machineState, this.stateManager); | ||
| } | ||
|
|
||
| const returnData = this.machineState.getReturnData(); | ||
| return AvmMessageCallResult.success(returnData); | ||
| } catch (e) { | ||
| // TODO: This should only accept AVM defined errors, anything else SHOULD be thrown upstream | ||
| const revertData = this.machineState.getReturnData(); | ||
| return AvmMessageCallResult.revert(revertData); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * Get the return data from avm execution | ||
| * TODO: this should fail if the code has not been executed | ||
| * - maybe move the return in run into a variable and track it | ||
| */ | ||
| returnData(): Fr[] { | ||
| return this.machineState.getReturnData(); | ||
| } | ||
| } |
18 changes: 18 additions & 0 deletions
18
yarn-project/acir-simulator/src/avm/journal/host_storage.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| import { CommitmentsDB, PublicContractsDB, PublicStateDB } from '../../index.js'; | ||
|
|
||
| /** - */ | ||
| export class HostStorage { | ||
| /** - */ | ||
| public readonly stateDb: PublicStateDB; | ||
| /** - */ | ||
| public readonly contractsDb: PublicContractsDB; | ||
|
|
||
| /** - */ | ||
| public readonly commitmentsDb: CommitmentsDB; | ||
|
|
||
| constructor(stateDb: PublicStateDB, contractsDb: PublicContractsDB, commitmentsDb: CommitmentsDB) { | ||
| this.stateDb = stateDb; | ||
| this.contractsDb = contractsDb; | ||
| this.commitmentsDb = commitmentsDb; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,2 @@ | ||
| export * from './host_storage.js'; | ||
| export * from './journal.js'; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| describe('journal', () => { | ||
| it('Should write to storage', () => {}); | ||
|
|
||
| it('Should read from storage', () => {}); | ||
|
|
||
| it('Should merge two journals together', () => {}); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.