Skip to content

Commit

Permalink
lints
Browse files Browse the repository at this point in the history
  • Loading branch information
clabby committed Aug 2, 2024
1 parent 098acbc commit 3d0130e
Show file tree
Hide file tree
Showing 19 changed files with 100 additions and 69 deletions.
31 changes: 14 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,9 @@

## What's a Howitzer?

Howitzer is an emulator designed to simulate a single MIPS thread context on the EVM. Its primary use is to execute the [`op-program`][op-program]
(also known as the fault-proof program) for the [OP Stack][monorepo]'s interactive dispute protocol. The `op-program` consists
of a stripped down version of `op-geth`'s state transition code in addition to the derivation pipeline, and produces deterministic results.
Subsequently, it is compiled to MIPS to be ran on top of Howitzer on-chain to prove fault in claims about the state of L2 on L1. Howitzer also has a
native implementation of the MIPS thread context that mirrors the on-chain version, which enables the [op-challenger][op-challenger] to generate
state commitments for an `op-program` execution trace and participate in dispute games.
Howitzer is a MIPS64 emulator designed to simulate deterministic execution within a single MIPS thread context both
natively and on the EVM. Its primary objective is to execute [Fault Proof Programs][fpp-specs] such as [`kona`][kona]
or [`op-program`][op-program] for the sake of the [OP Stack][monorepo]'s interactive dispute protocol.

_TL;DR:_

Expand All @@ -40,31 +37,29 @@ _TL;DR:_
- ...that runs an EVM
- ...emulating a MIPS64 machine
- ...that was originally a MIPS32 machine
- ...running [compiled Go code][op-program]
- ...running compiled [Rust][kona] or [Go][op-program] code
- ...that runs an EVM

## Overview

