Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(precompile): add a bool to bytes32 helper function #1170

Merged
merged 1 commit into from
Mar 8, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 3 additions & 5 deletions crates/precompile/src/bn128.rs
@@ -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
@@ -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);
}
}