From bec8cc0aa49517a13ff9132d3bf389cb9b20bcfa Mon Sep 17 00:00:00 2001 From: hinto-janai Date: Mon, 2 Sep 2024 13:09:52 -0400 Subject: [PATCH 1/3] helper: add and use `cast` module (#264) * helper: add `cast` module * fix crates * spacing --- Cargo.lock | 3 + consensus/rules/Cargo.toml | 2 +- consensus/rules/src/transactions/tests.rs | 6 +- consensus/src/block/alt_block.rs | 4 +- consensus/src/context/task.rs | 7 +- helper/Cargo.toml | 5 +- helper/src/cast.rs | 84 +++++++++++++++++++++++ helper/src/lib.rs | 3 + helper/src/map.rs | 6 +- net/epee-encoding/Cargo.toml | 1 + net/epee-encoding/src/lib.rs | 12 ++-- net/epee-encoding/src/value.rs | 39 +++++++---- net/levin/Cargo.toml | 2 + net/levin/src/codec.rs | 20 ++---- net/levin/src/lib.rs | 4 +- net/levin/src/message.rs | 12 ++-- net/levin/tests/fragmented_message.rs | 4 +- net/wire/Cargo.toml | 1 + net/wire/src/p2p.rs | 2 +- storage/blockchain/Cargo.toml | 2 +- storage/blockchain/src/ops/block.rs | 2 +- 21 files changed, 163 insertions(+), 58 deletions(-) create mode 100644 helper/src/cast.rs diff --git a/Cargo.lock b/Cargo.lock index 77531897..d004f954 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -646,6 +646,7 @@ version = "0.5.0" dependencies = [ "bytes", "cuprate-fixed-bytes", + "cuprate-helper", "hex", "paste", "ref-cast", @@ -713,6 +714,7 @@ version = "0.1.0" dependencies = [ "bitflags 2.5.0", "bytes", + "cuprate-helper", "futures", "proptest", "rand", @@ -893,6 +895,7 @@ dependencies = [ "bytes", "cuprate-epee-encoding", "cuprate-fixed-bytes", + "cuprate-helper", "cuprate-levin", "cuprate-types", "hex", diff --git a/consensus/rules/Cargo.toml b/consensus/rules/Cargo.toml index 2cf03e39..8ba321d6 100644 --- a/consensus/rules/Cargo.toml +++ b/consensus/rules/Cargo.toml @@ -11,7 +11,7 @@ proptest = ["dep:proptest", "dep:proptest-derive", "cuprate-types/proptest"] rayon = ["dep:rayon"] [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-cryptonight = {path = "../../cryptonight"} diff --git a/consensus/rules/src/transactions/tests.rs b/consensus/rules/src/transactions/tests.rs index cd0e8c3b..4da8fd53 100644 --- a/consensus/rules/src/transactions/tests.rs +++ b/consensus/rules/src/transactions/tests.rs @@ -9,6 +9,8 @@ use proptest::{collection::vec, prelude::*}; use monero_serai::transaction::Output; +use cuprate_helper::cast::u64_to_usize; + use super::*; use crate::decomposed_amount::DECOMPOSED_AMOUNTS; @@ -164,7 +166,7 @@ prop_compose! { if timebased || lock_height > 500_000_000 { Timelock::Time(time_for_time_lock) } else { - Timelock::Block(usize::try_from(lock_height).unwrap()) + Timelock::Block(u64_to_usize(lock_height)) } } } @@ -179,7 +181,7 @@ prop_compose! { match ty { 0 => Timelock::None, 1 => Timelock::Time(time_for_time_lock), - _ => Timelock::Block(usize::try_from(lock_height).unwrap()) + _ => Timelock::Block(u64_to_usize(lock_height)) } } } diff --git a/consensus/src/block/alt_block.rs b/consensus/src/block/alt_block.rs index 513697e9..9b94a27d 100644 --- a/consensus/src/block/alt_block.rs +++ b/consensus/src/block/alt_block.rs @@ -14,7 +14,7 @@ use cuprate_consensus_rules::{ miner_tx::MinerTxError, ConsensusError, }; -use cuprate_helper::asynch::rayon_spawn_async; +use cuprate_helper::{asynch::rayon_spawn_async, cast::u64_to_usize}; use cuprate_types::{ AltBlockInformation, Chain, ChainId, TransactionVerificationData, VerifiedTransactionInformation, @@ -101,7 +101,7 @@ where // Check the alt block timestamp is in the correct range. 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)? }; diff --git a/consensus/src/context/task.rs b/consensus/src/context/task.rs index 8939446a..2376c350 100644 --- a/consensus/src/context/task.rs +++ b/consensus/src/context/task.rs @@ -9,6 +9,7 @@ use tower::ServiceExt; use tracing::Instrument; use cuprate_consensus_rules::blocks::ContextToVerifyBlock; +use cuprate_helper::cast::u64_to_usize; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, Chain, @@ -168,9 +169,9 @@ impl ContextTask { .weight_cache .effective_median_block_weight(¤t_hf), top_hash: self.top_block_hash, - median_block_timestamp: self.difficulty_cache.median_timestamp( - usize::try_from(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW).unwrap(), - ), + median_block_timestamp: self + .difficulty_cache + .median_timestamp(u64_to_usize(BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW)), chain_height: self.chain_height, current_hf, next_difficulty: self.difficulty_cache.next_difficulty(¤t_hf), diff --git a/helper/Cargo.toml b/helper/Cargo.toml index 59e4e71d..9af25c60 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -10,14 +10,15 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/consensus" [features] # 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 = [] atomic = ["dep:crossbeam"] asynch = ["dep:futures", "dep:rayon"] +cast = [] constants = [] fs = ["dep:dirs"] num = [] -map = ["dep:monero-serai"] +map = ["cast", "dep:monero-serai"] time = ["dep:chrono", "std"] thread = ["std", "dep:target_os_lib"] diff --git a/helper/src/cast.rs b/helper/src/cast.rs new file mode 100644 index 00000000..81d0836a --- /dev/null +++ b/helper/src/cast.rs @@ -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); + } +} diff --git a/helper/src/lib.rs b/helper/src/lib.rs index 90f420d6..4dd31055 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -40,6 +40,9 @@ pub mod asynch; // async collides #[cfg(feature = "atomic")] pub mod atomic; +#[cfg(feature = "cast")] +pub mod cast; + #[cfg(feature = "constants")] pub mod constants; diff --git a/helper/src/map.rs b/helper/src/map.rs index 96d9f615..82d54940 100644 --- a/helper/src/map.rs +++ b/helper/src/map.rs @@ -7,6 +7,8 @@ //---------------------------------------------------------------------------------------------------- Use use monero_serai::transaction::Timelock; +use crate::cast::{u64_to_usize, usize_to_u64}; + //---------------------------------------------------------------------------------------------------- `(u64, u64) <-> u128` /// Split a [`u128`] value into 2 64-bit values. /// @@ -77,7 +79,7 @@ pub fn u64_to_timelock(u: u64) -> Timelock { if u == 0 { Timelock::None } else if u < 500_000_000 { - Timelock::Block(usize::try_from(u).unwrap()) + Timelock::Block(u64_to_usize(u)) } else { Timelock::Time(u) } @@ -97,7 +99,7 @@ pub fn u64_to_timelock(u: u64) -> Timelock { pub fn timelock_to_u64(timelock: Timelock) -> u64 { match timelock { Timelock::None => 0, - Timelock::Block(u) => u64::try_from(u).unwrap(), + Timelock::Block(u) => usize_to_u64(u), Timelock::Time(u) => u, } } diff --git a/net/epee-encoding/Cargo.toml b/net/epee-encoding/Cargo.toml index 7feac004..85ee2c93 100644 --- a/net/epee-encoding/Cargo.toml +++ b/net/epee-encoding/Cargo.toml @@ -15,6 +15,7 @@ default = ["std"] std = ["dep:thiserror", "bytes/std", "cuprate-fixed-bytes/std"] [dependencies] +cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] } cuprate-fixed-bytes = { path = "../fixed-bytes", default-features = false } paste = "1.0.14" diff --git a/net/epee-encoding/src/lib.rs b/net/epee-encoding/src/lib.rs index 5b64315e..fa3449b4 100644 --- a/net/epee-encoding/src/lib.rs +++ b/net/epee-encoding/src/lib.rs @@ -65,6 +65,8 @@ use core::{ops::Deref, str::from_utf8 as str_from_utf8}; use bytes::{Buf, BufMut, Bytes, BytesMut}; +use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; + pub mod container_as_blob; pub mod error; mod io; @@ -242,7 +244,7 @@ pub fn write_bytes, B: BufMut>(t: T, w: &mut B) -> Result<()> { let bytes = t.as_ref(); let len = bytes.len(); - write_varint(len.try_into()?, w)?; + write_varint(usize_to_u64(len), w)?; if w.remaining_mut() < len { return Err(Error::IO("Not enough capacity to write bytes")); @@ -286,7 +288,7 @@ where I: Iterator + ExactSizeIterator, B: BufMut, { - write_varint(iterator.len().try_into()?, w)?; + write_varint(usize_to_u64(iterator.len()), w)?; for item in iterator.into_iter() { item.write(w)?; } @@ -334,7 +336,7 @@ fn skip_epee_value(r: &mut B, skipped_objects: &mut u8) -> Result<()> { if let Some(size) = marker.inner_marker.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()))?; return advance(bytes_to_skip, r); }; @@ -352,8 +354,8 @@ fn skip_epee_value(r: &mut B, skipped_objects: &mut u8) -> Result<()> { | InnerMarker::U8 | InnerMarker::Bool => unreachable!("These types are constant size."), InnerMarker::String => { - let len = read_varint(r)?; - advance(len.try_into()?, r)?; + let len = u64_to_usize(read_varint(r)?); + advance(len, r)?; } InnerMarker::Object => { *skipped_objects += 1; diff --git a/net/epee-encoding/src/value.rs b/net/epee-encoding/src/value.rs index 094f0ef1..000d89c7 100644 --- a/net/epee-encoding/src/value.rs +++ b/net/epee-encoding/src/value.rs @@ -7,6 +7,7 @@ use core::fmt::Debug; use bytes::{Buf, BufMut, Bytes, BytesMut}; use cuprate_fixed_bytes::{ByteArray, ByteArrayVec}; +use cuprate_helper::cast::u64_to_usize; use crate::{ io::{checked_read_primitive, checked_write_primitive}, @@ -66,11 +67,11 @@ impl EpeeValue for Vec { "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 mut res = Vec::with_capacity(len.try_into()?); + let mut res = Vec::with_capacity(len); for _ in 0..len { res.push(T::read(r, &individual_marker)?); } @@ -167,11 +168,13 @@ impl EpeeValue for Vec { 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")); } - let mut res = vec![0; len.try_into()?]; + let mut res = vec![0; len]; r.copy_to_slice(&mut res); Ok(res) @@ -203,11 +206,13 @@ impl EpeeValue for Bytes { 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")); } - Ok(r.copy_to_bytes(len.try_into()?)) + Ok(r.copy_to_bytes(len)) } fn epee_default_value() -> Option { @@ -236,11 +241,13 @@ impl EpeeValue for BytesMut { 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")); } - let mut bytes = BytesMut::zeroed(len.try_into()?); + let mut bytes = BytesMut::zeroed(len); r.copy_to_slice(&mut bytes); Ok(bytes) @@ -272,11 +279,13 @@ impl EpeeValue for ByteArrayVec { 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")); } - 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")) } @@ -302,7 +311,7 @@ impl EpeeValue for ByteArray { 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 { return Err(Error::Format("Byte array has incorrect length")); } @@ -370,11 +379,11 @@ impl 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 mut res = Vec::with_capacity(len.try_into()?); + let mut res = Vec::with_capacity(len); for _ in 0..len { 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 mut res = Vec::with_capacity(len.try_into()?); + let mut res = Vec::with_capacity(len); for _ in 0..len { res.push(<$val>::read(r, &individual_marker)?); } diff --git a/net/levin/Cargo.toml b/net/levin/Cargo.toml index 13deabea..1c585b9c 100644 --- a/net/levin/Cargo.toml +++ b/net/levin/Cargo.toml @@ -12,6 +12,8 @@ default = [] tracing = ["dep:tracing", "tokio-util/tracing"] [dependencies] +cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] } + thiserror = { workspace = true } bytes = { workspace = true, features = ["std"] } bitflags = { workspace = true } diff --git a/net/levin/src/codec.rs b/net/levin/src/codec.rs index 3718d8c3..1177733f 100644 --- a/net/levin/src/codec.rs +++ b/net/levin/src/codec.rs @@ -20,6 +20,8 @@ use std::{fmt::Debug, marker::PhantomData}; use bytes::{Buf, BufMut, BytesMut}; use tokio_util::codec::{Decoder, Encoder}; +use cuprate_helper::cast::u64_to_usize; + use crate::{ header::{Flags, HEADER_SIZE}, message::{make_dummy_message, LevinMessage}, @@ -114,10 +116,7 @@ impl Decoder for LevinBucketCodec { std::mem::replace(&mut self.state, LevinBucketState::WaitingForBody(head)); } LevinBucketState::WaitingForBody(head) => { - let body_len = head - .size - .try_into() - .map_err(|_| BucketError::BucketExceededMaxSize)?; + let body_len = u64_to_usize(head.size); if src.len() < body_len { src.reserve(body_len - src.len()); return Ok(None); @@ -255,13 +254,11 @@ impl Decoder for LevinMessageCodec { 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 } else { 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 { return Err(BucketError::InvalidFragmentedMessage( @@ -300,12 +297,7 @@ impl Decoder for LevinMessageCodec { } // Check the fragmented message contains enough bytes to build the message. - if bytes.len().saturating_sub(HEADER_SIZE) - < header - .size - .try_into() - .map_err(|_| BucketError::BucketExceededMaxSize)? - { + if bytes.len().saturating_sub(HEADER_SIZE) < u64_to_usize(header.size) { return Err(BucketError::InvalidFragmentedMessage( "Fragmented message does not have enough bytes to fill bucket body", )); diff --git a/net/levin/src/lib.rs b/net/levin/src/lib.rs index 0a247f72..ab03bfb4 100644 --- a/net/levin/src/lib.rs +++ b/net/levin/src/lib.rs @@ -38,6 +38,8 @@ use std::fmt::Debug; use bytes::{Buf, Bytes}; use thiserror::Error; +use cuprate_helper::cast::usize_to_u64; + pub mod codec; pub mod header; pub mod message; @@ -212,7 +214,7 @@ impl BucketBuilder { Bucket { header: BucketHead { 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(), command: self.command.unwrap(), return_code: self.return_code.unwrap(), diff --git a/net/levin/src/message.rs b/net/levin/src/message.rs index af8227d7..19aa1b50 100644 --- a/net/levin/src/message.rs +++ b/net/levin/src/message.rs @@ -5,6 +5,8 @@ //! for more control over what is actually sent over the wire at certain times. use bytes::{Bytes, BytesMut}; +use cuprate_helper::cast::usize_to_u64; + use crate::{ header::{Flags, HEADER_SIZE}, Bucket, BucketBuilder, BucketError, BucketHead, LevinBody, LevinCommand, Protocol, @@ -106,9 +108,7 @@ pub fn make_fragmented_messages( new_body.resize(fragment_size - HEADER_SIZE, 0); bucket.body = new_body.freeze(); - bucket.header.size = (fragment_size - HEADER_SIZE) - .try_into() - .expect("Bucket size does not fit into u64"); + bucket.header.size = usize_to_u64(fragment_size - HEADER_SIZE); } return Ok(vec![bucket]); @@ -118,9 +118,7 @@ pub fn make_fragmented_messages( // The first fragment will set the START flag, the last will set the END flag. let fragment_head = BucketHead { signature: protocol.signature, - size: (fragment_size - HEADER_SIZE) - .try_into() - .expect("Bucket size does not fit into u64"), + size: usize_to_u64(fragment_size - HEADER_SIZE), have_to_return_data: false, // Just use a default command. command: T::Command::from(0), @@ -191,7 +189,7 @@ pub(crate) fn make_dummy_message(protocol: &Protocol, size: usi // A header to put on the dummy message. let header = BucketHead { 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, // Just use a default command. command: T::from(0), diff --git a/net/levin/tests/fragmented_message.rs b/net/levin/tests/fragmented_message.rs index 7799a719..512fd461 100644 --- a/net/levin/tests/fragmented_message.rs +++ b/net/levin/tests/fragmented_message.rs @@ -8,6 +8,8 @@ use tokio::{ }; use tokio_util::codec::{FramedRead, FramedWrite}; +use cuprate_helper::cast::u64_to_usize; + use cuprate_levin::{ message::make_fragmented_messages, BucketBuilder, BucketError, LevinBody, LevinCommand, LevinMessageCodec, MessageType, Protocol, @@ -54,7 +56,7 @@ impl LevinBody for TestBody { _: MessageType, _: Self::Command, ) -> Result { - let size = body.get_u64_le().try_into().unwrap(); + let size = u64_to_usize(body.get_u64_le()); // bucket Ok(TestBody::Bytes(size, body.copy_to_bytes(size))) } diff --git a/net/wire/Cargo.toml b/net/wire/Cargo.toml index 101daa39..cbeb5511 100644 --- a/net/wire/Cargo.toml +++ b/net/wire/Cargo.toml @@ -15,6 +15,7 @@ cuprate-levin = { path = "../levin" } cuprate-epee-encoding = { path = "../epee-encoding" } cuprate-fixed-bytes = { path = "../fixed-bytes" } cuprate-types = { path = "../../types", default-features = false, features = ["epee"] } +cuprate-helper = { path = "../../helper", default-features = false, features = ["cast"] } bitflags = { workspace = true, features = ["std"] } bytes = { workspace = true, features = ["std"] } diff --git a/net/wire/src/p2p.rs b/net/wire/src/p2p.rs index 97431099..3829d172 100644 --- a/net/wire/src/p2p.rs +++ b/net/wire/src/p2p.rs @@ -99,7 +99,7 @@ impl LevinCommandTrait for LevinCommand { LevinCommand::FluffyMissingTxsRequest => 1024 * 1024, // 1 MB LevinCommand::GetTxPoolCompliment => 1024 * 1024 * 4, // 4 MB - LevinCommand::Unknown(_) => usize::MAX.try_into().unwrap_or(u64::MAX), + LevinCommand::Unknown(_) => u64::MAX, } } diff --git a/storage/blockchain/Cargo.toml b/storage/blockchain/Cargo.toml index 7e79305a..58da21e6 100644 --- a/storage/blockchain/Cargo.toml +++ b/storage/blockchain/Cargo.toml @@ -39,7 +39,7 @@ thread_local = { workspace = true, optional = true } rayon = { workspace = true, optional = true } [dev-dependencies] -cuprate-helper = { path = "../../helper", features = ["thread"] } +cuprate-helper = { path = "../../helper", features = ["thread", "cast"] } cuprate-test-utils = { path = "../../test-utils" } tokio = { workspace = true, features = ["full"] } diff --git a/storage/blockchain/src/ops/block.rs b/storage/blockchain/src/ops/block.rs index 4f77d736..d1b83a45 100644 --- a/storage/blockchain/src/ops/block.rs +++ b/storage/blockchain/src/ops/block.rs @@ -442,7 +442,7 @@ mod test { 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(); } From b837d350a448ba400fdd0296464a58672db2cb7b Mon Sep 17 00:00:00 2001 From: hinto-janai Date: Mon, 2 Sep 2024 13:10:45 -0400 Subject: [PATCH 2/3] workspace: add naming convention lints (#261) * add lint to {Cargo,clippy}.toml * `RandomXVM` -> `RandomXVm` * epee: `TT` -> `T2` --- Cargo.toml | 2 ++ clippy.toml | 1 + consensus/src/block/alt_block.rs | 4 +-- consensus/src/block/batch_prepare.rs | 4 +-- consensus/src/context.rs | 8 ++--- consensus/src/context/alt_chains.rs | 4 +-- consensus/src/context/rx_vms.rs | 38 ++++++++++++------------ consensus/src/context/task.rs | 4 +-- consensus/src/tests/context/rx_vms.rs | 6 ++-- net/epee-encoding/tests/duplicate_key.rs | 6 ++-- 10 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 clippy.toml diff --git a/Cargo.toml b/Cargo.toml index 06b49a0a..1a0c6675 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -262,6 +262,7 @@ empty_structs_with_brackets = "deny" empty_enum_variants_with_brackets = "deny" empty_drop = "deny" clone_on_ref_ptr = "deny" +upper_case_acronyms = "deny" # Hot # inline_always = "deny" @@ -309,6 +310,7 @@ let_underscore_drop = "deny" unreachable_pub = "deny" unused_qualifications = "deny" variant_size_differences = "deny" +non_camel_case_types = "deny" # Hot # unused_results = "deny" diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 00000000..cc94ec53 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +upper-case-acronyms-aggressive = true diff --git a/consensus/src/block/alt_block.rs b/consensus/src/block/alt_block.rs index 9b94a27d..b20b4f26 100644 --- a/consensus/src/block/alt_block.rs +++ b/consensus/src/block/alt_block.rs @@ -24,7 +24,7 @@ use crate::{ block::{free::pull_ordered_transactions, PreparedBlock}, context::{ difficulty::DifficultyCache, - rx_vms::RandomXVM, + rx_vms::RandomXVm, weight::{self, BlockWeightsCache}, AltChainContextCache, AltChainRequestToken, BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW, }, @@ -195,7 +195,7 @@ async fn alt_rx_vm( parent_chain: Chain, alt_chain_context: &mut AltChainContextCache, context_svc: C, -) -> Result>, ExtendedConsensusError> +) -> Result>, ExtendedConsensusError> where C: Service< BlockChainContextRequest, diff --git a/consensus/src/block/batch_prepare.rs b/consensus/src/block/batch_prepare.rs index 9974d6d1..d32cd765 100644 --- a/consensus/src/block/batch_prepare.rs +++ b/consensus/src/block/batch_prepare.rs @@ -15,7 +15,7 @@ use cuprate_helper::asynch::rayon_spawn_async; use crate::{ block::{free::pull_ordered_transactions, PreparedBlock, PreparedBlockExPow}, - context::rx_vms::RandomXVM, + context::rx_vms::RandomXVm, transactions::new_tx_verification_data, BlockChainContextRequest, BlockChainContextResponse, ExtendedConsensusError, VerifyBlockResponse, @@ -148,7 +148,7 @@ where tracing::debug!("New randomX seed in batch, initialising VM"); let new_vm = rayon_spawn_async(move || { - Arc::new(RandomXVM::new(&new_vm_seed).expect("RandomX VM gave an error on set up!")) + Arc::new(RandomXVm::new(&new_vm_seed).expect("RandomX VM gave an error on set up!")) }) .await; diff --git a/consensus/src/context.rs b/consensus/src/context.rs index 26be75c3..9e713046 100644 --- a/consensus/src/context.rs +++ b/consensus/src/context.rs @@ -33,7 +33,7 @@ mod tokens; use cuprate_types::Chain; use difficulty::DifficultyCache; -use rx_vms::RandomXVM; +use rx_vms::RandomXVm; use weight::BlockWeightsCache; pub(crate) use alt_chains::{sealed::AltChainRequestToken, AltChainContextCache}; @@ -236,7 +236,7 @@ pub enum BlockChainContextRequest { /// seed. /// /// This should include the seed used to init this VM and the VM. - NewRXVM(([u8; 32], Arc)), + NewRXVM(([u8; 32], Arc)), /// A request to add a new block to the cache. Update(NewBlockData), /// Pop blocks from the cache to the specified height. @@ -313,7 +313,7 @@ pub enum BlockChainContextResponse { /// Blockchain context response. Context(BlockChainContext), /// A map of seed height to RandomX VMs. - RxVms(HashMap>), + RxVms(HashMap>), /// A list of difficulties. BatchDifficulties(Vec), /// An alt chain context cache. @@ -321,7 +321,7 @@ pub enum BlockChainContextResponse { /// A difficulty cache for an alt chain. AltChainDifficultyCache(DifficultyCache), /// A randomX VM for an alt chain. - AltChainRxVM(Arc), + AltChainRxVM(Arc), /// A weight cache for an alt chain AltChainWeightCache(BlockWeightsCache), /// A generic Ok response. diff --git a/consensus/src/context/alt_chains.rs b/consensus/src/context/alt_chains.rs index 5586226b..937e847e 100644 --- a/consensus/src/context/alt_chains.rs +++ b/consensus/src/context/alt_chains.rs @@ -11,7 +11,7 @@ use cuprate_types::{ use crate::{ ExtendedConsensusError, __private::Database, - context::{difficulty::DifficultyCache, rx_vms::RandomXVM, weight::BlockWeightsCache}, + context::{difficulty::DifficultyCache, rx_vms::RandomXVm, weight::BlockWeightsCache}, }; pub(crate) mod sealed { @@ -32,7 +32,7 @@ pub struct AltChainContextCache { pub difficulty_cache: Option, /// A cached RX VM. - pub cached_rx_vm: Option<(usize, Arc)>, + pub cached_rx_vm: Option<(usize, Arc)>, /// The chain height of the alt chain. pub chain_height: usize, diff --git a/consensus/src/context/rx_vms.rs b/consensus/src/context/rx_vms.rs index 01aa9738..b1ab102b 100644 --- a/consensus/src/context/rx_vms.rs +++ b/consensus/src/context/rx_vms.rs @@ -9,7 +9,7 @@ use std::{ }; use futures::{stream::FuturesOrdered, StreamExt}; -use randomx_rs::{RandomXCache, RandomXError, RandomXFlag, RandomXVM as VMInner}; +use randomx_rs::{RandomXCache, RandomXError, RandomXFlag, RandomXVM as VmInner}; use rayon::prelude::*; use thread_local::ThreadLocal; use tower::ServiceExt; @@ -33,16 +33,16 @@ const RX_SEEDS_CACHED: usize = 2; /// A multithreaded randomX VM. #[derive(Debug)] -pub struct RandomXVM { +pub struct RandomXVm { /// These RandomX VMs all share the same cache. - vms: ThreadLocal, + vms: ThreadLocal, /// The RandomX cache. cache: RandomXCache, /// The flags used to start the RandomX VMs. flags: RandomXFlag, } -impl RandomXVM { +impl RandomXVm { /// Create a new multithreaded randomX VM with the provided seed. pub fn new(seed: &[u8; 32]) -> Result { // TODO: allow passing in flags. @@ -50,7 +50,7 @@ impl RandomXVM { let cache = RandomXCache::new(flags, seed.as_slice())?; - Ok(RandomXVM { + Ok(RandomXVm { vms: ThreadLocal::new(), cache, flags, @@ -58,12 +58,12 @@ impl RandomXVM { } } -impl RandomX for RandomXVM { +impl RandomX for RandomXVm { type Error = RandomXError; fn calculate_hash(&self, buf: &[u8]) -> Result<[u8; 32], Self::Error> { self.vms - .get_or_try(|| VMInner::new(self.flags, Some(self.cache.clone()), None))? + .get_or_try(|| VmInner::new(self.flags, Some(self.cache.clone()), None))? .calculate_hash(buf) .map(|out| out.try_into().unwrap()) } @@ -72,17 +72,17 @@ impl RandomX for RandomXVM { /// The randomX VMs cache, keeps the VM needed to calculate the current block's PoW hash (if a VM is needed) and a /// couple more around this VM. #[derive(Clone, Debug)] -pub struct RandomXVMCache { +pub struct RandomXVmCache { /// The top [`RX_SEEDS_CACHED`] RX seeds. pub(crate) seeds: VecDeque<(usize, [u8; 32])>, /// The VMs for `seeds` (if after hf 12, otherwise this will be empty). - pub(crate) vms: HashMap>, + pub(crate) vms: HashMap>, /// A single cached VM that was given to us from a part of Cuprate. - pub(crate) cached_vm: Option<([u8; 32], Arc)>, + pub(crate) cached_vm: Option<([u8; 32], Arc)>, } -impl RandomXVMCache { +impl RandomXVmCache { #[instrument(name = "init_rx_vm_cache", level = "info", skip(database))] pub async fn init_from_chain_height( chain_height: usize, @@ -106,7 +106,7 @@ impl RandomXVMCache { .map(|(height, seed)| { ( *height, - Arc::new(RandomXVM::new(seed).expect("Failed to create RandomX VM!")), + Arc::new(RandomXVm::new(seed).expect("Failed to create RandomX VM!")), ) }) .collect() @@ -117,7 +117,7 @@ impl RandomXVMCache { HashMap::new() }; - Ok(RandomXVMCache { + Ok(RandomXVmCache { seeds, vms, cached_vm: None, @@ -125,7 +125,7 @@ impl RandomXVMCache { } /// Add a randomX VM to the cache, with the seed it was created with. - pub fn add_vm(&mut self, vm: ([u8; 32], Arc)) { + pub fn add_vm(&mut self, vm: ([u8; 32], Arc)) { self.cached_vm.replace(vm); } @@ -136,7 +136,7 @@ impl RandomXVMCache { height: usize, chain: Chain, database: D, - ) -> Result, ExtendedConsensusError> { + ) -> Result, ExtendedConsensusError> { let seed_height = randomx_seed_height(height); let BlockchainResponse::BlockHash(seed_hash) = database @@ -156,13 +156,13 @@ impl RandomXVMCache { } } - let alt_vm = rayon_spawn_async(move || Arc::new(RandomXVM::new(&seed_hash).unwrap())).await; + let alt_vm = rayon_spawn_async(move || Arc::new(RandomXVm::new(&seed_hash).unwrap())).await; Ok(alt_vm) } /// Get the main-chain RandomX VMs. - pub async fn get_vms(&mut self) -> HashMap> { + pub async fn get_vms(&mut self) -> HashMap> { match self.seeds.len().checked_sub(self.vms.len()) { // No difference in the amount of seeds to VMs. Some(0) => (), @@ -184,7 +184,7 @@ impl RandomXVMCache { } }; - rayon_spawn_async(move || Arc::new(RandomXVM::new(&next_seed_hash).unwrap())) + rayon_spawn_async(move || Arc::new(RandomXVm::new(&next_seed_hash).unwrap())) .await }; @@ -200,7 +200,7 @@ impl RandomXVMCache { seeds_clone .par_iter() .map(|(height, seed)| { - let vm = RandomXVM::new(seed).expect("Failed to create RandomX VM!"); + let vm = RandomXVm::new(seed).expect("Failed to create RandomX VM!"); let vm = Arc::new(vm); (*height, vm) }) diff --git a/consensus/src/context/task.rs b/consensus/src/context/task.rs index 2376c350..bc54285a 100644 --- a/consensus/src/context/task.rs +++ b/consensus/src/context/task.rs @@ -46,7 +46,7 @@ pub struct ContextTask { /// The weight cache. weight_cache: weight::BlockWeightsCache, /// The RX VM cache. - rx_vm_cache: rx_vms::RandomXVMCache, + rx_vm_cache: rx_vms::RandomXVmCache, /// The hard-fork state cache. hardfork_state: hardforks::HardForkState, @@ -128,7 +128,7 @@ impl ContextTask { let db = database.clone(); let rx_seed_handle = tokio::spawn(async move { - rx_vms::RandomXVMCache::init_from_chain_height(chain_height, ¤t_hf, db).await + rx_vms::RandomXVmCache::init_from_chain_height(chain_height, ¤t_hf, db).await }); let context_svc = ContextTask { diff --git a/consensus/src/tests/context/rx_vms.rs b/consensus/src/tests/context/rx_vms.rs index f18a9b59..5c198cf6 100644 --- a/consensus/src/tests/context/rx_vms.rs +++ b/consensus/src/tests/context/rx_vms.rs @@ -9,7 +9,7 @@ use cuprate_consensus_rules::{ }; use crate::{ - context::rx_vms::{get_last_rx_seed_heights, RandomXVMCache}, + context::rx_vms::{get_last_rx_seed_heights, RandomXVmCache}, tests::mock_db::*, }; @@ -42,7 +42,7 @@ fn rx_heights_consistent() { async fn rx_vm_created_on_hf_12() { let db = DummyDatabaseBuilder::default().finish(Some(10)); - let mut cache = RandomXVMCache::init_from_chain_height(10, &HardFork::V11, db) + let mut cache = RandomXVmCache::init_from_chain_height(10, &HardFork::V11, db) .await .unwrap(); @@ -67,7 +67,7 @@ proptest! { let rt = Builder::new_multi_thread().enable_all().build().unwrap(); rt.block_on(async move { - let cache = RandomXVMCache::init_from_chain_height(10, &hf, db).await.unwrap(); + let cache = RandomXVmCache::init_from_chain_height(10, &hf, db).await.unwrap(); assert!(cache.seeds.len() == cache.vms.len() || hf < HardFork::V12); }); } diff --git a/net/epee-encoding/tests/duplicate_key.rs b/net/epee-encoding/tests/duplicate_key.rs index c1b3148f..0ed87aff 100644 --- a/net/epee-encoding/tests/duplicate_key.rs +++ b/net/epee-encoding/tests/duplicate_key.rs @@ -9,12 +9,12 @@ epee_object!( a: u8, ); -struct TT { +struct T2 { a: u8, } epee_object!( - TT, + T2, a: u8 = 0, ); @@ -35,5 +35,5 @@ fn duplicate_key_with_default() { b'a', 0x0B, 0x00, ]; - assert!(from_bytes::(&mut &data[..]).is_err()); + assert!(from_bytes::(&mut &data[..]).is_err()); } From eead49beb09b4a0a8c4a2b0f38683311f53eb891 Mon Sep 17 00:00:00 2001 From: hinto-janai Date: Mon, 2 Sep 2024 13:12:54 -0400 Subject: [PATCH 3/3] lints: opt in manual lint crates (#263) * cargo.toml: transfer existing lints * rpc/interface: lints * rpc/json-rpc: lints * rpc/types: lints * storage/blockchain: lints * rpc/types: fix lints * cargo.toml: fix lint group priority * storage/blockchain: fix lints * fix misc lints * storage/database: fixes * storage/txpool: opt in lints + fixes * types: opt in + fixes * helper: opt in + fixes * types: remove borsh * rpc/interface: fix test * test fixes * database: fix lints * fix lint * tabs -> spaces * blockchain: `config/` -> `config.rs` --- Cargo.lock | 44 +++++--- Cargo.toml | 6 +- helper/Cargo.toml | 3 + helper/src/asynch.rs | 8 +- helper/src/atomic.rs | 2 + helper/src/fs.rs | 89 +++++---------- helper/src/lib.rs | 32 ------ helper/src/map.rs | 3 +- helper/src/network.rs | 8 +- helper/src/num.rs | 3 +- helper/src/thread.rs | 10 +- helper/src/time.rs | 2 + rpc/interface/Cargo.toml | 8 +- rpc/interface/src/lib.rs | 103 ++---------------- rpc/json-rpc/Cargo.toml | 5 +- rpc/json-rpc/src/lib.rs | 90 --------------- rpc/json-rpc/src/response.rs | 4 +- rpc/json-rpc/src/tests.rs | 1 + rpc/types/Cargo.toml | 9 +- rpc/types/src/lib.rs | 97 ++--------------- rpc/types/src/misc/mod.rs | 1 + storage/blockchain/Cargo.toml | 3 + storage/blockchain/src/{config => }/config.rs | 42 ++++++- storage/blockchain/src/config/mod.rs | 44 -------- storage/blockchain/src/lib.rs | 100 +---------------- storage/blockchain/src/service/free.rs | 4 +- storage/blockchain/src/service/tests.rs | 3 +- storage/database/Cargo.toml | 5 +- storage/database/src/backend/heed/env.rs | 2 +- storage/database/src/backend/heed/storable.rs | 4 +- storage/database/src/backend/redb/database.rs | 10 +- storage/database/src/config/mod.rs | 1 + storage/database/src/env.rs | 2 +- storage/database/src/key.rs | 4 +- storage/database/src/lib.rs | 102 +++-------------- storage/txpool/Cargo.toml | 3 + storage/txpool/src/config.rs | 2 +- storage/txpool/src/lib.rs | 14 +++ storage/txpool/src/ops/key_images.rs | 4 +- storage/txpool/src/service/free.rs | 4 +- storage/txpool/src/service/read.rs | 8 +- storage/txpool/src/service/write.rs | 2 +- storage/txpool/src/types.rs | 10 +- types/Cargo.toml | 6 +- types/src/lib.rs | 75 +------------ 45 files changed, 240 insertions(+), 742 deletions(-) rename storage/blockchain/src/{config => }/config.rs (82%) delete mode 100644 storage/blockchain/src/config/mod.rs diff --git a/Cargo.lock b/Cargo.lock index d004f954..950044c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,12 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + [[package]] name = "ahash" version = "0.8.11" @@ -160,7 +166,7 @@ dependencies = [ "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.7.3", "object", "rustc-demangle", ] @@ -798,6 +804,7 @@ dependencies = [ "cuprate-helper", "cuprate-json-rpc", "cuprate-rpc-types", + "cuprate-test-utils", "futures", "paste", "serde", @@ -813,12 +820,9 @@ version = "0.0.0" dependencies = [ "cuprate-epee-encoding", "cuprate-fixed-bytes", - "cuprate-json-rpc", "cuprate-test-utils", "cuprate-types", - "monero-serai", "paste", - "pretty_assertions", "serde", "serde_json", ] @@ -875,7 +879,6 @@ dependencies = [ name = "cuprate-types" version = "0.0.0" dependencies = [ - "borsh", "bytes", "cuprate-epee-encoding", "cuprate-fixed-bytes", @@ -1082,12 +1085,12 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -1241,9 +1244,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "524e8ac6999421f49a846c2d4411f337e53497d8ec55d67753beffa43c5d9205" dependencies = [ "atomic-waker", "bytes", @@ -1737,6 +1740,15 @@ dependencies = [ "adler", ] +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + [[package]] name = "mio" version = "0.8.11" @@ -2399,9 +2411,9 @@ dependencies = [ [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -2960,9 +2972,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "ureq" -version = "2.10.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72139d247e5f97a3eff96229a7ae85ead5328a39efe76f8bf5a06313d505b6ea" +checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ "base64", "flate2", @@ -3085,9 +3097,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] diff --git a/Cargo.toml b/Cargo.toml index 1a0c6675..0a98eab6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -279,13 +279,15 @@ upper_case_acronyms = "deny" # allow_attributes_without_reason = "deny" # missing_assert_message = "deny" # missing_docs_in_private_items = "deny" -# undocumented_unsafe_blocks = "deny" +undocumented_unsafe_blocks = "deny" # multiple_unsafe_ops_per_block = "deny" # single_char_lifetime_names = "deny" # wildcard_enum_match_arm = "deny" [workspace.lints.rust] # Cold +future_incompatible = { level = "deny", priority = -1 } +nonstandard_style = { level = "deny", priority = -1 } absolute_paths_not_starting_with_crate = "deny" explicit_outlives_requirements = "deny" keyword_idents_2018 = "deny" @@ -306,7 +308,7 @@ ambiguous_glob_imports = "deny" unused_unsafe = "deny" # Warm -let_underscore_drop = "deny" +let_underscore = { level = "deny", priority = -1 } unreachable_pub = "deny" unused_qualifications = "deny" variant_size_differences = "deny" diff --git a/helper/Cargo.toml b/helper/Cargo.toml index 9af25c60..c74e40fd 100644 --- a/helper/Cargo.toml +++ b/helper/Cargo.toml @@ -40,3 +40,6 @@ target_os_lib = { package = "libc", version = "0.2.151", optional = true } [dev-dependencies] tokio = { workspace = true, features = ["full"] } + +[lints] +workspace = true \ No newline at end of file diff --git a/helper/src/asynch.rs b/helper/src/asynch.rs index ea89dd79..9868191b 100644 --- a/helper/src/asynch.rs +++ b/helper/src/asynch.rs @@ -19,7 +19,7 @@ pub struct InfallibleOneshotReceiver(oneshot::Receiver); impl From> for InfallibleOneshotReceiver { fn from(value: oneshot::Receiver) -> Self { - InfallibleOneshotReceiver(value) + Self(value) } } @@ -43,7 +43,7 @@ where { let (tx, rx) = oneshot::channel(); rayon::spawn(move || { - let _ = tx.send(f()); + drop(tx.send(f())); }); rx.await.expect("The sender must not be dropped") } @@ -62,7 +62,7 @@ mod test { #[tokio::test] // Assert that basic channel operations work. async fn infallible_oneshot_receiver() { - let (tx, rx) = futures::channel::oneshot::channel::(); + let (tx, rx) = oneshot::channel::(); let msg = "hello world!".to_string(); tx.send(msg.clone()).unwrap(); @@ -84,7 +84,7 @@ mod test { let barrier = Arc::new(Barrier::new(2)); let task = |barrier: &Barrier| barrier.wait(); - let b_2 = barrier.clone(); + let b_2 = Arc::clone(&barrier); let (tx, rx) = std::sync::mpsc::channel(); diff --git a/helper/src/atomic.rs b/helper/src/atomic.rs index f253737a..47958964 100644 --- a/helper/src/atomic.rs +++ b/helper/src/atomic.rs @@ -49,6 +49,8 @@ pub type AtomicF64 = AtomicCell; //---------------------------------------------------------------------------------------------------- TESTS #[cfg(test)] mod tests { + #![allow(clippy::float_cmp)] + use super::*; #[test] diff --git a/helper/src/fs.rs b/helper/src/fs.rs index 7290361f..5d62a644 100644 --- a/helper/src/fs.rs +++ b/helper/src/fs.rs @@ -190,72 +190,41 @@ mod test { // - It must `ends_with()` the expected end PATH for the OS #[test] fn path_sanity_check() { - assert!(CUPRATE_CACHE_DIR.is_absolute()); - assert!(CUPRATE_CONFIG_DIR.is_absolute()); - assert!(CUPRATE_DATA_DIR.is_absolute()); - assert!(CUPRATE_BLOCKCHAIN_DIR.is_absolute()); + // Array of (PATH, expected_path_as_string). + // + // The different OS's will set the expected path below. + let mut array = [ + (&*CUPRATE_CACHE_DIR, ""), + (&*CUPRATE_CONFIG_DIR, ""), + (&*CUPRATE_DATA_DIR, ""), + (&*CUPRATE_BLOCKCHAIN_DIR, ""), + (&*CUPRATE_TXPOOL_DIR, ""), + ]; if cfg!(target_os = "windows") { - let dir = &*CUPRATE_CACHE_DIR; - println!("cuprate_cache_dir: {dir:?}"); - assert!(dir.ends_with(r"AppData\Local\Cuprate")); - - let dir = &*CUPRATE_CONFIG_DIR; - println!("cuprate_config_dir: {dir:?}"); - assert!(dir.ends_with(r"AppData\Roaming\Cuprate")); - - let dir = &*CUPRATE_DATA_DIR; - println!("cuprate_data_dir: {dir:?}"); - assert!(dir.ends_with(r"AppData\Roaming\Cuprate")); - - let dir = &*CUPRATE_BLOCKCHAIN_DIR; - println!("cuprate_blockchain_dir: {dir:?}"); - assert!(dir.ends_with(r"AppData\Roaming\Cuprate\blockchain")); - - let dir = &*CUPRATE_TXPOOL_DIR; - println!("cuprate_txpool_dir: {dir:?}"); - assert!(dir.ends_with(r"AppData\Roaming\Cuprate\txpool")); + array[0].1 = r"AppData\Local\Cuprate"; + array[1].1 = r"AppData\Roaming\Cuprate"; + array[2].1 = r"AppData\Roaming\Cuprate"; + array[3].1 = r"AppData\Roaming\Cuprate\blockchain"; + array[4].1 = r"AppData\Roaming\Cuprate\txpool"; } else if cfg!(target_os = "macos") { - let dir = &*CUPRATE_CACHE_DIR; - println!("cuprate_cache_dir: {dir:?}"); - assert!(dir.ends_with("Library/Caches/Cuprate")); - - let dir = &*CUPRATE_CONFIG_DIR; - println!("cuprate_config_dir: {dir:?}"); - assert!(dir.ends_with("Library/Application Support/Cuprate")); - - let dir = &*CUPRATE_DATA_DIR; - println!("cuprate_data_dir: {dir:?}"); - assert!(dir.ends_with("Library/Application Support/Cuprate")); - - let dir = &*CUPRATE_BLOCKCHAIN_DIR; - println!("cuprate_blockchain_dir: {dir:?}"); - assert!(dir.ends_with("Library/Application Support/Cuprate/blockchain")); - - let dir = &*CUPRATE_TXPOOL_DIR; - println!("cuprate_txpool_dir: {dir:?}"); - assert!(dir.ends_with("Library/Application Support/Cuprate/txpool")); + array[0].1 = "Library/Caches/Cuprate"; + array[1].1 = "Library/Application Support/Cuprate"; + array[2].1 = "Library/Application Support/Cuprate"; + array[3].1 = "Library/Application Support/Cuprate/blockchain"; + array[4].1 = "Library/Application Support/Cuprate/txpool"; } else { // Assumes Linux. - let dir = &*CUPRATE_CACHE_DIR; - println!("cuprate_cache_dir: {dir:?}"); - assert!(dir.ends_with(".cache/cuprate")); + array[0].1 = ".cache/cuprate"; + array[1].1 = ".config/cuprate"; + array[2].1 = ".local/share/cuprate"; + array[3].1 = ".local/share/cuprate/blockchain"; + array[4].1 = ".local/share/cuprate/txpool"; + }; - let dir = &*CUPRATE_CONFIG_DIR; - println!("cuprate_config_dir: {dir:?}"); - assert!(dir.ends_with(".config/cuprate")); - - let dir = &*CUPRATE_DATA_DIR; - println!("cuprate_data_dir: {dir:?}"); - assert!(dir.ends_with(".local/share/cuprate")); - - let dir = &*CUPRATE_BLOCKCHAIN_DIR; - println!("cuprate_blockchain_dir: {dir:?}"); - assert!(dir.ends_with(".local/share/cuprate/blockchain")); - - let dir = &*CUPRATE_TXPOOL_DIR; - println!("cuprate_txpool_dir: {dir:?}"); - assert!(dir.ends_with(".local/share/cuprate/txpool")); + for (path, expected) in array { + assert!(path.is_absolute()); + assert!(path.ends_with(expected)); } } } diff --git a/helper/src/lib.rs b/helper/src/lib.rs index 4dd31055..de0d9555 100644 --- a/helper/src/lib.rs +++ b/helper/src/lib.rs @@ -1,36 +1,4 @@ #![doc = include_str!("../README.md")] -//---------------------------------------------------------------------------------------------------- Lints -#![allow(clippy::len_zero, clippy::type_complexity, clippy::module_inception)] -#![deny(nonstandard_style, deprecated, missing_docs, unused_mut)] -#![forbid( - unused_unsafe, - future_incompatible, - break_with_label_and_loop, - coherence_leak_check, - duplicate_macro_attributes, - exported_private_dependencies, - for_loops_over_fallibles, - large_assignments, - overlapping_range_endpoints, - // private_in_public, - semicolon_in_expressions_from_macros, - redundant_semicolons, - unconditional_recursion, - unreachable_patterns, - unused_allocation, - unused_braces, - unused_comparisons, - unused_doc_comments, - unused_parens, - unused_labels, - while_true, - keyword_idents, - non_ascii_idents, - noop_method_call, - unreachable_pub, - single_use_lifetimes, - // variant_size_differences, -)] #![cfg_attr(not(feature = "std"), no_std)] //---------------------------------------------------------------------------------------------------- Public API diff --git a/helper/src/map.rs b/helper/src/map.rs index 82d54940..ea6dfc49 100644 --- a/helper/src/map.rs +++ b/helper/src/map.rs @@ -29,6 +29,7 @@ use crate::cast::{u64_to_usize, usize_to_u64}; /// ``` #[inline] pub const fn split_u128_into_low_high_bits(value: u128) -> (u64, u64) { + #[allow(clippy::cast_possible_truncation)] (value as u64, (value >> 64) as u64) } @@ -60,7 +61,7 @@ pub const fn combine_low_high_bits_to_u128(low_bits: u64, high_bits: u64) -> u12 /// Map a [`u64`] to a [`Timelock`]. /// /// Height/time is not differentiated via type, but rather: -/// "height is any value less than 500_000_000 and timestamp is any value above" +/// "height is any value less than `500_000_000` and timestamp is any value above" /// so the `u64/usize` is stored without any tag. /// /// See [`timelock_to_u64`] for the inverse function. diff --git a/helper/src/network.rs b/helper/src/network.rs index 684e71a4..f3224b33 100644 --- a/helper/src/network.rs +++ b/helper/src/network.rs @@ -30,11 +30,11 @@ pub enum Network { impl Network { /// Returns the network ID for the current network. - pub fn network_id(&self) -> [u8; 16] { + pub const fn network_id(&self) -> [u8; 16] { match self { - Network::Mainnet => MAINNET_NETWORK_ID, - Network::Testnet => TESTNET_NETWORK_ID, - Network::Stagenet => STAGENET_NETWORK_ID, + Self::Mainnet => MAINNET_NETWORK_ID, + Self::Testnet => TESTNET_NETWORK_ID, + Self::Stagenet => STAGENET_NETWORK_ID, } } } diff --git a/helper/src/num.rs b/helper/src/num.rs index f90357e9..674ed354 100644 --- a/helper/src/num.rs +++ b/helper/src/num.rs @@ -89,8 +89,9 @@ where /// assert_eq!(median(vec), 5); /// ``` /// -/// # Safety +/// # Invariant /// If not sorted the output will be invalid. +#[allow(clippy::debug_assert_with_mut_call)] pub fn median(array: impl AsRef<[T]>) -> T where T: Add diff --git a/helper/src/thread.rs b/helper/src/thread.rs index 96958ff6..04a26069 100644 --- a/helper/src/thread.rs +++ b/helper/src/thread.rs @@ -28,10 +28,10 @@ macro_rules! impl_thread_percent { $( $(#[$doc])* pub fn $fn_name() -> NonZeroUsize { - // SAFETY: // unwrap here is okay because: // - THREADS().get() is always non-zero // - max() guards against 0 + #[allow(clippy::cast_possible_truncation, clippy::cast_sign_loss, clippy::cast_precision_loss)] NonZeroUsize::new(max(1, (threads().get() as f64 * $percent).floor() as usize)).unwrap() } )* @@ -58,10 +58,10 @@ impl_thread_percent! { /// Originally from . /// /// # Windows -/// Uses SetThreadPriority() with THREAD_PRIORITY_IDLE (-15). +/// Uses `SetThreadPriority()` with `THREAD_PRIORITY_IDLE` (-15). /// /// # Unix -/// Uses libc::nice() with the max nice level. +/// Uses `libc::nice()` with the max nice level. /// /// On macOS and *BSD: +20 /// On Linux: +19 @@ -74,7 +74,7 @@ pub fn low_priority_thread() { // SAFETY: calling C. // We are _lowering_ our priority, not increasing, so this function should never fail. unsafe { - let _ = SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE); + drop(SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE)); } } @@ -87,7 +87,7 @@ pub fn low_priority_thread() { // SAFETY: calling C. // We are _lowering_ our priority, not increasing, so this function should never fail. unsafe { - let _ = libc::nice(NICE_MAX); + libc::nice(NICE_MAX); } } } diff --git a/helper/src/time.rs b/helper/src/time.rs index 28aff7f5..ce39c2dc 100644 --- a/helper/src/time.rs +++ b/helper/src/time.rs @@ -129,6 +129,7 @@ pub const fn secs_to_clock(seconds: u32) -> (u8, u8, u8) { debug_assert!(m < 60); debug_assert!(s < 60); + #[allow(clippy::cast_possible_truncation)] // checked above (h as u8, m, s) } @@ -153,6 +154,7 @@ pub fn time() -> u32 { /// /// This is guaranteed to return a value between `0..=86399` pub fn time_utc() -> u32 { + #[allow(clippy::cast_sign_loss)] // checked in function calls unix_clock(chrono::offset::Local::now().timestamp() as u64) } diff --git a/rpc/interface/Cargo.toml b/rpc/interface/Cargo.toml index a83c0f07..5f173177 100644 --- a/rpc/interface/Cargo.toml +++ b/rpc/interface/Cargo.toml @@ -20,13 +20,17 @@ cuprate-helper = { path = "../../helper", features = ["asynch"], default- axum = { version = "0.7.5", features = ["json"], default-features = false } serde = { workspace = true, optional = true } -serde_json = { workspace = true, features = ["std"] } tower = { workspace = true } paste = { workspace = true } futures = { workspace = true } [dev-dependencies] +cuprate-test-utils = { path = "../../test-utils" } + axum = { version = "0.7.5", features = ["json", "tokio", "http2"] } serde_json = { workspace = true, features = ["std"] } tokio = { workspace = true, features = ["full"] } -ureq = { version = "2.10.0", features = ["json"] } \ No newline at end of file +ureq = { version = "2.10.0", features = ["json"] } + +[lints] +workspace = true \ No newline at end of file diff --git a/rpc/interface/src/lib.rs b/rpc/interface/src/lib.rs index 43bd9e1c..d4376979 100644 --- a/rpc/interface/src/lib.rs +++ b/rpc/interface/src/lib.rs @@ -1,99 +1,6 @@ #![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_cfg))] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - while_true, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - single_use_lifetimes, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - unused_doc_comments, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style, - unreachable_pub -)] -#![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - // FIXME: good lint but too many false positives - // with our `Env` + `RwLock` setup. - clippy::significant_drop_tightening, - - // FIXME: good lint but is less clear in most cases. - clippy::items_after_statements, - - // TODO - rustdoc::bare_urls, - - clippy::multiple_crate_versions, - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, -)] -// Allow some lints in tests. -#![cfg_attr( - test, - allow( - clippy::cognitive_complexity, - clippy::needless_pass_by_value, - clippy::cast_possible_truncation, - clippy::too_many_lines - ) -)] - -//---------------------------------------------------------------------------------------------------- Mod mod route; mod router_builder; mod rpc_error; @@ -110,3 +17,13 @@ pub use rpc_handler::RpcHandler; pub use rpc_handler_dummy::RpcHandlerDummy; pub use rpc_request::RpcRequest; pub use rpc_response::RpcResponse; + +// false-positive: used in `README.md`'s doc-test. +#[cfg(test)] +mod test { + extern crate axum; + extern crate cuprate_test_utils; + extern crate serde_json; + extern crate tokio; + extern crate ureq; +} diff --git a/rpc/json-rpc/Cargo.toml b/rpc/json-rpc/Cargo.toml index 777f3264..5d2544e4 100644 --- a/rpc/json-rpc/Cargo.toml +++ b/rpc/json-rpc/Cargo.toml @@ -17,4 +17,7 @@ serde_json = { workspace = true, features = ["std"] } thiserror = { workspace = true } [dev-dependencies] -pretty_assertions = { workspace = true } \ No newline at end of file +pretty_assertions = { workspace = true } + +[lints] +workspace = true \ No newline at end of file diff --git a/rpc/json-rpc/src/lib.rs b/rpc/json-rpc/src/lib.rs index ce7467a1..dfc4b181 100644 --- a/rpc/json-rpc/src/lib.rs +++ b/rpc/json-rpc/src/lib.rs @@ -1,94 +1,5 @@ #![doc = include_str!("../README.md")] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - while_true, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - single_use_lifetimes, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, - unreachable_pub, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - clippy::missing_docs_in_private_items, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style -)] -#![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - // FIXME: good lint but too many false positives - // with our `Env` + `RwLock` setup. - clippy::significant_drop_tightening, - - // FIXME: good lint but is less clear in most cases. - clippy::items_after_statements, - - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, -)] -// Allow some lints in tests. -#![cfg_attr( - test, - allow( - clippy::cognitive_complexity, - clippy::needless_pass_by_value, - clippy::cast_possible_truncation, - clippy::too_many_lines - ) -)] - -//---------------------------------------------------------------------------------------------------- Mod/Use pub mod error; mod id; @@ -103,6 +14,5 @@ pub use request::Request; mod response; pub use response::Response; -//---------------------------------------------------------------------------------------------------- TESTS #[cfg(test)] mod tests; diff --git a/rpc/json-rpc/src/response.rs b/rpc/json-rpc/src/response.rs index efd768b5..2b846069 100644 --- a/rpc/json-rpc/src/response.rs +++ b/rpc/json-rpc/src/response.rs @@ -304,14 +304,14 @@ where if payload.is_none() { payload = Some(Ok(map.next_value::()?)); } else { - return Err(serde::de::Error::duplicate_field("result/error")); + return Err(Error::duplicate_field("result/error")); } } Key::Error => { if payload.is_none() { payload = Some(Err(map.next_value::()?)); } else { - return Err(serde::de::Error::duplicate_field("result/error")); + return Err(Error::duplicate_field("result/error")); } } Key::Unknown => { diff --git a/rpc/json-rpc/src/tests.rs b/rpc/json-rpc/src/tests.rs index ff8f0496..3ee60881 100644 --- a/rpc/json-rpc/src/tests.rs +++ b/rpc/json-rpc/src/tests.rs @@ -52,6 +52,7 @@ where } /// Tests an input JSON string matches an expected type `T`. +#[allow(clippy::needless_pass_by_value)] // serde signature fn assert_de(json: &'static str, expected: T) where T: DeserializeOwned + std::fmt::Debug + Clone + PartialEq, diff --git a/rpc/types/Cargo.toml b/rpc/types/Cargo.toml index 9c996818..08b13b18 100644 --- a/rpc/types/Cargo.toml +++ b/rpc/types/Cargo.toml @@ -18,13 +18,14 @@ cuprate-epee-encoding = { path = "../../net/epee-encoding", optional = true } cuprate-fixed-bytes = { path = "../../net/fixed-bytes" } cuprate-types = { path = "../../types" } -monero-serai = { workspace = true } paste = { workspace = true } serde = { workspace = true, optional = true } [dev-dependencies] cuprate-test-utils = { path = "../../test-utils" } -cuprate-json-rpc = { path = "../json-rpc" } -serde_json = { workspace = true } -pretty_assertions = { workspace = true } \ No newline at end of file +serde = { workspace = true } +serde_json = { workspace = true } + +[lints] +workspace = true \ No newline at end of file diff --git a/rpc/types/src/lib.rs b/rpc/types/src/lib.rs index c5f890f6..51ea3cc2 100644 --- a/rpc/types/src/lib.rs +++ b/rpc/types/src/lib.rs @@ -1,96 +1,6 @@ #![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_cfg))] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - while_true, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - single_use_lifetimes, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - unused_doc_comments, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style, - unreachable_pub -)] -#![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - // FIXME: good lint but too many false positives - // with our `Env` + `RwLock` setup. - clippy::significant_drop_tightening, - - // FIXME: good lint but is less clear in most cases. - clippy::items_after_statements, - - clippy::multiple_crate_versions, - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, -)] -// Allow some lints in tests. -#![cfg_attr( - test, - allow( - clippy::cognitive_complexity, - clippy::needless_pass_by_value, - clippy::cast_possible_truncation, - clippy::too_many_lines - ) -)] - -//---------------------------------------------------------------------------------------------------- Mod mod constants; mod defaults; mod free; @@ -112,3 +22,10 @@ pub use constants::{ CORE_RPC_VERSION_MINOR, }; pub use rpc_call::{RpcCall, RpcCallValue}; + +// false-positive: used in tests +#[cfg(test)] +mod test { + extern crate cuprate_test_utils; + extern crate serde_json; +} diff --git a/rpc/types/src/misc/mod.rs b/rpc/types/src/misc/mod.rs index bd6454dd..c5c1840e 100644 --- a/rpc/types/src/misc/mod.rs +++ b/rpc/types/src/misc/mod.rs @@ -15,6 +15,7 @@ mod binary_string; mod distribution; mod key_image_spent_status; +#[allow(clippy::module_inception)] mod misc; mod pool_info_extent; mod status; diff --git a/storage/blockchain/Cargo.toml b/storage/blockchain/Cargo.toml index 58da21e6..e0399033 100644 --- a/storage/blockchain/Cargo.toml +++ b/storage/blockchain/Cargo.toml @@ -48,3 +48,6 @@ pretty_assertions = { workspace = true } proptest = { workspace = true } hex = { workspace = true } hex-literal = { workspace = true } + +[lints] +workspace = true diff --git a/storage/blockchain/src/config/config.rs b/storage/blockchain/src/config.rs similarity index 82% rename from storage/blockchain/src/config/config.rs rename to storage/blockchain/src/config.rs index 957c67c0..e4b76068 100644 --- a/storage/blockchain/src/config/config.rs +++ b/storage/blockchain/src/config.rs @@ -1,4 +1,44 @@ -//! The main [`Config`] struct, holding all configurable values. +//! Database configuration. +//! +//! This module contains the main [`Config`]uration struct +//! for the database [`Env`](cuprate_database::Env)ironment, +//! and blockchain-specific configuration. +//! +//! It also contains types related to configuration settings. +//! +//! The main constructor is the [`ConfigBuilder`]. +//! +//! These configurations are processed at runtime, meaning +//! the `Env` can/will dynamically adjust its behavior based +//! on these values. +//! +//! # Example +//! ```rust +//! use cuprate_blockchain::{ +//! cuprate_database::{Env, config::SyncMode}, +//! config::{ConfigBuilder, ReaderThreads}, +//! }; +//! +//! # fn main() -> Result<(), Box> { +//! let tmp_dir = tempfile::tempdir()?; +//! let db_dir = tmp_dir.path().to_owned(); +//! +//! let config = ConfigBuilder::new() +//! // Use a custom database directory. +//! .db_directory(db_dir.into()) +//! // Use as many reader threads as possible (when using `service`). +//! .reader_threads(ReaderThreads::OnePerThread) +//! // Use the fastest sync mode. +//! .sync_mode(SyncMode::Fast) +//! // Build into `Config` +//! .build(); +//! +//! // Start a database `service` using this configuration. +//! let (_, _, env) = cuprate_blockchain::service::init(config.clone())?; +//! // It's using the config we provided. +//! assert_eq!(env.config(), &config.db_config); +//! # Ok(()) } +//! ``` //---------------------------------------------------------------------------------------------------- Import use std::{borrow::Cow, path::Path}; diff --git a/storage/blockchain/src/config/mod.rs b/storage/blockchain/src/config/mod.rs deleted file mode 100644 index 555a6e6e..00000000 --- a/storage/blockchain/src/config/mod.rs +++ /dev/null @@ -1,44 +0,0 @@ -//! Database configuration. -//! -//! This module contains the main [`Config`]uration struct -//! for the database [`Env`](cuprate_database::Env)ironment, -//! and blockchain-specific configuration. -//! -//! It also contains types related to configuration settings. -//! -//! The main constructor is the [`ConfigBuilder`]. -//! -//! These configurations are processed at runtime, meaning -//! the `Env` can/will dynamically adjust its behavior based -//! on these values. -//! -//! # Example -//! ```rust -//! use cuprate_blockchain::{ -//! cuprate_database::{Env, config::SyncMode}, -//! config::{ConfigBuilder, ReaderThreads}, -//! }; -//! -//! # fn main() -> Result<(), Box> { -//! let tmp_dir = tempfile::tempdir()?; -//! let db_dir = tmp_dir.path().to_owned(); -//! -//! let config = ConfigBuilder::new() -//! // Use a custom database directory. -//! .db_directory(db_dir.into()) -//! // Use as many reader threads as possible (when using `service`). -//! .reader_threads(ReaderThreads::OnePerThread) -//! // Use the fastest sync mode. -//! .sync_mode(SyncMode::Fast) -//! // Build into `Config` -//! .build(); -//! -//! // Start a database `service` using this configuration. -//! let (_, _, env) = cuprate_blockchain::service::init(config.clone())?; -//! // It's using the config we provided. -//! assert_eq!(env.config(), &config.db_config); -//! # Ok(()) } -//! ``` - -mod config; -pub use config::{Config, ConfigBuilder, ReaderThreads}; diff --git a/storage/blockchain/src/lib.rs b/storage/blockchain/src/lib.rs index e544a69e..f66cd99b 100644 --- a/storage/blockchain/src/lib.rs +++ b/storage/blockchain/src/lib.rs @@ -1,103 +1,9 @@ #![doc = include_str!("../README.md")] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - while_true, - clippy::missing_docs_in_private_items, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - single_use_lifetimes, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, - unreachable_pub, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - unused_crate_dependencies, - unused_doc_comments, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style -)] #![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - // FIXME: good lint but too many false positives - // with our `Env` + `RwLock` setup. - clippy::significant_drop_tightening, - - // FIXME: good lint but is less clear in most cases. - clippy::items_after_statements, - - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, -)] -// Allow some lints when running in debug mode. -#![cfg_attr( - debug_assertions, - allow( - clippy::todo, - clippy::multiple_crate_versions, - // unused_crate_dependencies, - ) -)] -// Allow some lints in tests. -#![cfg_attr( - test, - allow( - clippy::cognitive_complexity, - clippy::needless_pass_by_value, - clippy::cast_possible_truncation, - clippy::too_many_lines - ) + // See `cuprate-database` for reasoning. + clippy::significant_drop_tightening )] + // Only allow building 64-bit targets. // // This allows us to assume 64-bit diff --git a/storage/blockchain/src/service/free.rs b/storage/blockchain/src/service/free.rs index e748bbbe..2e7c9086 100644 --- a/storage/blockchain/src/service/free.rs +++ b/storage/blockchain/src/service/free.rs @@ -37,8 +37,8 @@ pub fn init( let db = Arc::new(crate::open(config)?); // Spawn the Reader thread pool and Writer. - let readers = init_read_service(db.clone(), reader_threads); - let writer = init_write_service(db.clone()); + let readers = init_read_service(Arc::clone(&db), reader_threads); + let writer = init_write_service(Arc::clone(&db)); Ok((readers, writer, db)) } diff --git a/storage/blockchain/src/service/tests.rs b/storage/blockchain/src/service/tests.rs index ed13f7b3..b68b5444 100644 --- a/storage/blockchain/src/service/tests.rs +++ b/storage/blockchain/src/service/tests.rs @@ -304,8 +304,9 @@ async fn test_template( // Assert we get back the same map of // `Amount`'s and `AmountIndex`'s. let mut response_output_count = 0; + #[allow(clippy::iter_over_hash_type)] // order doesn't matter in this test for (amount, output_map) in response { - let amount_index_set = map.get(&amount).unwrap(); + let amount_index_set = &map[&amount]; for (amount_index, output) in output_map { response_output_count += 1; diff --git a/storage/database/Cargo.toml b/storage/database/Cargo.toml index a70457f5..0ef4a97d 100644 --- a/storage/database/Cargo.toml +++ b/storage/database/Cargo.toml @@ -32,4 +32,7 @@ serde = { workspace = true, optional = true } [dev-dependencies] bytemuck = { version = "1.14.3", features = ["must_cast", "derive", "min_const_generics", "extern_crate_alloc"] } page_size = { version = "0.6.0" } -tempfile = { version = "3.10.0" } \ No newline at end of file +tempfile = { version = "3.10.0" } + +[lints] +workspace = true \ No newline at end of file diff --git a/storage/database/src/backend/heed/env.rs b/storage/database/src/backend/heed/env.rs index 0c2847fb..8c71e617 100644 --- a/storage/database/src/backend/heed/env.rs +++ b/storage/database/src/backend/heed/env.rs @@ -70,7 +70,7 @@ impl Drop for ConcreteEnv { // We need to do `mdb_env_set_flags(&env, MDB_NOSYNC|MDB_ASYNCMAP, 0)` // to clear the no sync and async flags such that the below `self.sync()` // _actually_ synchronously syncs. - if let Err(_e) = crate::Env::sync(self) { + if let Err(_e) = Env::sync(self) { // TODO: log error? } diff --git a/storage/database/src/backend/heed/storable.rs b/storage/database/src/backend/heed/storable.rs index 3566e88f..da0e0cb5 100644 --- a/storage/database/src/backend/heed/storable.rs +++ b/storage/database/src/backend/heed/storable.rs @@ -78,8 +78,8 @@ mod test { println!("left: {left:?}, right: {right:?}, expected: {expected:?}"); assert_eq!( as heed::Comparator>::compare( - & as heed::BytesEncode>::bytes_encode(&left).unwrap(), - & as heed::BytesEncode>::bytes_encode(&right).unwrap() + & as BytesEncode>::bytes_encode(&left).unwrap(), + & as BytesEncode>::bytes_encode(&right).unwrap() ), expected ); diff --git a/storage/database/src/backend/redb/database.rs b/storage/database/src/backend/redb/database.rs index cd9a0be9..dafb2417 100644 --- a/storage/database/src/backend/redb/database.rs +++ b/storage/database/src/backend/redb/database.rs @@ -23,7 +23,7 @@ use crate::{ /// Shared [`DatabaseRo::get()`]. #[inline] fn get( - db: &impl redb::ReadableTable, StorableRedb>, + db: &impl ReadableTable, StorableRedb>, key: &T::Key, ) -> Result { Ok(db.get(key)?.ok_or(RuntimeError::KeyNotFound)?.value()) @@ -32,7 +32,7 @@ fn get( /// Shared [`DatabaseRo::len()`]. #[inline] fn len( - db: &impl redb::ReadableTable, StorableRedb>, + db: &impl ReadableTable, StorableRedb>, ) -> Result { Ok(db.len()?) } @@ -40,7 +40,7 @@ fn len( /// Shared [`DatabaseRo::first()`]. #[inline] fn first( - db: &impl redb::ReadableTable, StorableRedb>, + db: &impl ReadableTable, StorableRedb>, ) -> Result<(T::Key, T::Value), RuntimeError> { let (key, value) = db.first()?.ok_or(RuntimeError::KeyNotFound)?; Ok((key.value(), value.value())) @@ -49,7 +49,7 @@ fn first( /// Shared [`DatabaseRo::last()`]. #[inline] fn last( - db: &impl redb::ReadableTable, StorableRedb>, + db: &impl ReadableTable, StorableRedb>, ) -> Result<(T::Key, T::Value), RuntimeError> { let (key, value) = db.last()?.ok_or(RuntimeError::KeyNotFound)?; Ok((key.value(), value.value())) @@ -58,7 +58,7 @@ fn last( /// Shared [`DatabaseRo::is_empty()`]. #[inline] fn is_empty( - db: &impl redb::ReadableTable, StorableRedb>, + db: &impl ReadableTable, StorableRedb>, ) -> Result { Ok(db.is_empty()?) } diff --git a/storage/database/src/config/mod.rs b/storage/database/src/config/mod.rs index 19a324e1..c6ed0c01 100644 --- a/storage/database/src/config/mod.rs +++ b/storage/database/src/config/mod.rs @@ -33,6 +33,7 @@ //! # Ok(()) } //! ``` +#[allow(clippy::module_inception)] mod config; pub use config::{Config, ConfigBuilder, READER_THREADS_DEFAULT}; diff --git a/storage/database/src/env.rs b/storage/database/src/env.rs index cae49733..82944434 100644 --- a/storage/database/src/env.rs +++ b/storage/database/src/env.rs @@ -163,7 +163,7 @@ pub trait Env: Sized { // We have the direct PATH to the file, // no need to use backend-specific functions. // - // SAFETY: as we are only accessing the metadata of + // INVARIANT: as we are only accessing the metadata of // the file and not reading the bytes, it should be // fine even with a memory mapped file being actively // written to. diff --git a/storage/database/src/key.rs b/storage/database/src/key.rs index 3273d4ed..2f3855a4 100644 --- a/storage/database/src/key.rs +++ b/storage/database/src/key.rs @@ -163,11 +163,11 @@ impl KeyCompare { #[inline] pub const fn as_compare_fn(self) -> fn(&[u8], &[u8]) -> Ordering { match self { - Self::Default => std::cmp::Ord::cmp, + Self::Default => Ord::cmp, Self::Number => |left, right| { let left = ::from_bytes(left); let right = ::from_bytes(right); - std::cmp::Ord::cmp(&left, &right) + Ord::cmp(&left, &right) }, Self::Custom(f) => f, } diff --git a/storage/database/src/lib.rs b/storage/database/src/lib.rs index 5946fe5e..45bfc53c 100644 --- a/storage/database/src/lib.rs +++ b/storage/database/src/lib.rs @@ -1,94 +1,18 @@ #![doc = include_str!("../README.md")] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - while_true, - clippy::missing_docs_in_private_items, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - single_use_lifetimes, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, - unreachable_pub, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - unused_crate_dependencies, - unused_doc_comments, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style -)] #![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - // FIXME: good lint but too many false positives - // with our `Env` + `RwLock` setup. - clippy::significant_drop_tightening, - - // FIXME: good lint but is less clear in most cases. - clippy::items_after_statements, - - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, - - // unused_crate_dependencies, // false-positive with `paste` -)] -// Allow some lints when running in debug mode. -#![cfg_attr( - debug_assertions, - allow( - clippy::todo, - clippy::multiple_crate_versions, - // unused_crate_dependencies, - ) + // This lint is allowed because the following + // code exists a lot in this crate: + // + // ```rust + // let env_inner = env.env_inner(); + // let tx_rw = env_inner.tx_rw()?; + // OpenTables::create_tables(&env_inner, &tx_rw)?; + // ``` + // + // Rust thinks `env_inner` can be dropped earlier + // but it cannot, we need it for the lifetime of + // the database transaction + tables. + clippy::significant_drop_tightening )] // Allow some lints in tests. #![cfg_attr( diff --git a/storage/txpool/Cargo.toml b/storage/txpool/Cargo.toml index d5ea77d0..70211d9e 100644 --- a/storage/txpool/Cargo.toml +++ b/storage/txpool/Cargo.toml @@ -41,3 +41,6 @@ cuprate-test-utils = { path = "../../test-utils" } tokio = { workspace = true } tempfile = { workspace = true } hex-literal = { workspace = true } + +[lints] +workspace = true \ No newline at end of file diff --git a/storage/txpool/src/config.rs b/storage/txpool/src/config.rs index 8d09b5e5..1ef0d734 100644 --- a/storage/txpool/src/config.rs +++ b/storage/txpool/src/config.rs @@ -211,7 +211,7 @@ impl Config { /// assert_eq!(config.reader_threads, ReaderThreads::default()); /// ``` pub fn new() -> Self { - Config { + Self { db_config: DbConfig::new(Cow::Borrowed(&*CUPRATE_TXPOOL_DIR)), reader_threads: ReaderThreads::default(), max_txpool_weight: 0, diff --git a/storage/txpool/src/lib.rs b/storage/txpool/src/lib.rs index f200c348..243dc4d9 100644 --- a/storage/txpool/src/lib.rs +++ b/storage/txpool/src/lib.rs @@ -1,4 +1,8 @@ #![doc = include_str!("../README.md")] +#![allow( + // See `cuprate-database` for reasoning. + clippy::significant_drop_tightening +)] pub mod config; mod free; @@ -13,3 +17,13 @@ pub use free::open; //re-exports pub use cuprate_database; + +// TODO: remove when used. +use tower as _; +#[cfg(test)] +mod test { + use cuprate_test_utils as _; + use hex_literal as _; + use tempfile as _; + use tokio as _; +} diff --git a/storage/txpool/src/ops/key_images.rs b/storage/txpool/src/ops/key_images.rs index c6e44152..04aa1b44 100644 --- a/storage/txpool/src/ops/key_images.rs +++ b/storage/txpool/src/ops/key_images.rs @@ -11,7 +11,7 @@ use crate::{ops::TxPoolWriteError, tables::SpentKeyImages, types::TransactionHas /// /// # Panics /// This function will panic if any of the [`Input`]s are not [`Input::ToKey`] -pub fn add_tx_key_images( +pub(super) fn add_tx_key_images( inputs: &[Input], tx_hash: &TransactionHash, kis_table: &mut impl DatabaseRw, @@ -31,7 +31,7 @@ pub fn add_tx_key_images( /// /// # Panics /// This function will panic if any of the [`Input`]s are not [`Input::ToKey`] -pub fn remove_tx_key_images( +pub(super) fn remove_tx_key_images( inputs: &[Input], kis_table: &mut impl DatabaseRw, ) -> Result<(), RuntimeError> { diff --git a/storage/txpool/src/service/free.rs b/storage/txpool/src/service/free.rs index 614ab5c4..003da552 100644 --- a/storage/txpool/src/service/free.rs +++ b/storage/txpool/src/service/free.rs @@ -30,8 +30,8 @@ pub fn init( let db = Arc::new(crate::open(config)?); // Spawn the Reader thread pool and Writer. - let readers = init_read_service(db.clone(), reader_threads); - let writer = init_write_service(db.clone()); + let readers = init_read_service(Arc::clone(&db), reader_threads); + let writer = init_write_service(Arc::clone(&db)); Ok((readers, writer, db)) } diff --git a/storage/txpool/src/service/read.rs b/storage/txpool/src/service/read.rs index c2fee66d..56541641 100644 --- a/storage/txpool/src/service/read.rs +++ b/storage/txpool/src/service/read.rs @@ -25,7 +25,7 @@ use crate::{ /// Should be called _once_ per actual database. #[cold] #[inline(never)] // Only called once. -pub fn init_read_service(env: Arc, threads: ReaderThreads) -> TxpoolReadHandle { +pub(super) fn init_read_service(env: Arc, threads: ReaderThreads) -> TxpoolReadHandle { init_read_service_with_pool(env, init_thread_pool(threads)) } @@ -35,10 +35,7 @@ pub fn init_read_service(env: Arc, threads: ReaderThreads) -> Txpoo /// Should be called _once_ per actual database. #[cold] #[inline(never)] // Only called once. -pub fn init_read_service_with_pool( - env: Arc, - pool: Arc, -) -> TxpoolReadHandle { +fn init_read_service_with_pool(env: Arc, pool: Arc) -> TxpoolReadHandle { DatabaseReadService::new(env, pool, map_request) } @@ -53,6 +50,7 @@ pub fn init_read_service_with_pool( /// 1. `Request` is mapped to a handler function /// 2. Handler function is called /// 3. [`TxpoolReadResponse`] is returned +#[allow(clippy::needless_pass_by_value)] fn map_request( env: &ConcreteEnv, // Access to the database request: TxpoolReadRequest, // The request we must fulfill diff --git a/storage/txpool/src/service/write.rs b/storage/txpool/src/service/write.rs index f6bdb385..8a3b1bf7 100644 --- a/storage/txpool/src/service/write.rs +++ b/storage/txpool/src/service/write.rs @@ -16,7 +16,7 @@ use crate::{ //---------------------------------------------------------------------------------------------------- init_write_service /// Initialize the txpool write service from a [`ConcreteEnv`]. -pub fn init_write_service(env: Arc) -> TxpoolWriteHandle { +pub(super) fn init_write_service(env: Arc) -> TxpoolWriteHandle { DatabaseWriteHandle::init(env, handle_txpool_request) } diff --git a/storage/txpool/src/types.rs b/storage/txpool/src/types.rs index 5c89d3b9..09b0ce0d 100644 --- a/storage/txpool/src/types.rs +++ b/storage/txpool/src/types.rs @@ -35,10 +35,11 @@ bitflags::bitflags! { pub struct TransactionInfo { /// The transaction's fee. pub fee: u64, - /// The transaction`s weight. + /// The transaction's weight. pub weight: usize, /// [`TxStateFlags`] of this transaction. pub flags: TxStateFlags, + #[allow(clippy::pub_underscore_fields)] /// Explicit padding so that we have no implicit padding bytes in `repr(C)`. /// /// Allows potential future expansion of this type. @@ -68,21 +69,21 @@ impl From for CachedVerificationState { fn from(value: RawCachedVerificationState) -> Self { // if the hash is all `0`s then there is no hash this is valid at. if value.raw_valid_at_hash == [0; 32] { - return CachedVerificationState::NotVerified; + return Self::NotVerified; } let raw_valid_past_timestamp = u64::from_le_bytes(value.raw_valid_past_timestamp); // if the timestamp is 0, there is no timestamp that needs to be passed. if raw_valid_past_timestamp == 0 { - return CachedVerificationState::ValidAtHashAndHF { + return Self::ValidAtHashAndHF { block_hash: value.raw_valid_at_hash, hf: HardFork::from_version(value.raw_hf) .expect("hard-fork values stored in the DB should always be valid"), }; } - CachedVerificationState::ValidAtHashAndHFWithTimeBasedLock { + Self::ValidAtHashAndHFWithTimeBasedLock { block_hash: value.raw_valid_at_hash, hf: HardFork::from_version(value.raw_hf) .expect("hard-fork values stored in the DB should always be valid"), @@ -91,6 +92,7 @@ impl From for CachedVerificationState { } } +#[allow(clippy::fallible_impl_from)] // only panics in invalid states impl From for RawCachedVerificationState { fn from(value: CachedVerificationState) -> Self { match value { diff --git a/types/Cargo.toml b/types/Cargo.toml index 4c31cfc0..4b9204b9 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -23,10 +23,12 @@ bytes = { workspace = true } curve25519-dalek = { workspace = true } monero-serai = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } -borsh = { workspace = true, optional = true } thiserror = { workspace = true } proptest = { workspace = true, optional = true } proptest-derive = { workspace = true, optional = true } -[dev-dependencies] \ No newline at end of file +[dev-dependencies] + +[lints] +workspace = true \ No newline at end of file diff --git a/types/src/lib.rs b/types/src/lib.rs index d70f4c31..0b0dbe67 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -1,76 +1,6 @@ #![doc = include_str!("../README.md")] -//---------------------------------------------------------------------------------------------------- Lints -// Forbid lints. -// Our code, and code generated (e.g macros) cannot overrule these. -#![forbid( - // `unsafe` is allowed but it _must_ be - // commented with `SAFETY: reason`. - clippy::undocumented_unsafe_blocks, - - // Never. - unused_unsafe, - redundant_semicolons, - unused_allocation, - coherence_leak_check, - single_use_lifetimes, - while_true, - clippy::missing_docs_in_private_items, - - // Maybe can be put into `#[deny]`. - unconditional_recursion, - for_loops_over_fallibles, - unused_braces, - unused_doc_comments, - unused_labels, - keyword_idents, - non_ascii_idents, - variant_size_differences, - - // Probably can be put into `#[deny]`. - future_incompatible, - let_underscore, - break_with_label_and_loop, - duplicate_macro_attributes, - exported_private_dependencies, - large_assignments, - overlapping_range_endpoints, - semicolon_in_expressions_from_macros, - noop_method_call, - unreachable_pub, -)] -// Deny lints. -// Some of these are `#[allow]`'ed on a per-case basis. -#![deny( - clippy::all, - clippy::correctness, - clippy::suspicious, - clippy::style, - clippy::complexity, - clippy::perf, - clippy::pedantic, - clippy::nursery, - clippy::cargo, - unused_mut, - missing_docs, - deprecated, - unused_comparisons, - nonstandard_style -)] -#![allow( - // FIXME: this lint affects crates outside of - // `database/` for some reason, allow for now. - clippy::cargo_common_metadata, - - // FIXME: adding `#[must_use]` onto everything - // might just be more annoying than useful... - // although it is sometimes nice. - clippy::must_use_candidate, - - clippy::module_name_repetitions, - clippy::module_inception, - clippy::redundant_pub_crate, - clippy::option_if_let_else, -)] +// `proptest` needs this internally. +#![cfg_attr(any(feature = "proptest"), allow(non_local_definitions))] // Allow some lints when running in debug mode. #![cfg_attr(debug_assertions, allow(clippy::todo, clippy::multiple_crate_versions))] @@ -97,4 +27,5 @@ pub use types::{ //---------------------------------------------------------------------------------------------------- Feature-gated #[cfg(feature = "blockchain")] pub mod blockchain; + //---------------------------------------------------------------------------------------------------- Private