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

@@ -446,7 +446,7 @@ impl SignableTransaction {
/// defined serialization.
pub fn serialize(&self) -> Vec<u8> {
let mut buf = Vec::with_capacity(256);
self.write(&mut buf).unwrap();
self.write(&mut buf).expect("write failed but <Vec as io::Write> doesn't fail");
buf
}
@@ -553,9 +553,13 @@ impl SignableTransaction {
let mut tx = tx.transaction_without_signatures();
// Sign the CLSAGs
let clsags_and_pseudo_outs =
Clsag::sign(rng, clsag_signs, mask_sum, tx.signature_hash().unwrap())
.map_err(SendError::ClsagError)?;
let clsags_and_pseudo_outs = Clsag::sign(
rng,
clsag_signs,
mask_sum,
tx.signature_hash().expect("signing a transaction which isn't signed?"),
)
.map_err(SendError::ClsagError)?;
// Fill in the CLSAGs/pseudo-outs
let inputs_len = tx.prefix().inputs.len();

View File

@@ -251,7 +251,7 @@ impl SignMachine<Transaction> for TransactionSignMachine {
}
let tx = tx.transaction_without_signatures();
let msg = tx.signature_hash().unwrap();
let msg = tx.signature_hash().expect("signing a transaction which isn't signed?");
// Iterate over each CLSAG calling sign
let mut shares = Vec::with_capacity(to_sign.len());

View File

@@ -73,7 +73,9 @@ impl SignableTransaction {
{
let id = (u64::from_le_bytes(id) ^ u64::from_le_bytes(*id_xor)).to_le_bytes();
let mut id_vec = Vec::with_capacity(1 + 8);
PaymentId::Encrypted(id).write(&mut id_vec).unwrap();
PaymentId::Encrypted(id)
.write(&mut id_vec)
.expect("write failed but <Vec as io::Write> doesn't fail");
extra.push_nonce(id_vec);
} else {
/*
@@ -96,7 +98,9 @@ impl SignableTransaction {
.expect("multiple change outputs?");
let mut id_vec = Vec::with_capacity(1 + 8);
// The dummy payment ID is [0; 8], which when xor'd with the mask, is just the mask
PaymentId::Encrypted(*payment_id_xor).write(&mut id_vec).unwrap();
PaymentId::Encrypted(*payment_id_xor)
.write(&mut id_vec)
.expect("write failed but <Vec as io::Write> doesn't fail");
extra.push_nonce(id_vec);
}
}
@@ -109,7 +113,7 @@ impl SignableTransaction {
}
let mut serialized = Vec::with_capacity(32 * amount_of_keys);
extra.write(&mut serialized).unwrap();
extra.write(&mut serialized).expect("write failed but <Vec as io::Write> doesn't fail");
serialized
}
@@ -180,7 +184,8 @@ impl SignableTransaction {
push_scalar(&mut bp);
}
for _ in 0 .. 2 {
write_varint(&lr_len, &mut bp).unwrap();
write_varint(&lr_len, &mut bp)
.expect("write failed but <Vec as io::Write> doesn't fail");
for _ in 0 .. lr_len {
push_point(&mut bp);
}
@@ -204,7 +209,8 @@ impl SignableTransaction {
push_scalar(&mut bp);
}
for _ in 0 .. 2 {
write_varint(&lr_len, &mut bp).unwrap();
write_varint(&lr_len, &mut bp)
.expect("write failed but <Vec as io::Write> doesn't fail");
for _ in 0 .. lr_len {
push_point(&mut bp);
}
@@ -261,7 +267,8 @@ impl SignableTransaction {
break;
}
}
weight_and_fee.unwrap()
weight_and_fee
.expect("length of highest possible fee was greater than highest possible fee length")
}
}

View File

@@ -21,7 +21,9 @@ fn seeded_rng(
mut input_keys: Vec<EdwardsPoint>,
) -> ChaCha20Rng {
// Apply the DST
let mut transcript = Zeroizing::new(vec![u8::try_from(dst.len()).unwrap()]);
let mut transcript = Zeroizing::new(vec![
u8::try_from(dst.len()).expect("internal RNG with constant DST had a too-long DST specified")
]);
transcript.extend(dst);
// Bind to the outgoing view key to prevent foreign entities from rebuilding the transcript
@@ -116,12 +118,12 @@ impl SignableTransaction {
fn transaction_keys(&self) -> (Zeroizing<Scalar>, Vec<Zeroizing<Scalar>>) {
let mut tx_keys = TransactionKeys::new(&self.outgoing_view_key, self.input_keys());
let tx_key = tx_keys.next().unwrap();
let tx_key = tx_keys.next().expect("TransactionKeys (never-ending) was exhausted");
let mut additional_keys = vec![];
if self.should_use_additional_keys() {
for _ in 0 .. self.payments.len() {
additional_keys.push(tx_keys.next().unwrap());
additional_keys.push(tx_keys.next().expect("TransactionKeys (never-ending) was exhausted"));
}
}
(tx_key, additional_keys)