Response to usage of unwrap in non-test code

This commit replaces all usage of `unwrap` with `expect` within
`networks/monero`, clarifying why the panic risked is unreachable. This commit
also replaces some uses of `unwrap` with solutions which are guaranteed not to
fail.

Notably, compilation on 128-bit systems is prevented, ensuring
`u64::try_from(usize::MAX)` will never panic at runtime.

Slight breaking changes are additionally included as necessary to massage out
some avoidable panics.
This commit is contained in:
Luke Parker
2025-08-08 21:28:47 -04:00
parent 4f65a0b147
commit a5f4c450c6
31 changed files with 310 additions and 169 deletions

View File

@@ -29,7 +29,11 @@ pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
let uv3 = u * v3;
let v7 = v3 * v3 * v;
let uv7 = u * v7;
uv3 * uv7.pow((-FieldElement::from(5u8)) * FieldElement::from(8u8).invert().unwrap())
uv3 *
uv7.pow(
(-FieldElement::from(5u8)) *
FieldElement::from(8u8).invert().expect("eight was coprime with the prime 2^{255}-19"),
)
};
let x = X.square() * x;
@@ -45,9 +49,23 @@ pub fn hash_to_point(bytes: [u8; 32]) -> EdwardsPoint {
#[allow(non_snake_case)]
let mut Y = z - w;
Y *= Z.invert().unwrap();
/*
If sign, `z = -486662`, else, `z = -486662 * v`
`w = v + 1`
We need `z + w \ne 0`, which would require `z \cong -w \mod 2^{255}-19`. This requires:
- If `sign`, `v \mod 2^{255}-19 \ne 486661`.
- If `!sign`, `(v + 1) \mod 2^{255}-19 \ne (v * 486662) \mod 2^{255}-19` which is equivalent to
`(v * 486661) \mod 2^{255}-19 \ne 1`.
In summary, if `sign`, `v` must not `486661`, and if `!sign`, `v` must not be the
multiplicative inverse of `486661`. Since `v` is the output of a hash function, this should
have negligible probability. Additionally, since the definition of `sign` is dependent on `v`,
it may be truly impossible to reach.
*/
Y *= Z.invert().expect("if sign, v was 486661. if !sign, v was 486661^{-1}");
let mut bytes = Y.to_repr();
bytes[31] |= sign.unwrap_u8() << 7;
decompress_point(bytes).unwrap().mul_by_cofactor()
decompress_point(bytes).expect("point from hash-to-curve wasn't on-curve").mul_by_cofactor()
}

View File

@@ -28,7 +28,7 @@ fn keccak256(data: &[u8]) -> [u8; 32] {
#[allow(non_snake_case)]
pub static H: LazyLock<EdwardsPoint> = LazyLock::new(|| {
decompress_point(keccak256(&ED25519_BASEPOINT_POINT.compress().to_bytes()))
.unwrap()
.expect("known on-curve point wasn't on-curve")
.mul_by_cofactor()
});
@@ -78,11 +78,11 @@ pub fn bulletproofs_generators(dst: &'static [u8]) -> Generators {
let i = 2 * i;
let mut even = preimage.clone();
write_varint(&i, &mut even).unwrap();
write_varint(&i, &mut even).expect("write failed but <Vec as io::Write> doesn't fail");
res.H.push(hash_to_point(keccak256(&even)));
let mut odd = preimage.clone();
write_varint(&(i + 1), &mut odd).unwrap();
write_varint(&(i + 1), &mut odd).expect("write failed but <Vec as io::Write> doesn't fail");
res.G.push(hash_to_point(keccak256(&odd)));
}
res