Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
feat(precompile): add a bool to bytes32 helper function
  • Loading branch information
DaniPopes committed Mar 8, 2024
commit 43f4769ab14e3b72821550e7ae648756c797132e
8 changes: 3 additions & 5 deletions crates/precompile/src/bn128.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::{
utilities::right_pad, Address, Error, Precompile, PrecompileResult, PrecompileWithAddress,
utilities::{bool_to_bytes32, right_pad},
Address, Error, Precompile, PrecompileResult, PrecompileWithAddress,
};
use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2};
use revm_primitives::Bytes;
Expand Down Expand Up @@ -222,10 +223,7 @@ fn run_pair(

mul == Gt::one()
};

let mut out = [0u8; 32];
out[31] = success as u8;
Ok((gas_used, out.into()))
Ok((gas_used, bool_to_bytes32(success)))
}

/*
Expand Down
45 changes: 39 additions & 6 deletions crates/precompile/src/utilities.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,26 @@
use revm_primitives::{b256, Bytes, B256};
use std::borrow::Cow;

/// Right-pads the given slice at `offset` with zeroes until `LEN`.
///
/// Returns the first `LEN` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn right_pad_with_offset<const LEN: usize>(data: &[u8], offset: usize) -> Cow<'_, [u8; LEN]> {
right_pad(data.get(offset..).unwrap_or_default())
}

/// Right-pads the given slice at `offset` with zeroes until `len`.
///
/// Returns the first `len` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn right_pad_with_offset_vec(data: &[u8], offset: usize, len: usize) -> Cow<'_, [u8]> {
right_pad_vec(data.get(offset..).unwrap_or_default(), len)
}

/// Right-pads the given slice with zeroes until `LEN`.
///
/// Returns the first `LEN` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn right_pad<const LEN: usize>(data: &[u8]) -> Cow<'_, [u8; LEN]> {
if let Some(data) = data.get(..LEN) {
Cow::Borrowed(data.try_into().unwrap())
Expand All @@ -33,7 +34,7 @@ pub fn right_pad<const LEN: usize>(data: &[u8]) -> Cow<'_, [u8; LEN]> {
/// Right-pads the given slice with zeroes until `len`.
///
/// Returns the first `len` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn right_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> {
if let Some(data) = data.get(..len) {
Cow::Borrowed(data)
Expand All @@ -47,7 +48,7 @@ pub fn right_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> {
/// Left-pads the given slice with zeroes until `LEN`.
///
/// Returns the first `LEN` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn left_pad<const LEN: usize>(data: &[u8]) -> Cow<'_, [u8; LEN]> {
if let Some(data) = data.get(..LEN) {
Cow::Borrowed(data.try_into().unwrap())
Expand All @@ -61,7 +62,7 @@ pub fn left_pad<const LEN: usize>(data: &[u8]) -> Cow<'_, [u8; LEN]> {
/// Left-pads the given slice with zeroes until `len`.
///
/// Returns the first `len` bytes if it does not need padding.
#[inline(always)]
#[inline]
pub fn left_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> {
if let Some(data) = data.get(..len) {
Cow::Borrowed(data)
Expand All @@ -72,6 +73,28 @@ pub fn left_pad_vec(data: &[u8], len: usize) -> Cow<'_, [u8]> {
}
}

/// Converts a boolean to a left-padded 32-byte `Bytes` value.
///
/// This is optimized to not allocate at runtime by using 2 static arrays.
#[inline]
pub const fn bool_to_bytes32(value: bool) -> Bytes {
Bytes::from_static(&bool_to_b256(value).0)
}

/// Converts a boolean to a left-padded `B256` value.
///
/// This is optimized to not allocate at runtime by using 2 static arrays.
#[inline]
pub const fn bool_to_b256(value: bool) -> &'static B256 {
const TRUE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000001");
const FALSE: &B256 = &b256!("0000000000000000000000000000000000000000000000000000000000000000");
if value {
TRUE
} else {
FALSE
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -140,4 +163,14 @@ mod tests {
assert!(matches!(padded, Cow::Borrowed(_)));
assert_eq!(padded[..], [1, 2, 3, 4, 5, 6, 7, 8]);
}

#[test]
fn bool2bytes() {
let f = bool_to_bytes32(false);
assert_eq!(f[..], [0; 32]);
let t = bool_to_bytes32(true);
assert_eq!(t.len(), 32);
assert_eq!(t[..31], [0; 31]);
assert_eq!(t[31], 1);
}
}