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