helper: add and use cast module (#264)

* helper: add `cast` module

* fix crates

* spacing
This commit is contained in:
hinto-janai 2024-09-02 13:09:52 -04:00 committed by GitHub
parent fdd1689665
commit bec8cc0aa4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
21 changed files with 163 additions and 58 deletions

3
Cargo.lock generated
View file

@ -646,6 +646,7 @@ version = "0.5.0"
dependencies = [ dependencies = [
"bytes", "bytes",
"cuprate-fixed-bytes", "cuprate-fixed-bytes",
"cuprate-helper",
"hex", "hex",
"paste", "paste",
"ref-cast", "ref-cast",
@ -713,6 +714,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"bitflags 2.5.0", "bitflags 2.5.0",
"bytes", "bytes",
"cuprate-helper",
"futures", "futures",
"proptest", "proptest",
"rand", "rand",
@ -893,6 +895,7 @@ dependencies = [
"bytes", "bytes",
"cuprate-epee-encoding", "cuprate-epee-encoding",
"cuprate-fixed-bytes", "cuprate-fixed-bytes",
"cuprate-helper",
"cuprate-levin", "cuprate-levin",
"cuprate-types", "cuprate-types",
"hex", "hex",

View file

@ -11,7 +11,7 @@ proptest = ["dep:proptest", "dep:proptest-derive", "cuprate-types/proptest"]
rayon = ["dep:rayon"] rayon = ["dep:rayon"]
[dependencies] [dependencies]
cuprate-helper = { path = "../../helper", default-features = false, features = ["std"] } cuprate-helper = { path = "../../helper", default-features = false, features = ["std", "cast"] }
cuprate-types = { path = "../../types", default-features = false } cuprate-types = { path = "../../types", default-features = false }
cuprate-cryptonight = {path = "../../cryptonight"} cuprate-cryptonight = {path = "../../cryptonight"}

View file

@ -9,6 +9,8 @@ use proptest::{collection::vec, prelude::*};
use monero_serai::transaction::Output; use monero_serai::transaction::Output;
use cuprate_helper::cast::u64_to_usize;
use super::*; use super::*;
use crate::decomposed_amount::DECOMPOSED_AMOUNTS; use crate::decomposed_amount::DECOMPOSED_AMOUNTS;
@ -164,7 +166,7 @@ prop_compose! {
if timebased || lock_height > 500_000_000 { if timebased || lock_height > 500_000_000 {
Timelock::Time(time_for_time_lock) Timelock::Time(time_for_time_lock)
} else { } else {
Timelock::Block(usize::try_from(lock_height).unwrap()) Timelock::Block(u64_to_usize(lock_height))
} }
} }
} }
@ -179,7 +181,7 @@ prop_compose! {
match ty { match ty {
0 => Timelock::None, 0 => Timelock::None,
1 => Timelock::Time(time_for_time_lock), 1 => Timelock::Time(time_for_time_lock),
_ => Timelock::Block(usize::try_from(lock_height).unwrap()) _ => Timelock::Block(u64_to_usize(lock_height))
} }
} }
} }

View file

