Skip to content

Commit

Permalink
docs: Add docs to revm-bytecode crate (bluealloy#2108)
Browse files Browse the repository at this point in the history
* docs: Bytecode crate

* fix test

* fmt and doc

* Doc

* add comments for EOF
  • Loading branch information
rakita authored Feb 24, 2025
1 parent b3300a1 commit be7e9a5
Show file tree
Hide file tree
Showing 22 changed files with 283 additions and 164 deletions.
4 changes: 2 additions & 2 deletions bins/revme/src/cmd/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ impl Cmd {
/// Runs statetest command.
pub fn run(&self) {
let container_kind = if self.eof_initcode {
Some(CodeType::ReturnContract)
Some(CodeType::Initcode)
} else if self.eof_runtime {
Some(CodeType::ReturnOrStop)
Some(CodeType::Runtime)
} else {
None
};
Expand Down
4 changes: 2 additions & 2 deletions bins/revme/src/cmd/eofvalidation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,9 +77,9 @@ pub fn run_test(path: &Path) -> Result<(), Error> {
}
test_sum += 1;
let kind = if test_vector.container_kind.is_some() {
Some(CodeType::ReturnContract)
Some(CodeType::Initcode)
} else {
Some(CodeType::ReturnOrStop)
Some(CodeType::Runtime)
};
// In future this can be generalized to cover multiple forks, Not just Osaka.
let Some(test_result) = test_vector.results.get("Osaka") else {
Expand Down
21 changes: 8 additions & 13 deletions crates/bytecode/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use core::fmt::Debug;
use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY};
use std::sync::Arc;

/// State of the [`Bytecode`] analysis
/// Main bytecode structure with all variants.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Bytecode {
Expand Down Expand Up @@ -81,7 +81,7 @@ impl Bytecode {
///
/// # Panics
///
/// Panics if bytecode is in incorrect format.
/// Panics if bytecode is in incorrect format. If you want to handle errors use [`Self::new_raw_checked`].
#[inline]
pub fn new_raw(bytecode: Bytes) -> Self {
Self::new_raw_checked(bytecode).expect("Expect correct EOF bytecode")
Expand Down Expand Up @@ -114,15 +114,10 @@ impl Bytecode {

/// Create new checked bytecode.
///
/// # Safety
/// # Panics
///
/// Bytecode needs to end with `STOP` (`0x00`) opcode as checked bytecode assumes
/// that it is safe to iterate over bytecode without checking lengths.
pub unsafe fn new_analyzed(
bytecode: Bytes,
original_len: usize,
jump_table: JumpTable,
) -> Self {
/// For possible panics see [`LegacyAnalyzedBytecode::new`].
pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self {
Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new(
bytecode,
original_len,
Expand Down Expand Up @@ -156,7 +151,7 @@ impl Bytecode {
self.bytes_ref().clone()
}

/// Returns bytes.
/// Returns raw bytes reference.
#[inline]
pub fn bytes_ref(&self) -> &Bytes {
match self {
Expand All @@ -166,13 +161,13 @@ impl Bytecode {
}
}

/// Returns bytes slice.
/// Returns raw bytes slice.
#[inline]
pub fn bytes_slice(&self) -> &[u8] {
self.bytes_ref()
}

/// Returns a reference to the original bytecode.
/// Returns the original bytecode.
#[inline]
pub fn original_bytes(&self) -> Bytes {
match self {
Expand Down
24 changes: 12 additions & 12 deletions crates/bytecode/src/eof.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
mod body;
mod code_info;
mod decode_helpers;
mod header;
pub mod printer;
mod types_section;
pub mod verification;

pub use body::EofBody;
pub use code_info::CodeInfo;
pub use header::EofHeader;
pub use types_section::TypesSection;
pub use verification::*;

use core::cmp::min;
Expand Down Expand Up @@ -39,7 +39,7 @@ impl Default for Eof {
fn default() -> Self {
let body = EofBody {
// Types section with zero inputs, zero outputs and zero max stack size.
types_section: vec![TypesSection::default()],
code_info: vec![CodeInfo::default()],
code_section: vec![1],
// One code section with a STOP byte.
code: Bytes::from_static(&[0x00]),
Expand Down Expand Up @@ -136,10 +136,10 @@ pub enum EofDecodeError {
MissingBodyWithoutData,
/// Body size is more than specified in the header
DanglingData,
/// Invalid types section data
InvalidTypesSection,
/// Invalid types section size
InvalidTypesSectionSize,
/// Invalid code info data
InvalidCodeInfo,
/// Invalid code info size
InvalidCodeInfoSize,
/// Invalid EOF magic number
InvalidEOFMagicNumber,
/// Invalid EOF version
Expand All @@ -154,8 +154,8 @@ pub enum EofDecodeError {
InvalidDataKind,
/// Invalid kind after code
InvalidKindAfterCode,
/// Mismatch of code and types sizes
MismatchCodeAndTypesSize,
/// Mismatch of code and info sizes
MismatchCodeAndInfoSize,
/// There should be at least one size
NonSizes,
/// Missing size
Expand All @@ -178,16 +178,16 @@ impl fmt::Display for EofDecodeError {
Self::MissingInput => "Short input while processing EOF",
Self::MissingBodyWithoutData => "Short body while processing EOF",
Self::DanglingData => "Body size is more than specified in the header",
Self::InvalidTypesSection => "Invalid types section data",
Self::InvalidTypesSectionSize => "Invalid types section size",
Self::InvalidCodeInfo => "Invalid types section data",
Self::InvalidCodeInfoSize => "Invalid types section size",
Self::InvalidEOFMagicNumber => "Invalid EOF magic number",
Self::InvalidEOFVersion => "Invalid EOF version",
Self::InvalidTypesKind => "Invalid number for types kind",
Self::InvalidCodeKind => "Invalid number for code kind",
Self::InvalidTerminalByte => "Invalid terminal code",
Self::InvalidDataKind => "Invalid data kind",
Self::InvalidKindAfterCode => "Invalid kind after code",
Self::MismatchCodeAndTypesSize => "Mismatch of code and types sizes",
Self::MismatchCodeAndInfoSize => "Mismatch of code and types sizes",
Self::NonSizes => "There should be at least one size",
Self::ShortInputForSizes => "Missing size",
Self::ZeroSize => "Size cant be zero",
Expand Down
14 changes: 7 additions & 7 deletions crates/bytecode/src/eof/body.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{Eof, EofDecodeError, EofHeader, TypesSection};
use super::{CodeInfo, Eof, EofDecodeError, EofHeader};
use primitives::Bytes;
use std::vec::Vec;

Expand All @@ -11,7 +11,7 @@ use std::vec::Vec;
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EofBody {
/// Code information
pub types_section: Vec<TypesSection>,
pub code_info: Vec<CodeInfo>,
/// Index of the last byte of each code section
pub code_section: Vec<usize>,
pub code: Bytes,
Expand All @@ -37,7 +37,7 @@ impl EofBody {
pub fn into_eof(self) -> Eof {
let mut prev_value = 0;
let header = EofHeader {
types_size: self.types_section.len() as u16 * 4,
types_size: self.code_info.len() as u16 * 4,
code_sizes: self
.code_section
.iter()
Expand Down Expand Up @@ -76,8 +76,8 @@ impl EofBody {

/// Encodes this body into the given buffer.
pub fn encode(&self, buffer: &mut Vec<u8>) {
for types_section in &self.types_section {
types_section.encode(buffer);
for code_info in &self.code_info {
code_info.encode(buffer);
}

buffer.extend_from_slice(&self.code);
Expand Down Expand Up @@ -108,9 +108,9 @@ impl EofBody {

let mut types_input = &input[header_len..];
for _ in 0..header.types_count() {
let (types_section, local_input) = TypesSection::decode(types_input)?;
let (code_info, local_input) = CodeInfo::decode(types_input)?;
types_input = local_input;
body.types_section.push(types_section);
body.code_info.push(code_info);
}

// Extract code section
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const EOF_NON_RETURNING_FUNCTION: u8 = 0x80;
/// Types section that contains stack information for matching code section
#[derive(Debug, Clone, Default, Hash, PartialEq, Eq, Copy, PartialOrd, Ord)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct TypesSection {
pub struct CodeInfo {
/// `inputs` - 1 byte - `0x00-0x7F`
///
/// Number of stack elements the code section consumes
Expand All @@ -25,8 +25,8 @@ pub struct TypesSection {
pub max_stack_size: u16,
}

impl TypesSection {
/// Returns new `TypesSection` with the given inputs, outputs, and max_stack_size.
impl CodeInfo {
/// Returns new `CodeInfo` with the given inputs, outputs, and max_stack_size.
pub fn new(inputs: u8, outputs: u8, max_stack_size: u16) -> Self {
Self {
inputs,
Expand Down Expand Up @@ -72,10 +72,10 @@ impl TypesSection {
/// Validates the section.
pub fn validate(&self) -> Result<(), EofDecodeError> {
if self.inputs > 0x7f || self.outputs > 0x80 || self.max_stack_size > 0x03FF {
return Err(EofDecodeError::InvalidTypesSection);
return Err(EofDecodeError::InvalidCodeInfo);
}
if self.inputs as u16 > self.max_stack_size {
return Err(EofDecodeError::InvalidTypesSection);
return Err(EofDecodeError::InvalidCodeInfo);
}
Ok(())
}
Expand Down
7 changes: 6 additions & 1 deletion crates/bytecode/src/eof/decode_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use super::EofDecodeError;

/// Consumes a u8 from the input.
/// Consumes a single byte from the input slice and returns a tuple containing the remaining input slice
/// and the consumed byte as a u8.
///
/// Returns `EofDecodeError::MissingInput` if the input slice is empty.
#[inline]
pub(crate) fn consume_u8(input: &[u8]) -> Result<(&[u8], u8), EofDecodeError> {
if input.is_empty() {
Expand All @@ -10,6 +13,8 @@ pub(crate) fn consume_u8(input: &[u8]) -> Result<(&[u8], u8), EofDecodeError> {
}

/// Consumes a u16 from the input.
///
/// Returns `EofDecodeError::MissingInput` if the input slice is less than 2 bytes.
#[inline]
pub(crate) fn consume_u16(input: &[u8]) -> Result<(&[u8], u16), EofDecodeError> {
if input.len() < 2 {
Expand Down
22 changes: 11 additions & 11 deletions crates/bytecode/src/eof/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use super::{
};
use std::vec::Vec;

/// EOF Header containing
/// EOF header structure that contains section sizes and metadata
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct EofHeader {
Expand All @@ -22,14 +22,14 @@ pub struct EofHeader {
pub container_sizes: Vec<u16>,
/// EOF data size
pub data_size: u16,
/// Sum code sizes
/// Sum of code sizes
pub sum_code_sizes: usize,
/// Sum container sizes
/// Sum of container sizes
pub sum_container_sizes: usize,
}

const KIND_TERMINAL: u8 = 0;
const KIND_TYPES: u8 = 1;
const KIND_CODE_INFO: u8 = 1;
const KIND_CODE: u8 = 2;
const KIND_CONTAINER: u8 = 3;
const KIND_DATA: u8 = 4;
Expand Down Expand Up @@ -113,7 +113,7 @@ impl EofHeader {
// `version` 1 byte 0x01 EOF version
buffer.push(0x01);
// `kind_types` 1 byte 0x01 kind marker for types size section
buffer.push(KIND_TYPES);
buffer.push(KIND_CODE_INFO);
// `types_size` 2 bytes 0x0004-0xFFFF
buffer.extend_from_slice(&self.types_size.to_be_bytes());
// `kind_code` 1 byte 0x02 kind marker for code size section
Expand Down Expand Up @@ -159,8 +159,8 @@ impl EofHeader {
}

// `kind_types` 1 byte 0x01 kind marker for types size section
let (input, kind_types) = consume_u8(input)?;
if kind_types != KIND_TYPES {
let (input, kind_code_info) = consume_u8(input)?;
if kind_code_info != KIND_CODE_INFO {
return Err(EofDecodeError::InvalidTypesKind);
}

Expand All @@ -170,12 +170,12 @@ impl EofHeader {
header.types_size = types_size;

if header.types_size % 4 != 0 {
return Err(EofDecodeError::InvalidTypesSection);
return Err(EofDecodeError::InvalidCodeInfo);
}

// `kind_code` 1 byte 0x02 kind marker for code size section
let (input, kind_types) = consume_u8(input)?;
if kind_types != KIND_CODE {
let (input, kind_code) = consume_u8(input)?;
if kind_code != KIND_CODE {
return Err(EofDecodeError::InvalidCodeKind);
}

Expand All @@ -192,7 +192,7 @@ impl EofHeader {
}

if sizes.len() != (types_size / 4) as usize {
return Err(EofDecodeError::MismatchCodeAndTypesSize);
return Err(EofDecodeError::MismatchCodeAndInfoSize);
}

header.code_sizes = sizes;
Expand Down
Loading

0 comments on commit be7e9a5

Please sign in to comment.