mirror of
https://github.com/arnaucube/miden-crypto.git
synced 2026-01-10 16:11:30 +01:00
merge v0.10.0 release
This commit is contained in:
@@ -217,15 +217,27 @@ impl Serializable for SecretKey {
|
||||
let mut buffer = Vec::with_capacity(1281);
|
||||
buffer.push(header);
|
||||
|
||||
let f_i8: Vec<i8> = neg_f.coefficients.iter().map(|&a| -a as i8).collect();
|
||||
let f_i8: Vec<i8> = neg_f
|
||||
.coefficients
|
||||
.iter()
|
||||
.map(|&a| FalconFelt::new(-a).balanced_value() as i8)
|
||||
.collect();
|
||||
let f_i8_encoded = encode_i8(&f_i8, WIDTH_SMALL_POLY_COEFFICIENT).unwrap();
|
||||
buffer.extend_from_slice(&f_i8_encoded);
|
||||
|
||||
let g_i8: Vec<i8> = g.coefficients.iter().map(|&a| a as i8).collect();
|
||||
let g_i8: Vec<i8> = g
|
||||
.coefficients
|
||||
.iter()
|
||||
.map(|&a| FalconFelt::new(a).balanced_value() as i8)
|
||||
.collect();
|
||||
let g_i8_encoded = encode_i8(&g_i8, WIDTH_SMALL_POLY_COEFFICIENT).unwrap();
|
||||
buffer.extend_from_slice(&g_i8_encoded);
|
||||
|
||||
let big_f_i8: Vec<i8> = neg_big_f.coefficients.iter().map(|&a| -a as i8).collect();
|
||||
let big_f_i8: Vec<i8> = neg_big_f
|
||||
.coefficients
|
||||
.iter()
|
||||
.map(|&a| FalconFelt::new(-a).balanced_value() as i8)
|
||||
.collect();
|
||||
let big_f_i8_encoded = encode_i8(&big_f_i8, WIDTH_BIG_POLY_COEFFICIENT).unwrap();
|
||||
buffer.extend_from_slice(&big_f_i8_encoded);
|
||||
target.write_bytes(&buffer);
|
||||
|
||||
@@ -6,11 +6,11 @@ pub mod blake;
|
||||
|
||||
mod rescue;
|
||||
pub mod rpo {
|
||||
pub use super::rescue::{Rpo256, RpoDigest};
|
||||
pub use super::rescue::{Rpo256, RpoDigest, RpoDigestError};
|
||||
}
|
||||
|
||||
pub mod rpx {
|
||||
pub use super::rescue::{Rpx256, RpxDigest};
|
||||
pub use super::rescue::{Rpx256, RpxDigest, RpxDigestError};
|
||||
}
|
||||
|
||||
// RE-EXPORTS
|
||||
|
||||
@@ -11,10 +11,10 @@ mod mds;
|
||||
use mds::{apply_mds, MDS};
|
||||
|
||||
mod rpo;
|
||||
pub use rpo::{Rpo256, RpoDigest};
|
||||
pub use rpo::{Rpo256, RpoDigest, RpoDigestError};
|
||||
|
||||
mod rpx;
|
||||
pub use rpx::{Rpx256, RpxDigest};
|
||||
pub use rpx::{Rpx256, RpxDigest, RpxDigestError};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
@@ -118,26 +118,106 @@ impl Randomizable for RpoDigest {
|
||||
// CONVERSIONS: FROM RPO DIGEST
|
||||
// ================================================================================================
|
||||
|
||||
impl From<&RpoDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: &RpoDigest) -> Self {
|
||||
value.0
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RpoDigestError {
|
||||
InvalidInteger,
|
||||
}
|
||||
|
||||
impl TryFrom<&RpoDigest> for [bool; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &RpoDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpoDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: RpoDigest) -> Self {
|
||||
value.0
|
||||
impl TryFrom<RpoDigest> for [bool; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: RpoDigest) -> Result<Self, Self::Error> {
|
||||
fn to_bool(v: u64) -> Option<bool> {
|
||||
if v <= 1 {
|
||||
Some(v == 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Ok([
|
||||
to_bool(value.0[0].as_int()).ok_or(RpoDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[1].as_int()).ok_or(RpoDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[2].as_int()).ok_or(RpoDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[3].as_int()).ok_or(RpoDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpoDigest> for [u8; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &RpoDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpoDigest> for [u8; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: RpoDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpoDigest> for [u16; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &RpoDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpoDigest> for [u16; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: RpoDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpoDigest> for [u32; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &RpoDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpoDigest> for [u32; DIGEST_SIZE] {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: RpoDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpoDigest> for [u64; DIGEST_SIZE] {
|
||||
fn from(value: &RpoDigest) -> Self {
|
||||
[
|
||||
value.0[0].as_int(),
|
||||
value.0[1].as_int(),
|
||||
value.0[2].as_int(),
|
||||
value.0[3].as_int(),
|
||||
]
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,9 +232,21 @@ impl From<RpoDigest> for [u64; DIGEST_SIZE] {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpoDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: &RpoDigest) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpoDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: RpoDigest) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpoDigest> for [u8; DIGEST_BYTES] {
|
||||
fn from(value: &RpoDigest) -> Self {
|
||||
value.as_bytes()
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,13 +256,6 @@ impl From<RpoDigest> for [u8; DIGEST_BYTES] {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpoDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: RpoDigest) -> Self {
|
||||
value.to_hex()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpoDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: &RpoDigest) -> Self {
|
||||
@@ -178,13 +263,83 @@ impl From<&RpoDigest> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpoDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: RpoDigest) -> Self {
|
||||
value.to_hex()
|
||||
}
|
||||
}
|
||||
|
||||
// CONVERSIONS: TO RPO DIGEST
|
||||
// ================================================================================================
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RpoDigestError {
|
||||
/// The provided u64 integer does not fit in the field's moduli.
|
||||
InvalidInteger,
|
||||
impl From<&[bool; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: &[bool; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[bool; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: [bool; DIGEST_SIZE]) -> Self {
|
||||
[value[0] as u32, value[1] as u32, value[2] as u32, value[3] as u32].into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: &[u8; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: [u8; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u16; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: &[u16; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u16; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: [u16; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u32; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: &[u32; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; DIGEST_SIZE]> for RpoDigest {
|
||||
fn from(value: [u32; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u64; DIGEST_SIZE]> for RpoDigest {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &[u64; DIGEST_SIZE]) -> Result<Self, RpoDigestError> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u64; DIGEST_SIZE]> for RpoDigest {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: [u64; DIGEST_SIZE]) -> Result<Self, RpoDigestError> {
|
||||
Ok(Self([
|
||||
value[0].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[1].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[2].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[3].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[Felt; DIGEST_SIZE]> for RpoDigest {
|
||||
@@ -199,6 +354,14 @@ impl From<[Felt; DIGEST_SIZE]> for RpoDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; DIGEST_BYTES]> for RpoDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
fn try_from(value: &[u8; DIGEST_BYTES]) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u8; DIGEST_BYTES]> for RpoDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
@@ -218,14 +381,6 @@ impl TryFrom<[u8; DIGEST_BYTES]> for RpoDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; DIGEST_BYTES]> for RpoDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
fn try_from(value: &[u8; DIGEST_BYTES]) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for RpoDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
@@ -234,33 +389,12 @@ impl TryFrom<&[u8]> for RpoDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u64; DIGEST_SIZE]> for RpoDigest {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: [u64; DIGEST_SIZE]) -> Result<Self, RpoDigestError> {
|
||||
Ok(Self([
|
||||
value[0].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[1].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[2].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
value[3].try_into().map_err(|_| RpoDigestError::InvalidInteger)?,
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u64; DIGEST_SIZE]> for RpoDigest {
|
||||
type Error = RpoDigestError;
|
||||
|
||||
fn try_from(value: &[u64; DIGEST_SIZE]) -> Result<Self, RpoDigestError> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for RpoDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
/// Expects the string to start with `0x`.
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
hex_to_bytes(value).and_then(|v| v.try_into())
|
||||
hex_to_bytes::<DIGEST_BYTES>(value).and_then(RpoDigest::try_from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,44 +507,72 @@ mod tests {
|
||||
Felt::new(rand_value()),
|
||||
]);
|
||||
|
||||
let v: [Felt; DIGEST_SIZE] = digest.into();
|
||||
// BY VALUE
|
||||
// ----------------------------------------------------------------------------------------
|
||||
let v: [bool; DIGEST_SIZE] = [true, false, true, true];
|
||||
let v2: RpoDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
assert_eq!(v, <[bool; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [Felt; DIGEST_SIZE] = (&digest).into();
|
||||
let v: [u8; DIGEST_SIZE] = [0_u8, 1_u8, 2_u8, 3_u8];
|
||||
let v2: RpoDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
assert_eq!(v, <[u8; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u16; DIGEST_SIZE] = [0_u16, 1_u16, 2_u16, 3_u16];
|
||||
let v2: RpoDigest = v.into();
|
||||
assert_eq!(v, <[u16; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u32; DIGEST_SIZE] = [0_u32, 1_u32, 2_u32, 3_u32];
|
||||
let v2: RpoDigest = v.into();
|
||||
assert_eq!(v, <[u32; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = digest.into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
let v: [Felt; DIGEST_SIZE] = digest.into();
|
||||
let v2: RpoDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = digest.into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = (&digest).into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = digest.into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = (&digest).into();
|
||||
let v2: RpoDigest = v.try_into().unwrap();
|
||||
// BY REF
|
||||
// ----------------------------------------------------------------------------------------
|
||||
let v: [bool; DIGEST_SIZE] = [true, false, true, true];
|
||||
let v2: RpoDigest = (&v).into();
|
||||
assert_eq!(v, <[bool; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u8; DIGEST_SIZE] = [0_u8, 1_u8, 2_u8, 3_u8];
|
||||
let v2: RpoDigest = (&v).into();
|
||||
assert_eq!(v, <[u8; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u16; DIGEST_SIZE] = [0_u16, 1_u16, 2_u16, 3_u16];
|
||||
let v2: RpoDigest = (&v).into();
|
||||
assert_eq!(v, <[u16; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u32; DIGEST_SIZE] = [0_u32, 1_u32, 2_u32, 3_u32];
|
||||
let v2: RpoDigest = (&v).into();
|
||||
assert_eq!(v, <[u32; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpoDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = digest.into();
|
||||
let v2: RpoDigest = (&v).try_into().unwrap();
|
||||
let v: [Felt; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpoDigest = (&v).into();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = (&digest).into();
|
||||
let v2: RpoDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = (&digest).into();
|
||||
let v2: RpoDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ use super::{
|
||||
};
|
||||
|
||||
mod digest;
|
||||
pub use digest::RpoDigest;
|
||||
pub use digest::{RpoDigest, RpoDigestError};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
@@ -22,9 +22,10 @@ mod tests;
|
||||
/// [specifications](https://eprint.iacr.org/2022/1577)
|
||||
///
|
||||
/// The parameters used to instantiate the function are:
|
||||
/// * Field: 64-bit prime field with modulus 2^64 - 2^32 + 1.
|
||||
/// * Field: 64-bit prime field with modulus p = 2^64 - 2^32 + 1.
|
||||
/// * State width: 12 field elements.
|
||||
/// * Capacity size: 4 field elements.
|
||||
/// * Rate size: r = 8 field elements.
|
||||
/// * Capacity size: c = 4 field elements.
|
||||
/// * Number of founds: 7.
|
||||
/// * S-Box degree: 7.
|
||||
///
|
||||
@@ -52,6 +53,17 @@ mod tests;
|
||||
/// to deserialize them into field elements and then hash them using
|
||||
/// [hash_elements()](Rpo256::hash_elements) function rather then hashing the serialized bytes
|
||||
/// using [hash()](Rpo256::hash) function.
|
||||
///
|
||||
/// ## Domain separation
|
||||
/// [merge_in_domain()](Rpo256::merge_in_domain) hashes two digests into one digest with some domain
|
||||
/// identifier and the current implementation sets the second capacity element to the value of
|
||||
/// this domain identifier. Using a similar argument to the one formulated for domain separation of
|
||||
/// the RPX hash function in Appendix C of its [specification](https://eprint.iacr.org/2023/1045),
|
||||
/// one sees that doing so degrades only pre-image resistance, from its initial bound of c.log_2(p),
|
||||
/// by as much as the log_2 of the size of the domain identifier space. Since pre-image resistance
|
||||
/// becomes the bottleneck for the security bound of the sponge in overwrite-mode only when it is
|
||||
/// lower than 2^128, we see that the target 128-bit security level is maintained as long as
|
||||
/// the size of the domain identifier space, including for padding, is less than 2^128.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct Rpo256();
|
||||
|
||||
|
||||
@@ -118,26 +118,106 @@ impl Randomizable for RpxDigest {
|
||||
// CONVERSIONS: FROM RPX DIGEST
|
||||
// ================================================================================================
|
||||
|
||||
impl From<&RpxDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: &RpxDigest) -> Self {
|
||||
value.0
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RpxDigestError {
|
||||
InvalidInteger,
|
||||
}
|
||||
|
||||
impl TryFrom<&RpxDigest> for [bool; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &RpxDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpxDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: RpxDigest) -> Self {
|
||||
value.0
|
||||
impl TryFrom<RpxDigest> for [bool; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: RpxDigest) -> Result<Self, Self::Error> {
|
||||
fn to_bool(v: u64) -> Option<bool> {
|
||||
if v <= 1 {
|
||||
Some(v == 1)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Ok([
|
||||
to_bool(value.0[0].as_int()).ok_or(RpxDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[1].as_int()).ok_or(RpxDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[2].as_int()).ok_or(RpxDigestError::InvalidInteger)?,
|
||||
to_bool(value.0[3].as_int()).ok_or(RpxDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpxDigest> for [u8; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &RpxDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpxDigest> for [u8; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: RpxDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpxDigest> for [u16; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &RpxDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpxDigest> for [u16; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: RpxDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&RpxDigest> for [u32; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &RpxDigest) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<RpxDigest> for [u32; DIGEST_SIZE] {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: RpxDigest) -> Result<Self, Self::Error> {
|
||||
Ok([
|
||||
value.0[0].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[1].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[2].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value.0[3].as_int().try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpxDigest> for [u64; DIGEST_SIZE] {
|
||||
fn from(value: &RpxDigest) -> Self {
|
||||
[
|
||||
value.0[0].as_int(),
|
||||
value.0[1].as_int(),
|
||||
value.0[2].as_int(),
|
||||
value.0[3].as_int(),
|
||||
]
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,6 +232,18 @@ impl From<RpxDigest> for [u64; DIGEST_SIZE] {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpxDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: &RpxDigest) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpxDigest> for [Felt; DIGEST_SIZE] {
|
||||
fn from(value: RpxDigest) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpxDigest> for [u8; DIGEST_BYTES] {
|
||||
fn from(value: &RpxDigest) -> Self {
|
||||
value.as_bytes()
|
||||
@@ -164,13 +256,6 @@ impl From<RpxDigest> for [u8; DIGEST_BYTES] {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpxDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: RpxDigest) -> Self {
|
||||
value.to_hex()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&RpxDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: &RpxDigest) -> Self {
|
||||
@@ -178,13 +263,83 @@ impl From<&RpxDigest> for String {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<RpxDigest> for String {
|
||||
/// The returned string starts with `0x`.
|
||||
fn from(value: RpxDigest) -> Self {
|
||||
value.to_hex()
|
||||
}
|
||||
}
|
||||
|
||||
// CONVERSIONS: TO RPX DIGEST
|
||||
// ================================================================================================
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum RpxDigestError {
|
||||
/// The provided u64 integer does not fit in the field's moduli.
|
||||
InvalidInteger,
|
||||
impl From<&[bool; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: &[bool; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[bool; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: [bool; DIGEST_SIZE]) -> Self {
|
||||
[value[0] as u32, value[1] as u32, value[2] as u32, value[3] as u32].into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u8; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: &[u8; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: [u8; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u16; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: &[u16; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u16; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: [u16; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[u32; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: &[u32; DIGEST_SIZE]) -> Self {
|
||||
(*value).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u32; DIGEST_SIZE]> for RpxDigest {
|
||||
fn from(value: [u32; DIGEST_SIZE]) -> Self {
|
||||
Self([value[0].into(), value[1].into(), value[2].into(), value[3].into()])
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u64; DIGEST_SIZE]> for RpxDigest {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &[u64; DIGEST_SIZE]) -> Result<Self, RpxDigestError> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u64; DIGEST_SIZE]> for RpxDigest {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: [u64; DIGEST_SIZE]) -> Result<Self, RpxDigestError> {
|
||||
Ok(Self([
|
||||
value[0].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[1].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[2].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[3].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&[Felt; DIGEST_SIZE]> for RpxDigest {
|
||||
@@ -199,6 +354,14 @@ impl From<[Felt; DIGEST_SIZE]> for RpxDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; DIGEST_BYTES]> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
fn try_from(value: &[u8; DIGEST_BYTES]) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u8; DIGEST_BYTES]> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
@@ -218,14 +381,6 @@ impl TryFrom<[u8; DIGEST_BYTES]> for RpxDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8; DIGEST_BYTES]> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
fn try_from(value: &[u8; DIGEST_BYTES]) -> Result<Self, Self::Error> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
@@ -234,42 +389,12 @@ impl TryFrom<&[u8]> for RpxDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<[u64; DIGEST_SIZE]> for RpxDigest {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: [u64; DIGEST_SIZE]) -> Result<Self, RpxDigestError> {
|
||||
Ok(Self([
|
||||
value[0].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[1].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[2].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
value[3].try_into().map_err(|_| RpxDigestError::InvalidInteger)?,
|
||||
]))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u64; DIGEST_SIZE]> for RpxDigest {
|
||||
type Error = RpxDigestError;
|
||||
|
||||
fn try_from(value: &[u64; DIGEST_SIZE]) -> Result<Self, RpxDigestError> {
|
||||
(*value).try_into()
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
/// Expects the string to start with `0x`.
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
hex_to_bytes(value).and_then(|v| v.try_into())
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
/// Expects the string to start with `0x`.
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
value.as_str().try_into()
|
||||
hex_to_bytes::<DIGEST_BYTES>(value).and_then(RpxDigest::try_from)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -282,6 +407,15 @@ impl TryFrom<&String> for RpxDigest {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for RpxDigest {
|
||||
type Error = HexParseError;
|
||||
|
||||
/// Expects the string to start with `0x`.
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
value.as_str().try_into()
|
||||
}
|
||||
}
|
||||
|
||||
// SERIALIZATION / DESERIALIZATION
|
||||
// ================================================================================================
|
||||
|
||||
@@ -308,6 +442,17 @@ impl Deserializable for RpxDigest {
|
||||
}
|
||||
}
|
||||
|
||||
// ITERATORS
|
||||
// ================================================================================================
|
||||
impl IntoIterator for RpxDigest {
|
||||
type Item = Felt;
|
||||
type IntoIter = <[Felt; 4] as IntoIterator>::IntoIter;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.0.into_iter()
|
||||
}
|
||||
}
|
||||
|
||||
// TESTS
|
||||
// ================================================================================================
|
||||
|
||||
@@ -338,7 +483,6 @@ mod tests {
|
||||
assert_eq!(d1, d2);
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn digest_encoding() {
|
||||
let digest = RpxDigest([
|
||||
@@ -363,44 +507,72 @@ mod tests {
|
||||
Felt::new(rand_value()),
|
||||
]);
|
||||
|
||||
let v: [Felt; DIGEST_SIZE] = digest.into();
|
||||
// BY VALUE
|
||||
// ----------------------------------------------------------------------------------------
|
||||
let v: [bool; DIGEST_SIZE] = [true, false, true, true];
|
||||
let v2: RpxDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
assert_eq!(v, <[bool; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [Felt; DIGEST_SIZE] = (&digest).into();
|
||||
let v: [u8; DIGEST_SIZE] = [0_u8, 1_u8, 2_u8, 3_u8];
|
||||
let v2: RpxDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
assert_eq!(v, <[u8; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u16; DIGEST_SIZE] = [0_u16, 1_u16, 2_u16, 3_u16];
|
||||
let v2: RpxDigest = v.into();
|
||||
assert_eq!(v, <[u16; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u32; DIGEST_SIZE] = [0_u32, 1_u32, 2_u32, 3_u32];
|
||||
let v2: RpxDigest = v.into();
|
||||
assert_eq!(v, <[u32; DIGEST_SIZE]>::try_from(v2).unwrap());
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = digest.into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
let v: [Felt; DIGEST_SIZE] = digest.into();
|
||||
let v2: RpxDigest = v.into();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = digest.into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = (&digest).into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = digest.into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = (&digest).into();
|
||||
let v2: RpxDigest = v.try_into().unwrap();
|
||||
// BY REF
|
||||
// ----------------------------------------------------------------------------------------
|
||||
let v: [bool; DIGEST_SIZE] = [true, false, true, true];
|
||||
let v2: RpxDigest = (&v).into();
|
||||
assert_eq!(v, <[bool; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u8; DIGEST_SIZE] = [0_u8, 1_u8, 2_u8, 3_u8];
|
||||
let v2: RpxDigest = (&v).into();
|
||||
assert_eq!(v, <[u8; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u16; DIGEST_SIZE] = [0_u16, 1_u16, 2_u16, 3_u16];
|
||||
let v2: RpxDigest = (&v).into();
|
||||
assert_eq!(v, <[u16; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u32; DIGEST_SIZE] = [0_u32, 1_u32, 2_u32, 3_u32];
|
||||
let v2: RpxDigest = (&v).into();
|
||||
assert_eq!(v, <[u32; DIGEST_SIZE]>::try_from(&v2).unwrap());
|
||||
|
||||
let v: [u64; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpxDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = digest.into();
|
||||
let v2: RpxDigest = (&v).try_into().unwrap();
|
||||
let v: [Felt; DIGEST_SIZE] = (&digest).into();
|
||||
let v2: RpxDigest = (&v).into();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: [u8; DIGEST_BYTES] = (&digest).into();
|
||||
let v2: RpxDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
|
||||
let v: String = (&digest).into();
|
||||
let v2: RpxDigest = (&v).try_into().unwrap();
|
||||
assert_eq!(digest, v2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ use super::{
|
||||
};
|
||||
|
||||
mod digest;
|
||||
pub use digest::RpxDigest;
|
||||
pub use digest::{RpxDigest, RpxDigestError};
|
||||
|
||||
pub type CubicExtElement = CubeExtension<Felt>;
|
||||
|
||||
@@ -55,6 +55,17 @@ pub type CubicExtElement = CubeExtension<Felt>;
|
||||
/// to deserialize them into field elements and then hash them using
|
||||
/// [hash_elements()](Rpx256::hash_elements) function rather then hashing the serialized bytes
|
||||
/// using [hash()](Rpx256::hash) function.
|
||||
///
|
||||
/// ## Domain separation
|
||||
/// [merge_in_domain()](Rpx256::merge_in_domain) hashes two digests into one digest with some domain
|
||||
/// identifier and the current implementation sets the second capacity element to the value of
|
||||
/// this domain identifier. Using a similar argument to the one formulated for domain separation
|
||||
/// in Appendix C of the [specifications](https://eprint.iacr.org/2023/1045), one sees that doing
|
||||
/// so degrades only pre-image resistance, from its initial bound of c.log_2(p), by as much as
|
||||
/// the log_2 of the size of the domain identifier space. Since pre-image resistance becomes
|
||||
/// the bottleneck for the security bound of the sponge in overwrite-mode only when it is
|
||||
/// lower than 2^128, we see that the target 128-bit security level is maintained as long as
|
||||
/// the size of the domain identifier space, including for padding, is less than 2^128.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
|
||||
pub struct Rpx256();
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use alloc::{string::String, vec::Vec};
|
||||
use core::{fmt, ops::Deref, slice};
|
||||
|
||||
use winter_math::log2;
|
||||
|
||||
use super::{InnerNodeInfo, MerkleError, MerklePath, NodeIndex, Rpo256, RpoDigest, Word};
|
||||
use crate::utils::{uninit_vector, word_to_hex};
|
||||
|
||||
@@ -70,7 +68,7 @@ impl MerkleTree {
|
||||
///
|
||||
/// Merkle tree of depth 1 has two leaves, depth 2 has four leaves etc.
|
||||
pub fn depth(&self) -> u8 {
|
||||
log2(self.nodes.len() / 2) as u8
|
||||
(self.nodes.len() / 2).ilog2() as u8
|
||||
}
|
||||
|
||||
/// Returns a node at the specified depth and index value.
|
||||
|
||||
@@ -214,7 +214,7 @@ impl PartialMerkleTree {
|
||||
/// # Errors
|
||||
/// Returns an error if:
|
||||
/// - the specified index has depth set to 0 or the depth is greater than the depth of this
|
||||
/// Merkle tree.
|
||||
/// Merkle tree.
|
||||
/// - the specified index is not contained in the nodes map.
|
||||
pub fn get_path(&self, mut index: NodeIndex) -> Result<MerklePath, MerkleError> {
|
||||
if index.is_root() {
|
||||
|
||||
@@ -287,8 +287,7 @@ fn test_empty_leaf_hash() {
|
||||
#[test]
|
||||
fn test_smt_get_value() {
|
||||
let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, ONE]);
|
||||
let key_2: RpoDigest =
|
||||
RpoDigest::from([2_u32.into(), 2_u32.into(), 2_u32.into(), 2_u32.into()]);
|
||||
let key_2: RpoDigest = RpoDigest::from([2_u32, 2_u32, 2_u32, 2_u32]);
|
||||
|
||||
let value_1 = [ONE; WORD_SIZE];
|
||||
let value_2 = [2_u32.into(); WORD_SIZE];
|
||||
@@ -302,8 +301,7 @@ fn test_smt_get_value() {
|
||||
assert_eq!(value_2, returned_value_2);
|
||||
|
||||
// Check that a key with no inserted value returns the empty word
|
||||
let key_no_value =
|
||||
RpoDigest::from([42_u32.into(), 42_u32.into(), 42_u32.into(), 42_u32.into()]);
|
||||
let key_no_value = RpoDigest::from([42_u32, 42_u32, 42_u32, 42_u32]);
|
||||
|
||||
assert_eq!(EMPTY_WORD, smt.get_value(&key_no_value));
|
||||
}
|
||||
@@ -312,8 +310,7 @@ fn test_smt_get_value() {
|
||||
#[test]
|
||||
fn test_smt_entries() {
|
||||
let key_1: RpoDigest = RpoDigest::from([ONE, ONE, ONE, ONE]);
|
||||
let key_2: RpoDigest =
|
||||
RpoDigest::from([2_u32.into(), 2_u32.into(), 2_u32.into(), 2_u32.into()]);
|
||||
let key_2: RpoDigest = RpoDigest::from([2_u32, 2_u32, 2_u32, 2_u32]);
|
||||
|
||||
let value_1 = [ONE; WORD_SIZE];
|
||||
let value_2 = [2_u32.into(); WORD_SIZE];
|
||||
@@ -347,7 +344,7 @@ fn test_empty_smt_leaf_serialization() {
|
||||
#[test]
|
||||
fn test_single_smt_leaf_serialization() {
|
||||
let single_leaf = SmtLeaf::new_single(
|
||||
RpoDigest::from([10_u32.into(), 11_u32.into(), 12_u32.into(), 13_u32.into()]),
|
||||
RpoDigest::from([10_u32, 11_u32, 12_u32, 13_u32]),
|
||||
[1_u32.into(), 2_u32.into(), 3_u32.into(), 4_u32.into()],
|
||||
);
|
||||
|
||||
@@ -363,11 +360,11 @@ fn test_single_smt_leaf_serialization() {
|
||||
fn test_multiple_smt_leaf_serialization_success() {
|
||||
let multiple_leaf = SmtLeaf::new_multiple(vec![
|
||||
(
|
||||
RpoDigest::from([10_u32.into(), 11_u32.into(), 12_u32.into(), 13_u32.into()]),
|
||||
RpoDigest::from([10_u32, 11_u32, 12_u32, 13_u32]),
|
||||
[1_u32.into(), 2_u32.into(), 3_u32.into(), 4_u32.into()],
|
||||
),
|
||||
(
|
||||
RpoDigest::from([100_u32.into(), 101_u32.into(), 102_u32.into(), 13_u32.into()]),
|
||||
RpoDigest::from([100_u32, 101_u32, 102_u32, 13_u32]),
|
||||
[11_u32.into(), 12_u32.into(), 13_u32.into(), 14_u32.into()],
|
||||
),
|
||||
])
|
||||
|
||||
@@ -126,11 +126,10 @@ impl<K: Ord + Clone, V: Clone> KvMap<K, V> for RecordingMap<K, V> {
|
||||
///
|
||||
/// If the key is part of the initial data set, the key access is recorded.
|
||||
fn get(&self, key: &K) -> Option<&V> {
|
||||
self.data.get(key).map(|value| {
|
||||
self.data.get(key).inspect(|&value| {
|
||||
if !self.updates.contains(key) {
|
||||
self.trace.borrow_mut().insert(key.clone(), value.clone());
|
||||
}
|
||||
value
|
||||
})
|
||||
}
|
||||
|
||||
@@ -155,11 +154,10 @@ impl<K: Ord + Clone, V: Clone> KvMap<K, V> for RecordingMap<K, V> {
|
||||
/// returned.
|
||||
fn insert(&mut self, key: K, value: V) -> Option<V> {
|
||||
let new_update = self.updates.insert(key.clone());
|
||||
self.data.insert(key.clone(), value).map(|old_value| {
|
||||
self.data.insert(key.clone(), value).inspect(|old_value| {
|
||||
if new_update {
|
||||
self.trace.borrow_mut().insert(key, old_value.clone());
|
||||
}
|
||||
old_value
|
||||
})
|
||||
}
|
||||
|
||||
@@ -167,12 +165,11 @@ impl<K: Ord + Clone, V: Clone> KvMap<K, V> for RecordingMap<K, V> {
|
||||
///
|
||||
/// If the key exists in the data set, the old value is returned.
|
||||
fn remove(&mut self, key: &K) -> Option<V> {
|
||||
self.data.remove(key).map(|old_value| {
|
||||
self.data.remove(key).inspect(|old_value| {
|
||||
let new_update = self.updates.insert(key.clone());
|
||||
if new_update {
|
||||
self.trace.borrow_mut().insert(key.clone(), old_value.clone());
|
||||
}
|
||||
old_value
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -58,13 +58,13 @@ impl Display for HexParseError {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
HexParseError::InvalidLength { expected, actual } => {
|
||||
write!(f, "Hex encoded RpoDigest must have length 66, including the 0x prefix. expected {expected} got {actual}")
|
||||
write!(f, "Expected hex data to have length {expected}, including the 0x prefix. Got {actual}")
|
||||
}
|
||||
HexParseError::MissingPrefix => {
|
||||
write!(f, "Hex encoded RpoDigest must start with 0x prefix")
|
||||
write!(f, "Hex encoded data must start with 0x prefix")
|
||||
}
|
||||
HexParseError::InvalidChar => {
|
||||
write!(f, "Hex encoded RpoDigest must contain characters [a-zA-Z0-9]")
|
||||
write!(f, "Hex encoded data must contain characters [a-zA-Z0-9]")
|
||||
}
|
||||
HexParseError::OutOfRange => {
|
||||
write!(f, "Hex encoded values of an RpoDigest must be inside the field modulus")
|
||||
|
||||
Reference in New Issue
Block a user