Skip to content

Commit 5f03e67

Browse files
authored
feat: dencun support (#313)
* consensus layer changes * execution changes * fmt
1 parent 63dc560 commit 5f03e67

File tree

9 files changed

+315
-288
lines changed

9 files changed

+315
-288
lines changed

Cargo.lock

Lines changed: 210 additions & 244 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ milagro_bls = { git = "https://github.com/Snowfork/milagro_bls" }
3131

3232
# execution
3333
ethers = "2.0.11"
34-
revm = { git = "https://github.com/bluealloy/revm", rev = "ac5c74824fb1a5935a65252903a2585ab9dd7825", default-features = false, features = ["std", "serde"] }
34+
revm = { git = "https://github.com/bluealloy/revm", rev = "23cbac479f616eba5ab11ddfe6d5814b9c492202", default-features = false, features = ["std", "serde"] }
3535
triehash-ethereum = { git = "https://github.com/openethereum/parity-ethereum", rev = "55c90d4016505317034e3e98f699af07f5404b63" }
3636

3737
# async/futures

config/src/config.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ impl Config {
8080
self.forks.bellatrix.fork_version.clone()
8181
} else if epoch >= self.forks.altair.epoch {
8282
self.forks.altair.fork_version.clone()
83+
} else if epoch >= self.forks.deneb.epoch {
84+
self.forks.deneb.fork_version.clone()
8385
} else {
8486
self.forks.genesis.fork_version.clone()
8587
}

config/src/networks.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ pub fn mainnet() -> BaseConfig {
9898
epoch: 194048,
9999
fork_version: hex_str_to_bytes("0x03000000").unwrap(),
100100
},
101+
deneb: Fork {
102+
epoch: u64::MAX,
103+
fork_version: hex_str_to_bytes("0x04000000").unwrap(),
104+
},
101105
},
102106
max_checkpoint_age: 1_209_600, // 14 days
103107
#[cfg(not(target_arch = "wasm32"))]
@@ -139,6 +143,10 @@ pub fn goerli() -> BaseConfig {
139143
epoch: 162304,
140144
fork_version: hex_str_to_bytes("0x03001020").unwrap(),
141145
},
146+
deneb: Fork {
147+
epoch: 231680,
148+
fork_version: hex_str_to_bytes("0x04001020").unwrap(),
149+
},
142150
},
143151
max_checkpoint_age: 1_209_600, // 14 days
144152
#[cfg(not(target_arch = "wasm32"))]
@@ -180,6 +188,10 @@ pub fn sepolia() -> BaseConfig {
180188
epoch: 56832,
181189
fork_version: hex_str_to_bytes("0x90000072").unwrap(),
182190
},
191+
deneb: Fork {
192+
epoch: u64::MAX,
193+
fork_version: hex_str_to_bytes("0x90000073").unwrap(),
194+
},
183195
},
184196
max_checkpoint_age: 1_209_600, // 14 days
185197
#[cfg(not(target_arch = "wasm32"))]

config/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ pub struct Forks {
1919
pub altair: Fork,
2020
pub bellatrix: Fork,
2121
pub capella: Fork,
22+
pub deneb: Fork,
2223
}
2324

2425
#[derive(Serialize, Deserialize, Debug, Default, Clone)]

consensus/src/types/mod.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ pub struct BeaconBlock {
2626
}
2727