- [`howitzer`](./bin) - The binary for executing MIPS64 programs natively on top of Howitzer with a detached preimage server.
- [`howitzer-kernel`](./crates/kernel) - High-level library for running the Howitzer FPVM with a detached preimage server.
- [`howitzer-fpvm`](./crates/fpvm) - Contains the native implementation of the MIPS thread context emulator.
- [`howitzer-contracts`](https://github.com/ethereum-optimism/optimism/tree/develop/packages/contracts-bedrock/src/cannon) - [*in OP monorepo*] Contains the Solidity implementation of the MIPS thread context and the Preimage Oracle. (TODO: Will be replaced with Howitzer contracts, as the VM architectures will differ.)
- [`howitzer-contracts`](./contracts) - Contains the EVM implementation of the MIPS thread context emulator.

## Credits

This repository is heavily inspired by the original [Cannon][cannon], built by [George Hotz][geohot] and members of the [OP Labs][op-labs] team. The original implementation is written in Go, and can be found [in the Optimism monorepo][cannon]. All
This repository is heavily inspired by the original [Cannon][cannon] VM, built by [George Hotz][geohot] and members of the
[OP Labs][op-labs] team. The original implementation is written in Go, and can be found [in the Optimism monorepo][cannon]. All
credits for the original idea and reference implementation of this concept go to these folks.

## Benchmarks

### `howitzer-fpvm` benchmarks

_TODO_

## Contributing

To get started, a few dependencies are required:

- [Rust toolchain][rustup]
- Recommended: [`cargo-nextest`][nextest]
- [Just][just]
- [Go toolchain][golang]
- [binutils][binutils]

Expand Down Expand Up @@ -106,11 +101,13 @@ script provided.
[op-labs]: https://oplabs.co
[monorepo]: https://github.com/ethereum-optimism/optimism
[cannon]: https://github.com/ethereum-optimism/optimism/tree/develop/cannon
[kona]: https://github.com/ethereum-optimism/kona
[op-program]: https://github.com/ethereum-optimism/optimism/tree/develop/op-program
[op-challenger]: https://github.com/ethereum-optimism/optimism/tree/develop/op-challenger
[fpp-specs]: https://specs.optimism.io/fault-proof/index.html
[cannon-specs]: https://github.com/ethereum-optimism/optimism/blob/develop/specs/cannon-fault-proof-vm.md
[rustup]: https://rustup.rs/
[golang]: https://go.dev/doc/install
[binutils]: https://www.gnu.org/software/binutils/
[nextest]: https://nexte.st/
[fpp-specs]: https://github.com/ethereum-optimism/optimism/blob/develop/specs/fault-proof.md
[cannon-specs]: https://github.com/ethereum-optimism/optimism/blob/develop/specs/cannon-fault-proof-vm.md
[just]: https://github.com/casey/just
2 changes: 1 addition & 1 deletion crates/fpvm/benches/execution.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use criterion::{criterion_group, criterion_main, Bencher, Criterion};
use howitzer_fpvm::{
mips::InstrumentedState,
test_utils::{ClaimTestOracle, StaticOracle},
utils::patch::{load_elf, patch_go, patch_stack},
InstrumentedState,
};
use kona_preimage::{HintRouter, PreimageFetcher};
use pprof::criterion::{Output, PProfProfiler};
Expand Down
11 changes: 5 additions & 6 deletions crates/fpvm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#![doc = include_str!("../README.md")]

mod mips;
pub use mips::InstrumentedState;
#![warn(missing_debug_implementations, missing_docs, unreachable_pub, rustdoc::all)]
#![deny(unused_must_use, rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

pub mod memory;

pub mod utils;

pub mod mips;
pub mod state;
pub mod utils;

#[cfg(feature = "mipsevm")]
pub mod evm;
Expand Down
5 changes: 2 additions & 3 deletions crates/fpvm/src/memory/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
/// An [Address] is a 64 bit address in the MIPS emulator's memory.
pub type Address = u64;

pub(crate) mod trie;

pub(crate) mod page;
pub mod page;
pub mod trie;

mod trie_memory;
pub use trie_memory::{MemoryReader, TrieMemory};
21 changes: 15 additions & 6 deletions crates/fpvm/src/memory/page.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
//! This module contains the [Page] type as well as associated page parameterization constants.
/// An index of a [Page] within a [TrieMemory] structure.
pub(crate) type PageIndex = u64;
/// An index of a [Page] within an [Address].
///
/// [Address]: super::Address
pub type PageIndex = u64;

/// A page of memory, representing [PAGE_SIZE] bytes of data.
pub(crate) type Page = [u8; PAGE_SIZE];
pub type Page = [u8; PAGE_SIZE];

pub(crate) const PAGE_ADDRESS_SIZE: usize = 12;
pub(crate) const PAGE_SIZE: usize = 1 << PAGE_ADDRESS_SIZE;
pub(crate) const PAGE_ADDRESS_MASK: usize = PAGE_SIZE - 1;
/// The size of a page address in bits.
pub const PAGE_ADDRESS_SIZE: usize = 12;

/// The size of a [Page] in bytes.
pub const PAGE_SIZE: usize = 1 << PAGE_ADDRESS_SIZE;

/// The mask to apply to an [Address] to obtain the page address.
///
/// [Address]: super::Address
pub const PAGE_ADDRESS_MASK: usize = PAGE_SIZE - 1;

/// An empty page of memory, zeroed out.
pub(crate) const EMPTY_PAGE: Page = [0u8; PAGE_SIZE];
13 changes: 8 additions & 5 deletions crates/fpvm/src/memory/trie_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use super::{
};
use crate::{
memory::page::{PAGE_ADDRESS_MASK, PAGE_ADDRESS_SIZE, PAGE_SIZE},
mips::mips_isa::{DoubleWord, Word},
mips::isa::{DoubleWord, Word},
};
use alloy_primitives::{Bytes, B256};
use alloy_rlp::{Decodable, Encodable};
Expand Down Expand Up @@ -235,11 +235,11 @@ impl TrieMemory {
}
}

