revm_interpreter/instructions/
utility.rs

1pub use crate::InstructionResult;
2pub use primitives::U256;
3use primitives::{Address, B256};
4
5/// Pushes an arbitrary length slice of bytes onto the stack, padding the last word with zeros
6/// if necessary.
7///
8/// # Panics
9///
10/// Panics if slice is longer than 32 bytes.
11#[inline]
12pub fn cast_slice_to_u256(slice: &[u8], dest: &mut U256) {
13    if slice.is_empty() {
14        return;
15    }
16    assert!(slice.len() <= 32, "slice too long");
17
18    let n_words = (slice.len() + 31) / 32;
19
20    // SAFETY: Length checked above.
21    unsafe {
22        //let dst = self.data.as_mut_ptr().add(self.data.len()).cast::<u64>();
23        //self.data.set_len(new_len);
24        let dst = dest.as_limbs_mut().as_mut_ptr();
25
26        let mut i = 0;
27
28        // Write full words
29        let words = slice.chunks_exact(32);
30        let partial_last_word = words.remainder();
31        for word in words {
32            // Note: We unroll `U256::from_be_bytes` here to write directly into the buffer,
33            // instead of creating a 32 byte array on the stack and then copying it over.
34            for l in word.rchunks_exact(8) {
35                dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
36                i += 1;
37            }
38        }
39
40        if partial_last_word.is_empty() {
41            return;
42        }
43
44        // Write limbs of partial last word
45        let limbs = partial_last_word.rchunks_exact(8);
46        let partial_last_limb = limbs.remainder();
47        for l in limbs {
48            dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
49            i += 1;
50        }
51
52        // Write partial last limb by padding with zeros
53        if !partial_last_limb.is_empty() {
54            let mut tmp = [0u8; 8];
55            tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb);
56            dst.add(i).write(u64::from_be_bytes(tmp));
57            i += 1;
58        }
59
60        debug_assert_eq!((i + 3) / 4, n_words, "wrote too much");
61
62        // Zero out upper bytes of last word
63        let m = i % 4; // 32 / 8
64        if m != 0 {
65            dst.add(i).write_bytes(0, 4 - m);
66        }
67    }
68}
69
70pub trait IntoU256 {
71    fn into_u256(self) -> U256;
72}
73
74impl IntoU256 for Address {
75    fn into_u256(self) -> U256 {
76        self.into_word().into_u256()
77    }
78}
79
80impl IntoU256 for B256 {
81    fn into_u256(self) -> U256 {
82        U256::from_be_bytes(self.0)
83    }
84}
85
86pub trait IntoAddress {
87    fn into_address(self) -> Address;
88}
89
90impl IntoAddress for U256 {
91    fn into_address(self) -> Address {
92        Address::from_word(B256::from(self.to_be_bytes()))
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use primitives::address;
99
100    use super::*;
101
102    #[test]
103    fn test_into_u256() {
104        let addr = address!("0000000000000000000000000000000000000001");
105        let u256 = addr.into_u256();
106        assert_eq!(u256, U256::from(0x01));
107        assert_eq!(u256.into_address(), addr);
108    }
109}