Skip to content
Open
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
12 changes: 6 additions & 6 deletions src/jet/type_name.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,12 @@ impl TypeName {
for c in self.0.iter().rev() {
match c {
b'1' => stack.push(Final::unit()),
b'2' => stack.push(Final::two_two_n(0)),
b'c' => stack.push(Final::two_two_n(3)),
b's' => stack.push(Final::two_two_n(4)),
b'i' => stack.push(Final::two_two_n(5)),
b'l' => stack.push(Final::two_two_n(6)),
b'h' => stack.push(Final::two_two_n(8)),
b'2' => stack.push(Final::two_two_n_fixed::<0>()),
b'c' => stack.push(Final::two_two_n_fixed::<3>()),
b's' => stack.push(Final::two_two_n_fixed::<4>()),
b'i' => stack.push(Final::two_two_n_fixed::<5>()),
b'l' => stack.push(Final::two_two_n_fixed::<6>()),
b'h' => stack.push(Final::two_two_n_fixed::<8>()),
b'+' | b'*' => {
let left = stack.pop().expect("Illegal type name syntax!");
let right = stack.pop().expect("Illegal type name syntax!");
Expand Down
164 changes: 163 additions & 1 deletion src/merkle/tmr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,129 @@ impl Tmr {
])),
];

/// The TMRs of the types (TWO^8)^<(2^(N + 1)) for small values of n
#[rustfmt::skip]
pub const BUFFER8_TWO_N_PLUS_ONE: [Tmr; 16] = [
Tmr(Midstate([
0x66, 0x8c, 0x79, 0xa6, 0xf0, 0xe0, 0x86, 0xa6,
0x2d, 0x73, 0xf0, 0xc6, 0x52, 0xb1, 0x5c, 0x56,
0xb1, 0xd3, 0x53, 0x68, 0xe1, 0xff, 0xad, 0x76,
0xc9, 0xd4, 0xdb, 0xae, 0xb5, 0x2d, 0xe6, 0x2f,
])),
Tmr(Midstate([
0x9f, 0x91, 0xf5, 0x19, 0x9b, 0xb8, 0x16, 0x7a,
0x3b, 0x6c, 0xf8, 0xd0, 0x39, 0x75, 0x6e, 0x1b,
0x33, 0x18, 0x42, 0x6e, 0xef, 0x3a, 0x9b, 0xa0,
0x90, 0x2c, 0x91, 0xdc, 0x5f, 0x7e, 0x63, 0x39,
])),
Tmr(Midstate([
0x16, 0x98, 0x45, 0xb0, 0xe2, 0xf0, 0x4a, 0x83,
0x76, 0xfe, 0x91, 0x14, 0xbd, 0x35, 0x3a, 0x29,
0xe9, 0xb7, 0x80, 0x42, 0xb7, 0x70, 0x1b, 0xa1,
0x6d, 0x02, 0xc4, 0x62, 0x18, 0xef, 0x8b, 0xdf,
])),
Tmr(Midstate([
0xbd, 0x59, 0x57, 0x8c, 0x45, 0x78, 0xfe, 0xc4,
0xef, 0x2a, 0x29, 0xc1, 0xad, 0xea, 0x4c, 0xe1,
0x30, 0x6c, 0x1a, 0x2b, 0x10, 0xd6, 0x18, 0xbc,
0x58, 0x44, 0x67, 0x84, 0x17, 0x97, 0x3b, 0x8e,
])),
Tmr(Midstate([
0x88, 0xd1, 0x8c, 0x11, 0x5f, 0x86, 0x54, 0x40,
0x5f, 0xd7, 0x1d, 0xe8, 0x7e, 0x6f, 0xf0, 0x80,
0x6c, 0x5d, 0xa7, 0x97, 0xca, 0xaf, 0x48, 0xe2,
0x47, 0xea, 0xcc, 0x43, 0x99, 0x96, 0x89, 0x1a,
])),
Tmr(Midstate([
0x90, 0x65, 0x22, 0xe1, 0x6d, 0xf3, 0x6f, 0x83,
0xa4, 0x50, 0x32, 0x8a, 0xf8, 0x4e, 0x2f, 0x3e,
0x52, 0xf6, 0xd6, 0x49, 0xa7, 0x88, 0xe3, 0xb2,
0x1c, 0xca, 0xe3, 0xcd, 0x9a, 0x24, 0x66, 0x77,
])),
Tmr(Midstate([
0x3a, 0xba, 0x4c, 0xce, 0x0e, 0x46, 0xc5, 0x54,
0xb4, 0x4f, 0x70, 0x21, 0x3d, 0x4d, 0x8b, 0xd8,
0xe8, 0xf1, 0x7e, 0x2b, 0xd1, 0x7b, 0xdf, 0xb7,
0x15, 0x0a, 0xdf, 0xfd, 0x9a, 0xdf, 0x80, 0x9d,
])),
Tmr(Midstate([
0x7d, 0x81, 0x2a, 0xf0, 0x44, 0xcb, 0x04, 0xd2,
0xaf, 0x4f, 0xc8, 0xe9, 0xb5, 0x30, 0x66, 0x03,
0x9b, 0xd5, 0x89, 0x2a, 0x56, 0xa5, 0xd5, 0x64,
0x1c, 0x5c, 0x58, 0xc8, 0x6e, 0xed, 0x8a, 0x35,
])),
Tmr(Midstate([
0x23, 0x0e, 0xa9, 0x70, 0x03, 0x3e, 0x47, 0xc5,
0x61, 0x68, 0x1e, 0xe7, 0x20, 0x58, 0xb9, 0xc0,
0x75, 0x5b, 0x8d, 0x87, 0x22, 0x80, 0x18, 0x4f,
0x2e, 0x3f, 0xe3, 0x93, 0xc0, 0x47, 0x8f, 0x1a,
])),
Tmr(Midstate([
0x6e, 0x90, 0x88, 0x04, 0x20, 0x46, 0x2b, 0x84,
0xf2, 0x16, 0x30, 0x2a, 0x09, 0x56, 0x9c, 0xc8,
0xd4, 0x47, 0x54, 0x4a, 0xcd, 0x8a, 0xbc, 0x53,
0xd8, 0xa7, 0xcf, 0x21, 0x9b, 0x44, 0x9c, 0x95,
])),
Tmr(Midstate([
0x7a, 0xd1, 0x5d, 0xed, 0x85, 0x02, 0xa6, 0xf1,
0x1e, 0xb8, 0xa4, 0x9b, 0x25, 0xc8, 0xd7, 0x62,
0xa0, 0xfe, 0x00, 0x4f, 0xb5, 0x7d, 0x73, 0x43,
0xbd, 0xf4, 0x90, 0xed, 0x7e, 0xd2, 0xf4, 0x07,
])),
Tmr(Midstate([
0xaa, 0x30, 0x30, 0x15, 0x71, 0xcf, 0x8d, 0x2d,
0x64, 0xe9, 0x65, 0x4b, 0x0c, 0xbd, 0xe0, 0x54,
0x01, 0x77, 0xab, 0xc2, 0xf2, 0xef, 0xfb, 0x7f,
0x05, 0x2e, 0x27, 0xa8, 0xcc, 0xcc, 0xee, 0x62,
])),
Tmr(Midstate([
0x28, 0x6d, 0x4d, 0x57, 0x6d, 0xb8, 0xe8, 0x45,
0x00, 0x9c, 0x74, 0x84, 0xe0, 0x0a, 0x9f, 0xa3,
0xf3, 0x18, 0xa8, 0x21, 0x9e, 0x38, 0x66, 0x2c,
0xda, 0x11, 0x75, 0x78, 0x22, 0xe4, 0x53, 0xbb,
])),
Tmr(Midstate([
0x10, 0x56, 0xa7, 0x17, 0xdc, 0x0c, 0x86, 0xb7,
0x49, 0x97, 0x5e, 0x9c, 0x36, 0x4a, 0xb5, 0xa6,
0x64, 0x77, 0xc4, 0x2d, 0xe1, 0x6e, 0x5b, 0x05,
0x29, 0x81, 0x4f, 0x4c, 0xba, 0x95, 0x7c, 0xb3,
])),
Tmr(Midstate([
0x94, 0x59, 0x0e, 0xf5, 0x66, 0x10, 0xaa, 0x7f,
0xec, 0x46, 0x5b, 0x72, 0x32, 0xab, 0xa3, 0xf4,
0x7c, 0x94, 0x2b, 0x8e, 0x8d, 0xc8, 0x76, 0x82,
0x51, 0xd3, 0x70, 0x2c, 0x99, 0xb9, 0xef, 0xef,
])),
Tmr(Midstate([
0xd0, 0x7f, 0x71, 0xb7, 0xcd, 0x48, 0xb8, 0x50,
0xad, 0x09, 0x06, 0x8b, 0x9b, 0x48, 0xe0, 0xf8,
0x5f, 0x84, 0xc0, 0x1b, 0x34, 0x58, 0x6a, 0x51,
0x34, 0x61, 0xfa, 0xf7, 0x6d, 0x54, 0x34, 0x64,
])),
];

/// The TMR of the `Ctx8` type used by the SHA256 jets.
#[rustfmt::skip]
pub const CTX8: Tmr = Tmr(Midstate([
0x8d, 0x5c, 0xe5, 0xf6, 0xeb, 0xfc, 0x70, 0x61,
0xe7, 0x91, 0x16, 0xbd, 0xf6, 0x6f, 0xb4, 0xe4,
0xc6, 0xca, 0x32, 0xa0, 0x1c, 0xda, 0x48, 0xf6,
0xed, 0xc1, 0x0a, 0xee, 0xfd, 0x31, 0x0e, 0x8c,
]));

/// The TMR for the unit type
pub const fn unit() -> Tmr {
Self::UNIT_IV
}

/// The TMR for the successor of a type.
///
/// Given a type `X`, we define its successor `S X` as `1 + X`.
/// In Rust notation this would be `Option<X>`.
pub fn successor(self) -> Tmr {
Self::SUM_IV.update(Tmr::unit(), self)
}

/// The TMR for the sum of two types, whose TMRs are given
pub fn sum(tmr1: Tmr, tmr2: Tmr) -> Tmr {
Self::SUM_IV.update(tmr1, tmr2)
Expand All @@ -256,8 +374,9 @@ impl Tmr {
mod tests {
use super::*;

use crate::jet::Jet;
use crate::merkle::bip340_iv;
use crate::types;
use crate::types::{self, Final};

#[test]
fn ivs() {
Expand Down Expand Up @@ -317,4 +436,47 @@ mod tests {
}
});
}

#[test]
fn const_buffer8() {
use std::sync::Arc;

let two_8_tmr = Tmr::TWO_TWO_N[3];
let buf_0_tmr = two_8_tmr.successor();

let two_8 = Final::two_two_n_fixed::<3>();
let buf_0 = Arc::clone(&two_8).successor();

assert_eq!(buf_0, Final::buffer8_two_n_plus_one(0).unwrap());
assert_eq!(two_8.tmr(), two_8_tmr);
assert_eq!(buf_0.tmr(), buf_0_tmr);
assert_eq!(buf_0_tmr, Tmr::BUFFER8_TWO_N_PLUS_ONE[0]);

let mut tmr = buf_0_tmr;
let mut fin = buf_0;
assert_eq!(Tmr::BUFFER8_TWO_N_PLUS_ONE.len(), 16);
for n in 1..Tmr::BUFFER8_TWO_N_PLUS_ONE.len() {
tmr = Tmr::product(Tmr::TWO_TWO_N[n + 3].successor(), tmr);
fin = Final::product(Final::two_two_n(n + 3).unwrap().successor(), fin);

assert_eq!(fin.tmr(), tmr);
assert_eq!(fin, Final::buffer8_two_n_plus_one(n).unwrap());
assert_eq!(tmr, Tmr::BUFFER8_TWO_N_PLUS_ONE[n]);

// For the case of n == 5, i.e. a 63-byte buffer (63 = 2^(n + 1) - 1),
// we can check against the SHA256 Ctx8 type to make sure that our
// computations are actually correct.
if n == 5 {
let extra_ctx_stuff = Final::product(
Final::two_two_n_fixed::<6>(), // 2^64
Final::two_two_n_fixed::<8>(), // 2^256
);
let synthetic_ctx_ty = Final::product(Arc::clone(&fin), extra_ctx_stuff);
let actual_ctx_ty = crate::jet::Core::Sha256Ctx8Init.target_ty().to_final();
assert_eq!(synthetic_ctx_ty, actual_ctx_ty,);
assert_eq!(synthetic_ctx_ty, Final::ctx8());
assert_eq!(synthetic_ctx_ty.tmr(), Tmr::CTX8);
}
}
}
}
129 changes: 122 additions & 7 deletions src/types/final_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ macro_rules! construct_final_two_two_n {
#[doc = "Create the type of"]
#[doc = $text]
#[doc = "words.\n\nThe type is precomputed and fast to access."]
#[inline]
pub fn $name() -> Arc<Self> {
super::precomputed::nth_power_of_2($n)
}
Expand All @@ -174,11 +175,80 @@ impl Final {
})
}

