Encoding via rejection sampling#38
Conversation
b-wagn
left a comment
There was a problem hiding this comment.
Thanks for the PR! This is great :) Left some comments.
b-wagn
left a comment
There was a problem hiding this comment.
I am happy with it :) thanks a lot! maybe @tcoratger can have a very quick look before we merge
tcoratger
left a comment
There was a problem hiding this comment.
Looks nice, just left a few super minor comments but not blockers for me, feel free to merge when you think this is ready.
| // Check that Poseidon of width 24 is enough | ||
| assert!( | ||
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE <= 24, | ||
| "Poseidon of width 24 is not enough" | ||
| ); | ||
| assert!(HASH_LEN_FE <= 24, "Poseidon of width 24 is not enough"); | ||
|
|
||
| // Check that we have enough hash output field elements | ||
| assert!( | ||
| HASH_LEN_FE >= DIMENSION.div_ceil(Z), | ||
| "Not enough hash output field elements for the requested dimension" | ||
| ); | ||
| assert!( | ||
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE >= HASH_LEN_FE, | ||
| "Input shorter than requested output" | ||
| ); | ||
|
|
||
| // Base check | ||
| assert!( | ||
| Self::BASE <= 1 << 8, | ||
| "Aborting Hypercube Message Hash: Base must be at most 2^8" | ||
| ); |
There was a problem hiding this comment.
I think that this is the same for the other file but I just thought a bit more about this function and I think that if we add this const {} thing around the assertions, the assertions will be done at compile time and so the code will simply refuse to compile if the assertions are not correct.
| // Check that Poseidon of width 24 is enough | |
| assert!( | |
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE <= 24, | |
| "Poseidon of width 24 is not enough" | |
| ); | |
| assert!(HASH_LEN_FE <= 24, "Poseidon of width 24 is not enough"); | |
| // Check that we have enough hash output field elements | |
| assert!( | |
| HASH_LEN_FE >= DIMENSION.div_ceil(Z), | |
| "Not enough hash output field elements for the requested dimension" | |
| ); | |
| assert!( | |
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE >= HASH_LEN_FE, | |
| "Input shorter than requested output" | |
| ); | |
| // Base check | |
| assert!( | |
| Self::BASE <= 1 << 8, | |
| "Aborting Hypercube Message Hash: Base must be at most 2^8" | |
| ); | |
| const{ | |
| // Check that Poseidon of width 24 is enough | |
| assert!( | |
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE <= 24, | |
| "Poseidon of width 24 is not enough" | |
| ); | |
| assert!(HASH_LEN_FE <= 24, "Poseidon of width 24 is not enough"); | |
| // Check that we have enough hash output field elements | |
| assert!( | |
| HASH_LEN_FE >= DIMENSION.div_ceil(Z), | |
| "Not enough hash output field elements for the requested dimension" | |
| ); | |
| assert!( | |
| PARAMETER_LEN + RAND_LEN_FE + TWEAK_LEN_FE + MSG_LEN_FE >= HASH_LEN_FE, | |
| "Input shorter than requested output" | |
| ); | |
| // Base check | |
| assert!( | |
| Self::BASE <= 1 << 8, | |
| "Aborting Hypercube Message Hash: Base must be at most 2^8" | |
| ); | |
| } |
| randomness: &Self::Randomness, | ||
| message: &[u8; MESSAGE_LENGTH], | ||
| ) -> Result<Vec<u8>, HypercubeAbortError> { | ||
| let hash_fe = poseidon_message_hash_fe::< |
There was a problem hiding this comment.
Not sure this is strictly needed but maybe just nice to have since these are just compile time assertions.
| let hash_fe = poseidon_message_hash_fe::< | |
| // Enforce constraints at compile-time to prevent runtime panics. | |
| const { | |
| assert!( | |
| HASH_LEN_FE >= DIMENSION.div_ceil(Z), | |
| "Not enough hash output field elements for the requested dimension" | |
| ); | |
| assert!( | |
| Q as u64 * (BASE as u64).pow(Z as u32) <= u64::MAX, | |
| "Q * w^z exceeds u64 bounds" | |
| ); | |
| } | |
| let hash_fe = poseidon_message_hash_fe::< |
| let q_wz = Q as u64 * (BASE as u64).pow(Z as u32); | ||
| let num_useful_fe = DIMENSION.div_ceil(Z); |
There was a problem hiding this comment.
I think that the previous comment of @b-wagn was valid no? We should simply have this no?
I agree that in principle the compile should be smart enough to handle this but since this is a small change only maybe that is better to handle it ourselves directly?
| let q_wz = Q as u64 * (BASE as u64).pow(Z as u32); | |
| let num_useful_fe = DIMENSION.div_ceil(Z); | |
| // Compute thresholds at compile-time | |
| const Q_WZ: u64 = Q as u64 * (BASE as u64).pow(Z as u32); | |
| const NUM_USEFUL_FE: usize = DIMENSION.div_ceil(Z); |
| d_i /= BASE as u64; | ||
| } | ||
| } | ||
| assert_eq!(chunks.len(), DIMENSION); |
There was a problem hiding this comment.
I think that we can only have this as a debug assertion since this is just a sanity check in order to avoid panic at runtime since this should never happen no?
| assert_eq!(chunks.len(), DIMENSION); | |
| // Sanity check to ensure we hit our exact dimension | |
| debug_assert_eq!(chunks.len(), DIMENSION); |
|
|
||
| #[derive(Debug, Error)] | ||
| #[error("Hash aborted: field element exceeded Q * w^z threshold.")] | ||
| pub struct HypercubeAbortError; |
There was a problem hiding this comment.
In case we want to have more errors in the future, this is more Rusty to have this no?
| pub struct HypercubeAbortError; | |
| #[derive(Debug, Error, PartialEq, Eq)] | |
| pub enum HypercubeHashError { | |
| #[error("Hash aborted: field element exceeded Q * w^z threshold.")] | |
| Abort, | |
| } |
Goal: implem section 6.1 from borting Random Oracles: How to Build them, How to Use them
Still some work remaing to define nice instanciations (i.e. fixing the parameters), but maybe this can be done in a second PR?