Debug + Display for Field

This commit is contained in:
Remco Bloemen 2022-03-18 15:13:06 -07:00
parent 4fdb8ff9f5
commit a21ae33661
3 changed files with 56 additions and 26 deletions

View File

@ -1,7 +1,11 @@
use crate::util::{bytes_from_hex, deserialize_bytes, keccak256, serialize_bytes};
use crate::util::{bytes_from_hex, bytes_to_hex, deserialize_bytes, keccak256, serialize_bytes};
use ark_bn254::Fr as ArkField;
use ark_ff::{BigInteger as _, PrimeField as _};
use core::{str, str::FromStr};
use core::{
fmt::{Debug, Display},
str,
str::FromStr,
};
use ff::{PrimeField as _, PrimeFieldRepr as _};
use num_bigint::{BigInt, Sign};
use poseidon_rs::Fr as PosField;
@ -10,7 +14,7 @@ use serde::{Deserialize, Deserializer, Serialize, Serializer};
/// An element of the BN254 scalar field Fr.
///
/// Represented as a big-endian byte vector without Montgomery reduction.
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
// TODO: Make sure value is always reduced.
pub struct Field([u8; 32]);
@ -69,6 +73,22 @@ impl From<Field> for BigInt {
}
}
impl Debug for Field {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let hex = bytes_to_hex::<32, 66>(&self.0);
let hex_str = str::from_utf8(&hex).expect("hex is always valid utf8");
write!(f, "Field({})", hex_str)
}
}
impl Display for Field {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let hex = bytes_to_hex::<32, 66>(&self.0);
let hex_str = str::from_utf8(&hex).expect("hex is always valid utf8");
write!(f, "{}", hex_str)
}
}
/// Serialize a field element.
///
/// For human readable formats a `0x` prefixed lower case hex string is used.

View File

@ -1,11 +1,12 @@
use crate::util::{bytes_from_hex, deserialize_bytes, serialize_bytes};
use crate::util::{bytes_from_hex, bytes_to_hex, deserialize_bytes, serialize_bytes};
use core::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
str,
str::FromStr,
};
use ethers_core::types::U256;
use num_bigint::{BigInt, Sign};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::{
fmt::{Debug, Display, Formatter, Result as FmtResult},
str::FromStr,
};
/// Container for 256-bit hash values.
#[derive(Clone, Copy, PartialEq, Eq, Default)]
@ -23,20 +24,6 @@ impl Hash {
}
}
/// Debug print hashes using `hex!(..)` literals.
impl Debug for Hash {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "Hash(hex!(\"{}\"))", hex::encode(&self.0))
}
}
/// Display print hashes as `0x...`.
impl Display for Hash {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
write!(f, "0x{}", hex::encode(&self.0))
}
}
/// Conversion from Ether U256
impl From<&Hash> for U256 {
fn from(hash: &Hash) -> Self {
@ -75,6 +62,22 @@ impl From<&Hash> for BigInt {
}
}
impl Debug for Hash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let hex = bytes_to_hex::<32, 66>(&self.0);
let hex_str = str::from_utf8(&hex).expect("hex is always valid utf8");
write!(f, "Field({})", hex_str)
}
}
impl Display for Hash {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let hex = bytes_to_hex::<32, 66>(&self.0);
let hex_str = str::from_utf8(&hex).expect("hex is always valid utf8");
write!(f, "{}", hex_str)
}
}
/// Parse Hash from hex string.
/// Hex strings can be upper/lower/mixed case and have an optional `0x` prefix
/// but they must always be exactly 32 bytes.

View File

@ -16,6 +16,16 @@ pub(crate) fn keccak256(bytes: &[u8]) -> [u8; 32] {
output
}
pub(crate) fn bytes_to_hex<const N: usize, const M: usize>(bytes: &[u8; N]) -> [u8; M] {
// TODO: Replace `M` with a const expression once it's stable.
debug_assert_eq!(M, 2 * N + 2);
let mut result = [0u8; M];
result[0] = b'0';
result[1] = b'x';
hex::encode_to_slice(&bytes[..], &mut result[2..]).expect("the buffer is correctly sized");
result
}
/// Helper to serialize byte arrays
pub(crate) fn serialize_bytes<const N: usize, const M: usize, S: Serializer>(
serializer: S,
@ -25,10 +35,7 @@ pub(crate) fn serialize_bytes<const N: usize, const M: usize, S: Serializer>(
debug_assert_eq!(M, 2 * N + 2);
if serializer.is_human_readable() {
// Write as a 0x prefixed lower-case hex string
let mut buffer = [0u8; M];
buffer[0] = b'0';
buffer[1] = b'x';
hex::encode_to_slice(&bytes[..], &mut buffer[2..]).expect("the buffer is correctly sized");
let buffer = bytes_to_hex::<N, M>(bytes);
let string = str::from_utf8(&buffer).expect("the buffer is valid UTF-8");
serializer.serialize_str(string)
} else {