/// Computes the successor of the type.
///
/// Given a type `X`, we define its successor `S X` as `1 + X`.
/// In Rust notation this would be `Option<X>`.
pub fn successor(self: Arc<Self>) -> Arc<Self> {
Self::sum(Self::unit(), self)
}

/// Create the type `2^(2^n)` for the given `n`.
///
/// The type is precomputed and fast to access.
pub fn two_two_n(n: usize) -> Arc<Self> {
super::precomputed::nth_power_of_2(n)
#[inline]
pub fn two_two_n(n: usize) -> Result<Arc<Self>, TypeTooLargeError> {
let maximum = Tmr::TWO_TWO_N.len();
if n < maximum {
Ok(super::precomputed::nth_power_of_2(n))
} else {
Err(TypeTooLargeError {
ty: "2^(2^n)",
n,
maximum,
})
}
}

/// Create the type `2^(2^N)` for the compile-time constant `N`.
///
/// Will fail to compile if `N` exceeds 31.
#[inline]
pub fn two_two_n_fixed<const N: usize>() -> Arc<Self> {
// This crazy construction amounts to a compile-time assertion that N is less than the max.
struct Hack<const N: usize>;
impl<const N: usize> Hack<N> {
const IS_IN_RANGE: () = {
assert!(N < Tmr::TWO_TWO_N.len());
};
}
let () = Hack::<N>::IS_IN_RANGE;

super::precomputed::nth_power_of_2(N)
}

/// Create the type `(TWO^8)^<2^(n+1)` for the given `n`.
///
/// Here
/// * The notation X^<2 is notation for the type (S X)
/// * The notation X^<(2*n) is notation for the type S (X^n) * X^<n
///
/// And `S X` is the successor of `X`, i.e. `Option<X>`
///
/// The type is precomputed and fast to access.
#[inline]
pub fn buffer8_two_n_plus_one(n: usize) -> Result<Arc<Self>, TypeTooLargeError> {
let maximum = Tmr::BUFFER8_TWO_N_PLUS_ONE.len();
if n < maximum {
Ok(super::precomputed::buffer8_two_n_plus_one(n))
} else {
// This is arguably a programming error and a panic would be justified, but it's
// hard to say how SimplicityHL will use this. I also think the current maximum
// may be too small and we could bump into this with real code, so better to let
// the caller decide how to handle that.
Err(TypeTooLargeError {
ty: "(TWO^8)^<2^(n+1)",
n,
maximum,
})
}
}

/// Create the `Ctx8` type used by the SHA256 jets.
///
/// The type is precomputed and fast to access.
pub fn ctx8() -> Arc<Self> {
super::precomputed::ctx8()
}

construct_final_two_two_n!(u1, 0, "1-bit");
Expand Down Expand Up @@ -289,25 +359,70 @@ impl Final {
}
}

