Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -24,6 +24,7 @@ pub enum AvmOpcode {
SENDER,
FEEPERL2GAS,
FEEPERDAGAS,
TRANSACTIONFEE,
CONTRACTCALLDEPTH,
CHAINID,
VERSION,
Expand Down Expand Up @@ -100,6 +101,7 @@ impl AvmOpcode {
AvmOpcode::SENDER => "SENDER",
AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS",
AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS",
AvmOpcode::TRANSACTIONFEE => "TRANSACTIONFEE",
AvmOpcode::CONTRACTCALLDEPTH => "CONTRACTCALLDEPTH",
// Execution Environment - Globals
AvmOpcode::CHAINID => "CHAINID",
Expand Down
1 change: 1 addition & 0 deletions avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -743,6 +743,7 @@ fn handle_getter_instruction(
"avmOpcodeSender" => AvmOpcode::SENDER,
"avmOpcodeFeePerL2Gas" => AvmOpcode::FEEPERL2GAS,
"avmOpcodeFeePerDaGas" => AvmOpcode::FEEPERDAGAS,
"avmOpcodeTransactionFee" => AvmOpcode::TRANSACTIONFEE,
"avmOpcodeChainId" => AvmOpcode::CHAINID,
"avmOpcodeVersion" => AvmOpcode::VERSION,
"avmOpcodeBlockNumber" => AvmOpcode::BLOCKNUMBER,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ enum class OpCode : uint8_t {
SENDER,
FEEPERL2GAS,
FEEPERDAGAS,
TRANSACTIONFEE,
CONTRACTCALLDEPTH,
// Execution Environment - Globals
CHAINID,
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/public-vm/_nested-context.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ nestedExecutionEnvironment = ExecutionEnvironment {
storageAddress: isDelegateCall ? context.storageAddress : M[addrOffset],
feePerL2Gas: context.environment.feePerL2Gas,
feePerDaGas: context.environment.feePerDaGas,
transactionFee: context.environment.transactionFee,
contractCallDepth: context.contractCallDepth + 1,
contractCallPointer: context.worldStateAccessTrace.contractCalls.length + 1,
globals: context.globals,
Expand Down
1 change: 1 addition & 0 deletions docs/docs/protocol-specs/public-vm/avm-circuit.md
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ AvmSessionInputs {
contractCallDepth: field,
isStaticCall: boolean,
isDelegateCall: boolean,
transactionFee: field,
// Initializes Machine State
l2GasLeft: field,
daGasLeft: field,
Expand Down
44 changes: 24 additions & 20 deletions docs/docs/protocol-specs/public-vm/context.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@ Many terms and definitions here are borrowed from the [Ethereum Yellow Paper](ht
An **execution context** contains the information and state relevant to a contract call's execution. When a contract call is made, an execution context is [initialized](#context-initialization) before the contract code's execution begins.

#### _AvmContext_

| Field | Type |
| --- | --- |
| --------------------------------------------------------- | ----------------------- |
| environment | `ExecutionEnvironment` |
| [machineState](./state#machine-state) | `MachineState` |
| [worldState](./state#avm-world-state) | `AvmWorldState` |
Expand All @@ -21,30 +22,33 @@ An **execution context** contains the information and state relevant to a contra
A context's **execution environment** remains constant throughout a contract call's execution. When a contract call initializes its execution context, it [fully specifies the execution environment](#context-initialization).

### _ExecutionEnvironment_
| Field | Type | Description |
| --- | --- | --- |
| address | `AztecAddress` | |
| storageAddress | `AztecAddress` | |
| sender | `AztecAddress` | |
| portal | `EthAddress` | |
| feePerL2Gas | `field` | |
| feePerDaGas | `field` | |
| contractCallDepth | `field` | Depth of the current call (how many nested calls deep is it). |
| contractCallPointer | `field` | Uniquely identifies each contract call processed by an AVM session. An initial call is assigned pointer value of 1 (expanded on in the AVM circuit section's ["Call Pointer"](./avm-circuit#call-pointer) subsection). |
| globals | `PublicGlobalVariables` | |
| isStaticCall | `boolean` | |
| isDelegateCall | `boolean` | |
| calldata | `[field; <calldata-length>]` | |

| Field | Type | Description |
| ------------------- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| address | `AztecAddress` | |
| storageAddress | `AztecAddress` | |
| sender | `AztecAddress` | |
| portal | `EthAddress` | |
| feePerL2Gas | `field` | |
| feePerDaGas | `field` | |
| transactionFee | `field` | Computed transaction fee based on gas fees, inclusion fee, and gas usage. Zero in all phases but teardown. |
| contractCallDepth | `field` | Depth of the current call (how many nested calls deep is it). |
| contractCallPointer | `field` | Uniquely identifies each contract call processed by an AVM session. An initial call is assigned pointer value of 1 (expanded on in the AVM circuit section's ["Call Pointer"](./avm-circuit#call-pointer) subsection). |
| globals | `PublicGlobalVariables` | |
| isStaticCall | `boolean` | |
| isDelegateCall | `boolean` | |
| calldata | `[field; <calldata-length>]` | |

## Contract Call Results

When a contract call halts, it sets the context's **contract call results** to communicate results to the caller.

### _ContractCallResults_
| Field | Type | Description |
| --- | --- | --- |
| reverted | `boolean` | |
| output | `[field; <output-length>]` | |

| Field | Type | Description |
| -------- | -------------------------- | ----------- |
| reverted | `boolean` | |
| output | `[field; <output-length>]` | |

## Context initialization

Expand Down Expand Up @@ -117,4 +121,4 @@ INITIAL_CONTRACT_CALL_RESULTS = ContractCallResults {

import NestedContext from "./_nested-context.md";

<NestedContext />
<NestedContext />
19 changes: 19 additions & 0 deletions docs/src/preprocess/InstructionSet/InstructionSet.js
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,25 @@ const INSTRUCTION_SET_RAW = [
"Tag checks": "",
"Tag updates": "`T[dstOffset] = u32`",
},
{
id: "transactionfee",
Name: "`TRANSACTIONFEE`",
Category: "Execution Environment",
Flags: [{ name: "indirect", description: INDIRECT_FLAG_DESCRIPTION }],
Args: [
{
name: "dstOffset",
description:
"memory offset specifying where to store operation's result",
},
],
Expression: "`M[dstOffset] = context.environment.transactionFee`",
Summary:
"Get the computed transaction fee during teardown phase, zero otherwise",
Details: "",
"Tag checks": "",
"Tag updates": "`T[dstOffset] = u32`",
},
{
id: "contractcalldepth",
Name: "`CONTRACTCALLDEPTH`",
Expand Down
6 changes: 4 additions & 2 deletions noir-projects/aztec-nr/aztec/src/context/avm_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ impl PublicContextInterface for AvmContext {
}

fn transaction_fee(self) -> Field {
assert(false, "'transaction_fee' not implemented!");
0
transaction_fee()
}

fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool {
Expand Down Expand Up @@ -219,6 +218,9 @@ fn fee_per_l2_gas() -> Field {}
#[oracle(avmOpcodeFeePerDaGas)]
fn fee_per_da_gas() -> Field {}

#[oracle(avmOpcodeTransactionFee)]
fn transaction_fee() -> Field {}

#[oracle(avmOpcodeChainId)]
fn chain_id() -> Field {}

Expand Down
2 changes: 1 addition & 1 deletion noir-projects/aztec-nr/aztec/src/context/interface.nr
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ trait PublicContextInterface {
fn fee_recipient(self) -> AztecAddress;
fn fee_per_da_gas(self) -> Field;
fn fee_per_l2_gas(self) -> Field;
fn transaction_fee(self) -> Field;
fn message_portal(&mut self, recipient: EthAddress, content: Field);
fn consume_l1_to_l2_message(&mut self, content: Field, secret: Field, sender: EthAddress, leaf_index: Field);
fn emit_unencrypted_log<T,N,M>(&mut self, log: T);
Expand All @@ -54,7 +55,6 @@ trait PublicContextInterface {
args: [Field]
) -> FunctionReturns<RETURNS_COUNT>;
fn nullifier_exists(self, unsiloed_nullifier: Field, address: AztecAddress) -> bool;
fn transaction_fee(self) -> Field;
}

struct PrivateCallInterface<T> {
Expand Down
5 changes: 2 additions & 3 deletions noir-projects/aztec-nr/aztec/src/context/public_context.nr
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl PublicContext {
unencrypted_logs_hashes: BoundedVec::new(),
unencrypted_log_preimages_length: 0,
historical_header: inputs.historical_header,
prover_address: AztecAddress::zero(),
prover_address: AztecAddress::zero()
}
}

Expand Down Expand Up @@ -144,7 +144,6 @@ impl PublicContext {
}

pub fn finish(self) -> PublicCircuitPublicInputs {

// Compute the public call stack hashes
let pub_circuit_pub_inputs = PublicCircuitPublicInputs {
call_context: self.inputs.call_context, // Done
Expand Down Expand Up @@ -358,7 +357,7 @@ fn emit_unencrypted_log_oracle<T>(
_contract_address: AztecAddress,
_event_selector: Field,
_message: T,
_counter: u32,
_counter: u32
) -> Field {}

struct FunctionReturns<N> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,11 @@ contract AvmTest {
context.fee_per_da_gas()
}

#[aztec(public-vm)]
fn get_transaction_fee() -> pub Field {
context.transaction_fee()
}

#[aztec(public-vm)]
fn get_chain_id() -> pub Field {
context.chain_id()
Expand Down
1 change: 1 addition & 0 deletions yarn-project/simulator/src/avm/avm_gas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ export const GasCosts: Record<Opcode, Gas | typeof DynamicGasCost> = {
[Opcode.SENDER]: TemporaryDefaultGasCost,
[Opcode.FEEPERL2GAS]: TemporaryDefaultGasCost,
[Opcode.FEEPERDAGAS]: TemporaryDefaultGasCost,
[Opcode.TRANSACTIONFEE]: TemporaryDefaultGasCost,
[Opcode.CONTRACTCALLDEPTH]: TemporaryDefaultGasCost,
[Opcode.CHAINID]: TemporaryDefaultGasCost,
[Opcode.VERSION]: TemporaryDefaultGasCost,
Expand Down
5 changes: 5 additions & 0 deletions yarn-project/simulator/src/avm/avm_simulator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ describe('AVM simulator: transpiled Noir contracts', () => {
await testEnvGetter('feePerDaGas', fee, 'get_fee_per_da_gas');
});

it('getTransactionFee', async () => {
const fee = new Fr(1);
await testEnvGetter('transactionFee', fee, 'get_transaction_fee');
});

it('chainId', async () => {
const chainId = new Fr(1);
await testEnvGetter('chainId', chainId, 'get_chain_id', /*globalVar=*/ true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,25 @@ import {
Sender,
StorageAddress,
Timestamp,
TransactionFee,
Version,
} from './environment_getters.js';

type EnvInstruction = typeof FeePerL2Gas | typeof FeePerDAGas | typeof Sender | typeof StorageAddress | typeof Address;
type EnvInstruction =
| typeof FeePerL2Gas
| typeof FeePerDAGas
| typeof Sender
| typeof StorageAddress
| typeof Address
| typeof TransactionFee;

describe.each([
[FeePerL2Gas, 'feePerL2Gas'],
[FeePerDAGas, 'feePerDaGas'],
[Sender, 'sender'],
[StorageAddress, 'storageAddress'],
[Address, 'address'],
[TransactionFee, 'transactionFee'],
])('Environment getters instructions', (clsValue: EnvInstruction, key: string) => {
it(`${clsValue.name} should (de)serialize correctly`, () => {
const buf = Buffer.from([
Expand Down
9 changes: 9 additions & 0 deletions yarn-project/simulator/src/avm/opcodes/environment_getters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,15 @@ export class FeePerDAGas extends EnvironmentGetterInstruction {
}
}

export class TransactionFee extends EnvironmentGetterInstruction {
static type: string = 'TRANSACTIONFEE';
static readonly opcode: Opcode = Opcode.TRANSACTIONFEE;

protected getEnvironmentValue(env: AvmExecutionEnvironment) {
return env.transactionFee;
}
}

export class ChainId extends EnvironmentGetterInstruction {
static type: string = 'CHAINID';
static readonly opcode: Opcode = Opcode.CHAINID;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import {
StorageAddress,
Sub,
Timestamp,
TransactionFee,
Version,
Xor,
} from '../opcodes/index.js';
Expand Down Expand Up @@ -82,6 +83,7 @@ const INSTRUCTION_SET = () =>
[Sender.opcode, Sender],
[FeePerL2Gas.opcode, FeePerL2Gas],
[FeePerDAGas.opcode, FeePerDAGas],
[TransactionFee.opcode, TransactionFee],
//[Contractcalldepth.opcode, Contractcalldepth],
// Execution Environment - Globals
[ChainId.opcode, ChainId],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export enum Opcode {
SENDER,
FEEPERL2GAS,
FEEPERDAGAS,
TRANSACTIONFEE,
CONTRACTCALLDEPTH,
CHAINID,
VERSION,
Expand Down