Skip to content

Encoding via rejection sampling#38

Open
TomWambsgans wants to merge 10 commits intoleanEthereum:mainfrom
TomWambsgans:encoding-via-rejection-sampling
Open

Encoding via rejection sampling#38
TomWambsgans wants to merge 10 commits intoleanEthereum:mainfrom
TomWambsgans:encoding-via-rejection-sampling

Conversation

@TomWambsgans
Copy link
Contributor

@TomWambsgans TomWambsgans commented Mar 9, 2026

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?

@TomWambsgans TomWambsgans marked this pull request as ready for review March 10, 2026 05:41
Copy link
Contributor

@b-wagn b-wagn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! This is great :) Left some comments.

Copy link
Contributor

@b-wagn b-wagn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am happy with it :) thanks a lot! maybe @tcoratger can have a very quick look before we merge

Copy link
Contributor

@tcoratger tcoratger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks nice, just left a few super minor comments but not blockers for me, feel free to merge when you think this is ready.

Comment on lines +110 to +131
// 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"
);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
// 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::<
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is strictly needed but maybe just nice to have since these are just compile time assertions.

Suggested change
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::<

Comment on lines +86 to +87
let q_wz = Q as u64 * (BASE as u64).pow(Z as u32);
let num_useful_fe = DIMENSION.div_ceil(Z);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Suggested change
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);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Suggested change
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case we want to have more errors in the future, this is more Rusty to have this no?

Suggested change
pub struct HypercubeAbortError;
#[derive(Debug, Error, PartialEq, Eq)]
pub enum HypercubeHashError {
#[error("Hash aborted: field element exceeded Q * w^z threshold.")]
Abort,
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants