revm_interpreter/instructions/
utility.rs

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