Skip to content

Commit

Permalink
Merge pull request #37 from kroma-network/feat/enable-shanghai
Browse files Browse the repository at this point in the history
feat: enable shanghai
  • Loading branch information
dongchangYoo authored Apr 22, 2024
2 parents 4f431bf + aea22da commit 8f08b12
Show file tree
Hide file tree
Showing 22 changed files with 515 additions and 243 deletions.
2 changes: 1 addition & 1 deletion bus-mapping/src/circuit_input_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ impl<'a> CircuitInputBuilder {
state_ref.block_ctx.rwc.0,
state_ref.call().map(|c| c.call_id).unwrap_or(0),
state_ref.call_ctx()?.memory.len(),
if geth_step.op.is_push() {
if geth_step.op.is_push_with_data() {
format!("{:?}", geth_trace.struct_logs[index + 1].stack.last())
} else if geth_step.op.is_call_without_value() {
format!(
Expand Down
17 changes: 15 additions & 2 deletions bus-mapping/src/evm/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,11 +158,14 @@ type FnGenAssociatedOps = fn(
) -> Result<Vec<ExecStep>, Error>;

fn fn_gen_associated_ops(opcode_id: &OpcodeId) -> FnGenAssociatedOps {
if opcode_id.is_push() {
if opcode_id.is_push_with_data() {
return StackOnlyOpcode::<0, 1>::gen_associated_ops;
}

match opcode_id {
// TODO(chokobole): This is a temporary solution to prevent the state circuit from
// generating an error "non-first access reads don't change value".
OpcodeId::PUSH0 => StackOnlyOpcode::<0, 1>::gen_associated_ops,
OpcodeId::STOP => Stop::gen_associated_ops,
OpcodeId::ADD => StackOnlyOpcode::<2, 1>::gen_associated_ops,
OpcodeId::MUL => StackOnlyOpcode::<2, 1>::gen_associated_ops,
Expand Down Expand Up @@ -496,7 +499,17 @@ pub fn gen_begin_tx_ops(
)?;

// Add caller and callee into access list
for address in [call.caller_address, call.address] {
for address in [
call.caller_address,
call.address,
// for EIP-3651(Warm COINBASE)
state
.block
.headers
.get(&state.tx.block_num)
.unwrap()
.coinbase,
] {
let is_warm_prev = !state.sdb.add_account_to_access_list(address);
state.tx_accesslist_account_write(
&mut exec_step,
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/evm/opcodes/extcodesize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ mod extcodesize_tests {
};

// Test for empty account.
test_ok(&Account::default(), false);
test_ok(&Account::default(), true);
// Test for cold account.
test_ok(&account, false);
// Test for warm account.
Expand Down
2 changes: 1 addition & 1 deletion bus-mapping/src/evm/opcodes/stackonlyop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ mod stackonlyop_tests {
use std::ops::{BitOr, BitXor};

#[cfg(feature = "kroma")]
const CALL_ID: usize = 739;
const CALL_ID: usize = 740;
#[cfg(not(feature = "kroma"))]
const CALL_ID: usize = 1;

Expand Down
9 changes: 4 additions & 5 deletions circuit-benchmarks/src/bytecode_circuit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
mod tests {
use ark_std::{end_timer, start_timer};
use bus_mapping::evm::OpcodeId;
use eth_types::Field;
use eth_types::{evm_types::MAX_CODE_SIZE, Field};
use halo2_proofs::{
halo2curves::bn256::{Bn256, Fr, G1Affine},
plonk::{create_proof, keygen_pk, keygen_vk, verify_proof},
Expand Down Expand Up @@ -42,13 +42,12 @@ mod tests {
// Unique string used by bench results module for parsing the result
const BENCHMARK_ID: &str = "Bytecode Circuit";

// Contract code size exceeds 24576 bytes may not be deployable on Mainnet.
const MAX_BYTECODE_LEN: usize = 24576;

let num_rows = 1 << degree;
const NUM_BLINDING_ROWS: usize = 7 - 1;
let max_bytecode_row_num = num_rows - NUM_BLINDING_ROWS;
let bytecode_len = std::cmp::min(MAX_BYTECODE_LEN, max_bytecode_row_num);

// Contract code size exceeds 24576 bytes may not be deployable on Mainnet.
let bytecode_len = std::cmp::min(MAX_CODE_SIZE as usize, max_bytecode_row_num);
let bytecodes_num: usize = max_bytecode_row_num / bytecode_len;

// Create the circuit
Expand Down
85 changes: 61 additions & 24 deletions eth-types/src/bytecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,9 @@ impl Bytecode {
self
}

/// Push
/// Push, value is useless for `PUSH0`
pub fn push(&mut self, n: u8, value: Word) -> &mut Self {
debug_assert!((1..=32).contains(&n), "invalid push");
debug_assert!((..=32).contains(&n), "invalid push");

// Write the op code
self.write_op((OpcodeId::push_n(n)).expect("valid push size"));
Expand Down Expand Up @@ -186,7 +186,7 @@ impl Bytecode {
pub fn append_asm(&mut self, op: &str) -> Result<(), Error> {
match OpcodeWithData::from_str(op)? {
OpcodeWithData::Opcode(op) => self.write_op(op),
OpcodeWithData::Push(n, value) => self.push(n, value),
OpcodeWithData::PushWithData(n, value) => self.push(n, value),
};
Ok(())
}
Expand All @@ -197,7 +197,7 @@ impl Bytecode {
OpcodeWithData::Opcode(opcode) => {
self.write_op(opcode);
}
OpcodeWithData::Push(n, word) => {
OpcodeWithData::PushWithData(n, word) => {
self.push(n, word);
}
}
Expand All @@ -214,17 +214,18 @@ impl Bytecode {
#[derive(Clone, PartialEq, Eq)]
pub enum OpcodeWithData {
/// A non-push opcode
/// A `PUSH0` or non-push opcode
Opcode(OpcodeId),
/// A push opcode
Push(u8, Word),
/// A `PUSH1` .. `PUSH32` opcode
PushWithData(u8, Word),
}

impl OpcodeWithData {
/// get the opcode
pub fn opcode(&self) -> OpcodeId {
match self {
OpcodeWithData::Opcode(op) => *op,
OpcodeWithData::Push(n, _) => OpcodeId::push_n(*n).expect("valid push size"),
OpcodeWithData::PushWithData(n, _) => OpcodeId::push_n(*n).expect("valid push size"),
}
}
}
Expand All @@ -238,28 +239,32 @@ impl FromStr for OpcodeWithData {
if let Some(push) = op.strip_prefix("PUSH") {
let n_value: Vec<_> = push.splitn(3, ['(', ')']).collect();
let n = n_value[0].parse::<u8>().map_err(|_| err())?;
if n < 1 || n > 32 {
if n > 32 {
return Err(err());
}
let value = if n_value[1].starts_with("0x") {
Word::from_str_radix(&n_value[1][2..], 16)
} else {
Word::from_str_radix(n_value[1], 10)

// Parse `PUSH0` below only for shanghai (otherwise as an invalid opcode).
if n > 0 {
let value = if n_value[1].starts_with("0x") {
Word::from_str_radix(&n_value[1][2..], 16)
} else {
Word::from_str_radix(n_value[1], 10)
}
.map_err(|_| err())?;

return Ok(OpcodeWithData::PushWithData(n, value));
}
.map_err(|_| err())?;
Ok(OpcodeWithData::Push(n, value))
} else {
let opcode = OpcodeId::from_str(op).map_err(|_| err())?;
Ok(OpcodeWithData::Opcode(opcode))
}
let opcode = OpcodeId::from_str(op).map_err(|_| err())?;
Ok(OpcodeWithData::Opcode(opcode))
}
}

impl ToString for OpcodeWithData {
fn to_string(&self) -> String {
match self {
OpcodeWithData::Opcode(opcode) => format!("{opcode:?}"),
OpcodeWithData::Push(n, word) => format!("PUSH{n}({word})"),
OpcodeWithData::PushWithData(n, word) => format!("PUSH{n}({word})"),
}
}
}
Expand All @@ -272,13 +277,15 @@ impl<'a> Iterator for BytecodeIterator<'a> {
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|byte| {
let op = OpcodeId::from(byte.value);
if op.is_push() {
let n = op.data_len();
let n = op.data_len();
if n > 0 {
assert!(op.is_push_with_data());

let mut value = vec![0u8; n];
for value_byte in value.iter_mut() {
*value_byte = self.0.next().unwrap().value;
}
OpcodeWithData::Push(n as u8, Word::from(value.as_slice()))
OpcodeWithData::PushWithData(n as u8, Word::from(value.as_slice()))
} else {
OpcodeWithData::Opcode(op)
}
Expand All @@ -294,7 +301,7 @@ impl From<Vec<u8>> for Bytecode {
while let Some(byte) = input_iter.next() {
let op = OpcodeId::from(*byte);
code.write_op(op);
if op.is_push() {
if op.is_push_with_data() {
let n = op.postfix().expect("opcode with postfix");
for _ in 0..n {
match input_iter.next() {
Expand Down Expand Up @@ -332,14 +339,14 @@ macro_rules! bytecode_internal {
($code:ident, ) => {};
// PUSHX op codes
($code:ident, $x:ident ($v:expr) $($rest:tt)*) => {{
debug_assert!($crate::evm_types::OpcodeId::$x.is_push(), "invalid push");
debug_assert!($crate::evm_types::OpcodeId::$x.is_push_with_data(), "invalid push");
let n = $crate::evm_types::OpcodeId::$x.postfix().expect("opcode with postfix");
$code.push(n, $v.into());
$crate::bytecode_internal!($code, $($rest)*);
}};
// Default opcode without any inputs
($code:ident, $x:ident $($rest:tt)*) => {{
debug_assert!(!$crate::evm_types::OpcodeId::$x.is_push(), "invalid push");
debug_assert!(!$crate::evm_types::OpcodeId::$x.is_push_with_data(), "invalid push");
$code.write_op($crate::evm_types::OpcodeId::$x);
$crate::bytecode_internal!($code, $($rest)*);
}};
Expand All @@ -355,6 +362,13 @@ macro_rules! bytecode_internal {
}};
}

impl Bytecode {
/// Helper function for `PUSH0`
pub fn op_push0(&mut self) -> &mut Self {
self.push(0, Word::zero())
}
}

#[cfg(test)]
mod tests {
use crate::{bytecode::OpcodeWithData, Bytecode};
Expand All @@ -363,6 +377,8 @@ mod tests {
#[test]
fn test_bytecode_roundtrip() {
let code = bytecode! {
PUSH0
POP
PUSH8(0x123)
POP
PUSH24(0x321)
Expand Down Expand Up @@ -396,4 +412,25 @@ mod tests {

assert_eq!(code.code, code2.code);
}

#[test]
fn test_asm_disasm_for_shanghai() {
let code = bytecode! {
PUSH0
POP
PUSH1(5)
PUSH2(0xa)
MUL
STOP
};
let mut code2 = Bytecode::default();
code.iter()
.map(|op| op.to_string())
.map(|op| OpcodeWithData::from_str(&op).unwrap())
.for_each(|op| {
code2.append_op(op);
});

assert_eq!(code.code, code2.code);
}
}
6 changes: 6 additions & 0 deletions eth-types/src/evm_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ impl fmt::Debug for Gas {
}
}

/// Gas per word of the init code when creating a contract.
pub const INIT_CODE_WORD_GAS: u64 = 2;
/// Maximum bytecode size to permit for a contract.
pub const MAX_CODE_SIZE: u64 = 24576;
/// Maximum initcode size to permit in a creation transaction and create instructions.
pub const MAX_INIT_CODE_SIZE: u64 = 2 * MAX_CODE_SIZE;
/// This constant ((2^32 - 1) * 32) is the highest number that can be used without overflowing the
/// square operation of gas calculation.
/// <https://github.com/ethereum/go-ethereum/blob/e6b6a8b738069ad0579f6798ee59fde93ed13b43/core/vm/gas_table.go#L38>
Expand Down
Loading

0 comments on commit 8f08b12

Please sign in to comment.