spaceandtimelabs / sxt-proof-of-sql

Space and Time | Proof of SQL
Other
1.79k stars 80 forks source link

MontScalar infallible conversions for trivial types #146

Closed Dustin-Ray closed 1 month ago

Dustin-Ray commented 1 month ago

Is there a reason why we need a try_from on any of the unsigned integer types? Seems to me that anything 64 bits and under should be able to be infallibly converted to Scalar, since those bit widths should always fit. Maybe we choose a scalar someday around 128 bits but that seems unlikely as well.

Feels kind of wrong to keep having to .expect() these conversions like so:

S::try_from(i.into()).expect("u8 value will always fit into S") + alpha

Maybe we just need to add these From conversions somewhere in here:

I see something here that converts a slice of bytes to MontScalar, I just need individual bytes, so maybe we can put it in here with something similar to this:

impl<T: MontConfig<4>> From<&[u8]> for MontScalar<T> {
    fn from(x: &[u8]) -> Self {
        if x.is_empty() {
            return Self::zero();
        }

        let hash = blake3::hash(x);
        let mut bytes: [u8; 32] = hash.into();
        bytes[31] &= 0b00001111_u8;

        Self::from_le_bytes_mod_order(&bytes)
    }
}

Although this appears to be taking the hash of the slice and converting that result into MontScalar.

JayWhite2357 commented 1 month ago

The Scalar trait has many infallible conversions as bounds. In this particular case, I believe that the + for<'a> core::convert::From<&'a u8> conversion just needed to be added, which is already implemented for MontScalar.

We certainly could add conversions from [u8; N] arrays where N < 32, but I don't think we are in need of it. See https://github.com/spaceandtimelabs/sxt-proof-of-sql/pull/141#discussion_r1759635797.