Skip to content

Commit

Permalink
[feat] curie update (#8)
Browse files Browse the repository at this point in the history
* curie update

* add missing gate
  • Loading branch information
lightsing authored Jun 25, 2024
1 parent 074cba2 commit 416278c
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 33 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions crates/interpreter/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ all = "warn"
[dependencies]
revm-primitives = { path = "../primitives", version = "4.0.0", default-features = false }

cfg-if = "1.0"
paste = { version = "1.0", optional = true }
phf = { version = "0.11", default-features = false, optional = true, features = [
"macros",
Expand Down
18 changes: 16 additions & 2 deletions crates/interpreter/src/instructions/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,14 @@ pub fn sstore<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host:
/// EIP-1153: Transient storage opcodes
/// Store value to transient storage
pub fn tstore<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
check!(interpreter, CANCUN);
cfg_if::cfg_if! {
if #[cfg(feature = "scroll")] {
check!(interpreter, CURIE);
} else {
check!(interpreter, CANCUN);
}
}

require_non_staticcall!(interpreter);
gas!(interpreter, gas::WARM_STORAGE_READ_COST);

Expand All @@ -243,7 +250,14 @@ pub fn tstore<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host:
/// EIP-1153: Transient storage opcodes
/// Load value from transient storage
pub fn tload<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
check!(interpreter, CANCUN);
cfg_if::cfg_if! {
if #[cfg(feature = "scroll")] {
check!(interpreter, CURIE);
} else {
check!(interpreter, CANCUN);
}
}

gas!(interpreter, gas::WARM_STORAGE_READ_COST);

pop_top!(interpreter, index);
Expand Down
19 changes: 17 additions & 2 deletions crates/interpreter/src/instructions/host_env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn gasprice<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut H) {
/// EIP-3198: BASEFEE opcode
pub fn basefee<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
#[cfg(feature = "scroll")]
if SPEC::enabled(BERNOULLI) {
if !SPEC::enabled(CURIE) {
interpreter.instruction_result = crate::InstructionResult::NotActivated;
return;
}
Expand All @@ -64,6 +64,14 @@ pub fn origin<H: Host + ?Sized>(interpreter: &mut Interpreter, host: &mut H) {

// EIP-4844: Shard Blob Transactions
pub fn blob_hash<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
cfg_if::cfg_if! {
if #[cfg(feature = "scroll")] {
check!(interpreter, CURIE);
} else {
check!(interpreter, CANCUN);
}
}

check!(interpreter, CANCUN);
gas!(interpreter, gas::VERYLOW);
pop_top!(interpreter, index);
Expand All @@ -76,7 +84,14 @@ pub fn blob_hash<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, ho

/// EIP-7516: BLOBBASEFEE opcode
pub fn blob_basefee<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, host: &mut H) {
check!(interpreter, CANCUN);
cfg_if::cfg_if! {
if #[cfg(feature = "scroll")] {
check!(interpreter, CURIE);
} else {
check!(interpreter, CANCUN);
}
}

gas!(interpreter, gas::BASE);
push!(
interpreter,
Expand Down
9 changes: 8 additions & 1 deletion crates/interpreter/src/instructions/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,14 @@ pub fn msize<H: Host + ?Sized>(interpreter: &mut Interpreter, _host: &mut H) {

// EIP-5656: MCOPY - Memory copying instruction
pub fn mcopy<H: Host + ?Sized, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
check!(interpreter, CANCUN);
cfg_if::cfg_if! {
if #[cfg(feature = "scroll")] {
check!(interpreter, CURIE);
} else {
check!(interpreter, CANCUN);
}
}

pop!(interpreter, dst, src, len);

// into usize or fail
Expand Down
2 changes: 1 addition & 1 deletion crates/precompile/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ impl PrecompileSpecId {
#[cfg(feature = "optimism")]
ECOTONE => Self::CANCUN,
#[cfg(feature = "scroll")]
BERNOULLI => Self::BERNOULLI,
BERNOULLI | CURIE => Self::BERNOULLI,
}
}
}
Expand Down
16 changes: 14 additions & 2 deletions crates/primitives/src/specification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ pub enum SpecId {
MERGE = 15,
SHANGHAI = 16,
BERNOULLI = 17,
CANCUN = 18,
PRAGUE = 19,
CURIE = 18,
CANCUN = 19,
PRAGUE = 20,
#[default]
LATEST = u8::MAX,
}
Expand Down Expand Up @@ -185,6 +186,8 @@ impl From<SpecId> for &'static str {
SpecId::ECOTONE => "Ecotone",
#[cfg(feature = "scroll")]
SpecId::BERNOULLI => "Bernoulli",
#[cfg(feature = "scroll")]
SpecId::CURIE => "Curie",
SpecId::LATEST => "Latest",
}
}
Expand Down Expand Up @@ -247,6 +250,8 @@ spec!(ECOTONE, EcotoneSpec);
// Scroll Hardforks
#[cfg(feature = "scroll")]
spec!(BERNOULLI, BernoulliSpec);
#[cfg(feature = "scroll")]
spec!(CURIE, CurieSpec);

