diff --git a/Cargo.lock b/Cargo.lock index e45f7e42..089236a2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -933,6 +933,7 @@ dependencies = [ "proptest-derive", "serde", "serde_json", + "strum", "thiserror", ] @@ -2674,6 +2675,28 @@ dependencies = [ "spin", ] +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.77", +] + [[package]] name = "subtle" version = "2.6.1" diff --git a/Cargo.toml b/Cargo.toml index fa348ccd..6c322fbd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,6 +78,7 @@ rayon = { version = "1.10.0", default-features = false } serde_bytes = { version = "0.11.15", default-features = false } serde_json = { version = "1.0.128", default-features = false } serde = { version = "1.0.210", default-features = false } +strum = { version = "0.26.3", default-features = false } thiserror = { version = "1.0.63", default-features = false } thread_local = { version = "1.1.8", default-features = false } tokio-util = { version = "0.7.12", default-features = false } diff --git a/binaries/cuprated/src/rpc.rs b/binaries/cuprated/src/rpc.rs index a52fc98c..9d12c1b5 100644 --- a/binaries/cuprated/src/rpc.rs +++ b/binaries/cuprated/src/rpc.rs @@ -4,9 +4,9 @@ mod bin; mod handler; +mod helper; mod json; mod other; mod request; -mod helper; pub use handler::CupratedRpcHandler; diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index 7c95b1b3..5d6477c5 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -92,7 +92,7 @@ pub(super) async fn block_header_by_hash( let block = blockchain::block_by_hash(&mut state.blockchain_read, hash).await?; let header: ExtendedBlockHeader = todo!(); //blockchain::block_extended_header_by_hash(state.blockchain_read, hash).await?; - let block_header = into_block_header(header.height, top_height, fill_pow_hash, block, header); + let block_header = into_block_header(todo!(), top_height, fill_pow_hash, block, header); Ok(block_header) } @@ -105,8 +105,7 @@ pub(super) async fn top_block_header( let block: Block = todo!(); let header: ExtendedBlockHeader = todo!(); - let block_header = - into_block_header(header.height, header.height, fill_pow_hash, block, header); + let block_header = into_block_header(todo!(), todo!(), fill_pow_hash, block, header); Ok(block_header) } @@ -148,7 +147,7 @@ pub(super) fn hex_to_hash(hex: String) -> Result<[u8; 32], Error> { /// [`BlockchainResponse::ChainHeight`] minus 1. pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [u8; 32]), Error> { - let (chain_height, hash) = blockchain::chain_height(state).await?; + let (chain_height, hash) = blockchain::chain_height(&mut state.blockchain_read).await?; let height = chain_height.saturating_sub(1); Ok((height, hash)) } @@ -158,11 +157,12 @@ pub(super) async fn key_image_spent( state: &mut CupratedRpcHandler, key_image: [u8; 32], ) -> Result { - if blockchain::key_image_spent(state, key_image).await? { - Ok(KeyImageSpentStatus::SpentInBlockchain) - } else if todo!("key image is spent in tx pool") { - Ok(KeyImageSpentStatus::SpentInPool) - } else { - Ok(KeyImageSpentStatus::Unspent) - } + todo!("impl key image vec check responding KeyImageSpentStatus") + // if blockchain::key_image_spent(state, key_image).await? { + // Ok(KeyImageSpentStatus::SpentInBlockchain) + // } else if todo!("key image is spent in tx pool") { + // Ok(KeyImageSpentStatus::SpentInPool) + // } else { + // Ok(KeyImageSpentStatus::Unspent) + // } } diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 2ba6796b..604ed91e 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -8,9 +8,10 @@ use tower::{Service, ServiceExt}; use cuprate_consensus::{BlockchainReadRequest, BlockchainResponse}; use cuprate_constants::{ build::RELEASE, - rpc::{BLOCK_SIZE_SANITY_LEEWAY, RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}, + rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}, }; use cuprate_helper::cast::u64_to_usize; +use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, json::{ @@ -114,7 +115,7 @@ async fn on_get_block_hash( request: OnGetBlockHashRequest, ) -> Result { let [height] = request.block_height; - let hash = blockchain::block_hash(&mut state, height).await?; + let hash = blockchain::block_hash(&mut state.blockchain_read, height, todo!()).await?; let block_hash = hex::encode(hash); Ok(OnGetBlockHashResponse { block_hash }) @@ -127,11 +128,11 @@ async fn submit_block( ) -> Result { let [blob] = request.block_blob; - let limit = blockchain::cumulative_block_weight_limit(&mut state).await?; + let limit = todo!(); //blockchain::cumulative_block_weight_limit(&mut state.blockchain_read).await?; - if blob.len() > limit + BLOCK_SIZE_SANITY_LEEWAY { - return Err(anyhow!("Block size is too big, rejecting block")); - } + // if blob.len() > limit + BLOCK_SIZE_SANITY_LEEWAY { + // return Err(anyhow!("Block size is too big, rejecting block")); + // } let bytes = hex::decode(blob)?; let block = Block::read(&mut bytes.as_slice())?; @@ -173,12 +174,12 @@ async fn get_last_block_header( }) } -/// +/// async fn get_block_header_by_hash( mut state: CupratedRpcHandler, request: GetBlockHeaderByHashRequest, ) -> Result { - if state.restricted && request.hashes.len() > RESTRICTED_BLOCK_COUNT { + if state.restricted() && request.hashes.len() > RESTRICTED_BLOCK_COUNT { return Err(anyhow!( "Too many block headers requested in restricted mode" )); @@ -239,7 +240,7 @@ async fn get_block_headers_range( return Err(anyhow!("Invalid start/end heights")); } - if state.restricted + if state.restricted() && request.end_height.saturating_sub(request.start_height) + 1 > RESTRICTED_BLOCK_HEADER_RANGE { @@ -280,10 +281,10 @@ async fn get_block( ) -> Result { let block = if request.hash.is_empty() { helper::check_height(&mut state, request.height).await?; - blockchain::block(&mut state, request.height).await? + blockchain::block(&mut state.blockchain_read, request.height).await? } else { let hash = helper::hex_to_hash(request.hash)?; - blockchain::block_by_hash(&mut state, hash).await? + blockchain::block_by_hash(&mut state.blockchain_read, hash).await? }; Ok(todo!()) @@ -375,7 +376,8 @@ async fn hard_fork_info( let hard_fork = if request.version > 0 { HardFork::from_version(request.version)? } else { - blockchain::current_hard_fork(&mut state).await? + // blockchain::current_hard_fork(&mut state).await? + todo!() }; Ok(HardForkInfoResponse { diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index d3426b46..c28a47f1 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -817,8 +817,17 @@ define_request_and_response! { hard_fork_info, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 1958..=1995, - HardForkInfo (empty), - Request {}, + HardForkInfo, + + #[doc = serde_doc_test!( + HARD_FORK_INFO => HardForkInfo { + version: 16, + } + )] + #[derive(Copy)] + Request { + version: u8, + }, #[doc = serde_doc_test!( HARD_FORK_INFO_RESPONSE => HardForkInfoResponse { @@ -827,9 +836,9 @@ define_request_and_response! { enabled: true, state: 0, threshold: 0, - version: 16, + version: 3, votes: 10080, - voting: 16, + voting: 3, window: 10080 } )] diff --git a/test-utils/src/rpc/data/json.rs b/test-utils/src/rpc/data/json.rs index a05af670..3d463062 100644 --- a/test-utils/src/rpc/data/json.rs +++ b/test-utils/src/rpc/data/json.rs @@ -608,7 +608,10 @@ define_request_and_response! { r#"{ "jsonrpc": "2.0", "id": "0", - "method": "hard_fork_info" + "method": "hard_fork_info", + "params": { + "version": 16 + } }"#; Response = r#"{ diff --git a/types/Cargo.toml b/types/Cargo.toml index 1c762902..8ac6b25f 100644 --- a/types/Cargo.toml +++ b/types/Cargo.toml @@ -27,6 +27,7 @@ curve25519-dalek = { workspace = true } monero-serai = { workspace = true } hex = { workspace = true, features = ["serde", "alloc"], optional = true } serde = { workspace = true, features = ["derive"], optional = true } +strum = { workspace = true, features = ["derive"] } thiserror = { workspace = true } proptest = { workspace = true, optional = true } diff --git a/types/src/hard_fork.rs b/types/src/hard_fork.rs index 8b2cd78c..92dfb5b7 100644 --- a/types/src/hard_fork.rs +++ b/types/src/hard_fork.rs @@ -1,6 +1,10 @@ //! The [`HardFork`] type. use std::time::Duration; +use strum::{ + AsRefStr, Display, EnumCount, EnumIs, EnumString, FromRepr, IntoStaticStr, VariantArray, +}; + use monero_serai::block::BlockHeader; /// Target block time for hf 1. @@ -27,7 +31,25 @@ pub enum HardForkError { } /// An identifier for every hard-fork Monero has had. -#[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Hash)] +#[derive( + Default, + Debug, + PartialEq, + Eq, + PartialOrd, + Ord, + Copy, + Clone, + Hash, + EnumCount, + Display, + AsRefStr, + EnumIs, + EnumString, + FromRepr, + IntoStaticStr, + VariantArray, +)] #[cfg_attr(any(feature = "proptest"), derive(proptest_derive::Arbitrary))] #[repr(u8)] pub enum HardFork { @@ -52,6 +74,14 @@ pub enum HardFork { } impl HardFork { + /// TODO + /// + /// ```rust + /// # use crate::hard_fork::HardFork; + /// assert_eq!(HardFork::CURRENT, HardFork::V16); + /// ``` + pub const CURRENT: Self = Self::VARIANTS[Self::COUNT - 1]; + /// Returns the hard-fork for a blocks [`BlockHeader::hardfork_version`] field. /// /// ref: @@ -61,25 +91,21 @@ impl HardFork { /// Will return [`Err`] if the version is not a valid [`HardFork`]. #[inline] pub const fn from_version(version: u8) -> Result { - Ok(match version { - 1 => Self::V1, - 2 => Self::V2, - 3 => Self::V3, - 4 => Self::V4, - 5 => Self::V5, - 6 => Self::V6, - 7 => Self::V7, - 8 => Self::V8, - 9 => Self::V9, - 10 => Self::V10, - 11 => Self::V11, - 12 => Self::V12, - 13 => Self::V13, - 14 => Self::V14, - 15 => Self::V15, - 16 => Self::V16, - _ => return Err(HardForkError::HardForkUnknown), - }) + #[expect( + clippy::cast_possible_truncation, + reason = "we check that `HardFork::COUNT` fits into a `u8`." + )] + const COUNT_AS_U8: u8 = { + const COUNT: usize = HardFork::COUNT; + assert!(COUNT <= u8::MAX as usize); + COUNT as u8 + }; + + if version != 0 && version <= COUNT_AS_U8 { + Ok(Self::VARIANTS[(version - 1) as usize]) + } else { + Err(HardForkError::HardForkUnknown) + } } /// Returns the hard-fork for a blocks [`BlockHeader::hardfork_signal`] (vote) field. @@ -92,7 +118,7 @@ impl HardFork { return Self::V1; } // This must default to the latest hard-fork! - Self::from_version(vote).unwrap_or(Self::V16) + Self::from_version(vote).unwrap_or(Self::CURRENT) } /// Returns the [`HardFork`] version and vote from this block header. @@ -127,4 +153,9 @@ impl HardFork { _ => BLOCK_TIME_V2, } } + + /// TODO + pub const fn is_current(self) -> bool { + matches!(self, Self::CURRENT) + } }