Skip to content

Commit 52f1f01

Browse files
authored
feat: add tests for shift instructions (bluealloy#1254)
* feat: add tests for shift instructions * Use LatestSpec instead of CancunSpec * Run cargo fmt * Use parans instead of brackets * Simplify host/interpreter initialization * Remove unused imports * Remove test case comments * Use U256 types
1 parent c3f0503 commit 52f1f01

File tree

2 files changed

+284
-3
lines changed

2 files changed

+284
-3
lines changed

bins/revm-test/src/bin/analysis.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ fn main() {
2525
.with_db(BenchmarkDB::new_bytecode(bytecode_raw))
2626
.build();
2727

28-
// just to spead up processor.
28+
// Just to warm up the processor.
2929
for _ in 0..10000 {
3030
let _ = evm.transact().unwrap();
3131
}

crates/interpreter/src/instructions/bitwise.rs

+283-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
Host, Interpreter,
66
};
77
use core::cmp::Ordering;
8+
use revm_primitives::uint;
89

910
pub fn lt<H: Host>(interpreter: &mut Interpreter, _host: &mut H) {
1011
gas!(interpreter, gas::VERYLOW);
@@ -103,19 +104,299 @@ pub fn sar<H: Host, SPEC: Spec>(interpreter: &mut Interpreter, _host: &mut H) {
103104

104105
let value_sign = i256_sign_compl(op2);
105106

106-
*op2 = if value_sign == Sign::Zero || op1 >= U256::from(256) {
107+
// If the shift count is 255+, we can short-circuit. This is because shifting by 255 bits is the
108+
// maximum shift that still leaves 1 bit in the original 256-bit number. Shifting by 256 bits or
109+
// more would mean that no original bits remain. The result depends on what the highest bit of
110+
// the value is.
111+
*op2 = if value_sign == Sign::Zero || op1 >= U256::from(255) {
107112
match value_sign {
108113
// value is 0 or >=1, pushing 0
109114
Sign::Plus | Sign::Zero => U256::ZERO,
110115
// value is <0, pushing -1
111116
Sign::Minus => U256::MAX,
112117
}
113118
} else {
114-
const ONE: U256 = U256::from_limbs([1, 0, 0, 0]);
119+
const ONE: U256 = uint!(1_U256);
120+
// SAFETY: shift count is checked above; it's less than 255.
115121
let shift = usize::try_from(op1).unwrap();
116122
match value_sign {
117123
Sign::Plus | Sign::Zero => op2.wrapping_shr(shift),
118124
Sign::Minus => two_compl(op2.wrapping_sub(ONE).wrapping_shr(shift).wrapping_add(ONE)),
119125
}
120126
};
121127
}
128+
129+
#[cfg(test)]
130+
mod tests {
131+
use crate::instructions::bitwise::{sar, shl, shr};
132+
use crate::{Contract, DummyHost, Interpreter};
133+
use revm_primitives::{uint, Env, LatestSpec, U256};
134+
135+
#[test]
136+
fn test_shift_left() {
137+
let mut host = DummyHost::new(Env::default());
138+
let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
139+
140+
struct TestCase {
141+
value: U256,
142+
shift: U256,
143+
expected: U256,
144+
}
145+
146+
uint! {
147+
let test_cases = [
148+
TestCase {
149+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
150+
shift: 0x00_U256,
151+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
152+
},
153+
TestCase {
154+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
155+
shift: 0x01_U256,
156+
expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
157+
},
158+
TestCase {
159+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
160+
shift: 0xff_U256,
161+
expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
162+
},
163+
TestCase {
164+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
165+
shift: 0x0100_U256,
166+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
167+
},
168+
TestCase {
169+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
170+
shift: 0x0101_U256,
171+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
172+
},
173+
TestCase {
174+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
175+
shift: 0x00_U256,
176+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
177+
},
178+
TestCase {
179+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
180+
shift: 0x01_U256,
181+
expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
182+
},
183+
TestCase {
184+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
185+
shift: 0xff_U256,
186+
expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
187+
},
188+
TestCase {
189+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
190+
shift: 0x0100_U256,
191+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
192+
},
193+
TestCase {
194+
value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
195+
shift: 0x01_U256,
196+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
197+
},
198+
TestCase {
199+
value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
200+
shift: 0x01_U256,
201+
expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
202+
},
203+
];
204+
}
205+
206+
for test in test_cases {
207+
host.clear();
208+
push!(interpreter, test.value);
209+
push!(interpreter, test.shift);
210+
shl::<DummyHost, LatestSpec>(&mut interpreter, &mut host);
211+
pop!(interpreter, res);
212+
assert_eq!(res, test.expected);
213+
}
214+
}
215+
216+
#[test]
217+
fn test_logical_shift_right() {
218+
let mut host = DummyHost::new(Env::default());
219+
let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
220+
221+
struct TestCase {
222+
value: U256,
223+
shift: U256,
224+
expected: U256,
225+
}
226+
227+
uint! {
228+
let test_cases = [
229+
TestCase {
230+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
231+
shift: 0x00_U256,
232+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
233+
},
234+
TestCase {
235+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
236+
shift: 0x01_U256,
237+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
238+
},
239+
TestCase {
240+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
241+
shift: 0x01_U256,
242+
expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
243+
},
244+
TestCase {
245+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
246+
shift: 0xff_U256,
247+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
248+
},
249+
TestCase {
250+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
251+
shift: 0x0100_U256,
252+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
253+
},
254+
TestCase {
255+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
256+
shift: 0x0101_U256,
257+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
258+
},
259+
TestCase {
260+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
261+
shift: 0x00_U256,
262+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
263+
},
264+
TestCase {
265+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
266+
shift: 0x01_U256,
267+
expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
268+
},
269+
TestCase {
270+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
271+
shift: 0xff_U256,
272+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
273+
},
274+
TestCase {
275+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
276+
shift: 0x0100_U256,
277+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
278+
},
279+
TestCase {
280+
value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
281+
shift: 0x01_U256,
282+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
283+
},
284+
];
285+
}
286+
287+
for test in test_cases {
288+
host.clear();
289+
push!(interpreter, test.value);
290+
push!(interpreter, test.shift);
291+
shr::<DummyHost, LatestSpec>(&mut interpreter, &mut host);
292+
pop!(interpreter, res);
293+
assert_eq!(res, test.expected);
294+
}
295+
}
296+
297+
#[test]
298+
fn test_arithmetic_shift_right() {
299+
let mut host = DummyHost::new(Env::default());
300+
let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false);
301+
302+
struct TestCase {
303+
value: U256,
304+
shift: U256,
305+
expected: U256,
306+
}
307+
308+
uint! {
309+
let test_cases = [
310+
TestCase {
311+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
312+
shift: 0x00_U256,
313+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
314+
},
315+
TestCase {
316+
value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
317+
shift: 0x01_U256,
318+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
319+
},
320+
TestCase {
321+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
322+
shift: 0x01_U256,
323+
expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
324+
},
325+
TestCase {
326+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
327+
shift: 0xff_U256,
328+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
329+
},
330+
TestCase {
331+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
332+
shift: 0x0100_U256,
333+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
334+
},
335+
TestCase {
336+
value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
337+
shift: 0x0101_U256,
338+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
339+
},
340+
TestCase {
341+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
342+
shift: 0x00_U256,
343+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
344+
},
345+
TestCase {
346+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
347+
shift: 0x01_U256,
348+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
349+
},
350+
TestCase {
351+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
352+
shift: 0xff_U256,
353+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
354+
},
355+
TestCase {
356+
value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
357+
shift: 0x0100_U256,
358+
expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
359+
},
360+
TestCase {
361+
value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
362+
shift: 0x01_U256,
363+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
364+
},
365+
TestCase {
366+
value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
367+
shift: 0xfe_U256,
368+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
369+
},
370+
TestCase {
371+
value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
372+
shift: 0xf8_U256,
373+
expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
374+
},
375+
TestCase {
376+
value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
377+
shift: 0xfe_U256,
378+
expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
379+
},
380+
TestCase {
381+
value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
382+
shift: 0xff_U256,
383+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
384+
},
385+
TestCase {
386+
value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
387+
shift: 0x0100_U256,
388+
expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
389+
},
390+
];
391+
}
392+
393+
for test in test_cases {
394+
host.clear();
395+
push!(interpreter, test.value);
396+
push!(interpreter, test.shift);
397+
sar::<DummyHost, LatestSpec>(&mut interpreter, &mut host);
398+
pop!(interpreter, res);
399+
assert_eq!(res, test.expected);
400+
}
401+
}
402+
}

0 commit comments

Comments
 (0)