/// Attempted to produce a `(TWO^8)^(2^(n+1))` type exceeding the maximum size.
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct TypeTooLargeError {
ty: &'static str,
n: usize,
maximum: usize,
}

impl fmt::Display for TypeTooLargeError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"maximum n for {} is {}; got {}",
self.ty, self.maximum, self.n
)
}
}

impl std::error::Error for TypeTooLargeError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
let Self {
ty: _,
n: _,
maximum: _,
} = self;
None
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn two_two_n_consistent() {
// This test probably does not need to be exhaustive.
assert_eq!(Final::two_two_n_fixed::<0>(), Final::two_two_n(0).unwrap());
assert_eq!(Final::two_two_n_fixed::<1>(), Final::two_two_n(1).unwrap());
assert_eq!(Final::two_two_n_fixed::<2>(), Final::two_two_n(2).unwrap());
assert_eq!(Final::two_two_n_fixed::<3>(), Final::two_two_n(3).unwrap());
assert_eq!(Final::two_two_n_fixed::<4>(), Final::two_two_n(4).unwrap());
assert_eq!(Final::two_two_n_fixed::<5>(), Final::two_two_n(5).unwrap());
assert_eq!(Final::two_two_n_fixed::<6>(), Final::two_two_n(6).unwrap());
assert_eq!(Final::two_two_n_fixed::<7>(), Final::two_two_n(7).unwrap());
}

