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

feat: crate docs #39

Merged
merged 12 commits into from
Apr 8, 2024
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 5 additions & 2 deletions bin/alphanet/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
//! # Reth Alphanet
//! # Reth AlphaNet
//!
//! Reth AlphaNet is a testnet OP Stack rollup aimed at enabling experimentation of bleeding edge
//! Ethereum Research.
//! Ethereum Research. It aims to showcase how Reth's pluggable and modularized architecture can
//! serve as a distribution channel for research ideas.

#![warn(unused_crate_dependencies)]

Expand All @@ -17,9 +18,11 @@ use reth_node_optimism::{args::RollupArgs, OptimismEngineTypes, OptimismNode};

// We use jemalloc for performance reasons.
#[cfg(all(feature = "jemalloc", unix))]
#[doc(hidden)]
#[global_allocator]
static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;

#[doc(hidden)]
fn main() {
reth::sigsegv_handler::install();

Expand Down
2 changes: 2 additions & 0 deletions crates/instructions/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ revm-precompile.workspace = true
revm-primitives.workspace = true

[dev-dependencies]
reth.workspace = true
reth-node-api.workspace = true
secp256k1 = { version = "0.28.2", default-features = false, features = [
"alloc",
"recovery",
Expand Down
5 changes: 5 additions & 0 deletions crates/instructions/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
//! Ephemeral context for custom instructions.
//!
//! Management of state available for custom instructions during the execution
//! of a single transaction.

use std::{cell::RefCell, collections::HashMap, rc::Rc};

#[derive(Clone, Default)]
Expand Down
95 changes: 87 additions & 8 deletions crates/instructions/src/eip3074.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,68 @@
//! EIP-3074 custom instructions.
//!
//! To insert the instructions in a custom EVM an instructions context must be
//! constructed and passed to the instructions themselves. It should be cleared at the end
//! of each transaction, like this:
//! ```
//! use alphanet_instructions::{context::InstructionsContext, eip3074};
//! use reth::primitives::{ChainSpec, Transaction, U256};
//! use reth_node_api::{ConfigureEvm, ConfigureEvmEnv};
//! use revm::{Database, Evm, EvmBuilder};
//! use revm_primitives::{Address, Bytes, CfgEnvWithHandlerCfg, TxEnv};
//! use std::sync::Arc;
//!
//! #[derive(Debug, Clone, Copy, Default)]
//! #[non_exhaustive]
//! struct AlphaNetEvmConfig;
//!
//! impl ConfigureEvm for AlphaNetEvmConfig {
//! fn evm<'a, DB: Database + 'a>(&self, db: DB) -> Evm<'a, (), DB> {
//! // this instructions context will allow to set the `authorized` context variable.
//! let instructions_context = InstructionsContext::default();
//! let to_capture_instructions = instructions_context.clone();
//! let to_capture_post_execution = instructions_context.clone();
//! EvmBuilder::default()
//! .with_db(db)
//! .append_handler_register_box(Box::new(move |handler| {
//! if let Some(ref mut table) = handler.instruction_table {
//! for boxed_instruction_with_opcode in
//! eip3074::boxed_instructions(to_capture_instructions.clone())
//! {
//! table.insert_boxed(
//! boxed_instruction_with_opcode.opcode,
//! boxed_instruction_with_opcode.boxed_instruction,
//! );
//! }
//! }
//! let post_execution_context = instructions_context.clone();
//! handler.post_execution.end = Arc::new(move |_, outcome: _| {
//! // at the end if the transaction execution we clear the instructions
//! post_execution_context.clear();
//! outcome
//! });
//! }))
//! .build()
//! }
//! }
//!
//! impl ConfigureEvmEnv for AlphaNetEvmConfig {
//! type TxMeta = Bytes;
//! fn fill_tx_env<T>(_: &mut TxEnv, _: T, _: Address, _: <Self as ConfigureEvmEnv>::TxMeta)
//! where
//! T: AsRef<Transaction>,
//! {
//! todo!()
//! }
//! fn fill_cfg_env(
//! _: &mut CfgEnvWithHandlerCfg,
//! _: &ChainSpec,
//! _: &reth::primitives::Header,
//! _: U256,
//! ) {
//! todo!()
//! }
//! }
//! ```
use crate::{context::InstructionsContext, BoxedInstructionWithOpCode};
use revm::{Database, Evm};
use revm_interpreter::{
Expand All @@ -11,15 +76,25 @@ use revm_primitives::{
alloy_primitives::B512, keccak256, spec_to_generic, Address, SpecId, B256, U256,
};

/// Numeric op code for the `AUTH` mnemonic.
const AUTH_OPCODE: u8 = 0xF6;
/// Numeric op code for the `AUTHCALL` mnemonic.
const AUTHCALL_OPCODE: u8 = 0xF7;
/// Constant used to compose the message expected by `AUTH`
const MAGIC: u8 = 0x04;
/// Gas to charge when the authority has been previously loaded.
const WARM_AUTHORITY_GAS: u64 = 100;
/// Gas to charge when the authority has not been previously loaded.
const COLD_AUTHORITY_GAS: u64 = 2600;
/// Fixed gas to charge.
const FIXED_FEE_GAS: u64 = 3100;
/// Context variable name to store (AUTH) and retrieve (AUTHCALL) the validated
/// authority.
const AUTHORIZED_VAR_NAME: &str = "authorized";

/// eip3074 boxed instructions.
/// Generates an iterator over EIP3074 boxed instructions. Defining the
/// instructions inside a `Box` allows them to capture variables defined in its
/// environment.
pub fn boxed_instructions<'a, EXT: 'a, DB: Database + 'a>(
context: InstructionsContext,
) -> impl Iterator<Item = BoxedInstructionWithOpCode<'a, Evm<'a, EXT, DB>>> {
Expand Down Expand Up @@ -49,7 +124,8 @@ pub fn boxed_instructions<'a, EXT: 'a, DB: Database + 'a>(
.into_iter()
}

// keccak256(MAGIC || chainId || nonce || invokerAddress || commit)
/// Composes the message expected by the AUTH instruction in this format:
/// `keccak256(MAGIC || chainId || nonce || invokerAddress || commit)`
fn compose_msg(chain_id: u64, nonce: u64, invoker_address: Address, commit: B256) -> B256 {
let mut msg = [0u8; 129];
msg[0] = MAGIC;
Expand All @@ -60,9 +136,10 @@ fn compose_msg(chain_id: u64, nonce: u64, invoker_address: Address, commit: B256
keccak256(msg.as_slice())
}

// AUTH instruction, see EIP-3074:
//
// <https://eips.ethereum.org/EIPS/eip-3074#auth-0xf6>
/// `AUTH` instruction, interprets data from the stack and memory to validate an
/// `authority` account for subsequent `AUTHCALL` invocations. See also:
///
/// <https://eips.ethereum.org/EIPS/eip-3074#auth-0xf6>
fn auth_instruction<EXT, DB: Database>(
interp: &mut Interpreter,
evm: &mut Evm<'_, EXT, DB>,
Expand Down Expand Up @@ -127,9 +204,11 @@ fn auth_instruction<EXT, DB: Database>(
}
}

// AUTHCALL instruction, see EIP-3074:
//
// <https://eips.ethereum.org/EIPS/eip-3074#authcall-0xf7>
/// `AUTHCALL` instruction, tries to read a context variable set by a previous
/// `AUTH` invocation and, if present, uses it as the `caller` in a `CALL`
/// executed as the next action. See also:
///
/// <https://eips.ethereum.org/EIPS/eip-3074#authcall-0xf7>
fn authcall_instruction<EXT, DB: Database>(
interp: &mut Interpreter,
evm: &mut Evm<'_, EXT, DB>,
Expand Down
13 changes: 5 additions & 8 deletions crates/instructions/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
//! # alphanet-instructions
//! # AlphaNet instructions
//!
//! Custom instructions for Alphanet.
//! Collection of custom OP codes for AlphaNet and related functionality.

#![warn(unused_crate_dependencies)]
#![cfg_attr(not(test), warn(unused_crate_dependencies))]

use revm_interpreter::opcode::BoxedInstruction;

/// EIP-3074 custom instructions.
pub mod eip3074;

/// Instructions context.
pub mod context;
pub mod eip3074;

/// Association of OpCode and correspondent boxed instruction.
/// Association of OP codes and correspondent boxed instruction.
pub struct BoxedInstructionWithOpCode<'a, H> {
/// Opcode.
pub opcode: u8,
Expand Down
40 changes: 32 additions & 8 deletions crates/node/src/evm.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Implementation of the ConfigureEvmEnv trait.

use alphanet_instructions::{context::InstructionsContext, eip3074, BoxedInstructionWithOpCode};
use alphanet_precompile::{bls12_381, secp256r1};
use reth::primitives::{
Expand All @@ -20,7 +22,7 @@ use std::sync::Arc;
#[non_exhaustive]
pub struct AlphaNetEvmConfig;

// Inserts the given precompiles with address in the context precompiles.
/// Inserts the given precompiles with address in the context precompiles.
fn insert_precompiles<I>(precompiles: &mut Precompiles, precompiles_with_address: I)
where
I: Iterator<Item = PrecompileWithAddress>,
Expand All @@ -30,7 +32,7 @@ where
}
}

// Inserts the given boxed instructions with opcodes in the instructions table.
/// Inserts the given boxed instructions with opcodes in the instructions table.
fn insert_boxed_instructions<'a, I, H>(
table: &mut InstructionTables<'a, H>,
boxed_instructions_with_opcodes: I,
Expand Down Expand Up @@ -76,13 +78,13 @@ impl AlphaNetEvmConfig {
/// [ConfigureEvm::evm_with_inspector]
///
/// This will use the default mainnet instructions and append additional instructions.
fn append_custom_instructions<EXT, DB>(handler: &mut EvmHandler<'_, EXT, DB>)
where
fn append_custom_instructions<EXT, DB>(
handler: &mut EvmHandler<'_, EXT, DB>,
instructions_context: InstructionsContext,
) where
DB: Database,
{
if let Some(ref mut table) = handler.instruction_table {
let instructions_context = InstructionsContext::default();

insert_boxed_instructions(
table,
eip3074::boxed_instructions(instructions_context.clone()),
Expand All @@ -95,23 +97,45 @@ impl AlphaNetEvmConfig {

impl ConfigureEvm for AlphaNetEvmConfig {
fn evm<'a, DB: Database + 'a>(&self, db: DB) -> Evm<'a, (), DB> {
let instructions_context = InstructionsContext::default();
EvmBuilder::default()
.with_db(db)
// add additional precompiles
.append_handler_register(Self::set_precompiles)
// add custom instructions
.append_handler_register(Self::append_custom_instructions)
.append_handler_register_box(Box::new(move |h| {
Self::append_custom_instructions(h, instructions_context.clone());
let post_execution_context = instructions_context.clone();
#[allow(clippy::arc_with_non_send_sync)]
{
h.post_execution.end = Arc::new(move |_, outcome: _| {
post_execution_context.clear();
outcome
});
}
}))
.build()
}

fn evm_with_inspector<'a, DB: Database + 'a, I>(&self, db: DB, inspector: I) -> Evm<'a, I, DB> {
let instructions_context = InstructionsContext::default();
Comment on lines 120 to +121
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heads up, this function signature was changed on main because this is currently incorrect, because we're not appending the inspector register

https://github.com/paradigmxyz/reth/blob/c6857efa8a10e2e86396ac6385d1008b8128e694/crates/evm/src/lib.rs#L66-L70

EvmBuilder::default()
.with_db(db)
.with_external_context(inspector)
// add additional precompiles
.append_handler_register(Self::set_precompiles)
// add custom instructions
.append_handler_register(Self::append_custom_instructions)
.append_handler_register_box(Box::new(move |h| {
Self::append_custom_instructions(h, instructions_context.clone());
let post_execution_context = instructions_context.clone();
#[allow(clippy::arc_with_non_send_sync)]
{
h.post_execution.end = Arc::new(move |_, outcome: _| {
post_execution_context.clear();
outcome
});
}
}))
.build()
}
}
Expand Down
2 changes: 0 additions & 2 deletions crates/node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,5 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
#![warn(unused_crate_dependencies)]

/// Implementation of the ConfigureEvmEnv trait.
pub mod evm;
/// Node types config.
pub mod node;
2 changes: 2 additions & 0 deletions crates/node/src/node.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
//! Node types config.

use crate::evm::AlphaNetEvmConfig;
use reth::builder::NodeTypes;
use reth_node_optimism::OptimismEngineTypes;
Expand Down
3 changes: 3 additions & 0 deletions crates/precompile/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ blst = "0.3.11"
p256 = { version = "0.13.2", features = ["ecdsa"] }

[dev-dependencies]
reth-node-api.workspace = true
reth.workspace = true
revm.workspace = true
criterion.workspace = true
eyre.workspace = true
rstest.workspace = true
Expand Down
Loading
Loading