Skip to content
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

docs(yellowpaper): AVM call instructions, split out sections, cleanup #4594

Merged
merged 24 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 18 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ pub enum AvmOpcode {
// Control Flow - Contract Calls
CALL,
STATICCALL,
DELEGATECALL,
RETURN,
REVERT,

Expand Down Expand Up @@ -161,6 +162,7 @@ impl AvmOpcode {
// Control Flow - Contract Calls
AvmOpcode::CALL => "CALL",
AvmOpcode::STATICCALL => "STATICCALL",
AvmOpcode::DELEGATECALL => "DELEGATECALL",
AvmOpcode::RETURN => "RETURN",
AvmOpcode::REVERT => "REVERT",

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ const std::unordered_map<OpCode, size_t> Bytecode::OPERANDS_NUM = {
//// Control Flow - Contract Calls
//{ OpCode::CALL, },
//{ OpCode::STATICCALL, },
//{ OpCode::DELEGATECALL, },
{ OpCode::RETURN, 2 },
// { OpCode::REVERT, },

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ enum class OpCode : uint8_t {
// Control Flow - Contract Calls
CALL,
STATICCALL,
DELEGATECALL,
RETURN,
REVERT,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ const INSTRUCTION_SET = () =>
// Control Flow - Contract Calls
[Call.opcode, Call],
[StaticCall.opcode, StaticCall],
//[DelegateCall.opcode, DelegateCall],
[Return.opcode, Return],
[Revert.opcode, Revert],

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ export enum Opcode {
SENDL2TOL1MSG,
CALL,
STATICCALL,
DELEGATECALL,
RETURN,
REVERT,
KECCAK,
Expand Down
2 changes: 1 addition & 1 deletion yellow-paper/docs/contract-deployment/instances.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ Specific to private functions:

Specific to public functions:

- The bytecode loaded by the [AVM](../public-vm/avm.md) for the contract matches the `bytecode_commitment` in the contract class, verified using the [bytecode validation circuit](../public-vm/bytecode-validation-circuit.md).
- The bytecode loaded by the [AVM](../public-vm/intro) for the contract matches the `bytecode_commitment` in the contract class, verified using the [bytecode validation circuit](../public-vm/bytecode-validation-circuit).
- The contract Deployment Nullifier has been emitted, or prove that it hasn't, in which case the transaction is expected to revert. This check is done via a merkle (non-)membership proof of the Deployment Nullifier. Note that a public function should be callable in the same transaction in which its contract Deployment Nullifier was emitted.

Note that, since constructors are handled at the application level, the kernel circuit is not required to check the Initialization Nullifier before executing code.
Expand Down
45 changes: 45 additions & 0 deletions yellow-paper/docs/public-vm/_nested-context.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
A nested contract call's execution environment and machine state are derived from the caller's context and the call instruction's arguments.

```jsx
// contract being called into
contract = callingContext.worldState.contracts[M[addrOffset]]

nestedExecutionEnvironment = ExecutionEnvironment {
origin: context.origin,
sender: isDelegateCall ? context.sender : context.address,
address: M[addrOffset],
storageAddress: isDelegateCall ? context.storageAddress : M[addrOffset],
portal: contract.portal,
feePerL1Gas: context.environment.feePerL1Gas,
feePerL2Gas: context.environment.feePerL2Gas,
feePerDaGas: context.environment.feePerDaGas,
contractCallDepth: context.contractCallDepth + 1,
contractCallPointer: context.worldStateAccessTrace.contractCalls.length + 1,
globals: context.globals,
isStaticCall: isStaticCall,
isDelegateCall: isDelegateCall,
calldata: context.memory[M[argsOffset]:M[argsOffset]+argsSize],
bytecode: contract.bytecode,
}

nestedMachineState = MachineState {
l1GasLeft: context.machineState.memory[M[gasOffset]],
l2GasLeft: context.machineState.memory[M[gasOffset+1]],
daGasLeft: context.machineState.memory[M[gasOffset+2]],
pc = 0,
internalCallStack = [], // initialized as empty
memory = [0, ..., 0], // all 2^32 entries are initialized to zero
}
```

The nested call's execution context is then initialized.
```jsx
nestedContext = AvmContext {
environment: nestedExecutionEnvironment,
machineState: nestedMachineState,
worldState: context.worldState,
worldStateAccessTrace: context.worldStateAccessTrace,
accruedSubstate: { [], ... [], }, // all empty
results: {reverted: false, output: []},
}
```
6 changes: 3 additions & 3 deletions yellow-paper/docs/public-vm/avm-circuit.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ Prior to the VM circuit's execution, a vector is assembled to contain the byteco
Each entry in the bytecode vector will be paired with a call pointer and program counter. This **Bytecode Table** maps a call pointer and program counter to an instruction, and is used by the Instruction Controller to fetch instructions.
> Note: "call pointer" is expanded on in a later section.

Each contract's public bytecode is committed to during contract deployment. As part of the AVM circuit verification algorithm, the bytecode vector (as a concatenation of all relevant contract bytecodes) is verified against the corresponding bytecode commitments. This is expanded on in ["Bytecode Validation Circuit"](./bytecode-validation-circuit.md). While the AVM circuit enforces that the correct instructions are executed according to its bytecode table, the verifier checks that bytecode table against the previously validated bytecode commitments.
Each contract's public bytecode is committed to during contract deployment. As part of the AVM circuit verification algorithm, the bytecode vector (as a concatenation of all relevant contract bytecodes) is verified against the corresponding bytecode commitments. This is expanded on in ["Bytecode Validation Circuit"](./bytecode-validation-circuit). While the AVM circuit enforces that the correct instructions are executed according to its bytecode table, the verifier checks that bytecode table against the previously validated bytecode commitments.
dbanks12 marked this conversation as resolved.
Show resolved Hide resolved

## Instruction Controller
The Instruction Controller's responsibilities include instruction fetching and decoding.

### Instruction fetching
The Instruction Controller's **instruction fetch** mechanism makes use of the bytecode table to determine which instruction to execute based on the call pointer and program counter. Each instruction fetch corresponds to a circuit lookup to enforce that the correct instruction is processed for a given contract and program counter.

The combination of the instruction fetch circuitry, the bytecode table, and the ["Bytecode Validation Circuit"](./bytecode-validation-circuit.md) ensure that VM circuit processes the proper sequence of instructions.
The combination of the instruction fetch circuitry, the bytecode table, and the ["Bytecode Validation Circuit"](./bytecode-validation-circuit) ensure that VM circuit processes the proper sequence of instructions.

### Instruction decoding and sub-operations
An instruction (its opcode, flags, and arguments) represents some high-level VM operation. For example, an `ADD` instruction says "add two items from memory and store the result in memory". The Instruction Controller **instruction decode** mechanism decodes instructions into sub-operations. While an instruction likely requires many circuit components, a **sub-operation** is a smaller task that can be fed to just one VM circuit component for processing. By decoding an instruction into sub-operations, the VM circuit translates high-level instructions into smaller achievable tasks. To continue with the `ADD` example, it would translate "add two items from memory and store the result in memory" to "load an item from memory, load another item from memory, add them, and store the result to memory."
Expand Down Expand Up @@ -192,7 +192,7 @@ AvmSessionPublicInputs {
sessionResults: AvmSessionResults,
}
```
> The `ExecutionEnvironment` structure is defined in [the AVM's high level specification](./avm.md). `initialEnvironment` here omits `calldata` and `bytecode`.
> The `ExecutionEnvironment` structure is defined in [the AVM's execution context](./context). `initialEnvironment` here omits `calldata` and `bytecode`.

> The `WorldStateAccessTrace` and `AccruedSubstate` types are defined in ["State"](./state). Their vectors are assigned constant/maximum lengths when used as circuit inputs.

Expand Down
Loading
Loading