From 0d0a544e68d6e7f954ff63d6a577795fed0af0f6 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 11 Sep 2024 20:29:58 -0400 Subject: [PATCH] add `CumulativeBlockWeightLimit`, `submit_block` --- binaries/cuprated/src/rpc/blockchain.rs | 17 +++++++++++++++++ binaries/cuprated/src/rpc/constants.rs | 5 ++++- binaries/cuprated/src/rpc/helper.rs | 1 + binaries/cuprated/src/rpc/json.rs | 24 ++++++++++++++++++++++-- storage/blockchain/src/service/read.rs | 12 ++++++++++++ types/src/blockchain.rs | 6 ++++++ 6 files changed, 62 insertions(+), 3 deletions(-) diff --git a/binaries/cuprated/src/rpc/blockchain.rs b/binaries/cuprated/src/rpc/blockchain.rs index da0c7702..e424e11e 100644 --- a/binaries/cuprated/src/rpc/blockchain.rs +++ b/binaries/cuprated/src/rpc/blockchain.rs @@ -206,6 +206,23 @@ pub(super) async fn find_first_unknown( Ok(resp.map(|(index, height)| (index, usize_to_u64(height)))) } +/// [`BlockchainResponse::CumulativeBlockWeightLimit`] +pub(super) async fn cumulative_block_weight_limit( + state: &mut CupratedRpcHandlerState, +) -> Result { + let BlockchainResponse::CumulativeBlockWeightLimit(limit) = state + .blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::CumulativeBlockWeightLimit) + .await? + else { + unreachable!(); + }; + + Ok(limit) +} + // FindBlock([u8; 32]), // FilterUnknownHashes(HashSet<[u8; 32]>), // BlockExtendedHeaderInRange(Range, Chain), diff --git a/binaries/cuprated/src/rpc/constants.rs b/binaries/cuprated/src/rpc/constants.rs index 3d0485dd..cd7da211 100644 --- a/binaries/cuprated/src/rpc/constants.rs +++ b/binaries/cuprated/src/rpc/constants.rs @@ -1,6 +1,7 @@ //! TODO //! -//! +//! - +//! - pub const MAX_RESTRICTED_FAKE_OUTS_COUNT: usize = 40; pub const MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT: usize = 5000; @@ -15,3 +16,5 @@ pub const RESTRICTED_BLOCK_HEADER_RANGE: u64 = 1000; pub const RESTRICTED_TRANSACTIONS_COUNT: usize = 100; pub const RESTRICTED_SPENT_KEY_IMAGES_COUNT: usize = 5000; pub const RESTRICTED_BLOCK_COUNT: usize = 1000; + +pub const BLOCK_SIZE_SANITY_LEEWAY: usize = 100; diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index d683ae91..8fa2763f 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -10,6 +10,7 @@ use std::sync::Arc; use anyhow::{anyhow, Error}; use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus}; use futures::StreamExt; +use monero_serai::block::Block; use tower::{Service, ServiceExt}; use cuprate_consensus::BlockchainResponse; diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index bc267f0d..7faa3eac 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,7 +1,9 @@ +use core::slice::SlicePattern; use std::sync::Arc; use anyhow::{anyhow, Error}; use futures::StreamExt; +use monero_serai::block::Block; use tower::{Service, ServiceExt}; use cuprate_consensus::BlockchainResponse; @@ -44,6 +46,8 @@ use crate::{ version::CUPRATED_VERSION_IS_RELEASE, }; +use super::constants::BLOCK_SIZE_SANITY_LEEWAY; + /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( state: CupratedRpcHandlerState, @@ -127,12 +131,28 @@ async fn on_get_block_hash( /// async fn submit_block( - state: CupratedRpcHandlerState, + mut state: CupratedRpcHandlerState, request: SubmitBlockRequest, ) -> Result { + let [blob] = request.block_blob; + + let limit = blockchain::cumulative_block_weight_limit(&mut state).await?; + + 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())?; + + // + let block_id = todo!("submit block to DB"); + todo!("relay to P2P"); + todo!("send to txpool"); + Ok(SubmitBlockResponse { base: ResponseBase::ok(), - block_id: todo!(), + block_id, }) } diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 23a8151f..1f1b16d1 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -104,6 +104,7 @@ fn map_request( R::KeyImagesSpent(set) => key_images_spent(env, set), R::CompactChainHistory => compact_chain_history(env), R::FindFirstUnknown(block_ids) => find_first_unknown(env, &block_ids), + R::CumulativeBlockWeightLimit => cumulative_block_weight_limit(env), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -544,3 +545,14 @@ fn find_first_unknown(env: &ConcreteEnv, block_ids: &[BlockHash]) -> ResponseRes BlockchainResponse::FindFirstUnknown(Some((idx, last_known_height + 1))) }) } + +/// [`BlockchainReadRequest::CumulativeBlockWeightLimit`] +fn cumulative_block_weight_limit(env: &ConcreteEnv) -> ResponseResult { + let env_inner = env.env_inner(); + let tx_ro = env_inner.tx_ro()?; + + let table_blocks = env_inner.open_db_ro::(&tx_ro)?; + let limit = todo!(); + + Ok(BlockchainResponse::CumulativeBlockWeightLimit(limit)) +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 219621b6..d4d6bc9e 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -118,6 +118,9 @@ pub enum BlockchainReadRequest { /// order, or else the returned response is unspecified and meaningless, /// as this request performs a binary search. FindFirstUnknown(Vec<[u8; 32]>), + + /// TODO + CumulativeBlockWeightLimit, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -239,6 +242,9 @@ pub enum BlockchainResponse { /// This will be [`None`] if all blocks were known. FindFirstUnknown(Option<(usize, usize)>), + /// TODO + CumulativeBlockWeightLimit(usize), + //------------------------------------------------------ Writes /// Response to [`BlockchainWriteRequest::WriteBlock`]. ///