mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-09 04:39:24 +00:00
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:
@@ -135,35 +135,13 @@ impl SimpleRequestRpc {
|
||||
};
|
||||
|
||||
async fn body_from_response(response: Response<'_>) -> Result<Vec<u8>, RpcError> {
|
||||
/*
|
||||
let length = usize::try_from(
|
||||
response
|
||||
.headers()
|
||||
.get("content-length")
|
||||
.ok_or(RpcError::InvalidNode("no content-length header"))?
|
||||
.to_str()
|
||||
.map_err(|_| RpcError::InvalidNode("non-ascii content-length value"))?
|
||||
.parse::<u32>()
|
||||
.map_err(|_| RpcError::InvalidNode("non-u32 content-length value"))?,
|
||||
)
|
||||
.unwrap();
|
||||
// Only pre-allocate 1 MB so a malicious node which claims a content-length of 1 GB actually
|
||||
// has to send 1 GB of data to cause a 1 GB allocation
|
||||
let mut res = Vec::with_capacity(length.max(1024 * 1024));
|
||||
let mut body = response.into_body();
|
||||
while res.len() < length {
|
||||
let Some(data) = body.data().await else { break };
|
||||
res.extend(data.map_err(|e| RpcError::ConnectionError(format!("{e:?}")))?.as_ref());
|
||||
}
|
||||
*/
|
||||
|
||||
let mut res = Vec::with_capacity(128);
|
||||
response
|
||||
.body()
|
||||
.await
|
||||
.map_err(|e| RpcError::ConnectionError(format!("{e:?}")))?
|
||||
.read_to_end(&mut res)
|
||||
.unwrap();
|
||||
.map_err(|e| RpcError::ConnectionError(format!("{e:?}")))?;
|
||||
Ok(res)
|
||||
}
|
||||
|
||||
@@ -219,7 +197,12 @@ impl SimpleRequestRpc {
|
||||
})?
|
||||
.to_header_string(),
|
||||
)
|
||||
.unwrap(),
|
||||
.map_err(|_| {
|
||||
RpcError::InternalError(
|
||||
"digest-auth challenge response wasn't a valid string for an HTTP header"
|
||||
.to_string(),
|
||||
)
|
||||
})?,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -269,7 +252,7 @@ impl SimpleRequestRpc {
|
||||
))?
|
||||
}
|
||||
} else {
|
||||
body_from_response(response.unwrap()).await?
|
||||
body_from_response(response.expect("no response yet also no error?")).await?
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -121,7 +121,7 @@ impl FeeRate {
|
||||
/// defined serialization.
|
||||
pub fn serialize(&self) -> Vec<u8> {
|
||||
let mut res = Vec::with_capacity(16);
|
||||
self.write(&mut res).unwrap();
|
||||
self.write(&mut res).expect("write failed but <Vec as io::Write> doesn't fail");
|
||||
res
|
||||
}
|
||||
|
||||
@@ -139,15 +139,22 @@ impl FeeRate {
|
||||
///
|
||||
/// This function may panic upon overflow.
|
||||
pub fn calculate_fee_from_weight(&self, weight: usize) -> u64 {
|
||||
let fee = self.per_weight * u64::try_from(weight).unwrap();
|
||||
let fee =
|
||||
self.per_weight * u64::try_from(weight).expect("couldn't convert weight (usize) to u64");
|
||||
let fee = fee.div_ceil(self.mask) * self.mask;
|
||||
debug_assert_eq!(weight, self.calculate_weight_from_fee(fee), "Miscalculated weight from fee");
|
||||
debug_assert_eq!(
|
||||
Some(weight),
|
||||
self.calculate_weight_from_fee(fee),
|
||||
"Miscalculated weight from fee"
|
||||
);
|
||||
fee
|
||||
}
|
||||
|
||||
/// Calculate the weight from the fee.
|
||||
pub fn calculate_weight_from_fee(&self, fee: u64) -> usize {
|
||||
usize::try_from(fee / self.per_weight).unwrap()
|
||||
///
|
||||
/// Returns `None` if the weight would not fit within a `usize`.
|
||||
pub fn calculate_weight_from_fee(&self, fee: u64) -> Option<usize> {
|
||||
usize::try_from(fee / self.per_weight).ok()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,8 +279,14 @@ pub trait Rpc: Sync + Clone {
|
||||
let res = self
|
||||
.post(
|
||||
route,
|
||||
if let Some(params) = params {
|
||||
serde_json::to_string(¶ms).unwrap().into_bytes()
|
||||
if let Some(params) = params.as_ref() {
|
||||
serde_json::to_string(params)
|
||||
.map_err(|e| {
|
||||
RpcError::InternalError(format!(
|
||||
"couldn't convert parameters ({params:?}) to JSON: {e:?}"
|
||||
))
|
||||
})?
|
||||
.into_bytes()
|
||||
} else {
|
||||
vec![]
|
||||
},
|
||||
@@ -295,7 +308,10 @@ pub trait Rpc: Sync + Clone {
|
||||
async move {
|
||||
let mut req = json!({ "method": method });
|
||||
if let Some(params) = params {
|
||||
req.as_object_mut().unwrap().insert("params".into(), params);
|
||||
req
|
||||
.as_object_mut()
|
||||
.expect("accessing object as object failed?")
|
||||
.insert("params".into(), params);
|
||||
}
|
||||
Ok(self.rpc_call::<_, JsonRpcResponse<Response>>("json_rpc", Some(req)).await?.result)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user