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]> {
110 let mut bitmap = vec![0u8; code.len().div_ceil(8)];
111 #[cfg(any(
112 target_arch = "aarch64",
113 all(target_arch = "x86_64", target_feature = "ssse3")
114 ))]
115 let any = by_block::jumpdests(code, &mut bitmap);
116 #[cfg(not(any(
117 target_arch = "aarch64",
118 all(target_arch = "x86_64", target_feature = "ssse3")
119 )))]
120 let any = jumpdests_by_opcode(code, &mut bitmap);
121 if any {
125 Arc::from(bitmap)
126 } else {
127 EMPTY_JUMPDESTS.clone()
128 }
129 }
130
131 #[inline]
134 pub fn is_valid_jumpdest(&self, offset: usize) -> bool {
135 self.jumpdests
136 .get(offset / 8)
137 .is_some_and(|byte| byte & (1 << (offset % 8)) != 0)
138 }
139
140 #[inline]
142 pub fn jumpdests(&self) -> &[u8] {
143 &self.jumpdests
144 }
145
146 #[inline]
147 pub fn code(&self) -> &[u8] {
148 self.bytecode.get(..self.bytecode_len).unwrap_or_default()
149 }
150
151 #[inline]
152 pub fn code_bytes(&self) -> Bytes {
153 self.bytecode.slice(..self.bytecode_len)
154 }
155
156 #[inline]
157 pub fn len(&self) -> usize {
158 self.bytecode_len
159 }
160
161 #[inline]
162 pub fn is_empty(&self) -> bool {
163 self.bytecode_len == 0
164 }
165
166 #[inline]
170 pub fn dispatch_buf(&self) -> &[u8] {
171 &self.bytecode
172 }
173
174 pub fn size(&self) -> usize {
185 let hash_size = size_of::<H256>();
186 let bytes_size = size_of::<Bytes>() + self.bytecode.len();
187 let bitmap_size = size_of::<Arc<[u8]>>() + self.jumpdests.len();
188 hash_size + bytes_size + bitmap_size
189 }
190}
191
192const OP_JUMPDEST: u8 = 0x5B;
195const OP_PUSH1: u8 = 0x60;
196const OP_PUSH32: u8 = 0x7F;
197
198#[cfg_attr(
206 any(
207 target_arch = "aarch64",
208 all(target_arch = "x86_64", target_feature = "ssse3")
209 ),
210 allow(dead_code)
211)]
212fn jumpdests_by_opcode(code: &[u8], bitmap: &mut [u8]) -> bool {
213 let mut any = false;
214 let mut current_byte = usize::MAX;
215 let mut bits = 0u8;
216 let mut i = 0;
217 while i < code.len() {
218 match code[i] {
219 OP_JUMPDEST => {
220 if i / 8 != current_byte {
221 if let Some(byte) = bitmap.get_mut(current_byte) {
222 *byte = bits;
223 }
224 current_byte = i / 8;
225 bits = 0;
226 }
227 bits |= 1 << (i % 8);
228 any = true;
229 }
230 c @ OP_PUSH1..=OP_PUSH32 => i += usize::from(c - OP_PUSH1) + 1,
232 _ => (),
233 }
234 i += 1;
235 }
236 if let Some(byte) = bitmap.get_mut(current_byte) {
237 *byte = bits;
238 }
239 any
240}
241
242#[cfg(any(
254 target_arch = "aarch64",
255 all(target_arch = "x86_64", target_feature = "ssse3")
256))]
257mod by_block {
258 use super::{OP_JUMPDEST, OP_PUSH1};
259 use lanes::Lanes;
260
261 const BLOCK: usize = 64;
263 const GROUP: usize = 16;
265
266 pub(super) fn jumpdests(code: &[u8], bitmap: &mut [u8]) -> bool {
268 let mut walks = Walks::new();
269 let (blocks, tail) = code.as_chunks::<BLOCK>();
270 let mut carry = 0;
271 let mut any = 0;
272 for (block, word) in blocks.iter().zip(bitmap.as_chunks_mut::<8>().0) {
274 let valid = block_jumpdests(block, &mut carry, &mut walks);
275 *word = valid.to_le_bytes();
276 any |= valid;
277 }
278 if !tail.is_empty() {
279 let mut padded = [0; BLOCK];
281 padded[..tail.len()].copy_from_slice(tail);
282 let valid = block_jumpdests(&padded, &mut carry, &mut walks);
283 let rest = &mut bitmap[blocks.len() * 8..];
284 rest.copy_from_slice(&valid.to_le_bytes()[..rest.len()]);
285 any |= valid;
286 }
287 any != 0
288 }
289
290 struct Walks {
297 exits: [u8; 2 * BLOCK],
298 low_stops: [u8; 2 * BLOCK],
299 high_stops: [u8; 2 * BLOCK],
300 }
301
302 impl Walks {
303 fn new() -> Self {
304 Self {
305 exits: core::array::from_fn(|i| i as u8),
306 low_stops: [0; 2 * BLOCK],
307 high_stops: [0; 2 * BLOCK],
308 }
309 }
310 }
311
312 #[inline(always)]
317 fn block_jumpdests(block: &[u8; BLOCK], carry: &mut usize, walks: &mut Walks) -> u64 {
318 let groups = block.as_chunks::<GROUP>().0;
319 let groups: [Lanes; BLOCK / GROUP] = core::array::from_fn(|g| Lanes::load(&groups[g]));
320 let jumpdests = Lanes::bits(groups.map(|bytes| bytes.eq(Lanes::splat(OP_JUMPDEST))));
321 for (g, bytes) in groups.into_iter().enumerate() {
322 let (exits, low_stops, high_stops) = group_walks(bytes);
323 let exits = exits.add(Lanes::splat((g * GROUP) as u8));
325 exits.store(&mut walks.exits.as_chunks_mut::<GROUP>().0[g]);
326 low_stops.store(&mut walks.low_stops.as_chunks_mut::<GROUP>().0[g]);
327 high_stops.store(&mut walks.high_stops.as_chunks_mut::<GROUP>().0[g]);
328 }
329 let mut at = *carry;
330 let mut opcodes = 0;
331 for _ in 0..BLOCK / GROUP {
332 let i = at % (2 * BLOCK);
334 let stops = u64::from(walks.low_stops[i]) | (u64::from(walks.high_stops[i]) << 8);
335 let group_start = i & (BLOCK - GROUP);
337 opcodes |= stops << group_start;
338 at = usize::from(walks.exits[i]);
339 }
340 *carry = at - BLOCK;
343 jumpdests & opcodes
344 }
345
346 #[inline(always)]
357 fn group_walks(bytes: Lanes) -> (Lanes, Lanes, Lanes) {
358 const POSITIONS_PLUS_ONE: [u8; GROUP] =
359 [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
360 const LOW_POSITION_BITS: [u8; GROUP] =
361 [1, 2, 4, 8, 16, 32, 64, 128, 0, 0, 0, 0, 0, 0, 0, 0];
362 const HIGH_POSITION_BITS: [u8; GROUP] =
363 [0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 4, 8, 16, 32, 64, 128];
364 let is_push = bytes.and(Lanes::splat(0xE0)).eq(Lanes::splat(OP_PUSH1));
367 let immediates = is_push.and(bytes.sub(Lanes::splat(OP_PUSH1 - 1)));
368 let mut exits = Lanes::load(&POSITIONS_PLUS_ONE).add(immediates);
370 let mut low_stops = Lanes::load(&LOW_POSITION_BITS);
371 let mut high_stops = Lanes::load(&HIGH_POSITION_BITS);
372 for round in 0..4 {
377 if round < 3 {
378 low_stops = low_stops.or(low_stops.lookup(exits));
379 }
380 high_stops = high_stops.or(high_stops.lookup(exits));
381 exits = exits.max(exits.lookup(exits));
382 }
383 (exits, low_stops, high_stops)
384 }
385
386 #[cfg(target_arch = "aarch64")]
387 mod lanes {
388 use core::arch::aarch64::*;
389
390 #[derive(Clone, Copy)]
392 pub(super) struct Lanes(uint8x16_t);
393
394 impl Lanes {
398 #[inline(always)]
399 pub(super) fn load(bytes: &[u8; 16]) -> Self {
400 unsafe { Self(vld1q_u8(bytes.as_ptr())) }
401 }
402
403 #[inline(always)]
404 pub(super) fn store(self, out: &mut [u8; 16]) {
405 unsafe { vst1q_u8(out.as_mut_ptr(), self.0) }
406 }
407
408 #[inline(always)]
409 pub(super) fn splat(byte: u8) -> Self {
410 unsafe { Self(vdupq_n_u8(byte)) }
411 }
412
413 #[inline(always)]
414 pub(super) fn and(self, other: Self) -> Self {
415 unsafe { Self(vandq_u8(self.0, other.0)) }
416 }
417
418 #[inline(always)]
419 pub(super) fn or(self, other: Self) -> Self {
420 unsafe { Self(vorrq_u8(self.0, other.0)) }
421 }
422
423 #[inline(always)]
424 pub(super) fn add(self, other: Self) -> Self {
425 unsafe { Self(vaddq_u8(self.0, other.0)) }
426 }
427
428 #[inline(always)]
429 pub(super) fn sub(self, other: Self) -> Self {
430 unsafe { Self(vsubq_u8(self.0, other.0)) }
431 }
432
433 #[inline(always)]
435 pub(super) fn eq(self, other: Self) -> Self {
436 unsafe { Self(vceqq_u8(self.0, other.0)) }
437 }
438
439 #[inline(always)]
440 pub(super) fn max(self, other: Self) -> Self {
441 unsafe { Self(vmaxq_u8(self.0, other.0)) }
442 }
443
444 #[inline(always)]
446 pub(super) fn lookup(self, indices: Self) -> Self {
447 unsafe { Self(vqtbl1q_u8(self.0, indices.0)) }
448 }
449
450 #[inline(always)]
456 pub(super) fn bits(masks: [Self; 4]) -> u64 {
457 unsafe {
458 let position_bits = vreinterpretq_u8_u64(vdupq_n_u64(0x8040_2010_0804_0201));
459 let [a, b, c, d] = masks.map(|m| vandq_u8(m.0, position_bits));
460 let quarters = vpaddq_u8(vpaddq_u8(a, b), vpaddq_u8(c, d));
461 vgetq_lane_u64::<0>(vreinterpretq_u64_u8(vpaddq_u8(quarters, quarters)))
462 }
463 }
464 }
465 }
466
467 #[cfg(target_arch = "x86_64")]
468 mod lanes {
469 use core::arch::x86_64::*;
470
471 #[derive(Clone, Copy)]
473 pub(super) struct Lanes(__m128i);
474
475 impl Lanes {
479 #[inline(always)]
480 pub(super) fn load(bytes: &[u8; 16]) -> Self {
481 unsafe { Self(_mm_loadu_si128(bytes.as_ptr().cast())) }
482 }
483
484 #[inline(always)]
485 pub(super) fn store(self, out: &mut [u8; 16]) {
486 unsafe { _mm_storeu_si128(out.as_mut_ptr().cast(), self.0) }
487 }
488
489 #[inline(always)]
490 pub(super) fn splat(byte: u8) -> Self {
491 unsafe { Self(_mm_set1_epi8(byte as i8)) }
492 }
493
494 #[inline(always)]
495 pub(super) fn and(self, other: Self) -> Self {
496 unsafe { Self(_mm_and_si128(self.0, other.0)) }
497 }
498
499 #[inline(always)]
500 pub(super) fn or(self, other: Self) -> Self {
501 unsafe { Self(_mm_or_si128(self.0, other.0)) }
502 }
503
504 #[inline(always)]
505 pub(super) fn add(self, other: Self) -> Self {
506 unsafe { Self(_mm_add_epi8(self.0, other.0)) }
507 }
508
509 #[inline(always)]
510 pub(super) fn sub(self, other: Self) -> Self {
511 unsafe { Self(_mm_sub_epi8(self.0, other.0)) }
512 }
513
514 #[inline(always)]
516 pub(super) fn eq(self, other: Self) -> Self {
517 unsafe { Self(_mm_cmpeq_epi8(self.0, other.0)) }
518 }
519
520 #[inline(always)]
521 pub(super) fn max(self, other: Self) -> Self {
522 unsafe { Self(_mm_max_epu8(self.0, other.0)) }
523 }
524
525 #[inline(always)]
528 pub(super) fn lookup(self, indices: Self) -> Self {
529 unsafe {
533 let indices = _mm_add_epi8(indices.0, _mm_set1_epi8(0x70));
534 Self(_mm_shuffle_epi8(self.0, indices))
535 }
536 }
537
538 #[inline(always)]
540 pub(super) fn bits(masks: [Self; 4]) -> u64 {
541 masks.iter().enumerate().fold(0, |bits, (i, m)| {
542 let lanes = unsafe { _mm_movemask_epi8(m.0) } as u16;
543 bits | (u64::from(lanes) << (16 * i))
544 })
545 }
546 }
547 }
548}
549
550#[derive(Serialize, Deserialize)]
568struct CodeSerde {
569 hash: H256,
570 code: Bytes,
571 jump_targets: Arc<[u32]>,
572}
573
574impl Serialize for Code {
575 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
576 CodeSerde {
577 hash: self.hash,
578 code: self.code_bytes(),
579 jump_targets: Arc::from([]),
580 }
581 .serialize(serializer)
582 }
583}
584
585impl<'de> Deserialize<'de> for Code {
586 fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
587 let CodeSerde {
590 hash,
591 code,
592 jump_targets: _,
593 } = CodeSerde::deserialize(deserializer)?;
594 Ok(Self::from_parts_unchecked(
595 hash,
596 &code,
597 Self::compute_jumpdests(&code),
598 ))
599 }
600}
601
602#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
603pub struct CodeMetadata {
604 pub length: u64,
605}
606
607#[derive(Clone, Default, Debug, PartialEq, Eq, Serialize, Deserialize)]
608pub struct Account {
609 pub info: AccountInfo,
610 pub code: Code,
611 pub storage: FxHashMap<H256, U256>,
612}
613
614#[derive(Clone, Debug, PartialEq, Serialize, Deserialize, Eq, Hash)]
615pub struct AccountInfo {
616 pub code_hash: H256,
617 pub balance: U256,
618 pub nonce: u64,
619}
620
621#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
622pub struct AccountState {
623 pub nonce: u64,
624 pub balance: U256,
625 pub storage_root: H256,
626 pub code_hash: H256,
627}
628
629#[derive(Clone, Copy, Debug, Default, PartialEq)]
637pub struct AccountStateSlimCodec(pub AccountState);
638
639impl Default for AccountInfo {
640 fn default() -> Self {
641 Self {
642 code_hash: *EMPTY_KECCAK_HASH,
643 balance: Default::default(),
644 nonce: Default::default(),
645 }
646 }
647}
648
649impl Default for AccountState {
650 fn default() -> Self {
651 Self {
652 nonce: Default::default(),
653 balance: Default::default(),
654 storage_root: *EMPTY_TRIE_HASH,
655 code_hash: *EMPTY_KECCAK_HASH,
656 }
657 }
658}
659
660impl Default for Code {
661 fn default() -> Self {
662 Self {
663 bytecode: Bytes::from_static(&[0u8; BYTECODE_PADDING]),
664 bytecode_len: 0,
665 hash: *EMPTY_KECCAK_HASH,
666 jumpdests: EMPTY_JUMPDESTS.clone(),
667 }
668 }
669}
670
671impl From<GenesisAccount> for Account {
672 fn from(genesis: GenesisAccount) -> Self {
673 let code = Code::from_bytecode(genesis.code, &NativeCrypto);
674 Self {
675 info: AccountInfo {
676 code_hash: code.hash,
677 balance: genesis.balance,
678 nonce: genesis.nonce,
679 },
680 code,
681 storage: genesis
682 .storage
683 .iter()
684 .map(|(k, v)| (H256(k.to_big_endian()), *v))
685 .collect(),
686 }
687 }
688}
689
690pub fn code_hash(code: &Bytes, crypto: &dyn Crypto) -> H256 {
691 H256(crypto.keccak256(code.as_ref()))
692}
693
694pub const EIP7702_DELEGATION_PREFIX: [u8; 3] = [0xef, 0x01, 0x00];
697pub const EIP7702_DELEGATED_CODE_LEN: usize = 23;
700
701pub fn is_eip7702_delegation(code: &[u8]) -> bool {
704 code.len() == EIP7702_DELEGATED_CODE_LEN && code.starts_with(&EIP7702_DELEGATION_PREFIX)
705}
706
707impl RLPEncode for AccountInfo {
708 fn encode(&self, buf: &mut dyn bytes::BufMut) {
709 Encoder::new(buf)
710 .encode_field(&self.code_hash)
711 .encode_field(&self.balance)
712 .encode_field(&self.nonce)
713 .finish();
714 }
715}
716
717impl RLPDecode for AccountInfo {
718 fn decode_unfinished(rlp: &[u8]) -> Result<(AccountInfo, &[u8]), RLPDecodeError> {
719 let decoder = Decoder::new(rlp)?;
720 let (code_hash, decoder) = decoder.decode_field("code_hash")?;
721 let (balance, decoder) = decoder.decode_field("balance")?;
722 let (nonce, decoder) = decoder.decode_field("nonce")?;
723 let account_info = AccountInfo {
724 code_hash,
725 balance,
726 nonce,
727 };
728 Ok((account_info, decoder.finish()?))
729 }
730}
731
732impl RLPEncode for AccountState {
733 fn encode(&self, buf: &mut dyn bytes::BufMut) {
734 Encoder::new(buf)
735 .encode_field(&self.nonce)
736 .encode_field(&self.balance)
737 .encode_field(&self.storage_root)
738 .encode_field(&self.code_hash)
739 .finish();
740 }
741}
742
743impl RLPDecode for AccountState {
744 fn decode_unfinished(rlp: &[u8]) -> Result<(AccountState, &[u8]), RLPDecodeError> {
745 let decoder = Decoder::new(rlp)?;
746 let (nonce, decoder) = decoder.decode_field("nonce")?;
747 let (balance, decoder) = decoder.decode_field("balance")?;
748 let (storage_root, decoder) = decoder.decode_field("storage_root")?;
749 let (code_hash, decoder) = decoder.decode_field("code_hash")?;
750 let state = AccountState {
751 nonce,
752 balance,
753 storage_root,
754 code_hash,
755 };
756 Ok((state, decoder.finish()?))
757 }
758}
759
760impl RLPEncode for AccountStateSlimCodec {
761 fn encode(&self, buf: &mut dyn BufMut) {
762 struct StorageRootCodec<'a>(&'a H256);
763 impl RLPEncode for StorageRootCodec<'_> {
764 fn encode(&self, buf: &mut dyn BufMut) {
765 let data = if *self.0 != *EMPTY_TRIE_HASH {
766 self.0.as_bytes()
767 } else {
768 &[]
769 };
770
771 data.encode(buf);
772 }
773 }
774
775 struct CodeHashCodec<'a>(&'a H256);
776 impl RLPEncode for CodeHashCodec<'_> {
777 fn encode(&self, buf: &mut dyn BufMut) {
778 let data = if *self.0 != *EMPTY_KECCAK_HASH {
779 self.0.as_bytes()
780 } else {
781 &[]
782 };
783
784 data.encode(buf);
785 }
786 }
787
788 Encoder::new(buf)
789 .encode_field(&self.0.nonce)
790 .encode_field(&self.0.balance)
791 .encode_field(&StorageRootCodec(&self.0.storage_root))
792 .encode_field(&CodeHashCodec(&self.0.code_hash))
793 .finish();
794 }
795}
796
797impl RLPDecode for AccountStateSlimCodec {
798 fn decode_unfinished(rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
799 struct StorageRootCodec(H256);
800 impl RLPDecode for StorageRootCodec {
801 fn decode_unfinished(mut rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
802 let value = match rlp.split_off_first() {
803 Some(0x80) => *EMPTY_TRIE_HASH,
804 Some(0xA0) => {
805 let data;
806 (data, rlp) = rlp
807 .split_first_chunk::<32>()
808 .ok_or(RLPDecodeError::InvalidLength)?;
809 H256(*data)
810 }
811 _ => return Err(RLPDecodeError::InvalidLength),
812 };
813
814 Ok((Self(value), rlp))
815 }
816 }
817
818 struct CodeHashCodec(H256);
819 impl RLPDecode for CodeHashCodec {
820 fn decode_unfinished(mut rlp: &[u8]) -> Result<(Self, &[u8]), RLPDecodeError> {
821 let value = match rlp.split_off_first() {
822 Some(0x80) => *EMPTY_KECCAK_HASH,
823 Some(0xA0) => {
824 let data;
825 (data, rlp) = rlp
826 .split_first_chunk::<32>()
827 .ok_or(RLPDecodeError::InvalidLength)?;
828 H256(*data)
829 }
830 _ => return Err(RLPDecodeError::InvalidLength),
831 };
832
833 Ok((Self(value), rlp))
834 }
835 }
836
837 let decoder = Decoder::new(rlp)?;
838 let (nonce, decoder) = decoder.decode_field("nonce")?;
839 let (balance, decoder) = decoder.decode_field("balance")?;
840 let (StorageRootCodec(storage_root), decoder) = decoder.decode_field("storage_root")?;
841 let (CodeHashCodec(code_hash), decoder) = decoder.decode_field("code_hash")?;
842
843 Ok((
844 Self(AccountState {
845 nonce,
846 balance,
847 storage_root,
848 code_hash,
849 }),
850 decoder.finish()?,
851 ))
852 }
853}
854
855pub fn compute_storage_root(storage: &BTreeMap<U256, U256>, crypto: &dyn Crypto) -> H256 {
856 let iter = storage.iter().filter_map(|(k, v)| {
857 (!v.is_zero()).then_some((
858 crypto.keccak256(&k.to_big_endian()).to_vec(),
859 v.encode_to_vec(),
860 ))
861 });
862 Trie::compute_hash_from_unsorted_iter(iter, crypto)
863}
864
865impl From<&GenesisAccount> for AccountState {
866 fn from(value: &GenesisAccount) -> Self {
867 AccountState {
868 nonce: value.nonce,
869 balance: value.balance,
870 storage_root: compute_storage_root(&value.storage, &NativeCrypto),
871 code_hash: code_hash(&value.code, &NativeCrypto),
872 }
873 }
874}
875
876impl Account {
877 pub fn new(balance: U256, code: Code, nonce: u64, storage: FxHashMap<H256, U256>) -> Self {
878 Self {
879 info: AccountInfo {
880 balance,
881 code_hash: code.hash,
882 nonce,
883 },
884 code,
885 storage,
886 }
887 }
888}
889
890impl AccountInfo {
891 pub fn is_empty(&self) -> bool {
892 self.balance.is_zero() && self.nonce == 0 && self.code_hash == *EMPTY_KECCAK_HASH
893 }
894}
895
896#[cfg(test)]
897mod test {
898 use std::str::FromStr;
899
900 use super::*;
901
902 #[derive(serde::Serialize)]
906 struct OldCodeSerde {
907 hash: H256,
908 code: Bytes,
909 jump_targets: Vec<u32>,
910 }
911
912 #[derive(serde::Serialize)]
917 struct OldWrap {
918 code: OldCodeSerde,
919 tail: u64,
920 }
921 #[derive(serde::Deserialize)]
922 struct NewWrap {
923 code: Code,
924 tail: u64,
925 }
926
927 #[test]
933 fn embedded_code_decodes_an_old_layout_bincode_row() {
934 let bytecode = Bytes::from(vec![0x60, 0x00, 0x5b, 0x00]);
936 let hash = H256::from_low_u64_be(0xabc);
937 const SENTINEL: u64 = 0x0123_4567_89ab_cdef;
938 let old = OldWrap {
939 code: OldCodeSerde {
940 hash,
941 code: bytecode.clone(),
942 jump_targets: vec![2], },
944 tail: SENTINEL,
945 };
946 let bytes = bincode::serialize(&old).expect("serialize old layout");
947
948 let decoded: NewWrap = bincode::deserialize(&bytes).expect("decode old row under new Code");
949 assert_eq!(decoded.code.hash, hash);
950 assert_eq!(decoded.code.code_bytes(), bytecode);
951 assert_eq!(
953 decoded.tail, SENTINEL,
954 "field after Code corrupted by layout shift"
955 );
956 assert!(decoded.code.is_valid_jumpdest(2));
958 assert!(!decoded.code.is_valid_jumpdest(1));
959 }
960
961 #[test]
962 fn test_code_hash() {
963 let empty_code = Bytes::new();
964 let hash = code_hash(&empty_code, &NativeCrypto);
965 assert_eq!(
966 hash,
967 H256::from_str("c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470")
968 .unwrap()
969 )
970 }
971
972 #[test]
973 fn test_is_eip7702_delegation_valid() {
974 let mut code = Vec::with_capacity(23);
976 code.extend_from_slice(&EIP7702_DELEGATION_PREFIX);
977 code.extend_from_slice(&[0x42; 20]);
978 assert!(is_eip7702_delegation(&code));
979 }
980
981 #[test]
982 fn test_is_eip7702_delegation_rejects_empty() {
983 assert!(!is_eip7702_delegation(&[]));
984 }
985
986 #[test]
987 fn test_is_eip7702_delegation_rejects_short() {
988 assert!(!is_eip7702_delegation(&EIP7702_DELEGATION_PREFIX));
990 }
991
992 #[test]
993 fn test_is_eip7702_delegation_rejects_long() {
994 let mut code = Vec::with_capacity(24);
996 code.extend_from_slice(&EIP7702_DELEGATION_PREFIX);
997 code.extend_from_slice(&[0x42; 21]);
998 assert!(!is_eip7702_delegation(&code));
999 }
1000
1001 #[test]
1002 fn test_is_eip7702_delegation_rejects_wrong_prefix() {
1003 let mut code = Vec::with_capacity(23);
1005 code.extend_from_slice(&[0xef, 0x01, 0x01]); code.extend_from_slice(&[0x42; 20]);
1007 assert!(!is_eip7702_delegation(&code));
1008 }
1009
1010 #[test]
1011 fn test_is_eip7702_delegation_rejects_arbitrary_contract_code() {
1012 let code = vec![0x60, 0x60, 0x60, 0x40, 0x52 ];
1014 assert!(!is_eip7702_delegation(&code));
1015 }
1016
1017 #[cfg(any(
1020 target_arch = "aarch64",
1021 all(target_arch = "x86_64", target_feature = "ssse3")
1022 ))]
1023 mod by_block_against_the_scan {
1024 use super::*;
1025
1026 fn assert_same_jumpdests(code: &[u8]) {
1027 let mut want = vec![0; code.len().div_ceil(8)];
1028 let mut got = want.clone();
1029 let want_any = jumpdests_by_opcode(code, &mut want);
1030 let got_any = by_block::jumpdests(code, &mut got);
1031 assert_eq!((got_any, got), (want_any, want), "code {code:02x?}");
1032 }
1033
1034 #[test]
1038 fn matches_around_group_and_block_boundaries() {
1039 const BYTES: [u8; 9] = [
1042 0x00,
1043 OP_JUMPDEST,
1044 OP_PUSH1,
1045 OP_PUSH1 + 1,
1046 OP_PUSH1 + 14,
1047 OP_PUSH1 + 15,
1048 OP_PUSH1 + 16,
1049 OP_PUSH32 - 1,
1050 OP_PUSH32,
1051 ];
1052 let lengths = [
1053 1, 15, 16, 17, 31, 32, 33, 63, 64, 65, 96, 127, 128, 129, 193,
1054 ];
1055 for filler in [OP_JUMPDEST, OP_PUSH1] {
1059 for len in lengths {
1060 for at in 0..len {
1061 for first in BYTES {
1062 for second in [None].into_iter().chain(BYTES.map(Some)) {
1063 let mut code = vec![filler; len];
1064 code[at] = first;
1065 if let (Some(second), Some(byte)) = (second, code.get_mut(at + 1)) {
1066 *byte = second;
1067 }
1068 assert_same_jumpdests(&code);
1069 }
1070 }
1071 }
1072 }
1073 }
1074 }
1075
1076 #[test]
1079 fn matches_on_random_code() {
1080 let mut state = 0x9E37_79B9_7F4A_7C15_u64;
1082 let mut next = move || {
1083 state ^= state << 13;
1084 state ^= state >> 7;
1085 state ^= state << 17;
1086 state
1087 };
1088 let jumpdest_and_pushes: Vec<u8> = std::iter::once(OP_JUMPDEST)
1089 .chain(OP_PUSH1..=OP_PUSH32)
1090 .collect();
1091 let all_bytes: Vec<u8> = (0..=u8::MAX).collect();
1092 let mixes: [&[u8]; 4] = [
1093 &[0x00, OP_JUMPDEST, OP_PUSH1],
1094 &[OP_JUMPDEST, OP_PUSH1, OP_PUSH1 + 1],
1095 &jumpdest_and_pushes,
1096 &all_bytes,
1097 ];
1098 for mix in mixes {
1099 for _ in 0..200 {
1100 let len = (next() % 4096) as usize;
1101 let code: Vec<u8> = (0..len)
1102 .map(|_| mix[(next() % mix.len() as u64) as usize])
1103 .collect();
1104 assert_same_jumpdests(&code);
1105 }
1106 }
1107 }
1108 }
1109}