referrerpolicy=no-referrer-when-downgrade

pallet_revive/vm/evm/instructions/
bitwise.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18use super::{i256::i256_cmp, Context};
19use crate::vm::Ext;
20use core::cmp::Ordering;
21use revm::{
22	interpreter::{gas as revm_gas, interpreter_types::StackTr},
23	primitives::U256,
24};
25
26/// Implements the LT instruction - less than comparison.
27pub fn lt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
28	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
29	popn_top!([op1], op2, context.interpreter);
30	*op2 = U256::from(op1 < *op2);
31}
32
33/// Implements the GT instruction - greater than comparison.
34pub fn gt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
35	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
36	popn_top!([op1], op2, context.interpreter);
37
38	*op2 = U256::from(op1 > *op2);
39}
40
41/// Implements the CLZ instruction - count leading zeros.
42pub fn clz<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
43	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
44	popn_top!([], op1, context.interpreter);
45
46	let leading_zeros = op1.leading_zeros();
47	*op1 = U256::from(leading_zeros);
48}
49
50/// Implements the SLT instruction.
51///
52/// Signed less than comparison of two values from stack.
53pub fn slt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
54	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
55	popn_top!([op1], op2, context.interpreter);
56
57	*op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less);
58}
59
60/// Implements the SGT instruction.
61///
62/// Signed greater than comparison of two values from stack.
63pub fn sgt<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
64	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
65	popn_top!([op1], op2, context.interpreter);
66
67	*op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater);
68}
69
70/// Implements the EQ instruction.
71///
72/// Equality comparison of two values from stack.
73pub fn eq<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
74	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
75	popn_top!([op1], op2, context.interpreter);
76
77	*op2 = U256::from(op1 == *op2);
78}
79
80/// Implements the ISZERO instruction.
81///
82/// Checks if the top stack value is zero.
83pub fn iszero<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
84	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
85	popn_top!([], op1, context.interpreter);
86	*op1 = U256::from(op1.is_zero());
87}
88
89/// Implements the AND instruction.
90///
91/// Bitwise AND of two values from stack.
92pub fn bitand<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
93	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
94	popn_top!([op1], op2, context.interpreter);
95	*op2 = op1 & *op2;
96}
97
98/// Implements the OR instruction.
99///
100/// Bitwise OR of two values from stack.
101pub fn bitor<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
102	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
103	popn_top!([op1], op2, context.interpreter);
104
105	*op2 = op1 | *op2;
106}
107
108/// Implements the XOR instruction.
109///
110/// Bitwise XOR of two values from stack.
111pub fn bitxor<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
112	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
113	popn_top!([op1], op2, context.interpreter);
114
115	*op2 = op1 ^ *op2;
116}
117
118/// Implements the NOT instruction.
119///
120/// Bitwise NOT (negation) of the top stack value.
121pub fn not<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
122	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
123	popn_top!([], op1, context.interpreter);
124
125	*op1 = !*op1;
126}
127
128/// Implements the BYTE instruction.
129///
130/// Extracts a single byte from a word at a given index.
131pub fn byte<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
132	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
133	popn_top!([op1], op2, context.interpreter);
134
135	let o1 = as_usize_saturated!(op1);
136	*op2 = if o1 < 32 {
137		// `31 - o1` because `byte` returns LE, while we want BE
138		U256::from(op2.byte(31 - o1))
139	} else {
140		U256::ZERO
141	};
142}
143
144/// EIP-145: Bitwise shifting instructions in EVM
145pub fn shl<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
146	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
147	popn_top!([op1], op2, context.interpreter);
148
149	let shift = as_usize_saturated!(op1);
150	*op2 = if shift < 256 { *op2 << shift } else { U256::ZERO }
151}
152
153/// EIP-145: Bitwise shifting instructions in EVM
154pub fn shr<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
155	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
156	popn_top!([op1], op2, context.interpreter);
157
158	let shift = as_usize_saturated!(op1);
159	*op2 = if shift < 256 { *op2 >> shift } else { U256::ZERO }
160}
161
162/// EIP-145: Bitwise shifting instructions in EVM
163pub fn sar<'ext, E: Ext>(context: Context<'_, 'ext, E>) {
164	gas_legacy!(context.interpreter, revm_gas::VERYLOW);
165	popn_top!([op1], op2, context.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#[cfg(test)]
178mod tests {
179	use super::{byte, clz, sar, shl, shr};
180	use revm::{
181		interpreter::{host::DummyHost, InstructionContext},
182		primitives::{hardfork::SpecId, uint, U256},
183	};
184
185	pub fn test_interpreter() -> revm::interpreter::Interpreter<
186		crate::vm::evm::EVMInterpreter<'static, crate::exec::mock_ext::MockExt<crate::tests::Test>>,
187	> {
188		use crate::tests::Test;
189		use revm::{
190			interpreter::{
191				interpreter::{RuntimeFlags, SharedMemory},
192				Interpreter, Stack,
193			},
194			primitives::hardfork::SpecId,
195		};
196
197		let mock_ext = Box::leak(Box::new(crate::exec::mock_ext::MockExt::<Test>::new()));
198
199		Interpreter {
200			gas: revm::interpreter::Gas::new(0),
201			bytecode: Default::default(),
202			stack: Stack::new(),
203			return_data: Default::default(),
204			memory: SharedMemory::new(),
205			input: crate::vm::evm::EVMInputs::default(),
206			runtime_flag: RuntimeFlags { is_static: false, spec_id: SpecId::default() },
207			extend: mock_ext,
208		}
209	}
210
211	#[test]
212	fn test_shift_left() {
213		let mut interpreter = test_interpreter();
214
215		struct TestCase {
216			value: U256,
217			shift: U256,
218			expected: U256,
219		}
220
221		uint! {
222			let test_cases = [
223				TestCase {
224					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
225					shift: 0x00_U256,
226					expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
227				},
228				TestCase {
229					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
230					shift: 0x01_U256,
231					expected: 0x0000000000000000000000000000000000000000000000000000000000000002_U256,
232				},
233				TestCase {
234					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
235					shift: 0xff_U256,
236					expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
237				},
238				TestCase {
239					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
240					shift: 0x0100_U256,
241					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
242				},
243				TestCase {
244					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
245					shift: 0x0101_U256,
246					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
247				},
248				TestCase {
249					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
250					shift: 0x00_U256,
251					expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
252				},
253				TestCase {
254					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
255					shift: 0x01_U256,
256					expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
257				},
258				TestCase {
259					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
260					shift: 0xff_U256,
261					expected: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
262				},
263				TestCase {
264					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
265					shift: 0x0100_U256,
266					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
267				},
268				TestCase {
269					value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
270					shift: 0x01_U256,
271					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
272				},
273				TestCase {
274					value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
275					shift: 0x01_U256,
276					expected: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe_U256,
277				},
278			];
279		}
280
281		for test in test_cases {
282			push!(interpreter, test.value);
283			push!(interpreter, test.shift);
284			let context =
285				InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
286			shl(context);
287			let res = interpreter.stack.pop().unwrap();
288			assert_eq!(res, test.expected);
289		}
290	}
291
292	#[test]
293	fn test_logical_shift_right() {
294		let mut interpreter = test_interpreter();
295
296		struct TestCase {
297			value: U256,
298			shift: U256,
299			expected: U256,
300		}
301
302		uint! {
303			let test_cases = [
304				TestCase {
305					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
306					shift: 0x00_U256,
307					expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
308				},
309				TestCase {
310					value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
311					shift: 0x01_U256,
312					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
313				},
314				TestCase {
315					value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
316					shift: 0x01_U256,
317					expected: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
318				},
319				TestCase {
320					value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
321					shift: 0xff_U256,
322					expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
323				},
324				TestCase {
325					value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
326					shift: 0x0100_U256,
327					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
328				},
329				TestCase {
330					value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
331					shift: 0x0101_U256,
332					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
333				},
334				TestCase {
335					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
336					shift: 0x00_U256,
337					expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
338				},
339				TestCase {
340					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
341					shift: 0x01_U256,
342					expected: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
343				},
344				TestCase {
345					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
346					shift: 0xff_U256,
347					expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
348				},
349				TestCase {
350					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
351					shift: 0x0100_U256,
352					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
353				},
354				TestCase {
355					value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
356					shift: 0x01_U256,
357					expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
358				},
359			];
360		}
361
362		for test in test_cases {
363			push!(interpreter, test.value);
364			push!(interpreter, test.shift);
365			let context =
366				InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
367			shr(context);
368			let res = interpreter.stack.pop().unwrap();
369			assert_eq!(res, test.expected);
370		}
371	}
372
373	#[test]
374	fn test_arithmetic_shift_right() {
375		let mut interpreter = test_interpreter();
376
377		struct TestCase {
378			value: U256,
379			shift: U256,
380			expected: U256,
381		}
382
383		uint! {
384		let test_cases = [
385			TestCase {
386				value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
387				shift: 0x00_U256,
388				expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
389			},
390			TestCase {
391				value: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
392				shift: 0x01_U256,
393				expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
394			},
395			TestCase {
396				value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
397				shift: 0x01_U256,
398				expected: 0xc000000000000000000000000000000000000000000000000000000000000000_U256,
399			},
400			TestCase {
401				value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
402				shift: 0xff_U256,
403				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
404			},
405			TestCase {
406				value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
407				shift: 0x0100_U256,
408				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
409			},
410			TestCase {
411				value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256,
412				shift: 0x0101_U256,
413				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
414			},
415			TestCase {
416				value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
417				shift: 0x00_U256,
418				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
419			},
420			TestCase {
421				value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
422				shift: 0x01_U256,
423				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
424			},
425			TestCase {
426				value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
427				shift: 0xff_U256,
428				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
429			},
430			TestCase {
431				value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
432				shift: 0x0100_U256,
433				expected: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
434			},
435			TestCase {
436				value: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
437				shift: 0x01_U256,
438				expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
439			},
440			TestCase {
441				value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256,
442				shift: 0xfe_U256,
443				expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
444			},
445			TestCase {
446				value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
447				shift: 0xf8_U256,
448				expected: 0x000000000000000000000000000000000000000000000000000000000000007f_U256,
449			},
450			TestCase {
451				value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
452				shift: 0xfe_U256,
453				expected: 0x0000000000000000000000000000000000000000000000000000000000000001_U256,
454			},
455			TestCase {
456				value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
457				shift: 0xff_U256,
458				expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
459			},
460			TestCase {
461				value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
462				shift: 0x0100_U256,
463				expected: 0x0000000000000000000000000000000000000000000000000000000000000000_U256,
464			},
465		];
466			}
467
468		for test in test_cases {
469			push!(interpreter, test.value);
470			push!(interpreter, test.shift);
471			let context =
472				InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
473			sar(context);
474			let res = interpreter.stack.pop().unwrap();
475			assert_eq!(res, test.expected);
476		}
477	}
478
479	#[test]
480	fn test_byte() {
481		struct TestCase {
482			input: U256,
483			index: usize,
484			expected: U256,
485		}
486
487		let mut interpreter = test_interpreter();
488
489		let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128);
490		let test_cases = (0..32)
491			.map(|i| {
492				let byte_pos = 31 - i;
493
494				let shift_amount = U256::from(byte_pos * 8);
495				let byte_value = (input_value >> shift_amount) & U256::from(0xFF);
496				TestCase { input: input_value, index: i, expected: byte_value }
497			})
498			.collect::<Vec<_>>();
499
500		for test in test_cases.iter() {
501			push!(interpreter, test.input);
502			push!(interpreter, U256::from(test.index));
503			let context =
504				InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
505			byte(context);
506			let res = interpreter.stack.pop().unwrap();
507			assert_eq!(res, test.expected, "Failed at index: {}", test.index);
508		}
509	}
510
511	#[test]
512	fn test_clz() {
513		let mut interpreter = test_interpreter();
514		interpreter.runtime_flag.spec_id = SpecId::OSAKA;
515
516		struct TestCase {
517			value: U256,
518			expected: U256,
519		}
520
521		uint! {
522			let test_cases = [
523				TestCase { value: 0x0_U256, expected: 256_U256 },
524				TestCase { value: 0x1_U256, expected: 255_U256 },
525				TestCase { value: 0x2_U256, expected: 254_U256 },
526				TestCase { value: 0x3_U256, expected: 254_U256 },
527				TestCase { value: 0x4_U256, expected: 253_U256 },
528				TestCase { value: 0x7_U256, expected: 253_U256 },
529				TestCase { value: 0x8_U256, expected: 252_U256 },
530				TestCase { value: 0xff_U256, expected: 248_U256 },
531				TestCase { value: 0x100_U256, expected: 247_U256 },
532				TestCase { value: 0xffff_U256, expected: 240_U256 },
533				TestCase {
534					value: 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256, // U256::MAX
535					expected: 0_U256,
536				},
537				TestCase {
538					value: 0x8000000000000000000000000000000000000000000000000000000000000000_U256, // 1 << 255
539					expected: 0_U256,
540				},
541				TestCase { // Smallest value with 1 leading zero
542					value: 0x4000000000000000000000000000000000000000000000000000000000000000_U256, // 1 << 254
543					expected: 1_U256,
544				},
545				TestCase { // Value just below 1 << 255
546					value: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff_U256,
547					expected: 1_U256,
548				},
549			];
550		}
551
552		for test in test_cases {
553			push!(interpreter, test.value);
554			let context =
555				InstructionContext { host: &mut DummyHost, interpreter: &mut interpreter };
556			clz(context);
557			let res = interpreter.stack.pop().unwrap();
558			assert_eq!(
559				res, test.expected,
560				"CLZ for value {:#x} failed. Expected: {}, Got: {}",
561				test.value, test.expected, res
562			);
563		}
564	}
565}