@ -14,7 +14,7 @@ use cuprate_consensus_rules::{
miner_tx::MinerTxError, miner_tx::MinerTxError,
ConsensusError, ConsensusError,
}; };
use cuprate_helper::asynch::rayon_spawn_async; use cuprate_helper::{asynch::rayon_spawn_async, cast::u64_to_usize};
use cuprate_types::{ use cuprate_types::{
AltBlockInformation, Chain, ChainId, TransactionVerificationData, AltBlockInformation, Chain, ChainId, TransactionVerificationData,
VerifiedTransactionInformation, VerifiedTransactionInformation,
@ -101,7 +101,7 @@ where
// Check the alt block timestamp is in the correct range. // Check the alt block timestamp is in the correct range.
if let Some(median_timestamp) = if let Some(median_timestamp) =
difficulty_cache.median_timestamp(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW.try_into().unwrap()) difficulty_cache.median_timestamp(u64_to_usize(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW))
{ {
check_timestamp(&prepped_block.block, median_timestamp).map_err(ConsensusError::Block)? check_timestamp(&prepped_block.block, median_timestamp).map_err(ConsensusError::Block)?
}; };

View file

@ -9,6 +9,7 @@ use tower::ServiceExt;
use tracing::Instrument; use tracing::Instrument;
use cuprate_consensus_rules::blocks::ContextToVerifyBlock; use cuprate_consensus_rules::blocks::ContextToVerifyBlock;
use cuprate_helper::cast::u64_to_usize;
use cuprate_types::{ use cuprate_types::{
blockchain::{BlockchainReadRequest, BlockchainResponse}, blockchain::{BlockchainReadRequest, BlockchainResponse},
Chain, Chain,
@ -168,9 +169,9 @@ impl<D: Database + Clone + Send + 'static> ContextTask<D> {
.weight_cache .weight_cache
.effective_median_block_weight(&current_hf), .effective_median_block_weight(&current_hf),
top_hash: self.top_block_hash, top_hash: self.top_block_hash,
median_block_timestamp: self.difficulty_cache.median_timestamp( median_block_timestamp: self
usize::try_from(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW).unwrap(), .difficulty_cache
), .median_timestamp(u64_to_usize(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)),
chain_height: self.chain_height, chain_height: self.chain_height,
current_hf, current_hf,
next_difficulty: self.difficulty_cache.next_difficulty(&current_hf), next_difficulty: self.difficulty_cache.next_difficulty(&current_hf),

View file

@ -10,14 +10,15 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus"
[features] [features]
# All features on by default. # All features on by default.
default = ["std", "atomic", "asynch", "fs", "num", "map", "time", "thread", "constants"] default = ["std", "atomic", "asynch", "cast", "fs", "num", "map", "time", "thread", "constants"]
std = [] std = []
atomic = ["dep:crossbeam"] atomic = ["dep:crossbeam"]
asynch = ["dep:futures", "dep:rayon"] asynch = ["dep:futures", "dep:rayon"]
cast = []
constants = [] constants = []
fs = ["dep:dirs"] fs = ["dep:dirs"]
num = [] num = []
map = ["dep:monero-serai"] map = ["cast", "dep:monero-serai"]
time = ["dep:chrono", "std"] time = ["dep:chrono", "std"]
thread = ["std", "dep:target_os_lib"] thread = ["std", "dep:target_os_lib"]

84
helper/src/cast.rs Normal file
View file

@ -0,0 +1,84 @@
//! Casting.
//!
//! This modules provides utilities for casting between types.
//!
//! `#[no_std]` compatible.
#[rustfmt::skip]
//============================ SAFETY: DO NOT REMOVE ===========================//
// //
// //
// Only allow building 64-bit targets. //
// This allows us to assume 64-bit invariants in this file. //
#[cfg(not(target_pointer_width = "64"))]
compile_error!("Cuprate is only compatible with 64-bit CPUs");
// //
// //
//============================ SAFETY: DO NOT REMOVE ===========================//
//---------------------------------------------------------------------------------------------------- Free functions
/// Cast [`u64`] to [`usize`].
#[inline(always)]
pub const fn u64_to_usize(u: u64) -> usize {
u as usize
}
/// Cast [`u32`] to [`usize`].
#[inline(always)]
pub const fn u32_to_usize(u: u32) -> usize {
u as usize
}
/// Cast [`usize`] to [`u64`].
#[inline(always)]
pub const fn usize_to_u64(u: usize) -> u64 {
u as u64
}
/// Cast [`i64`] to [`isize`].
#[inline(always)]
pub const fn i64_to_isize(i: i64) -> isize {
i as isize
}
/// Cast [`i32`] to [`isize`].
#[inline(always)]
pub const fn i32_to_isize(i: i32) -> isize {
i as isize
}
/// Cast [`isize`] to [`i64`].
#[inline(always)]
pub const fn isize_to_i64(i: isize) -> i64 {
i as i64
}
//---------------------------------------------------------------------------------------------------- Tests
#[cfg(test)]
mod test {
use super::*;
#[test]
fn max_unsigned() {
assert_eq!(u32_to_usize(u32::MAX), u32::MAX as usize);
assert_eq!(usize_to_u64(u32_to_usize(u32::MAX)), u32::MAX as u64);
assert_eq!(u64_to_usize(u64::MAX), usize::MAX);
assert_eq!(usize_to_u64(u64_to_usize(u64::MAX)), u64::MAX);
assert_eq!(usize_to_u64(usize::MAX), u64::MAX);
assert_eq!(u64_to_usize(usize_to_u64(usize::MAX)), usize::MAX);
}
#[test]
fn max_signed() {
assert_eq!(i32_to_isize(i32::MAX), i32::MAX as isize);
assert_eq!(isize_to_i64(i32_to_isize(i32::MAX)), i32::MAX as i64);
assert_eq!(i64_to_isize(i64::MAX), isize::MAX);
assert_eq!(isize_to_i64(i64_to_isize(i64::MAX)), i64::MAX);
assert_eq!(isize_to_i64(isize::MAX), i64::MAX);
assert_eq!(i64_to_isize(isize_to_i64(isize::MAX)), isize::MAX);
}
}

View file

@ -40,6 +40,9 @@ pub mod asynch; // async collides
#[cfg(feature = "atomic")] #[cfg(feature = "atomic")]
pub mod atomic; pub mod atomic;
#[cfg(feature = "cast")]
pub mod cast;
#[cfg(feature = "constants")] #[cfg(feature = "constants")]
pub mod constants; pub mod constants;

View file

@ -7,6 +7,8 @@
//---------------------------------------------------------------------------------------------------- Use //---------------------------------------------------------------------------------------------------- Use
use monero_serai::transaction::Timelock; use monero_serai::transaction::Timelock;
use crate::cast::{u64_to_usize, usize_to_u64};
//---------------------------------------------------------------------------------------------------- `(u64, u64) <-> u128` //---------------------------------------------------------------------------------------------------- `(u64, u64) <-> u128`
/// Split a [`u128`] value into 2 64-bit values. /// Split a [`u128`] value into 2 64-bit values.
/// ///
@ -77,7 +79,7 @@ pub fn u64_to_timelock(u: u64) -> Timelock {
if u == 0 { if u == 0 {
Timelock::None Timelock::None
} else if u < 500_000_000 { } else if u < 500_000_000 {
Timelock::Block(usize::try_from(u).unwrap()) Timelock::Block(u64_to_usize(u))
} else { } else {
Timelock::Time(u) Timelock::Time(u)
} }
@ -97,7 +99,7 @@ pub fn u64_to_timelock(u: u64) -> Timelock {
pub fn timelock_to_u64(timelock: Timelock) -> u64 { pub fn timelock_to_u64(timelock: Timelock) -> u64 {
match timelock { match timelock {
Timelock::None => 0, Timelock::None => 0,
Timelock::Block(u) => u64::try_from(u).unwrap(), Timelock::Block(u) => usize_to_u64(u),
Timelock::Time(u) => u, Timelock::Time(u) => u,
} }
} }

View file

@ -15,6 +15,7 @@ default = ["std"]
std = ["dep:thiserror", "bytes/std", "cuprate-fixed-bytes/std"] std = ["dep:thiserror", "bytes/std", "cuprate-fixed-bytes/std"]
[dependencies] [dependencies]
cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] }
cuprate-fixed-bytes = { path = "../fixed-bytes", default-features = false } cuprate-fixed-bytes = { path = "../fixed-bytes", default-features = false }
paste = "1.0.14" paste = "1.0.14"

View file

@ -65,6 +65,8 @@ use core::{ops::Deref, str::from_utf8 as str_from_utf8};
use bytes::{Buf, BufMut, Bytes, BytesMut}; use bytes::{Buf, BufMut, Bytes, BytesMut};
use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
pub mod container_as_blob; pub mod container_as_blob;
pub mod error; pub mod error;
mod io; mod io;
@ -242,7 +244,7 @@ pub fn write_bytes<T: AsRef<[u8]>, B: BufMut>(t: T, w: &mut B) -> Result<()> {
let bytes = t.as_ref(); let bytes = t.as_ref();
let len = bytes.len(); let len = bytes.len();
write_varint(len.try_into()?, w)?; write_varint(usize_to_u64(len), w)?;
if w.remaining_mut() < len { if w.remaining_mut() < len {
return Err(Error::IO("Not enough capacity to write bytes")); return Err(Error::IO("Not enough capacity to write bytes"));
@ -286,7 +288,7 @@ where
I: Iterator<Item = T> + ExactSizeIterator, I: Iterator<Item = T> + ExactSizeIterator,
B: BufMut, B: BufMut,
{ {
write_varint(iterator.len().try_into()?, w)?; write_varint(usize_to_u64(iterator.len()), w)?;
for item in iterator.into_iter() { for item in iterator.into_iter() {
item.write(w)?; item.write(w)?;
} }
@ -334,7 +336,7 @@ fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
if let Some(size) = marker.inner_marker.size() { if let Some(size) = marker.inner_marker.size() {
let bytes_to_skip = size let bytes_to_skip = size
.checked_mul(len.try_into()?) .checked_mul(u64_to_usize(len))
.ok_or(Error::Value("List is too big".to_string()))?; .ok_or(Error::Value("List is too big".to_string()))?;
return advance(bytes_to_skip, r); return advance(bytes_to_skip, r);
}; };
@ -352,8 +354,8 @@ fn skip_epee_value<B: Buf>(r: &mut B, skipped_objects: &mut u8) -> Result<()> {
| InnerMarker::U8 | InnerMarker::U8
| InnerMarker::Bool => unreachable!("These types are constant size."), | InnerMarker::Bool => unreachable!("These types are constant size."),
InnerMarker::String => { InnerMarker::String => {
let len = read_varint(r)?; let len = u64_to_usize(read_varint(r)?);
advance(len.try_into()?, r)?; advance(len, r)?;
} }
InnerMarker::Object => { InnerMarker::Object => {
*skipped_objects += 1; *skipped_objects += 1;

View file

@ -7,6 +7,7 @@ use core::fmt::Debug;
use bytes::{Buf, BufMut, Bytes, BytesMut}; use bytes::{Buf, BufMut, Bytes, BytesMut};
use cuprate_fixed_bytes::{ByteArray, ByteArrayVec}; use cuprate_fixed_bytes::{ByteArray, ByteArrayVec};
use cuprate_helper::cast::u64_to_usize;
use crate::{ use crate::{
io::{checked_read_primitive, checked_write_primitive}, io::{checked_read_primitive, checked_write_primitive},
@ -66,11 +67,11 @@ impl<T: EpeeObject> EpeeValue for Vec<T> {
"Marker is not sequence when a sequence was expected", "Marker is not sequence when a sequence was expected",
)); ));
} }
let len = read_varint(r)?; let len = u64_to_usize(read_varint(r)?);
let individual_marker = Marker::new(marker.inner_marker); let individual_marker = Marker::new(marker.inner_marker);
let mut res = Vec::with_capacity(len.try_into()?); let mut res = Vec::with_capacity(len);
for _ in 0..len { for _ in 0..len {
res.push(T::read(r, &individual_marker)?); res.push(T::read(r, &individual_marker)?);
} }
@ -167,11 +168,13 @@ impl EpeeValue for Vec<u8> {
return Err(Error::Format("Byte array exceeded max length")); return Err(Error::Format("Byte array exceeded max length"));
} }
if r.remaining() < len.try_into()? { let len = u64_to_usize(len);
if r.remaining() < len {
return Err(Error::IO("Not enough bytes to fill object")); return Err(Error::IO("Not enough bytes to fill object"));
} }
let mut res = vec![0; len.try_into()?]; let mut res = vec![0; len];
r.copy_to_slice(&mut res); r.copy_to_slice(&mut res);
Ok(res) Ok(res)
@ -203,11 +206,13 @@ impl EpeeValue for Bytes {
return Err(Error::Format("Byte array exceeded max length")); return Err(Error::Format("Byte array exceeded max length"));
} }
if r.remaining() < len.try_into()? { let len = u64_to_usize(len);
if r.remaining() < len {
return Err(Error::IO("Not enough bytes to fill object")); return Err(Error::IO("Not enough bytes to fill object"));
} }
Ok(r.copy_to_bytes(len.try_into()?)) Ok(r.copy_to_bytes(len))
} }
fn epee_default_value() -> Option<Self> { fn epee_default_value() -> Option<Self> {
@ -236,11 +241,13 @@ impl EpeeValue for BytesMut {
return Err(Error::Format("Byte array exceeded max length")); return Err(Error::Format("Byte array exceeded max length"));
} }
if r.remaining() < len.try_into()? { let len = u64_to_usize(len);
if r.remaining() < len {
return Err(Error::IO("Not enough bytes to fill object")); return Err(Error::IO("Not enough bytes to fill object"));
} }
let mut bytes = BytesMut::zeroed(len.try_into()?); let mut bytes = BytesMut::zeroed(len);
r.copy_to_slice(&mut bytes); r.copy_to_slice(&mut bytes);
Ok(bytes) Ok(bytes)
@ -272,11 +279,13 @@ impl<const N: usize> EpeeValue for ByteArrayVec<N> {
return Err(Error::Format("Byte array exceeded max length")); return Err(Error::Format("Byte array exceeded max length"));
} }
if r.remaining() < usize::try_from(len)? { let len = u64_to_usize(len);
if r.remaining() < len {
return Err(Error::IO("Not enough bytes to fill object")); return Err(Error::IO("Not enough bytes to fill object"));
} }
ByteArrayVec::try_from(r.copy_to_bytes(usize::try_from(len)?)) ByteArrayVec::try_from(r.copy_to_bytes(len))
.map_err(|_| Error::Format("Field has invalid length")) .map_err(|_| Error::Format("Field has invalid length"))
} }
@ -302,7 +311,7 @@ impl<const N: usize> EpeeValue for ByteArray<N> {
return Err(Error::Format("Marker does not match expected Marker")); return Err(Error::Format("Marker does not match expected Marker"));
} }
let len: usize = read_varint(r)?.try_into()?; let len = u64_to_usize(read_varint(r)?);
if len != N { if len != N {
return Err(Error::Format("Byte array has incorrect length")); return Err(Error::Format("Byte array has incorrect length"));
} }
@ -370,11 +379,11 @@ impl<const N: usize> EpeeValue for Vec<[u8; N]> {
)); ));
} }
let len = read_varint(r)?; let len = u64_to_usize(read_varint(r)?);
let individual_marker = Marker::new(marker.inner_marker); let individual_marker = Marker::new(marker.inner_marker);
let mut res = Vec::with_capacity(len.try_into()?); let mut res = Vec::with_capacity(len);
for _ in 0..len { for _ in 0..len {
res.push(<[u8; N]>::read(r, &individual_marker)?); res.push(<[u8; N]>::read(r, &individual_marker)?);
} }
@ -406,11 +415,11 @@ macro_rules! epee_seq {
)); ));
} }
let len = read_varint(r)?; let len = u64_to_usize(read_varint(r)?);
let individual_marker = Marker::new(marker.inner_marker.clone()); let individual_marker = Marker::new(marker.inner_marker.clone());
let mut res = Vec::with_capacity(len.try_into()?); let mut res = Vec::with_capacity(len);
for _ in 0..len { for _ in 0..len {
res.push(<$val>::read(r, &individual_marker)?); res.push(<$val>::read(r, &individual_marker)?);
} }