#[test]
fn final_stringify() {
let ty1 = Final::two_two_n(10);
let ty1 = Final::two_two_n_fixed::<10>();
assert_eq!(ty1.to_string(), "2^1024");

let sum = Final::sum(Final::two_two_n(5), Final::two_two_n(10));
let sum = Final::sum(Final::two_two_n_fixed::<5>(), Final::two_two_n(10).unwrap());
assert_eq!(sum.to_string(), "2^32 + 2^1024");

let prod = Final::product(Final::two_two_n(5), Final::two_two_n(10));
let prod = Final::product(
Final::two_two_n_fixed::<5>(),
Final::two_two_n_fixed::<10>(),
);
assert_eq!(prod.to_string(), "2^32 × 2^1024");

let ty1 = Final::two_two_n(0);
let ty1 = Final::two_two_n_fixed::<0>();
assert_eq!(ty1.to_string(), "2");

let ty1 = Final::sum(Final::unit(), Final::two_two_n(2));
let ty1 = Final::sum(Final::unit(), Final::two_two_n_fixed::<2>());
assert_eq!(ty1.to_string(), "2^4?");
}
}
2 changes: 1 addition & 1 deletion src/types/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ mod union_bound;
mod variable;

pub use context::{BoundRef, Context};
pub use final_data::{CompleteBound, Final};
pub use final_data::{CompleteBound, Final, TypeTooLargeError};
pub use incomplete::Incomplete;

/// Error type for simplicity
Expand Down
Loading
Loading