/// Returns a human-readable string describing the size of the [Memory].
/// Returns a human-readable string describing the size of the [TrieMemory].
///
/// ## Returns
/// - A human-readable string describing the size of the [Memory] in B, KiB, MiB, GiB, TiB, PiB,
/// or EiB.
/// - A human-readable string describing the size of the [TrieMemory] in B, KiB, MiB, GiB, TiB,
/// PiB, or EiB.
pub fn usage(&self) -> String {
let total = (self.page_count() * PAGE_SIZE) as u64;
const UNIT: u64 = 1024;
Expand Down Expand Up @@ -288,13 +288,16 @@ impl<'de> Deserialize<'de> for TrieMemory {
/// Enables unaligned verbatim reads from the [TrieMemory]'s pages. If the pages for the address
/// space requested are not present, the reader will return zeroed out data for that region, rather
/// than fail.
#[derive(Debug)]
pub struct MemoryReader<'a> {
memory: &'a mut TrieMemory,
address: Address,
count: u64,
}

impl<'a> MemoryReader<'a> {
/// Create a new [MemoryReader] for the given [TrieMemory] structure that can read
/// `count` bytes starting from `address`.
pub fn new(memory: &'a mut TrieMemory, address: Address, count: u64) -> Self {
Self { memory, address, count }
}
Expand Down Expand Up @@ -335,7 +338,7 @@ mod test {
use super::TrieMemory;
use crate::{
memory::{trie_memory::PAGE_SIZE, Address},
mips::mips_isa::{DoubleWord, Word},
mips::isa::{DoubleWord, Word},
};
use alloy_trie::EMPTY_ROOT_HASH;
use std::io::Cursor;
Expand Down
8 changes: 5 additions & 3 deletions crates/fpvm/src/mips/instrumented.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This module contains the [InstrumentedState] definition.
use super::mips_isa::DoubleWord;
use super::isa::DoubleWord;
use crate::{
memory::Address,
state::{State, StepWitness},
Expand All @@ -14,6 +14,7 @@ use std::io::{BufWriter, Write};
/// the input and output buffers, and an implementation of the MIPS VM.
///
/// To perform an instruction step on the MIPS emulator, use the [InstrumentedState::step] method.
#[derive(Debug)]
pub struct InstrumentedState<O, E, P>
where
O: Write,
Expand All @@ -34,7 +35,7 @@ where
/// The memory proof, if it is enabled.
pub(crate) mem_proof: Option<Vec<Bytes>>,

/// The [PreimageOracle] used to fetch preimages.
/// The [HintRouter] + [PreimageFetcher] used to fetch preimages.
pub(crate) preimage_oracle: P,
/// Cached pre-image data, including 8 byte length prefix
pub(crate) last_preimage: Vec<u8>,
Expand All @@ -51,6 +52,7 @@ where
E: Write,
P: HintRouter + PreimageFetcher,
{
/// Create a new [InstrumentedState].
pub fn new(state: State, oracle: P, std_out: O, std_err: E) -> Self {
Self {
state,
Expand Down Expand Up @@ -134,13 +136,13 @@ where
mod test {
use crate::{
memory::Address,
mips::InstrumentedState,
state::State,
test_utils::{ClaimTestOracle, StaticOracle, BASE_ADDR_END, END_ADDR},
utils::{
meta::Meta,
patch::{load_elf, patch_go, patch_stack},
},
InstrumentedState,
};
use elf::{endian::AnyEndian, ElfBytes};
use std::{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ def_enum!(RegImmFunction {

#[cfg(test)]
mod test {
use crate::mips::mips_isa::{IType, JType, RType};
use crate::mips::isa::{IType, JType, RType};

#[test]
fn decode_j_type() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@
use super::{
def_enum,
mips_isa::{DoubleWord, Word},
isa::{DoubleWord, Word},
};
use crate::{
memory::{page, Address, MemoryReader},
InstrumentedState,
mips::InstrumentedState,
};
use anyhow::Result;
use kona_preimage::{HintRouter, PreimageFetcher};
use std::io::{self, BufReader, Read, Write};

/// https://www.cs.cmu.edu/afs/club/usr/jhutz/project/Linux/src/include/asm-mips/errno.h
/// [MIPS Syscall Definitions](https://www.cs.cmu.edu/afs/club/usr/jhutz/project/Linux/src/include/asm-mips/errno.h)
const MIPS_EBADF: u64 = 0x9;

/// https://www.cs.cmu.edu/afs/club/usr/jhutz/project/Linux/src/include/asm-mips/errno.h
/// [MIPS Syscall Definitions](https://www.cs.cmu.edu/afs/club/usr/jhutz/project/Linux/src/include/asm-mips/errno.h)
const MIPS_EINVAL: u64 = 0x16;

def_enum!(Fd {
Expand Down Expand Up @@ -237,7 +237,7 @@ where
Ok(())
}

/// Read the preimage for the given key and offset from the [PreimageOracle] server.
/// Read the preimage for the given key and offset from the preimage server.
///
/// ### Takes
/// - `key`: The key of the preimage (the preimage's [alloy_primitives::keccak256] digest).
Expand Down
13 changes: 7 additions & 6 deletions crates/fpvm/src/mips/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
mod instrumented;
pub use instrumented::InstrumentedState;

pub(crate) mod mips_vm;

pub(crate) mod mips_isa;

pub(crate) mod mips_linux;
pub mod isa;
pub mod linux;
pub mod vm;

/// Defines an enum type with underlying [u32] representation on variants, and a [TryFrom]
/// implementation automatically generated.
Expand All @@ -18,7 +16,10 @@ macro_rules! def_enum {
#[allow(clippy::upper_case_acronyms)]
#[repr(u32)]
pub enum $enum {
$( $variant = $value ),*
$(
#[doc = concat!(stringify!($variant), " = ", stringify!($value))]
$variant = $value
),*
}

impl TryFrom<u32> for $enum {
Expand Down
10 changes: 6 additions & 4 deletions crates/fpvm/src/mips/mips_vm.rs → crates/fpvm/src/mips/vm.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! This module contains the MIPS VM implementation for the [InstrumentedState].
use super::mips_isa::{
use super::isa::{
DoubleWord, IType, JType, Opcode, RType, RegImmFunction, Special2Function, SpecialFunction,
Word,
};
use crate::{memory::Address, utils::sign_extend, InstrumentedState};
use crate::{memory::Address, mips::InstrumentedState, utils::sign_extend};
use anyhow::Result;
use kona_preimage::{HintRouter, PreimageFetcher};
use std::io::Write;
Expand Down Expand Up @@ -649,13 +649,15 @@ where
Ok(())
}

/// Track an access to [crate::Memory] at the given [Address].
/// Track an access to [TrieMemory] at the given [Address].
///
/// ### Takes
/// - `effective_address`: The address in [crate::Memory] being accessed.
/// - `effective_address`: The address in [TrieMemory] being accessed.
///
/// ### Returns
/// - A [Result] indicating if the operation was successful.
///
/// [TrieMemory]: crate::memory::TrieMemory
#[inline]
pub(crate) fn track_mem_access(&mut self, effective_address: Address) -> Result<()> {
if self.mem_proof_enabled && self.last_mem_access != Some(effective_address) {
Expand Down
15 changes: 11 additions & 4 deletions crates/fpvm/src/state/vm_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use serde::{Deserialize, Serialize};
/// The size of an encoded [StateWitness] in bytes.
pub const STATE_WITNESS_SIZE: usize = 378;

/// A [StateWitness] is an encoded commitment to the current [crate::State] of the MIPS emulator.
/// A [StateWitness] is an encoded commitment to the current [State] of the MIPS emulator.
pub type StateWitness = [u8; STATE_WITNESS_SIZE];

/// Compute the hash of the [StateWitness]
Expand All @@ -23,22 +23,29 @@ pub fn state_hash(witness: StateWitness) -> [u8; 32] {

/// The [VMStatus] is an indicator within the [StateWitness] hash that indicates
/// the current status of the MIPS emulator.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[repr(u8)]
pub enum VMStatus {
/// The VM exited successfully, and the computation was valid.
Valid = 0,
/// The VM exited successfully, and the computation was invalid.
Invalid = 1,
/// The program panicked.
Panic = 2,
/// The program is still running.
Unfinished = 3,
}

/// The [State] struct contains the internal model of the MIPS emulator state.
///
/// The [State] by itself does not contain functionality for performing instruction steps
/// or executing the MIPS emulator. For this, use the [crate::InstrumentedState] struct.
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
/// or executing the MIPS emulator. For this, use the [InstrumentedState] struct.
///
/// [InstrumentedState]: crate::mips::InstrumentedState
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct State {
/// The [Memory] of the emulated MIPS thread context.
/// The memory of the emulated MIPS thread context.
pub memory: TrieMemory,
/// The preimage key for the given state.
#[serde(with = "crate::utils::ser::fixed_32_hex")]
Expand Down
Loading

0 comments on commit 3d0130e

Please sign in to comment.