View file

@ -12,6 +12,8 @@ default = []
tracing = ["dep:tracing", "tokio-util/tracing"] tracing = ["dep:tracing", "tokio-util/tracing"]
[dependencies] [dependencies]
cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] }
thiserror = { workspace = true } thiserror = { workspace = true }
bytes = { workspace = true, features = ["std"] } bytes = { workspace = true, features = ["std"] }
bitflags = { workspace = true } bitflags = { workspace = true }

View file

@ -20,6 +20,8 @@ use std::{fmt::Debug, marker::PhantomData};
use bytes::{Buf, BufMut, BytesMut}; use bytes::{Buf, BufMut, BytesMut};
use tokio_util::codec::{Decoder, Encoder}; use tokio_util::codec::{Decoder, Encoder};
use cuprate_helper::cast::u64_to_usize;
use crate::{ use crate::{
header::{Flags, HEADER_SIZE}, header::{Flags, HEADER_SIZE},
message::{make_dummy_message, LevinMessage}, message::{make_dummy_message, LevinMessage},
@ -114,10 +116,7 @@ impl<C: LevinCommand + Debug> Decoder for LevinBucketCodec<C> {
std::mem::replace(&mut self.state, LevinBucketState::WaitingForBody(head)); std::mem::replace(&mut self.state, LevinBucketState::WaitingForBody(head));
} }
LevinBucketState::WaitingForBody(head) => { LevinBucketState::WaitingForBody(head) => {
let body_len = head let body_len = u64_to_usize(head.size);
.size
.try_into()
.map_err(|_| BucketError::BucketExceededMaxSize)?;
if src.len() < body_len { if src.len() < body_len {
src.reserve(body_len - src.len()); src.reserve(body_len - src.len());
return Ok(None); return Ok(None);
@ -255,13 +254,11 @@ impl<T: LevinBody> Decoder for LevinMessageCodec<T> {
continue; continue;
}; };
let max_size = if self.bucket_codec.handshake_message_seen { let max_size = u64_to_usize(if self.bucket_codec.handshake_message_seen {
self.bucket_codec.protocol.max_packet_size self.bucket_codec.protocol.max_packet_size
} else { } else {
self.bucket_codec.protocol.max_packet_size_before_handshake self.bucket_codec.protocol.max_packet_size_before_handshake
} });
.try_into()
.expect("Levin max message size is too large, does not fit into a usize.");
if bytes.len().saturating_add(bucket.body.len()) > max_size { if bytes.len().saturating_add(bucket.body.len()) > max_size {
return Err(BucketError::InvalidFragmentedMessage( return Err(BucketError::InvalidFragmentedMessage(
@ -300,12 +297,7 @@ impl<T: LevinBody> Decoder for LevinMessageCodec<T> {
} }
// Check the fragmented message contains enough bytes to build the message. // Check the fragmented message contains enough bytes to build the message.
if bytes.len().saturating_sub(HEADER_SIZE) if bytes.len().saturating_sub(HEADER_SIZE) < u64_to_usize(header.size) {
< header
.size
.try_into()
.map_err(|_| BucketError::BucketExceededMaxSize)?
{
return Err(BucketError::InvalidFragmentedMessage( return Err(BucketError::InvalidFragmentedMessage(
"Fragmented message does not have enough bytes to fill bucket body", "Fragmented message does not have enough bytes to fill bucket body",
)); ));

View file

@ -38,6 +38,8 @@ use std::fmt::Debug;
use bytes::{Buf, Bytes}; use bytes::{Buf, Bytes};
use thiserror::Error; use thiserror::Error;
use cuprate_helper::cast::usize_to_u64;
pub mod codec; pub mod codec;
pub mod header; pub mod header;
pub mod message; pub mod message;
@ -212,7 +214,7 @@ impl<C: LevinCommand> BucketBuilder<C> {
Bucket { Bucket {
header: BucketHead { header: BucketHead {
signature: self.signature.unwrap(), signature: self.signature.unwrap(),
size: body.len().try_into().unwrap(), size: usize_to_u64(body.len()),
have_to_return_data: ty.have_to_return_data(), have_to_return_data: ty.have_to_return_data(),
command: self.command.unwrap(), command: self.command.unwrap(),
return_code: self.return_code.unwrap(), return_code: self.return_code.unwrap(),

View file

@ -5,6 +5,8 @@
//! for more control over what is actually sent over the wire at certain times. //! for more control over what is actually sent over the wire at certain times.
use bytes::{Bytes, BytesMut}; use bytes::{Bytes, BytesMut};
use cuprate_helper::cast::usize_to_u64;
use crate::{ use crate::{
header::{Flags, HEADER_SIZE}, header::{Flags, HEADER_SIZE},
Bucket, BucketBuilder, BucketError, BucketHead, LevinBody, LevinCommand, Protocol, Bucket, BucketBuilder, BucketError, BucketHead, LevinBody, LevinCommand, Protocol,
@ -106,9 +108,7 @@ pub fn make_fragmented_messages<T: LevinBody>(
new_body.resize(fragment_size - HEADER_SIZE, 0); new_body.resize(fragment_size - HEADER_SIZE, 0);
bucket.body = new_body.freeze(); bucket.body = new_body.freeze();
bucket.header.size = (fragment_size - HEADER_SIZE) bucket.header.size = usize_to_u64(fragment_size - HEADER_SIZE);
.try_into()
.expect("Bucket size does not fit into u64");
} }
return Ok(vec![bucket]); return Ok(vec![bucket]);
@ -118,9 +118,7 @@ pub fn make_fragmented_messages<T: LevinBody>(
// The first fragment will set the START flag, the last will set the END flag. // The first fragment will set the START flag, the last will set the END flag.
let fragment_head = BucketHead { let fragment_head = BucketHead {
signature: protocol.signature, signature: protocol.signature,
size: (fragment_size - HEADER_SIZE) size: usize_to_u64(fragment_size - HEADER_SIZE),
.try_into()
.expect("Bucket size does not fit into u64"),
have_to_return_data: false, have_to_return_data: false,
// Just use a default command. // Just use a default command.
command: T::Command::from(0), command: T::Command::from(0),
@ -191,7 +189,7 @@ pub(crate) fn make_dummy_message<T: LevinCommand>(protocol: &Protocol, size: usi
// A header to put on the dummy message. // A header to put on the dummy message.
let header = BucketHead { let header = BucketHead {
signature: protocol.signature, signature: protocol.signature,
size: size.try_into().expect("Bucket size does not fit into u64"), size: usize_to_u64(size),
have_to_return_data: false, have_to_return_data: false,
// Just use a default command. // Just use a default command.
command: T::from(0), command: T::from(0),

View file

@ -8,6 +8,8 @@ use tokio::{
}; };
use tokio_util::codec::{FramedRead, FramedWrite}; use tokio_util::codec::{FramedRead, FramedWrite};
use cuprate_helper::cast::u64_to_usize;
use cuprate_levin::{ use cuprate_levin::{
message::make_fragmented_messages, BucketBuilder, BucketError, LevinBody, LevinCommand, message::make_fragmented_messages, BucketBuilder, BucketError, LevinBody, LevinCommand,
LevinMessageCodec, MessageType, Protocol, LevinMessageCodec, MessageType, Protocol,
@ -54,7 +56,7 @@ impl LevinBody for TestBody {
_: MessageType, _: MessageType,
_: Self::Command, _: Self::Command,
) -> Result<Self, BucketError> { ) -> Result<Self, BucketError> {
let size = body.get_u64_le().try_into().unwrap(); let size = u64_to_usize(body.get_u64_le());
// bucket // bucket
Ok(TestBody::Bytes(size, body.copy_to_bytes(size))) Ok(TestBody::Bytes(size, body.copy_to_bytes(size)))
} }

View file

@ -15,6 +15,7 @@ cuprate-levin = { path = "../levin" }
cuprate-epee-encoding = { path = "../epee-encoding" } cuprate-epee-encoding = { path = "../epee-encoding" }
cuprate-fixed-bytes = { path = "../fixed-bytes" } cuprate-fixed-bytes = { path = "../fixed-bytes" }
cuprate-types = { path = "../../types", default-features = false, features = ["epee"] } cuprate-types = { path = "../../types", default-features = false, features = ["epee"] }
cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] }
bitflags = { workspace = true, features = ["std"] } bitflags = { workspace = true, features = ["std"] }
bytes = { workspace = true, features = ["std"] } bytes = { workspace = true, features = ["std"] }

View file

@ -99,7 +99,7 @@ impl LevinCommandTrait for LevinCommand {
LevinCommand::FluffyMissingTxsRequest => 1024 * 1024, // 1 MB LevinCommand::FluffyMissingTxsRequest => 1024 * 1024, // 1 MB
LevinCommand::GetTxPoolCompliment => 1024 * 1024 * 4, // 4 MB LevinCommand::GetTxPoolCompliment => 1024 * 1024 * 4, // 4 MB
LevinCommand::Unknown(_) => usize::MAX.try_into().unwrap_or(u64::MAX), LevinCommand::Unknown(_) => u64::MAX,
} }
} }

View file

@ -39,7 +39,7 @@ thread_local = { workspace = true, optional = true }
rayon = { workspace = true, optional = true } rayon = { workspace = true, optional = true }
[dev-dependencies] [dev-dependencies]
cuprate-helper = { path = "../../helper", features = ["thread"] } cuprate-helper = { path = "../../helper", features = ["thread", "cast"] }
cuprate-test-utils = { path = "../../test-utils" } cuprate-test-utils = { path = "../../test-utils" }
tokio = { workspace = true, features = ["full"] } tokio = { workspace = true, features = ["full"] }

View file

@ -442,7 +442,7 @@ mod test {
let mut block = BLOCK_V9_TX3.clone(); let mut block = BLOCK_V9_TX3.clone();
block.height = usize::try_from(u32::MAX).unwrap() + 1; block.height = cuprate_helper::cast::u32_to_usize(u32::MAX) + 1;
add_block(&block, &mut tables).unwrap(); add_block(&block, &mut tables).unwrap();
} }