#[macro_export]
macro_rules! spec_to_generic {
Expand Down Expand Up @@ -336,6 +341,11 @@ macro_rules! spec_to_generic {
use $crate::BernoulliSpec as SPEC;
$e
}
#[cfg(feature = "scroll")]
$crate::SpecId::CURIE => {
use $crate::CurieSpec as SPEC;
$e
}
}
}};
}
Expand Down Expand Up @@ -374,6 +384,8 @@ mod tests {
#[cfg(feature = "scroll")]
spec_to_generic!(BERNOULLI, assert_eq!(SPEC::SPEC_ID, BERNOULLI));
spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN));
#[cfg(feature = "scroll")]
spec_to_generic!(CURIE, assert_eq!(SPEC::SPEC_ID, CURIE));
spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE));
spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST));
}
Expand Down
2 changes: 1 addition & 1 deletion crates/revm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl<'a> Default for EvmBuilder<'a, SetGenericStage, (), EmptyDB> {

} else if #[cfg(all(feature = "scroll-default-handler",
not(feature = "negate-scroll-default-handler")))] {
let mut handler_cfg = HandlerCfg::new(SpecId::BERNOULLI);
let mut handler_cfg = HandlerCfg::new(SpecId::CURIE);
// set is_scroll to true by default.
handler_cfg.is_scroll = true;

Expand Down
10 changes: 6 additions & 4 deletions crates/revm/src/scroll/handler_register.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,10 @@ pub fn scroll_handle_register<DB: Database, EXT>(handler: &mut EvmHandler<'_, EX
pub fn load_accounts<SPEC: Spec, EXT, DB: Database>(
context: &mut Context<EXT, DB>,
) -> Result<(), EVMError<DB::Error>> {
let l1_block_info = crate::scroll::L1BlockInfo::try_fetch(&mut context.evm.inner.db)
.map_err(EVMError::Database)?;
let l1_block_info =
crate::scroll::L1BlockInfo::try_fetch(&mut context.evm.inner.db, SPEC::SPEC_ID)
.map_err(EVMError::Database)?;
println!("L1 block info: {:?}", l1_block_info);
context.evm.inner.l1_block_info = Some(l1_block_info);

mainnet::load_accounts::<SPEC, EXT, DB>(context)
Expand Down Expand Up @@ -66,7 +68,7 @@ pub fn deduct_caller<SPEC: Spec, EXT, DB: Database>(
.l1_block_info
.as_ref()
.expect("L1BlockInfo should be loaded")
.calculate_tx_l1_cost(rlp_bytes);
.calculate_tx_l1_cost(rlp_bytes, SPEC::SPEC_ID);
if tx_l1_cost.gt(&caller_account.info.balance) {
return Err(EVMError::Transaction(
InvalidTransaction::LackOfFundForMaxFee {
Expand Down Expand Up @@ -120,7 +122,7 @@ pub fn reward_beneficiary<SPEC: Spec, EXT, DB: Database>(
));
};

let l1_cost = l1_block_info.calculate_tx_l1_cost(rlp_bytes);
let l1_cost = l1_block_info.calculate_tx_l1_cost(rlp_bytes, SPEC::SPEC_ID);

coinbase_account.mark_touch();
coinbase_account.info.balance = coinbase_account
Expand Down
100 changes: 80 additions & 20 deletions crates/revm/src/scroll/l1block.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::primitives::{address, Address, U256};
use crate::primitives::{address, Address, SpecId, U256};
use crate::Database;

const ZERO_BYTE_COST: u64 = 4;
Expand All @@ -13,6 +13,10 @@ pub const L1_GAS_PRICE_ORACLE_ADDRESS: Address =
const L1_BASE_FEE_SLOT: U256 = U256::from_limbs([1u64, 0, 0, 0]);
const L1_OVERHEAD_SLOT: U256 = U256::from_limbs([2u64, 0, 0, 0]);
const L1_SCALAR_SLOT: U256 = U256::from_limbs([3u64, 0, 0, 0]);
const L1_BLOB_BASE_FEE_SLOT: U256 = U256::from_limbs([5u64, 0, 0, 0]);
const L1_COMMIT_SCALAR_SLOT: U256 = U256::from_limbs([6u64, 0, 0, 0]);
const L1_BLOB_SCALAR_SLOT: U256 = U256::from_limbs([7u64, 0, 0, 0]);
// const L1_IS_CURIE_SLOT: U256 = U256::from_limbs([8u64, 0, 0, 0]);

/// L1 block info
#[derive(Clone, Debug, Default)]
Expand All @@ -23,42 +27,98 @@ pub struct L1BlockInfo {
pub l1_fee_overhead: U256,
/// The current L1 fee scalar.
pub l1_base_fee_scalar: U256,
/// The current L1 blob base fee, None if before Curie.
pub l1_blob_base_fee: Option<U256>,
/// The current L1 commit scalar, None if before Curie.
pub l1_commit_scalar: Option<U256>,
/// The current L1 blob scalar, None if before Curie.
pub l1_blob_scalar: Option<U256>,
/// The current call data gas (l1_blob_scalar * l1_base_fee), None if before Curie.
pub calldata_gas: Option<U256>,
}

impl L1BlockInfo {
/// Try to fetch the L1 block info from the database.
pub fn try_fetch<DB: Database>(db: &mut DB) -> Result<L1BlockInfo, DB::Error> {
pub fn try_fetch<DB: Database>(db: &mut DB, spec_id: SpecId) -> Result<L1BlockInfo, DB::Error> {
let l1_base_fee = db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_BASE_FEE_SLOT)?;
let l1_fee_overhead = db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_OVERHEAD_SLOT)?;
let l1_base_fee_scalar = db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_SCALAR_SLOT)?;

Ok(L1BlockInfo {
l1_base_fee,
l1_fee_overhead,
l1_base_fee_scalar,
})
if !spec_id.is_enabled_in(SpecId::CURIE) {
Ok(L1BlockInfo {
l1_base_fee,
l1_fee_overhead,
l1_base_fee_scalar,
..Default::default()
})
} else {
let l1_blob_base_fee =
db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_BLOB_BASE_FEE_SLOT)?;
let l1_commit_scalar =
db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_COMMIT_SCALAR_SLOT)?;
let l1_blob_scalar = db.storage(L1_GAS_PRICE_ORACLE_ADDRESS, L1_BLOB_SCALAR_SLOT)?;

// calldata component of commit fees (calldata gas + execution)
let calldata_gas = l1_commit_scalar.saturating_mul(l1_base_fee);

Ok(L1BlockInfo {
l1_base_fee,
l1_fee_overhead,
l1_base_fee_scalar,
l1_blob_base_fee: Some(l1_blob_base_fee),
l1_commit_scalar: Some(l1_commit_scalar),
l1_blob_scalar: Some(l1_blob_scalar),
calldata_gas: Some(calldata_gas),
})
}
}

/// Calculate the data gas for posting the transaction on L1. Calldata costs 16 gas per non-zero
/// byte and 4 gas per zero byte.
pub fn data_gas(&self, input: &[u8]) -> U256 {
U256::from(input.iter().fold(0, |acc, byte| {
acc + if *byte == 0x00 {
ZERO_BYTE_COST
} else {
NON_ZERO_BYTE_COST
}
}))
pub fn data_gas(&self, input: &[u8], spec_id: SpecId) -> U256 {
if !spec_id.is_enabled_in(SpecId::CURIE) {
U256::from(input.iter().fold(0, |acc, byte| {
acc + if *byte == 0x00 {
ZERO_BYTE_COST
} else {
NON_ZERO_BYTE_COST
}
}))
.saturating_add(self.l1_fee_overhead)
.saturating_add(TX_L1_COMMIT_EXTRA_COST)
} else {
U256::from(input.len())
.saturating_mul(self.l1_blob_base_fee.unwrap())
.saturating_mul(self.l1_blob_scalar.unwrap())
}
}

/// Calculate the gas cost of a transaction based on L1 block data posted on L2.
pub fn calculate_tx_l1_cost(&self, input: &[u8]) -> U256 {
let tx_l1_gas = self.data_gas(input);
fn calculate_tx_l1_cost_bernoulli(&self, input: &[u8], spec_id: SpecId) -> U256 {
let tx_l1_gas = self.data_gas(input, spec_id);
tx_l1_gas
.saturating_add(self.l1_fee_overhead)
.saturating_add(TX_L1_COMMIT_EXTRA_COST)
.saturating_mul(self.l1_base_fee)
.saturating_mul(self.l1_base_fee_scalar)
.wrapping_div(TX_L1_FEE_PRECISION)
}

fn calculate_tx_l1_cost_curie(&self, input: &[u8], spec_id: SpecId) -> U256 {
// "commitScalar * l1BaseFee + blobScalar * _data.length * l1BlobBaseFee"
let blob_gas = self.data_gas(input, spec_id);

self.calldata_gas
.unwrap()
.saturating_add(blob_gas)
.wrapping_div(TX_L1_FEE_PRECISION)
}

/// Calculate the gas cost of a transaction based on L1 block data posted on L2.
pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: SpecId) -> U256 {
let l1fee = if !spec_id.is_enabled_in(SpecId::CURIE) {
self.calculate_tx_l1_cost_bernoulli(input, spec_id)
} else {
self.calculate_tx_l1_cost_curie(input, spec_id)
};
println!("l1fee: {:?}", l1fee);
l1fee
}
}

0 comments on commit 416278c

Please sign in to comment.