1use std::collections::BTreeMap;
2use std::sync::{Arc, LazyLock};
3
4use bytes::{BufMut, Bytes};
5use ethereum_types::{H256, U256};
6use ethrex_crypto::{Crypto, NativeCrypto};
7use ethrex_trie::Trie;
8use rustc_hash::FxHashMap;
9use serde::{Deserialize, Serialize};
10
11use ethrex_rlp::{
12 decode::RLPDecode,
13 encode::RLPEncode,
14 error::RLPDecodeError,
15 structs::{Decoder, Encoder},
16};
17
18use super::GenesisAccount;
19use crate::constants::{EMPTY_KECCAK_HASH, EMPTY_TRIE_HASH};
20
21static EMPTY_JUMPDESTS: LazyLock<Arc<[u8]>> = LazyLock::new(|| Arc::from(Vec::new()));
26
27pub const BYTECODE_PADDING: usize = 33;
32
33#[derive(Clone, Debug, PartialEq, Eq, Hash)]
34pub struct Code {
35 pub hash: H256,
41 bytecode: Bytes,
43 bytecode_len: usize,
45 jumpdests: Arc<[u8]>,
58}
59
60impl Code {
61 pub fn from_bytecode_unchecked(code: Bytes, hash: H256) -> Self {
68 let jumpdests = Self::compute_jumpdests(&code);
69 Self::from_parts_unchecked(hash, &code, jumpdests)
70 }
71
72 pub fn from_bytecode(code: Bytes, crypto: &dyn Crypto) -> Self {
75 let jumpdests = Self::compute_jumpdests(&code);
76 let hash = H256(crypto.keccak256(code.as_ref()));
77 Self::from_parts_unchecked(hash, &code, jumpdests)
78 }
79
80 pub fn from_parts_unchecked(hash: H256, code: &[u8], jumpdests: Arc<[u8]>) -> Self {
88 let bytecode_len = code.len();
89 let mut padded_code = Vec::with_capacity(bytecode_len + BYTECODE_PADDING);
90 padded_code.extend_from_slice(code);
91 padded_code.extend_from_slice(&[0u8; BYTECODE_PADDING]);
92 Self {
93 hash,
94 bytecode: Bytes::from_owner(padded_code),
95 bytecode_len,
96 jumpdests,
97 }
98 }
99
100 pub fn compute_jumpdests(code: &[u8]) -> Arc<[u8]> {
109 let mut bitmap = vec![0u8; code.len().div_ceil(8)];
110 let mut any = false;
111 let mut current_byte = usize::MAX;
112 let mut bits = 0u8;
113 let mut i = 0;
114 while i < code.len() {
115 match code[i] {
117 0x5B => {
119 if i / 8 != current_byte {
120 if let Some(byte) = bitmap.get_mut(current_byte) {
121 *byte = bits;
122 }
123 current_byte = i / 8;
124 bits = 0;
125 }
126 bits |= 1 << (i % 8);
127 any = true;
128 }
129 c @ 0x60..0x80 => {
131 i += (c - 0x5F) as usize;
133 }
134 _ => (),
135 }
136 i += 1;
137 }
138 if let Some(byte) = bitmap.get_mut(current_byte) {
139 *byte = bits;
140 }
141 if any {
145 Arc::from(bitmap)
146 } else {
147 EMPTY_JUMPDESTS.clone()
148 }
149 }
150
151 #[inline]
154 pub fn is_valid_jumpdest(&self, offset: usize) -> bool {
155 self.jumpdests
156 .get(offset / 8)
157 .is_some_and(|byte| byte & (1 << (offset % 8)) != 0)
158 }
159
160 #[inline]
162 pub fn jumpdests(&self) -> &[u8] {
163 &self.jumpdests
164 }
165
166 #[inline]
167 pub fn code(&self) -> &[u8] {
168 self.bytecode.get(..self.bytecode_len).unwrap_or_default()
169 }
170
171 #[inline]
172 pub fn code_bytes(&self) -> Bytes {
173 self.bytecode.slice(..self.bytecode_len)
174 }
175
176 #[inline]
177 pub fn len(&self) -> usize {
178 self.bytecode_len
179 }
180
181 #[inline]
182 pub fn is_empty(&self) -> bool {
183 self.bytecode_len == 0
184 }
185
186 #[inline]
190 pub fn dispatch_buf(&self) -> &[u8] {
191 &self.bytecode
192 }
193
194 pub fn size(&self) -> usize {
205 let hash_size = size_of::<H256>();
206 let bytes_size = size_of::<Bytes>() + self.bytecode.len();
207 let bitmap_size = size_of::<Arc<[u8]>>() + self.jumpdests.len();
208 hash_size + bytes_size + bitmap_size
209 }
210}
211
212#[derive(Serialize, Deserialize)]
230struct CodeSerde {
231 hash: H256,
232 code: Bytes,
233 jump_targets: Arc<[u32]>,
234}
235
236impl Serialize for Code {
237 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
238 CodeSerde {
239 hash: self.hash,
240 code: self.code_bytes(),
241 jump_targets: Arc::from([]),
242 }
243 .serialize(serializer)
244 }
245}
246
247impl<'de> Deserialize<'de> for Code {
248 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
249 let CodeSerde {
252 hash,
253 code,
254 jump_targets: _,
255 } = CodeSerde::deserialize(deserializer)?;
256 Ok(Self::from_parts_unchecked(
257 hash,
258 &code,
259 Self::compute_jumpdests(&code),
260 ))
261 }
262}
263
264#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
265pub struct CodeMetadata {
266 pub length: u64,
267}
268
269#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
270pub struct Account {
271 pub info: AccountInfo,
272 pub code: Code,
273 pub storage: FxHashMap<H256, U256>,
274}
275
276#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
277pub struct AccountInfo {
278 pub code_hash: H256,
279 pub balance: U256,
280 pub nonce: u64,
281}
282
283#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
284pub struct AccountState {
285 pub nonce: u64,
286 pub balance: U256,
287 pub storage_root: H256,
288 pub code_hash: H256,
289}
290
291#[derive(Clone, Copy, Debug, Default, PartialEq)]
299pub struct AccountStateSlimCodec(pub AccountState);
300
301impl Default for AccountInfo {
302 fn default() -> Self {
303 Self {
304 code_hash: *EMPTY_KECCAK_HASH,
305 balance: Default::default(),
306 nonce: Default::default(),
307 }
308 }
309}
310
311impl Default for AccountState {
312 fn default() -> Self {
313 Self {
314 nonce: Default::default(),
315 balance: Default::default(),
316 storage_root: *EMPTY_TRIE_HASH,
317 code_hash: *EMPTY_KECCAK_HASH,
318 }
319 }
320}
321
322impl Default for Code {
323 fn default() -> Self {
324 Self {
325 bytecode: Bytes::from_static(&[0u8; BYTECODE_PADDING]),
326 bytecode_len: 0,
327 hash: *EMPTY_KECCAK_HASH,
328 jumpdests: EMPTY_JUMPDESTS.clone(),
329 }
330 }
331}
332
333impl From<GenesisAccount> for Account {
334 fn from(genesis: GenesisAccount) -> Self {
335 let code = Code::from_bytecode(genesis.code, &NativeCrypto);
336 Self {
337 info: AccountInfo {
338 code_hash: code.hash,
339 balance: genesis.balance,
340 nonce: genesis.nonce,
341 },
342 code,
343 storage: genesis
344 .storage
345 .iter()
346 .map(|(k, v)| (H256(k.to_big_endian()), *v))
347 .collect(),
348 }
349 }
350}
351
352pub fn code_hash(code: &Bytes, crypto: &dyn Crypto) -> H256 {
353 H256(crypto.keccak256(code.as_ref()))
354}
355
356pub const EIP7702_DELEGATION_PREFIX: [u8; 3] = [0xef, 0x01, 0x00];
359pub const EIP7702_DELEGATED_CODE_LEN: usize = 23;
362
363pub fn is_eip7702_delegation(code: &[u8]) -> bool {
366 code.len() == EIP7702_DELEGATED_CODE_LEN && code.starts_with(&EIP7702_DELEGATION_PREFIX)
367}
368
369impl RLPEncode for AccountInfo {
370 fn encode(&self, buf: &mut dyn bytes::BufMut) {
371 Encoder::new(buf)
372 .encode_field(&self.code_hash)
373 .encode_field(&self.balance)
374 .encode_field(&self.nonce)
375 .finish();
376 }
377}
378
379impl RLPDecode for AccountInfo {
380 fn decode_unfinished(rlp: &[u8]) -> Result<(AccountInfo, &[u8]), RLPDecodeError> {
381 let decoder = Decoder::new(rlp)?;
382 let (code_hash, decoder) = decoder.decode_field("code_hash")?;
383 let (balance, decoder) = decoder.decode_field("balance")?;
384 let (nonce, decoder) = decoder.decode_field("nonce")?;
385 let account_info = AccountInfo {
386 code_hash,
387 balance,
388 nonce,
389 };
390 Ok((account_info, decoder.finish()?))
391 }
392}
393
394impl RLPEncode for AccountState {
395 fn encode(&self, buf: &mut dyn bytes::BufMut) {
396 Encoder::new(buf)
397 .encode_field(&self.nonce)
398 .encode_field(&self.balance)
399 .encode_field(&self.storage_root)
400 .encode_field(&self.code_hash)
401 .finish();
402 }
403}
404
405impl RLPDecode for AccountState {
406 fn decode_unfinished(rlp: &[u8]) -> Result<(AccountState, &[u8]), RLPDecodeError> {
407 let decoder = Decoder::new(rlp)?;
408 let (nonce, decoder) = decoder.decode_field("nonce")?;
409 let (balance, decoder) = decoder.decode_field("balance")?;
410 let (storage_root, decoder) = decoder.decode_field("storage_root")?;
411 let (code_hash, decoder) = decoder.decode_field("code_hash")?;
412 let state = AccountState {
413 nonce,
414 balance,
415 storage_root,
416 code_hash,
417 };
418 Ok((state, decoder.finish()?))
419 }
420}
421
422impl RLPEncode for AccountStateSlimCodec {
423 fn encode(&self, buf: &mut dyn BufMut) {
424 struct StorageRootCodec<'a>(&'a H256);
425 impl RLPEncode for StorageRootCodec<'_> {
426 fn encode(&self, buf: &mut dyn BufMut) {
427 let data = if *self.0 != *EMPTY_TRIE_HASH {
428 self.0.as_bytes()
429 } else {
430 &[]
431 };
432
433 data.encode(buf);
434 }
435 }
436
437 struct CodeHashCodec<'a>(&'a H256);
438 impl RLPEncode for CodeHashCodec<'_> {
439 fn encode(&self, buf: &mut dyn BufMut) {
440 let data = if *self.0 != *EMPTY_KECCAK_HASH {
441 self.0.as_bytes()
442 } else {
443 &[]
444 };
445
446 data.encode(buf);
447 }
448 }
449
450 Encoder::new(buf)
451 .encode_field(&self.0.nonce)
452 .encode_field(&self.0.balance)
453 .encode_field(&StorageRootCodec(&self.0.storage_root))
454 .encode_field(&CodeHashCodec(&self.0.code_hash))
455 .finish();
456 }
457}
458
459impl RLPDecode for AccountStateSlimCodec {
460 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
461 struct StorageRootCodec(H256);
462 impl RLPDecode for StorageRootCodec {
463 fn decode_unfinished(mut rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
464 let value = match rlp.split_off_first() {
465 Some(0x80) => *EMPTY_TRIE_HASH,
466 Some(0xA0) => {
467 let data;
468 (data, rlp) = rlp
469 .split_first_chunk::<32>()
470 .ok_or(RLPDecodeError::InvalidLength)?;
471 H256(*data)
472 }
473 _ => return Err(RLPDecodeError::InvalidLength),
474 };
475
476 Ok((Self(value), rlp))
477 }
478 }
479
480 struct CodeHashCodec(H256);
481 impl RLPDecode for CodeHashCodec {
482 fn decode_unfinished(mut rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
483 let value = match rlp.split_off_first() {
484 Some(0x80) => *EMPTY_KECCAK_HASH,
485 Some(0xA0) => {
486 let data;
487 (data, rlp) = rlp
488 .split_first_chunk::<32>()
489 .ok_or(RLPDecodeError::InvalidLength)?;
490 H256(*data)
491 }
492 _ => return Err(RLPDecodeError::InvalidLength),
493 };
494
495 Ok((Self(value), rlp))
496 }
497 }
498
499 let decoder = Decoder::new(rlp)?;
500 let (nonce, decoder) = decoder.decode_field("nonce")?;
501 let (balance, decoder) = decoder.decode_field("balance")?;
502 let (StorageRootCodec(storage_root), decoder) = decoder.decode_field("storage_root")?;
503 let (CodeHashCodec(code_hash), decoder) = decoder.decode_field("code_hash")?;
504
505 Ok((
506 Self(AccountState {
507 nonce,
508 balance,
509 storage_root,
510 code_hash,
511 }),
512 decoder.finish()?,
513 ))
514 }
515}
516
517pub fn compute_storage_root(storage: &BTreeMap<U256, U256>, crypto: &dyn Crypto) -> H256 {
518 let iter = storage.iter().filter_map(|(k, v)| {
519 (!v.is_zero()).then_some((
520 crypto.keccak256(&k.to_big_endian()).to_vec(),
521 v.encode_to_vec(),
522 ))
523 });
524 Trie::compute_hash_from_unsorted_iter(iter, crypto)
525}
526
527impl From<&GenesisAccount> for AccountState {
528 fn from(value: &GenesisAccount) -> Self {
529 AccountState {
530 nonce: value.nonce,
531 balance: value.balance,
532 storage_root: compute_storage_root(&value.storage, &NativeCrypto),
533 code_hash: code_hash(&value.code, &NativeCrypto),
534 }
535 }
536}
537
538impl Account {
539 pub fn new(balance: U256, code: Code, nonce: u64, storage: FxHashMap<H256, U256>) -> Self {
540 Self {
541 info: AccountInfo {
542 balance,
543 code_hash: code.hash,
544 nonce,
545 },
546 code,
547 storage,
548 }
549 }
550}
551
552impl AccountInfo {
553 pub fn is_empty(&self) -> bool {
554 self.balance.is_zero() && self.nonce == 0 && self.code_hash == *EMPTY_KECCAK_HASH
555 }
556}
557
558#[cfg(test)]
559mod test {
560 use std::str::FromStr;
561
562 use super::*;
563
564 #[derive(serde::Serialize)]
568 struct OldCodeSerde {
569 hash: H256,
570 code: Bytes,
571 jump_targets: Vec<u32>,
572 }
573
574 #[derive(serde::Serialize)]
579 struct OldWrap {
580 code: OldCodeSerde,
581 tail: u64,
582 }
583 #[derive(serde::Deserialize)]
584 struct NewWrap {
585 code: Code,
586 tail: u64,
587 }
588
589 #[test]
595 fn embedded_code_decodes_an_old_layout_bincode_row() {
596 let bytecode = Bytes::from(vec![0x60, 0x00, 0x5b, 0x00]);
598 let hash = H256::from_low_u64_be(0xabc);
599 const SENTINEL: u64 = 0x0123_4567_89ab_cdef;
600 let old = OldWrap {
601 code: OldCodeSerde {
602 hash,
603 code: bytecode.clone(),
604 jump_targets: vec![2], },
606 tail: SENTINEL,
607 };
608 let bytes = bincode::serialize(&old).expect("serialize old layout");
609
610 let decoded: NewWrap = bincode::deserialize(&bytes).expect("decode old row under new Code");
611 assert_eq!(decoded.code.hash, hash);
612 assert_eq!(decoded.code.code_bytes(), bytecode);
613 assert_eq!(
615 decoded.tail, SENTINEL,
616 "field after Code corrupted by layout shift"
617 );
618 assert!(decoded.code.is_valid_jumpdest(2));
620 assert!(!decoded.code.is_valid_jumpdest(1));
621 }
622
623 #[test]
624 fn test_code_hash() {
625 let empty_code = Bytes::new();
626 let hash = code_hash(&empty_code, &NativeCrypto);
627 assert_eq!(
628 hash,
629 H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
630 .unwrap()
631 )
632 }
633
634 #[test]
635 fn test_is_eip7702_delegation_valid() {
636 let mut code = Vec::with_capacity(23);
638 code.extend_from_slice(&EIP7702_DELEGATION_PREFIX);
639 code.extend_from_slice(&[0x42; 20]);
640 assert!(is_eip7702_delegation(&code));
641 }
642
643 #[test]
644 fn test_is_eip7702_delegation_rejects_empty() {
645 assert!(!is_eip7702_delegation(&[]));
646 }
647
648 #[test]
649 fn test_is_eip7702_delegation_rejects_short() {
650 assert!(!is_eip7702_delegation(&EIP7702_DELEGATION_PREFIX));
652 }
653
654 #[test]
655 fn test_is_eip7702_delegation_rejects_long() {
656 let mut code = Vec::with_capacity(24);
658 code.extend_from_slice(&EIP7702_DELEGATION_PREFIX);
659 code.extend_from_slice(&[0x42; 21]);
660 assert!(!is_eip7702_delegation(&code));
661 }
662
663 #[test]
664 fn test_is_eip7702_delegation_rejects_wrong_prefix() {
665 let mut code = Vec::with_capacity(23);
667 code.extend_from_slice(&[0xef, 0x01, 0x01]); code.extend_from_slice(&[0x42; 20]);
669 assert!(!is_eip7702_delegation(&code));
670 }
671
672 #[test]
673 fn test_is_eip7702_delegation_rejects_arbitrary_contract_code() {
674 let code = vec![0x60, 0x60, 0x60, 0x40, 0x52 ];
676 assert!(!is_eip7702_delegation(&code));
677 }
678}