mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-22 19:49:28 +00:00
helper: add and use cast
module (#264)
* helper: add `cast` module * fix crates * spacing
This commit is contained in:
parent
fdd1689665
commit
bec8cc0aa4
21 changed files with 163 additions and 58 deletions
3
Cargo.lock
generated
3
Cargo.lock
generated
|
@ -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",
|
||||||
|
|
|
@ -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"}
|
||||||
|
|
||||||
|
|
|
@ -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))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)?
|
||||||
};
|
};
|
||||||
|
|
|
@ -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(¤t_hf),
|
.effective_median_block_weight(¤t_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(¤t_hf),
|
next_difficulty: self.difficulty_cache.next_difficulty(¤t_hf),
|
||||||
|
|
|
@ -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
84
helper/src/cast.rs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)?);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
|
|
|
@ -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",
|
||||||
));
|
));
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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)))
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"] }
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue