revm_interpreter/instructions/
bitwise.rs

1use super::i256::i256_cmp;
2use crate::{
3    gas,
4    interpreter::Interpreter,
5    interpreter_types::{InterpreterTypes, LoopControl, RuntimeFlag, StackTr},
6    Host,
7};
8use core::cmp::Ordering;
9use primitives::U256;
10
11pub fn lt<WIRE: InterpreterTypes, H: Host + ?Sized>(
12    interpreter: &mut Interpreter<WIRE>,
13    _host: &mut H,
14) {
15    gas!(interpreter, gas::VERYLOW);
16    popn_top!([op1], op2, interpreter);
17    *op2 = U256::from(op1 < *op2);
18}
19
20pub fn gt<WIRE: InterpreterTypes, H: Host + ?Sized>(
21    interpreter: &mut Interpreter<WIRE>,
22    _host: &mut H,
23) {
24    gas!(interpreter, gas::VERYLOW);
25    popn_top!([op1], op2, interpreter);
26
27    *op2 = U256::from(op1 > *op2);
28}
29
30pub fn slt<WIRE: InterpreterTypes, H: Host + ?Sized>(
31    interpreter: &mut Interpreter<WIRE>,
32    _host: &mut H,
33) {
34    gas!(interpreter, gas::VERYLOW);
35    popn_top!([op1], op2, interpreter);
36
37    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
38}
39
40pub fn sgt<WIRE: InterpreterTypes, H: Host + ?Sized>(
41    interpreter: &mut Interpreter<WIRE>,
42    _host: &mut H,
43) {
44    gas!(interpreter, gas::VERYLOW);
45    popn_top!([op1], op2, interpreter);
46
47    *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
48}
49
50pub fn eq<WIRE: InterpreterTypes, H: Host + ?Sized>(
51    interpreter: &mut Interpreter<WIRE>,
52    _host: &mut H,
53) {
54    gas!(interpreter, gas::VERYLOW);
55    popn_top!([op1], op2, interpreter);
56
57    *op2 = U256::from(op1 == *op2);
58}
59
60pub fn iszero<WIRE: InterpreterTypes, H: Host + ?Sized>(
61    interpreter: &mut Interpreter<WIRE>,
62    _host: &mut H,
63) {
64    gas!(interpreter, gas::VERYLOW);
65    popn_top!([], op1, interpreter);
66    *op1 = U256::from(op1.is_zero());
67}
68
69pub fn bitand<WIRE: InterpreterTypes, H: Host + ?Sized>(
70    interpreter: &mut Interpreter<WIRE>,
71    _host: &mut H,
72) {
73    gas!(interpreter, gas::VERYLOW);
74    popn_top!([op1], op2, interpreter);
75    *op2 = op1 & *op2;
76}
77
78pub fn bitor<WIRE: InterpreterTypes, H: Host + ?Sized>(
79    interpreter: &mut Interpreter<WIRE>,
80    _host: &mut H,
81) {
82    gas!(interpreter, gas::VERYLOW);
83    popn_top!([op1], op2, interpreter);
84
85    *op2 = op1 | *op2;
86}
87
88pub fn bitxor<WIRE: InterpreterTypes, H: Host + ?Sized>(
89    interpreter: &mut Interpreter<WIRE>,
90    _host: &mut H,
91) {
92    gas!(interpreter, gas::VERYLOW);
93    popn_top!([op1], op2, interpreter);
94
95    *op2 = op1 ^ *op2;
96}
97
98pub fn not<WIRE: InterpreterTypes, H: Host + ?Sized>(
99    interpreter: &mut Interpreter<WIRE>,
100    _host: &mut H,
101) {
102    gas!(interpreter, gas::VERYLOW);
103    popn_top!([], op1, interpreter);
104
105    *op1 = !*op1;
106}
107
108pub fn byte<WIRE: InterpreterTypes, H: Host + ?Sized>(
109    interpreter: &mut Interpreter<WIRE>,
110    _host: &mut H,
111) {
112    gas!(interpreter, gas::VERYLOW);
113    popn_top!([op1], op2, interpreter);
114
115    let o1 = as_usize_saturated!(op1);
116    *op2 = if o1 < 32 {
117        // `31 - o1` because `byte` returns LE, while we want BE
118        U256::from(op2.byte(31 - o1))
119    } else {
120        U256::ZERO
121    };
122}
123
124/// EIP-145: Bitwise shifting instructions in EVM
125pub fn shl<WIRE: InterpreterTypes, H: Host + ?Sized>(
126    interpreter: &mut Interpreter<WIRE>,
127    _host: &mut H,
128) {
129    check!(interpreter, CONSTANTINOPLE);
130    gas!(interpreter, gas::VERYLOW);
131    popn_top!([op1], op2, interpreter);
132
133    let shift = as_usize_saturated!(op1);
134    *op2 = if shift < 256 {
135        *op2 << shift
136    } else {
137        U256::ZERO
138    }
139}
140
141/// EIP-145: Bitwise shifting instructions in EVM
142pub fn shr<WIRE: InterpreterTypes, H: Host + ?Sized>(
143    interpreter: &mut Interpreter<WIRE>,
144    _host: &mut H,
145) {
146    check!(interpreter, CONSTANTINOPLE);
147    gas!(interpreter, gas::VERYLOW);
148    popn_top!([op1], op2, interpreter);
149
150    let shift = as_usize_saturated!(op1);
151    *op2 = if shift < 256 {
152        *op2 >> shift
153    } else {
154        U256::ZERO
155    }
156}
157
158/// EIP-145: Bitwise shifting instructions in EVM
159pub fn sar<WIRE: InterpreterTypes, H: Host + ?Sized>(
160    interpreter: &mut Interpreter<WIRE>,
161    _host: &mut H,
162) {
163    check!(interpreter, CONSTANTINOPLE);
164    gas!(interpreter, gas::VERYLOW);
165    popn_top!([op1], op2, interpreter);
166
167    let shift = as_usize_saturated!(op1);
168    *op2 = if shift < 256 {
169        op2.arithmetic_shr(shift)
170    } else if op2.bit(255) {
171        U256::MAX
172    } else {
173        U256::ZERO
174    };
175}
176
177// TODO : Tests
178/*
179#[cfg(test)]
180mod tests {
181    use crate::instructions::bitwise::{byte, sar, shl, shr};
182    use crate::interpreter_wiring::StackTr;
183    use crate::{Contract, DummyHost, Interpreter};
184    use primitives::{uint, U256};
185    use specification::hardfork::LatestSpec;
186    use context_interface::{default::Env, DefaultEthereumWiring};
187
188    #[test]
189    fn test_shift_left() {
190        let mut host = DummyHost::new(Env::default());
191        let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
192
193        struct TestCase {
194            value: U256,
195            shift: U256,
196            expected: U256,
197        }
198
199        uint! {
200            let test_cases = [
201                TestCase {
202                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
203                    shift: 0x00_U256,
204                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
205                },
206                TestCase {
207                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
208                    shift: 0x01_U256,
209                    expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
210                },
211                TestCase {
212                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
213                    shift: 0xff_U256,
214                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
215                },
216                TestCase {
217                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
218                    shift: 0x0100_U256,
219                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
220                },
221                TestCase {
222                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
223                    shift: 0x0101_U256,
224                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
225                },
226                TestCase {
227                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
228                    shift: 0x00_U256,
229                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
230                },
231                TestCase {
232                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
233                    shift: 0x01_U256,
234                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
235                },
236                TestCase {
237                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
238                    shift: 0xff_U256,
239                    expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
240                },
241                TestCase {
242                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
243                    shift: 0x0100_U256,
244                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
245                },
246                TestCase {
247                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
248                    shift: 0x01_U256,
249                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
250                },
251                TestCase {
252                    value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
253                    shift: 0x01_U256,
254                    expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
255                },
256            ];
257        }
258
259        for test in test_cases {
260            host.clear();
261            push!(interpreter, test.value);
262            push!(interpreter, test.shift);
263            shl::<Interpreter, DummyHost<DefaultEthereumWiring>>(&mut interpreter, &mut host);
264            let res = interpreter.stack.pop().unwrap();
265            assert_eq!(res, test.expected);
266        }
267    }
268
269    #[test]
270    fn test_logical_shift_right() {
271        let mut host = DummyHost::new(Env::default());
272        let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
273
274        struct TestCase {
275            value: U256,
276            shift: U256,
277            expected: U256,
278        }
279
280        uint! {
281            let test_cases = [
282                TestCase {
283                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
284                    shift: 0x00_U256,
285                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
286                },
287                TestCase {
288                    value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
289                    shift: 0x01_U256,
290                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
291                },
292                TestCase {
293                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
294                    shift: 0x01_U256,
295                    expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
296                },
297                TestCase {
298                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
299                    shift: 0xff_U256,
300                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
301                },
302                TestCase {
303                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
304                    shift: 0x0100_U256,
305                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
306                },
307                TestCase {
308                    value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
309                    shift: 0x0101_U256,
310                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
311                },
312                TestCase {
313                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
314                    shift: 0x00_U256,
315                    expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
316                },
317                TestCase {
318                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
319                    shift: 0x01_U256,
320                    expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
321                },
322                TestCase {
323                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
324                    shift: 0xff_U256,
325                    expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
326                },
327                TestCase {
328                    value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
329                    shift: 0x0100_U256,
330                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
331                },
332                TestCase {
333                    value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
334                    shift: 0x01_U256,
335                    expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
336                },
337            ];
338        }
339
340        for test in test_cases {
341            host.clear();
342            push!(interpreter, test.value);
343            push!(interpreter, test.shift);
344            shr::<Interpreter, DummyHost<DefaultEthereumWiring>>(&mut interpreter, &mut host);
345            let res = interpreter.stack.pop().unwrap();
346            assert_eq!(res, test.expected);
347        }
348    }
349
350    #[test]
351    fn test_arithmetic_shift_right() {
352        let mut host = DummyHost::new(Env::default());
353        let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
354
355        struct TestCase {
356            value: U256,
357            shift: U256,
358            expected: U256,
359        }
360
361        uint! {
362        let test_cases = [
363            TestCase {
364                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
365                shift: 0x00_U256,
366                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
367            },
368            TestCase {
369                value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
370                shift: 0x01_U256,
371                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
372            },
373            TestCase {
374                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
375                shift: 0x01_U256,
376                expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
377            },
378            TestCase {
379                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
380                shift: 0xff_U256,
381                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
382            },
383            TestCase {
384                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
385                shift: 0x0100_U256,
386                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
387            },
388            TestCase {
389                value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
390                shift: 0x0101_U256,
391                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
392            },
393            TestCase {
394                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
395                shift: 0x00_U256,
396                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
397            },
398            TestCase {
399                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
400                shift: 0x01_U256,
401                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
402            },
403            TestCase {
404                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
405                shift: 0xff_U256,
406                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
407            },
408            TestCase {
409                value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
410                shift: 0x0100_U256,
411                expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
412            },
413            TestCase {
414                value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
415                shift: 0x01_U256,
416                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
417            },
418            TestCase {
419                value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
420                shift: 0xfe_U256,
421                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
422            },
423            TestCase {
424                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
425                shift: 0xf8_U256,
426                expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
427            },
428            TestCase {
429                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
430                shift: 0xfe_U256,
431                expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
432            },
433            TestCase {
434                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
435                shift: 0xff_U256,
436                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
437            },
438            TestCase {
439                value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
440                shift: 0x0100_U256,
441                expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
442            },
443        ];
444            }
445
446        for test in test_cases {
447            host.clear();
448            push!(interpreter, test.value);
449            push!(interpreter, test.shift);
450            sar::<Interpreter, DummyHost<DefaultEthereumWiring>>(&mut interpreter, &mut host);
451            let res = interpreter.stack.pop().unwrap();
452            assert_eq!(res, test.expected);
453        }
454    }
455
456    #[test]
457    fn test_byte() {
458        struct TestCase {
459            input: U256,
460            index: usize,
461            expected: U256,
462        }
463
464        let mut host = DummyHost::<DefaultEthereumWiring>::new(Env::default());
465        let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
466
467        let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
468        let test_cases = (0..32)
469            .map(|i| {
470                let byte_pos = 31 - i;
471
472                let shift_amount = U256::from(byte_pos * 8);
473                let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
474                TestCase {
475                    input: input_value,
476                    index: i,
477                    expected: byte_value,
478                }
479            })
480            .collect::<Vec<_>>();
481
482        for test in test_cases.iter() {
483            push!(interpreter, test.input);
484            push!(interpreter, U256::from(test.index));
485            byte(&mut interpreter, &mut host);
486            let res = interpreter.stack.pop().unwrap();
487            assert_eq!(res, test.expected, "Failed at index: {}", test.index);
488        }
489    }
490}
491*/