revm_interpreter/instructions/
utility.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
pub use crate::InstructionResult;
pub use primitives::U256;
use primitives::{Address, B256};

/// Pushes an arbitrary length slice of bytes onto the stack, padding the last word with zeros
/// if necessary.
///
/// # Panics
///
/// Panics if slice is longer than 32 bytes.
#[inline]
pub fn cast_slice_to_u256(slice: &[u8], dest: &mut U256) {
    if slice.is_empty() {
        return;
    }
    assert!(slice.len() <= 32, "slice too long");

    let n_words = (slice.len() + 31) / 32;

    // SAFETY: length checked above.
    unsafe {
        //let dst = self.data.as_mut_ptr().add(self.data.len()).cast::<u64>();
        //self.data.set_len(new_len);
        let dst = dest.as_limbs_mut().as_mut_ptr();

        let mut i = 0;

        // write full words
        let words = slice.chunks_exact(32);
        let partial_last_word = words.remainder();
        for word in words {
            // Note: we unroll `U256::from_be_bytes` here to write directly into the buffer,
            // instead of creating a 32 byte array on the stack and then copying it over.
            for l in word.rchunks_exact(8) {
                dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
                i += 1;
            }
        }

        if partial_last_word.is_empty() {
            return;
        }

        // write limbs of partial last word
        let limbs = partial_last_word.rchunks_exact(8);
        let partial_last_limb = limbs.remainder();
        for l in limbs {
            dst.add(i).write(u64::from_be_bytes(l.try_into().unwrap()));
            i += 1;
        }

        // write partial last limb by padding with zeros
        if !partial_last_limb.is_empty() {
            let mut tmp = [0u8; 8];
            tmp[8 - partial_last_limb.len()..].copy_from_slice(partial_last_limb);
            dst.add(i).write(u64::from_be_bytes(tmp));
            i += 1;
        }

        debug_assert_eq!((i + 3) / 4, n_words, "wrote too much");

        // zero out upper bytes of last word
        let m = i % 4; // 32 / 8
        if m != 0 {
            dst.add(i).write_bytes(0, 4 - m);
        }
    }
}

pub trait IntoU256 {
    fn into_u256(self) -> U256;
}

impl IntoU256 for Address {
    fn into_u256(self) -> U256 {
        self.into_word().into_u256()
    }
}

impl IntoU256 for B256 {
    fn into_u256(self) -> U256 {
        U256::from_be_bytes(self.0)
    }
}

pub trait IntoAddress {
    fn into_address(self) -> Address;
}

impl IntoAddress for U256 {
    fn into_address(self) -> Address {
        Address::from_word(B256::from(self.to_be_bytes()))
    }
}

#[cfg(test)]
mod tests {
    use primitives::address;

    use super::*;

    #[test]
    fn test_into_u256() {
        let addr = address!("0000000000000000000000000000000000000001");
        let u256 = addr.into_u256();
        assert_eq!(u256, U256::from(0x01));
        assert_eq!(u256.into_address(), addr);
    }
}