2828
#[superstruct(
29-
variants(Bellatrix, Capella),
29+
variants(Bellatrix, Capella, Deneb),
3030
variant_attributes(
3131
derive(serde::Deserialize, Clone, Debug, SimpleSerialize, Default),
3232
serde(deny_unknown_fields)
@@ -47,6 +47,8 @@ pub struct BeaconBlockBody {
4747
pub execution_payload: ExecutionPayload,
4848
#[superstruct(only(Capella))]
4949
bls_to_execution_changes: List<SignedBlsToExecutionChange, 16>,
50+
#[superstruct(only(Deneb))]
51+
blob_kzg_commitments: List<ByteVector<48>, 4096>,
5052
}
5153

5254
impl Default for BeaconBlockBody {
@@ -71,7 +73,7 @@ pub struct BlsToExecutionChange {
7173
}
7274

7375
#[superstruct(
74-
variants(Bellatrix, Capella),
76+
variants(Bellatrix, Capella, Deneb),
7577
variant_attributes(
7678
derive(serde::Deserialize, Debug, Default, SimpleSerialize, Clone),
7779
serde(deny_unknown_fields)
@@ -97,6 +99,10 @@ pub struct ExecutionPayload {
9799
pub transactions: List<Transaction, 1048576>,
98100
#[superstruct(only(Capella))]
99101
withdrawals: List<Withdrawal, 16>,
102+
#[superstruct(only(Deneb))]
103+
blob_gas_used: U64,
104+
#[superstruct(only(Deneb))]
105+
excess_blob_gas: U64,
100106
}
101107

102108
impl Default for ExecutionPayload {

consensus/src/types/utils.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ macro_rules! superstruct_ssz {
5252
match self {
5353
$type::Bellatrix(inner) => inner.hash_tree_root(),
5454
$type::Capella(inner) => inner.hash_tree_root(),
55+
$type::Deneb(inner) => inner.hash_tree_root(),
5556
}
5657
}
5758
}
@@ -71,6 +72,7 @@ macro_rules! superstruct_ssz {
7172
match self {
7273
$type::Bellatrix(inner) => inner.serialize(buffer),
7374
$type::Capella(inner) => inner.serialize(buffer),
75+
$type::Deneb(inner) => inner.serialize(buffer),
7476
}
7577
}
7678
}

execution/src/evm.rs

Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use std::{collections::HashMap, str::FromStr, sync::Arc};
22

3-
use bytes::Bytes;
43
use common::types::BlockTag;
54
use ethers::types::transaction::eip2930::AccessListItem;
65
use eyre::{Report, Result};
76
use futures::future::join_all;
87
use revm::{
98
primitives::{
10-
AccountInfo, Bytecode, Env, ExecutionResult, ResultAndState, TransactTo, B160, B256, U256,
9+
AccountInfo, Address, Bytecode, Bytes, Env, ExecutionResult, ResultAndState, TransactTo,
10+
B256, U256,
1111
},
1212
Database, EVM,
1313
};
@@ -39,7 +39,9 @@ impl<R: ExecutionRpc> Evm<R> {
3939

4040
match tx.result {
4141
ExecutionResult::Success { output, .. } => Ok(output.into_data().to_vec()),
42-
ExecutionResult::Revert { output, .. } => Err(EvmError::Revert(Some(output))),
42+
ExecutionResult::Revert { output, .. } => {
43+
Err(EvmError::Revert(Some(output.to_vec().into())))
44+
}
4345
ExecutionResult::Halt { .. } => Err(EvmError::Revert(None)),
4446
}
4547
}
@@ -84,19 +86,21 @@ impl<R: ExecutionRpc> Evm<R> {
8486

8587
async fn get_env(&self, opts: &CallOpts, tag: BlockTag) -> Env {
8688
let mut env = Env::default();
89+
let to = convert_address(&opts.to.unwrap_or_default());
90+
let from = convert_address(&opts.from.unwrap_or_default());
8791

88-
env.tx.transact_to = TransactTo::Call(opts.to.unwrap_or_default().into());
89-
env.tx.caller = opts.from.map(B160::from).unwrap_or_default();
92+
env.tx.transact_to = TransactTo::Call(to);
93+
env.tx.caller = from;
9094
env.tx.value = opts
9195
.value
92-
.map(|value| B256::from(value).into())
96+
.map(|value| convert_u256(&value))
9397
.unwrap_or_default();
9498

9599
env.tx.data = Bytes::from(opts.data.clone().unwrap_or_default().to_vec());
96100
env.tx.gas_limit = opts.gas.map(|v| v.as_u64()).unwrap_or(u64::MAX);
97101
env.tx.gas_price = opts
98102
.gas_price
99-
.map(|g| B256::from(g).into())
103+
.map(|gas_price| convert_u256(&gas_price))
100104
.unwrap_or_default();
101105

102106
let block = self
@@ -110,11 +114,10 @@ impl<R: ExecutionRpc> Evm<R> {
110114
.unwrap();
111115

112116
env.block.number = U256::from(block.number.as_u64());
113-
env.block.coinbase = block.miner.into();
117+
env.block.coinbase = convert_address(&block.miner);
114118
env.block.timestamp = U256::from(block.timestamp.as_u64());
115-
env.block.difficulty = block.difficulty.into();
116-
117-
env.cfg.chain_id = U256::from(self.chain_id);
119+
env.block.difficulty = convert_u256(&block.difficulty);
120+
env.cfg.chain_id = self.chain_id;
118121

119122
env
120123
}
@@ -133,15 +136,15 @@ impl<R: ExecutionRpc> ProofDB<R> {
133136
}
134137

135138
enum StateAccess {
136-
Basic(B160),
139+
Basic(Address),
137140
BlockHash(u64),
138-
Storage(B160, U256),
141+
Storage(Address, U256),
139142
}
140143

141144
struct EvmState<R: ExecutionRpc> {
142-
basic: HashMap<B160, AccountInfo>,
145+
basic: HashMap<Address, AccountInfo>,
143146
block_hash: HashMap<u64, B256>,
144-
storage: HashMap<B160, HashMap<U256, U256>>,
147+
storage: HashMap<Address, HashMap<U256, U256>>,
145148
block: BlockTag,
146149
access: Option<StateAccess>,
147150
execution: Arc<ExecutionClient<R>>,
@@ -163,32 +166,45 @@ impl<R: ExecutionRpc> EvmState<R> {
163166
if let Some(access) = &self.access.take() {
164167
match access {
165168
StateAccess::Basic(address) => {
169+
let address_ethers = ethers::types::Address::from_slice(address.as_slice());
166170
let account = self
167171
.execution
168-
.get_account(&(*address).into(), None, self.block)
172+
.get_account(&address_ethers, None, self.block)
169173
.await?;
174+
170175
let bytecode = Bytecode::new_raw(account.code.into());
171-
let account = AccountInfo::new(account.balance.into(), account.nonce, bytecode);
176+
let code_hash = B256::from_slice(account.code_hash.as_bytes());
177+
let balance = convert_u256(&account.balance);
178+
179+
let account = AccountInfo::new(balance, account.nonce, code_hash, bytecode);
172180
self.basic.insert(*address, account);
173181
}
174182
StateAccess::Storage(address, slot) => {
183+
let address_ethers = ethers::types::Address::from_slice(address.as_slice());
175184
let slot_ethers = ethers::types::H256::from_slice(&slot.to_be_bytes::<32>());
176185
let slots = [slot_ethers];
177186
let account = self
178187
.execution
179-
.get_account(&(*address).into(), Some(&slots), self.block)
188+
.get_account(&address_ethers, Some(&slots), self.block)
180189
.await?;
181190

182191
let storage = self.storage.entry(*address).or_default();
183192
let value = *account.slots.get(&slot_ethers).unwrap();
184-
storage.insert(*slot, value.into());
193+
194+
let mut value_slice = [0u8; 32];
195+
value.to_big_endian(value_slice.as_mut_slice());
196+
let value = U256::from_be_slice(&value_slice);
197+
198+
storage.insert(*slot, value);
185199
}
186200
StateAccess::BlockHash(number) => {
187201
let block = self
188202
.execution
189203
.get_block(BlockTag::Number(*number), false)
190204
.await?;
191-
self.block_hash.insert(*number, block.hash.into());
205+
206+
let hash = B256::from_slice(block.hash.as_bytes());
207+
self.block_hash.insert(*number, hash);
192208
}
193209
}
194210
}
@@ -200,7 +216,7 @@ impl<R: ExecutionRpc> EvmState<R> {
200216
self.access.is_some()
201217
}
202218

203-
pub fn get_basic(&mut self, address: B160) -> Result<AccountInfo> {
219+
pub fn get_basic(&mut self, address: Address) -> Result<AccountInfo> {
204220
if let Some(account) = self.basic.get(&address) {
205221
Ok(account.clone())
206222
} else {
@@ -209,7 +225,7 @@ impl<R: ExecutionRpc> EvmState<R> {
209225
}
210226
}
211227

212-
pub fn get_storage(&mut self, address: B160, slot: U256) -> Result<U256> {
228+
pub fn get_storage(&mut self, address: Address, slot: U256) -> Result<U256> {
213229
let storage = self.storage.entry(address).or_default();
214230
if let Some(slot) = storage.get(&slot) {
215231
Ok(*slot)
@@ -289,19 +305,23 @@ impl<R: ExecutionRpc> EvmState<R> {
289305
}
290306

291307
for (address, account) in account_map {
292-
let info = AccountInfo::new(
293-
account.balance.into(),
294-
account.nonce,
295-
Bytecode::new_raw(account.code.into()),
296-
);
308+
let bytecode = Bytecode::new_raw(account.code.into());
309+
let code_hash = B256::from_slice(account.code_hash.as_bytes());
310+
let balance = convert_u256(&account.balance);
297311

298-
self.basic.insert(address.into(), info);
312+
let info = AccountInfo::new(balance, account.nonce, code_hash, bytecode);
313+
314+
let address = convert_address(&address);
315+
self.basic.insert(address, info);
299316

300317
for (slot, value) in account.slots {
318+
let slot = B256::from_slice(slot.as_bytes());
319+
let value = convert_u256(&value);
320+
301321
self.storage
302-
.entry(address.into())
322+
.entry(address)
303323
.or_default()
304-
.insert(B256::from(slot).into(), value.into());
324+
.insert(B256::from(slot).into(), value);
305325
}
306326
}
307327

@@ -312,27 +332,29 @@ impl<R: ExecutionRpc> EvmState<R> {
312332
impl<R: ExecutionRpc> Database for ProofDB<R> {
313333
type Error = Report;
314334

315-
fn basic(&mut self, address: B160) -> Result<Option<AccountInfo>, Report> {
335+
fn basic(&mut self, address: Address) -> Result<Option<AccountInfo>, Report> {
316336
if is_precompile(&address) {
317337
return Ok(Some(AccountInfo::default()));
318338
}
319339

320340
trace!(
321341
target: "helios::evm",
322342
"fetch basic evm state for address=0x{}",
323-
hex::encode(address.as_bytes())
343+
hex::encode(address.as_slice())
324344
);
325345

326346
Ok(Some(self.state.get_basic(address)?))
327347
}
328348

329349
fn block_hash(&mut self, number: U256) -> Result<B256, Report> {
330350
trace!(target: "helios::evm", "fetch block hash for block={:?}", number);
331-
let number_ethers: ethers::types::U256 = number.into();
332-
self.state.get_block_hash(number_ethers.as_u64())
351+
let number = number
352+
.try_into()
353+
.map_err(|_| eyre::eyre!("invalid block number"))?;
354+
self.state.get_block_hash(number)
333355
}
334356

335-
fn storage(&mut self, address: B160, slot: U256) -> Result<U256, Report> {
357+
fn storage(&mut self, address: Address, slot: U256) -> Result<U256, Report> {
336358
trace!(target: "helios::evm", "fetch evm state for address={:?}, slot={}", address, slot);
337359
self.state.get_storage(address, slot)
338360
}
@@ -342,13 +364,24 @@ impl<R: ExecutionRpc> Database for ProofDB<R> {
342364
}
343365
}
344366

345-
fn is_precompile(address: &B160) -> bool {
346-
address.le(&B160::from_str("0x0000000000000000000000000000000000000009").unwrap())
347-
&& address.gt(&B160::zero())
367+
fn is_precompile(address: &Address) -> bool {
368+
address.le(&Address::from_str("0x0000000000000000000000000000000000000009").unwrap())
369+
&& address.gt(&Address::ZERO)
370+
}
371+
372+
fn convert_u256(value: &ethers::types::U256) -> U256 {
373+
let mut value_slice = [0u8; 32];
374+
value.to_big_endian(value_slice.as_mut_slice());
375+
U256::from_be_slice(&value_slice)
376+
}
377+
378+
fn convert_address(value: &ethers::types::Address) -> Address {
379+
Address::from_slice(value.as_bytes())
348380
}
349381

350382
#[cfg(test)]
351383
mod tests {
384+
use revm::primitives::KECCAK_EMPTY;
352385
use tokio::sync::{mpsc::channel, watch};
353386

354387
use crate::{rpc::mock_rpc::MockRpc, state::State};
@@ -371,8 +404,13 @@ mod tests {
371404
// Construct the proof database with the given client
372405
let mut proof_db = ProofDB::new(tag, Arc::new(execution));
373406

374-
let address = B160::from_str("0x388C818CA8B9251b393131C08a736A67ccB19297").unwrap();
375-
let info = AccountInfo::new(U256::from(500), 10, Bytecode::new_raw(Bytes::default()));
407+
let address = Address::from_str("0x388C818CA8B9251b393131C08a736A67ccB19297").unwrap();
408+
let info = AccountInfo::new(
409+
U256::from(500),
410+
10,
411+
KECCAK_EMPTY,
412+
Bytecode::new_raw(Bytes::default()),
413+
);
376414
proof_db.state.basic.insert(address, info.clone());
377415

378416
// Get the account from the proof database

execution/src/execution.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ impl<R: ExecutionRpc> ExecutionClient<R> {
102102
slot_map.insert(storage_proof.key, storage_proof.value);
103103
}
104104

105-
let code = if proof.code_hash == KECCAK_EMPTY.into() {
105+
let code = if proof.code_hash == H256::from_slice(KECCAK_EMPTY.as_slice()) {
106106
Vec::new()
107107
} else {
108108
let code = self.rpc.get_code(address, block.number.as_u64()).await?;

0 commit comments

Comments
 (0)