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

Implement EIP-4788 for Cancun #40

Merged
merged 5 commits into from
Feb 18, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions evm_arithmetization/src/cpu/kernel/aggregator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub(crate) fn combined_kernel() -> Kernel {
let files = vec![
"global jumped_to_0: PANIC",
"global jumped_to_1: PANIC",
include_str!("asm/beacon_roots.asm"),
include_str!("asm/bignum/add.asm"),
include_str!("asm/bignum/addmul.asm"),
include_str!("asm/bignum/cmp.asm"),
Expand Down
48 changes: 48 additions & 0 deletions evm_arithmetization/src/cpu/kernel/asm/beacon_roots.asm
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/// EIP-4788: Beacon block root in the EVM
Nashtare marked this conversation as resolved.
Show resolved Hide resolved
/// <https://eips.ethereum.org/EIPS/eip-4788#pseudocode>

global set_beacon_root:
PUSH start_txn
%timestamp
// stack: timestamp, start_txns
PUSH @HISTORY_BUFFER_LENGTH
DUP2
// stack: timestamp, 8191, timestamp, start_txns
MOD
// stack: timestamp_idx, timestamp, start_txns
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
PUSH write_beacon_roots_to_storage
%parent_beacon_block_root
// stack: calldata, write_beacon_roots_to_storage, timestamp_idx, timestamp, start_txns
DUP3
%add_const(@HISTORY_BUFFER_LENGTH)
// stack: root_idx, calldata, write_beacon_roots_to_storage, timestamp_idx, timestamp, start_txns

write_beacon_roots_to_storage:
// stack: slot, value, retdest
// First we write the value to MPT data, and get a pointer to it.
%get_trie_data_size
// stack: value_ptr, slot, value, retdest
SWAP2
// stack: value, slot, value_ptr, retdest
%append_to_trie_data
// stack: slot, value_ptr, retdest

// Next, call mpt_insert on the current account's storage root.
%stack (slot, value_ptr) -> (slot, value_ptr, after_beacon_roots_storage_insert)
%slot_to_storage_key
// stack: storage_key, value_ptr, after_beacon_roots_storage_insert, retdest
PUSH 64 // storage_key has 64 nibbles
%get_storage_trie(@BEACON_ROOTS_ADDRESS)
// stack: storage_root_ptr, 64, storage_key, value_ptr, after_beacon_roots_storage_insert, retdest
%jump(mpt_insert)

after_beacon_roots_storage_insert:
// stack: new_storage_root_ptr, retdest
%get_account_data(@BEACON_ROOTS_ADDRESS)
// stack: account_ptr, new_storage_root_ptr, retdest

// Update the copied account with our new storage root pointer.
%add_const(2)
// stack: account_storage_root_ptr_ptr, new_storage_root_ptr, retdest
%mstore_trie_data
JUMP
7 changes: 5 additions & 2 deletions evm_arithmetization/src/cpu/kernel/asm/main.asm
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ global hash_initial_tries:
// stack: trie_data_full_len
%mstore_global_metadata(@GLOBAL_METADATA_TRIE_DATA_SIZE)

// If txn_idx == 0, update the beacon_root.
Copy link
Contributor

Choose a reason for hiding this comment

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

DQ: where do we check if we are beyond the Cancun HF block?

Copy link
Collaborator Author

@Nashtare Nashtare Feb 16, 2024

Choose a reason for hiding this comment

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

We don't, neither for Shanghai at the moment, i.e. chains must use the correct prover according to the HF they are currently on.

%mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE)
ISZERO
%jumpi(set_beacon_root)

global start_txn:
// stack: (empty)
// The special case of an empty trie (i.e. for the first transaction)
// is handled outside of the kernel.
%mload_global_metadata(@GLOBAL_METADATA_TXN_NUMBER_BEFORE)
// stack: txn_nb
DUP1 %scalar_to_rlp
Expand Down
4 changes: 4 additions & 0 deletions evm_arithmetization/src/cpu/kernel/asm/memory/metadata.asm
Original file line number Diff line number Diff line change
Expand Up @@ -447,3 +447,7 @@ global sys_prevrandao:
%mload_global_metadata(@GLOBAL_METADATA_BLOCK_RANDOM)
%stack (random, kexit_info) -> (kexit_info, random)
EXIT_KERNEL

%macro parent_beacon_block_root
%mload_global_metadata(@GLOBAL_METADATA_PARENT_BEACON_BLOCK_ROOT)
%endmacro
22 changes: 22 additions & 0 deletions evm_arithmetization/src/cpu/kernel/asm/mpt/accounts.asm
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,25 @@
%mload_trie_data
// stack: storage_root_ptr
%endmacro

// Return a pointer to the provided account's data in the state trie.
%macro get_account_data(addr)
PUSH $addr %mpt_read_state_trie
// stack: account_ptr
// account_ptr should be non-null as long as the prover provided the proper
// Merkle data. But a bad prover may not have, and we don't want return a
// null pointer for security reasons.
DUP1 ISZERO %jumpi(panic)
// stack: account_ptr
%endmacro

// Returns a pointer to the root of the storage trie associated with the provided account.
%macro get_storage_trie(addr)
// stack: (empty)
%get_account_data($addr)
// stack: account_ptr
%add_const(2)
// stack: storage_root_ptr_ptr
%mload_trie_data
// stack: storage_root_ptr
%endmacro
4 changes: 2 additions & 2 deletions evm_arithmetization/src/cpu/kernel/asm/mpt/insert/insert.asm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ global mpt_insert:
global mpt_insert_hash_node:
PANIC

mpt_insert_empty:
global mpt_insert_empty:
// stack: node_type, node_payload_ptr, num_nibbles, key, value_ptr, retdest
%pop2
// stack: num_nibbles, key, value_ptr, retdest
Expand All @@ -38,7 +38,7 @@ mpt_insert_empty:
SWAP1
JUMP

mpt_insert_branch:
global mpt_insert_branch:
// stack: node_type, node_payload_ptr, num_nibbles, key, value_ptr, retdest
POP

Expand Down
6 changes: 3 additions & 3 deletions evm_arithmetization/src/cpu/kernel/asm/mpt/read.asm
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ global mpt_read_extension_not_found:
// Not found; return 0.
%stack (key_part, future_nibbles, key, node_payload_ptr, retdest) -> (retdest, 0)
JUMP
mpt_read_extension_found:
global mpt_read_extension_found:
// stack: key_part, future_nibbles, key, node_payload_ptr, retdest
DUP2 %mul_const(4) SHL // key_part_shifted = (key_part << (future_nibbles * 4))
// stack: key_part_shifted, future_nibbles, key, node_payload_ptr, retdest
Expand All @@ -121,7 +121,7 @@ mpt_read_extension_found:
// stack: child_ptr, future_nibbles, key, retdest
%jump(mpt_read) // recurse

mpt_read_leaf:
global mpt_read_leaf:
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The global label changes on mpt/insert.asm and mpt/read.asm are unrelated to this PR, but I got extremely confused when debugging through the Kernel logs when seeing mpt_read_leaf_not_found, while it actually was, because all these labels are below their global negative counterpart.
Hence I'd think this is better debugging wise if they were also made global, to prevent any confusion.

// stack: node_type, node_payload_ptr, num_nibbles, key, retdest
POP
// stack: node_payload_ptr, num_nibbles, key, retdest
Expand All @@ -142,7 +142,7 @@ global mpt_read_leaf_not_found:
// Not found; return 0.
%stack (node_payload_ptr, retdest) -> (retdest, 0)
JUMP
mpt_read_leaf_found:
global mpt_read_leaf_found:
// stack: node_payload_ptr, retdest
%add_const(2) // The value pointer is located after num_nibbles and the key.
// stack: value_ptr_ptr, retdest
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ pub(crate) enum GlobalMetadata {
BlockGasUsedAfter,
/// Current block header hash
BlockCurrentHash,
/// EIP-4788: hash tree root of the beacon chain parent block.
ParentBeaconBlockRoot,

/// Gas to refund at the end of the transaction.
RefundCounter,
Expand Down Expand Up @@ -101,7 +103,7 @@ pub(crate) enum GlobalMetadata {
}

impl GlobalMetadata {
pub(crate) const COUNT: usize = 49;
pub(crate) const COUNT: usize = 50;

/// Unscales this virtual offset by their respective `Segment` value.
pub(crate) const fn unscale(&self) -> usize {
Expand Down Expand Up @@ -134,6 +136,7 @@ impl GlobalMetadata {
Self::BlockGasUsed,
Self::BlockGasUsedBefore,
Self::BlockGasUsedAfter,
Self::ParentBeaconBlockRoot,
Self::RefundCounter,
Self::AccessedAddressesLen,
Self::AccessedStorageKeysLen,
Expand Down Expand Up @@ -190,6 +193,7 @@ impl GlobalMetadata {
Self::BlockGasUsedBefore => "GLOBAL_METADATA_BLOCK_GAS_USED_BEFORE",
Self::BlockGasUsedAfter => "GLOBAL_METADATA_BLOCK_GAS_USED_AFTER",
Self::BlockCurrentHash => "GLOBAL_METADATA_BLOCK_CURRENT_HASH",
Self::ParentBeaconBlockRoot => "GLOBAL_METADATA_PARENT_BEACON_BLOCK_ROOT",
Self::RefundCounter => "GLOBAL_METADATA_REFUND_COUNTER",
Self::AccessedAddressesLen => "GLOBAL_METADATA_ACCESSED_ADDRESSES_LEN",
Self::AccessedStorageKeysLen => "GLOBAL_METADATA_ACCESSED_STORAGE_KEYS_LEN",
Expand Down
41 changes: 40 additions & 1 deletion evm_arithmetization/src/cpu/kernel/constants/mod.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use std::collections::HashMap;

use ethereum_types::U256;
use ethereum_types::{H256, U256};
use hex_literal::hex;

use crate::cpu::kernel::constants::context_metadata::ContextMetadata;
use crate::cpu::kernel::constants::global_metadata::GlobalMetadata;
use crate::cpu::kernel::constants::journal_entry::JournalEntry;
use crate::cpu::kernel::constants::trie_type::PartialTrieType;
use crate::cpu::kernel::constants::txn_fields::NormalizedTxnField;
use crate::generation::mpt::AccountRlp;
use crate::memory::segments::Segment;

pub(crate) mod context_metadata;
Expand Down Expand Up @@ -56,6 +57,14 @@ pub(crate) fn evm_constants() -> HashMap<String, U256> {

c.insert(MAX_NONCE.0.into(), U256::from(MAX_NONCE.1));
c.insert(CALL_STACK_LIMIT.0.into(), U256::from(CALL_STACK_LIMIT.1));
c.insert(
cancun_constants::BEACON_ROOTS_ADDRESS.0.into(),
U256::from_big_endian(&cancun_constants::BEACON_ROOTS_ADDRESS.1),
);
c.insert(
cancun_constants::HISTORY_BUFFER_LENGTH.0.into(),
cancun_constants::HISTORY_BUFFER_LENGTH.1.into(),
);

for segment in Segment::all() {
c.insert(segment.var_name().into(), (segment as usize).into());
Expand Down Expand Up @@ -285,3 +294,33 @@ const CODE_SIZE_LIMIT: [(&str, u64); 3] = [

const MAX_NONCE: (&str, u64) = ("MAX_NONCE", 0xffffffffffffffff);
const CALL_STACK_LIMIT: (&str, u64) = ("CALL_STACK_LIMIT", 1024);

/// Cancun-related constants
Nashtare marked this conversation as resolved.
Show resolved Hide resolved
/// See <https://eips.ethereum.org/EIPS/eip-4788#deployment>.
pub mod cancun_constants {
use super::*;

pub const BEACON_ROOTS_ADDRESS: (&str, [u8; 20]) = (
"BEACON_ROOTS_ADDRESS",
hex!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"),
);

pub const HISTORY_BUFFER_LENGTH: (&str, u64) = ("HISTORY_BUFFER_LENGTH", 8191);

pub const BEACON_ROOTS_CONTRACT_CODE: [u8; 106] = hex!("60618060095f395ff33373fffffffffffffffffffffffffffffffffffffffe14604d57602036146024575f5ffd5b5f35801560495762001fff810690815414603c575f5ffd5b62001fff01545f5260205ff35b5f5ffd5b62001fff42064281555f359062001fff015500");
pub const BEACON_ROOTS_CONTRACT_CODE_HASH: [u8; 32] =
dvdplm marked this conversation as resolved.
Show resolved Hide resolved
hex!("468e991a328ab315e08296896adc222230a4960692e90cb6e096006ba6ae75d5");

pub const BEACON_ROOTS_CONTRACT_ADDRESS_HASHED: [u8; 32] =
hex!("37d65eaa92c6bc4c13a5ec45527f0c18ea8932588728769ec7aecfe6d9f32e42");

pub const BEACON_ROOTS_ACCOUNT: AccountRlp = AccountRlp {
nonce: U256::zero(),
balance: U256::zero(),
// Storage root for this account at genesis.
storage_root: H256(hex!(
"f58e5f1eae7ce386de44266ff0286a88dafe7e4269c1ffa97f79dbbcf4f59e5c"
)),
code_hash: H256(BEACON_ROOTS_CONTRACT_CODE_HASH),
};
}
3 changes: 3 additions & 0 deletions evm_arithmetization/src/cpu/kernel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ pub mod stack;
mod utils;

pub(crate) mod interpreter;

pub use constants::cancun_constants;

#[cfg(test)]
mod tests;

Expand Down
Loading