diff --git a/binaries/cuprated/src/blockchain/manager.rs b/binaries/cuprated/src/blockchain/manager.rs index 568ed572d..118c8dd62 100644 --- a/binaries/cuprated/src/blockchain/manager.rs +++ b/binaries/cuprated/src/blockchain/manager.rs @@ -69,7 +69,7 @@ pub async fn init_blockchain_manager( .ready() .await .expect(PANIC_CRITICAL_SERVICE_ERROR) - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await .expect(PANIC_CRITICAL_SERVICE_ERROR) else { diff --git a/binaries/cuprated/src/blockchain/manager/handler.rs b/binaries/cuprated/src/blockchain/manager/handler.rs index 303e2e492..9603bad54 100644 --- a/binaries/cuprated/src/blockchain/manager/handler.rs +++ b/binaries/cuprated/src/blockchain/manager/handler.rs @@ -464,7 +464,7 @@ impl super::BlockchainManager { .ready() .await .expect(PANIC_CRITICAL_SERVICE_ERROR) - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await .expect(PANIC_CRITICAL_SERVICE_ERROR) else { diff --git a/binaries/cuprated/src/blockchain/syncer.rs b/binaries/cuprated/src/blockchain/syncer.rs index 9de39a8ce..7d6874e0c 100644 --- a/binaries/cuprated/src/blockchain/syncer.rs +++ b/binaries/cuprated/src/blockchain/syncer.rs @@ -62,7 +62,7 @@ where let BlockChainContextResponse::Context(mut blockchain_ctx) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await? else { unreachable!(); @@ -131,7 +131,7 @@ where } let BlockChainContextResponse::Context(ctx) = context_svc - .oneshot(BlockChainContextRequest::GetContext) + .oneshot(BlockChainContextRequest::Context) .await? else { unreachable!(); diff --git a/binaries/cuprated/src/main.rs b/binaries/cuprated/src/main.rs index ad7382d74..d3fe1f566 100644 --- a/binaries/cuprated/src/main.rs +++ b/binaries/cuprated/src/main.rs @@ -3,6 +3,7 @@ #![allow( unused_imports, unreachable_pub, + unreachable_code, unused_crate_dependencies, dead_code, unused_variables, diff --git a/binaries/cuprated/src/rpc.rs b/binaries/cuprated/src/rpc.rs index 9ebcd1b82..fe8e5f214 100644 --- a/binaries/cuprated/src/rpc.rs +++ b/binaries/cuprated/src/rpc.rs @@ -6,5 +6,6 @@ mod bin; mod handler; mod json; mod other; +mod request; -pub use handler::{CupratedRpcHandler, CupratedRpcHandlerState}; +pub use handler::CupratedRpcHandler; diff --git a/binaries/cuprated/src/rpc/bin.rs b/binaries/cuprated/src/rpc/bin.rs index 60d92c127..b4e676dcc 100644 --- a/binaries/cuprated/src/rpc/bin.rs +++ b/binaries/cuprated/src/rpc/bin.rs @@ -10,11 +10,11 @@ use cuprate_rpc_types::{ json::{GetOutputDistributionRequest, GetOutputDistributionResponse}, }; -use crate::rpc::CupratedRpcHandlerState; +use crate::rpc::CupratedRpcHandler; /// Map a [`BinRequest`] to the function that will lead to a [`BinResponse`]. pub(super) async fn map_request( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: BinRequest, ) -> Result { use BinRequest as Req; @@ -36,49 +36,49 @@ pub(super) async fn map_request( } async fn get_blocks( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlocksRequest, ) -> Result { todo!() } async fn get_blocks_by_height( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlocksByHeightRequest, ) -> Result { todo!() } async fn get_hashes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetHashesRequest, ) -> Result { todo!() } async fn get_output_indexes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetOutputIndexesRequest, ) -> Result { todo!() } async fn get_outs( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetOutsRequest, ) -> Result { todo!() } async fn get_transaction_pool_hashes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionPoolHashesRequest, ) -> Result { todo!() } async fn get_output_distribution( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetOutputDistributionRequest, ) -> Result { todo!() diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index 8ba25eab6..af2e3f2c0 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -3,51 +3,131 @@ use std::task::{Context, Poll}; use anyhow::Error; -use futures::{channel::oneshot::channel, future::BoxFuture}; -use serde::{Deserialize, Serialize}; +use futures::future::BoxFuture; +use monero_serai::block::Block; use tower::Service; -use cuprate_blockchain::service::BlockchainReadHandle; -use cuprate_helper::asynch::InfallibleOneshotReceiver; -use cuprate_json_rpc::Id; +use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle}; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ bin::{BinRequest, BinResponse}, json::{JsonRpcRequest, JsonRpcResponse}, other::{OtherRequest, OtherResponse}, }; -use cuprate_txpool::service::TxpoolReadHandle; +use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle}; use crate::rpc::{bin, json, other}; -/// TODO +/// TODO: use real type when public. #[derive(Clone)] -pub struct CupratedRpcHandler { - /// Should this RPC server be [restricted](RpcHandler::restricted)? - // - // INVARIANT: - // We don't need to include this in `state` and check for - // `self.is_restricted()` because `cuprate-rpc-interface` handles that. - pub restricted: bool, - - /// State needed for request -> response mapping. - pub state: CupratedRpcHandlerState, +#[expect(clippy::large_enum_variant)] +pub enum BlockchainManagerRequest { + /// Pop blocks off the top of the blockchain. + /// + /// Input is the amount of blocks to pop. + PopBlocks { amount: usize }, + + /// Start pruning the blockchain. + Prune, + + /// Is the blockchain pruned? + Pruned, + + /// Relay a block to the network. + RelayBlock(Block), + + /// Is the blockchain in the middle of syncing? + /// + /// This returning `false` does not necessarily + /// mean [`BlockchainManagerRequest::Synced`] will + /// return `true`, for example, if the network has been + /// cut off and we have no peers, this will return `false`, + /// however, [`BlockchainManagerRequest::Synced`] may return + /// `true` if the latest known chain tip is equal to our height. + Syncing, + + /// Is the blockchain fully synced? + Synced, + + /// Current target block time. + Target, + + /// The height of the next block in the chain. + TargetHeight, +} + +/// TODO: use real type when public. +#[derive(Clone)] +pub enum BlockchainManagerResponse { + /// General OK response. + /// + /// Response to: + /// - [`BlockchainManagerRequest::Prune`] + /// - [`BlockchainManagerRequest::RelayBlock`] + Ok, + + /// Response to [`BlockchainManagerRequest::PopBlocks`] + PopBlocks { new_height: usize }, + + /// Response to [`BlockchainManagerRequest::Pruned`] + Pruned(bool), + + /// Response to [`BlockchainManagerRequest::Syncing`] + Syncing(bool), + + /// Response to [`BlockchainManagerRequest::Synced`] + Synced(bool), + + /// Response to [`BlockchainManagerRequest::Target`] + Target(std::time::Duration), + + /// Response to [`BlockchainManagerRequest::TargetHeight`] + TargetHeight { height: usize }, } +/// TODO: use real type when public. +pub type BlockchainManagerHandle = cuprate_database_service::DatabaseReadService< + BlockchainManagerRequest, + BlockchainManagerResponse, +>; + /// TODO #[derive(Clone)] -pub struct CupratedRpcHandlerState { +pub struct CupratedRpcHandler { + /// Should this RPC server be [restricted](RpcHandler::restricted)? + /// + /// This is not `pub` on purpose, as it should not be mutated after [`Self::new`]. + restricted: bool, + /// Read handle to the blockchain database. - pub blockchain: BlockchainReadHandle, + pub blockchain_read: BlockchainReadHandle, + + /// Handle to the blockchain manager. + pub blockchain_manager: BlockchainManagerHandle, /// Read handle to the transaction pool database. - pub txpool: TxpoolReadHandle, + pub txpool_read: TxpoolReadHandle, + + /// TODO: handle to txpool service. + pub txpool_manager: std::convert::Infallible, } impl CupratedRpcHandler { - /// TODO - pub fn init() { - todo!() + /// Create a new [`Self`]. + pub const fn new( + restricted: bool, + blockchain_read: BlockchainReadHandle, + blockchain_manager: BlockchainManagerHandle, + txpool_read: TxpoolReadHandle, + txpool_manager: std::convert::Infallible, + ) -> Self { + Self { + restricted, + blockchain_read, + blockchain_manager, + txpool_read, + txpool_manager, + } } } @@ -67,7 +147,7 @@ impl Service for CupratedRpcHandler { } fn call(&mut self, request: JsonRpcRequest) -> Self::Future { - let state = CupratedRpcHandlerState::clone(&self.state); + let state = self.clone(); Box::pin(json::map_request(state, request)) } } @@ -82,7 +162,7 @@ impl Service for CupratedRpcHandler { } fn call(&mut self, request: BinRequest) -> Self::Future { - let state = CupratedRpcHandlerState::clone(&self.state); + let state = self.clone(); Box::pin(bin::map_request(state, request)) } } @@ -97,7 +177,7 @@ impl Service for CupratedRpcHandler { } fn call(&mut self, request: OtherRequest) -> Self::Future { - let state = CupratedRpcHandlerState::clone(&self.state); + let state = self.clone(); Box::pin(other::map_request(state, request)) } } diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 41398d480..88b38b92f 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -23,11 +23,11 @@ use cuprate_rpc_types::json::{ SyncInfoRequest, SyncInfoResponse, }; -use crate::rpc::CupratedRpcHandlerState; +use crate::rpc::CupratedRpcHandler; /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: JsonRpcRequest, ) -> Result { use JsonRpcRequest as Req; @@ -84,210 +84,210 @@ pub(super) async fn map_request( } async fn get_block_count( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlockCountRequest, ) -> Result { todo!() } async fn on_get_block_hash( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: OnGetBlockHashRequest, ) -> Result { todo!() } async fn submit_block( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SubmitBlockRequest, ) -> Result { todo!() } async fn generate_blocks( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GenerateBlocksRequest, ) -> Result { todo!() } async fn get_last_block_header( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetLastBlockHeaderRequest, ) -> Result { todo!() } async fn get_block_header_by_hash( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlockHeaderByHashRequest, ) -> Result { todo!() } async fn get_block_header_by_height( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlockHeaderByHeightRequest, ) -> Result { todo!() } async fn get_block_headers_range( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlockHeadersRangeRequest, ) -> Result { todo!() } async fn get_block( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBlockRequest, ) -> Result { todo!() } async fn get_connections( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetConnectionsRequest, ) -> Result { todo!() } async fn get_info( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetInfoRequest, ) -> Result { todo!() } async fn hard_fork_info( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: HardForkInfoRequest, ) -> Result { todo!() } async fn set_bans( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetBansRequest, ) -> Result { todo!() } async fn get_bans( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetBansRequest, ) -> Result { todo!() } async fn banned( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: BannedRequest, ) -> Result { todo!() } async fn flush_transaction_pool( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: FlushTransactionPoolRequest, ) -> Result { todo!() } async fn get_output_histogram( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetOutputHistogramRequest, ) -> Result { todo!() } async fn get_coinbase_tx_sum( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetCoinbaseTxSumRequest, ) -> Result { todo!() } async fn get_version( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetVersionRequest, ) -> Result { todo!() } async fn get_fee_estimate( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetFeeEstimateRequest, ) -> Result { todo!() } async fn get_alternate_chains( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetAlternateChainsRequest, ) -> Result { todo!() } async fn relay_tx( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: RelayTxRequest, ) -> Result { todo!() } async fn sync_info( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SyncInfoRequest, ) -> Result { todo!() } async fn get_transaction_pool_backlog( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionPoolBacklogRequest, ) -> Result { todo!() } async fn get_miner_data( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetMinerDataRequest, ) -> Result { todo!() } async fn prune_blockchain( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: PruneBlockchainRequest, ) -> Result { todo!() } async fn calc_pow( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: CalcPowRequest, ) -> Result { todo!() } async fn flush_cache( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: FlushCacheRequest, ) -> Result { todo!() } async fn add_aux_pow( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { todo!() } async fn get_tx_ids_loose( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTxIdsLooseRequest, ) -> Result { todo!() diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs index c0df39931..16b58c41e 100644 --- a/binaries/cuprated/src/rpc/other.rs +++ b/binaries/cuprated/src/rpc/other.rs @@ -17,11 +17,11 @@ use cuprate_rpc_types::other::{ StopDaemonResponse, StopMiningRequest, StopMiningResponse, UpdateRequest, UpdateResponse, }; -use crate::rpc::CupratedRpcHandlerState; +use crate::rpc::CupratedRpcHandler; /// Map a [`OtherRequest`] to the function that will lead to a [`OtherResponse`]. pub(super) async fn map_request( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: OtherRequest, ) -> Result { use OtherRequest as Req; @@ -71,189 +71,189 @@ pub(super) async fn map_request( } async fn get_height( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetHeightRequest, ) -> Result { todo!() } async fn get_transactions( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionsRequest, ) -> Result { todo!() } async fn get_alt_blocks_hashes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetAltBlocksHashesRequest, ) -> Result { todo!() } async fn is_key_image_spent( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: IsKeyImageSpentRequest, ) -> Result { todo!() } async fn send_raw_transaction( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SendRawTransactionRequest, ) -> Result { todo!() } async fn start_mining( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: StartMiningRequest, ) -> Result { todo!() } async fn stop_mining( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: StopMiningRequest, ) -> Result { todo!() } async fn mining_status( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: MiningStatusRequest, ) -> Result { todo!() } async fn save_bc( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SaveBcRequest, ) -> Result { todo!() } async fn get_peer_list( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetPeerListRequest, ) -> Result { todo!() } async fn set_log_hash_rate( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetLogHashRateRequest, ) -> Result { todo!() } async fn set_log_level( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetLogLevelRequest, ) -> Result { todo!() } async fn set_log_categories( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetLogCategoriesRequest, ) -> Result { todo!() } async fn set_bootstrap_daemon( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetBootstrapDaemonRequest, ) -> Result { todo!() } async fn get_transaction_pool( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionPoolRequest, ) -> Result { todo!() } async fn get_transaction_pool_stats( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionPoolStatsRequest, ) -> Result { todo!() } async fn stop_daemon( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: StopDaemonRequest, ) -> Result { todo!() } async fn get_limit( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetLimitRequest, ) -> Result { todo!() } async fn set_limit( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: SetLimitRequest, ) -> Result { todo!() } async fn out_peers( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: OutPeersRequest, ) -> Result { todo!() } async fn in_peers( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: InPeersRequest, ) -> Result { todo!() } async fn get_net_stats( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetNetStatsRequest, ) -> Result { todo!() } async fn get_outs( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetOutsRequest, ) -> Result { todo!() } async fn update( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: UpdateRequest, ) -> Result { todo!() } async fn pop_blocks( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: PopBlocksRequest, ) -> Result { todo!() } async fn get_transaction_pool_hashes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetTransactionPoolHashesRequest, ) -> Result { todo!() } async fn get_public_nodes( - state: CupratedRpcHandlerState, + state: CupratedRpcHandler, request: GetPublicNodesRequest, ) -> Result { todo!() diff --git a/binaries/cuprated/src/rpc/request.rs b/binaries/cuprated/src/rpc/request.rs new file mode 100644 index 000000000..17e12b956 --- /dev/null +++ b/binaries/cuprated/src/rpc/request.rs @@ -0,0 +1,19 @@ +//! Convenience functions for requests/responses. +//! +//! This module implements many methods for +//! [`CupratedRpcHandler`](crate::rpc::CupratedRpcHandler) +//! that are simple wrappers around the request/response API provided +//! by the multiple [`tower::Service`]s. +//! +//! These exist to prevent noise like `unreachable!()` +//! from being everywhere in the actual handler functions. +//! +//! Each module implements methods for a specific API, e.g. +//! the [`blockchain`] modules contains methods for the +//! blockchain database [`tower::Service`] API. + +mod address_book; +mod blockchain; +mod blockchain_context; +mod blockchain_manager; +mod txpool; diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs new file mode 100644 index 000000000..2aa58e84b --- /dev/null +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -0,0 +1,104 @@ +//! Functions for TODO: doc enum message. + +use std::convert::Infallible; + +use anyhow::Error; +use tower::ServiceExt; + +use cuprate_helper::cast::usize_to_u64; +use cuprate_p2p_core::{ + services::{AddressBookRequest, AddressBookResponse}, + AddressBook, NetworkZone, +}; + +/// [`AddressBookRequest::PeerlistSize`] +pub(super) async fn peerlist_size( + address_book: &mut impl AddressBook, +) -> Result<(u64, u64), Error> { + let AddressBookResponse::PeerlistSize { white, grey } = address_book + .ready() + .await + .expect("TODO") + .call(AddressBookRequest::PeerlistSize) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok((usize_to_u64(white), usize_to_u64(grey))) +} + +/// [`AddressBookRequest::ConnectionCount`] +pub(super) async fn connection_count( + address_book: &mut impl AddressBook, +) -> Result<(u64, u64), Error> { + let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book + .ready() + .await + .expect("TODO") + .call(AddressBookRequest::ConnectionCount) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok((usize_to_u64(incoming), usize_to_u64(outgoing))) +} + +/// [`AddressBookRequest::SetBan`] +pub(super) async fn set_ban( + address_book: &mut impl AddressBook, + peer: cuprate_p2p_core::ban::SetBan, +) -> Result<(), Error> { + let AddressBookResponse::Ok = address_book + .ready() + .await + .expect("TODO") + .call(AddressBookRequest::SetBan(peer)) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(()) +} + +/// [`AddressBookRequest::GetBan`] +pub(super) async fn get_ban( + address_book: &mut impl AddressBook, + peer: Z::Addr, +) -> Result, Error> { + let AddressBookResponse::GetBan { unban_instant } = address_book + .ready() + .await + .expect("TODO") + .call(AddressBookRequest::GetBan(peer)) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(unban_instant) +} + +/// [`AddressBookRequest::GetBans`] +pub(super) async fn get_bans( + address_book: &mut impl AddressBook, +) -> Result<(), Error> { + let AddressBookResponse::GetBans(bans) = address_book + .ready() + .await + .expect("TODO") + .call(AddressBookRequest::GetBans) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(todo!()) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs new file mode 100644 index 000000000..8af80e509 --- /dev/null +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -0,0 +1,308 @@ +//! Functions for [`BlockchainReadRequest`]. + +use std::{ + collections::{HashMap, HashSet}, + ops::Range, +}; + +use anyhow::Error; +use cuprate_blockchain::service::BlockchainReadHandle; +use tower::{Service, ServiceExt}; + +use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; +use cuprate_types::{ + blockchain::{BlockchainReadRequest, BlockchainResponse}, + Chain, CoinbaseTxSum, ExtendedBlockHeader, MinerData, OutputHistogramEntry, + OutputHistogramInput, OutputOnChain, +}; + +/// [`BlockchainReadRequest::BlockExtendedHeader`]. +pub(super) async fn block_extended_header( + mut blockchain_read: BlockchainReadHandle, + height: u64, +) -> Result { + let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::BlockExtendedHeader(u64_to_usize( + height, + ))) + .await? + else { + unreachable!(); + }; + + Ok(header) +} + +/// [`BlockchainReadRequest::BlockHash`]. +pub(super) async fn block_hash( + mut blockchain_read: BlockchainReadHandle, + height: u64, + chain: Chain, +) -> Result<[u8; 32], Error> { + let BlockchainResponse::BlockHash(hash) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::BlockHash( + u64_to_usize(height), + chain, + )) + .await? + else { + unreachable!(); + }; + + Ok(hash) +} + +/// [`BlockchainReadRequest::FindBlock`]. +pub(super) async fn find_block( + mut blockchain_read: BlockchainReadHandle, + block_hash: [u8; 32], +) -> Result, Error> { + let BlockchainResponse::FindBlock(option) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::FindBlock(block_hash)) + .await? + else { + unreachable!(); + }; + + Ok(option) +} + +/// [`BlockchainReadRequest::FilterUnknownHashes`]. +pub(super) async fn filter_unknown_hashes( + mut blockchain_read: BlockchainReadHandle, + block_hashes: HashSet<[u8; 32]>, +) -> Result, Error> { + let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::FilterUnknownHashes(block_hashes)) + .await? + else { + unreachable!(); + }; + + Ok(output) +} + +/// [`BlockchainReadRequest::BlockExtendedHeaderInRange`] +pub(super) async fn block_extended_header_in_range( + mut blockchain_read: BlockchainReadHandle, + range: Range, + chain: Chain, +) -> Result, Error> { + let BlockchainResponse::BlockExtendedHeaderInRange(output) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::BlockExtendedHeaderInRange( + range, chain, + )) + .await? + else { + unreachable!(); + }; + + Ok(output) +} + +/// [`BlockchainReadRequest::ChainHeight`]. +pub(super) async fn chain_height( + mut blockchain_read: BlockchainReadHandle, +) -> Result<(u64, [u8; 32]), Error> { + let BlockchainResponse::ChainHeight(height, hash) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::ChainHeight) + .await? + else { + unreachable!(); + }; + + Ok((usize_to_u64(height), hash)) +} + +/// [`BlockchainReadRequest::GeneratedCoins`]. +pub(super) async fn generated_coins( + mut blockchain_read: BlockchainReadHandle, + block_height: u64, +) -> Result { + let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::GeneratedCoins(u64_to_usize( + block_height, + ))) + .await? + else { + unreachable!(); + }; + + Ok(generated_coins) +} + +/// [`BlockchainReadRequest::Outputs`] +pub(super) async fn outputs( + mut blockchain_read: BlockchainReadHandle, + outputs: HashMap>, +) -> Result>, Error> { + let BlockchainResponse::Outputs(outputs) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::Outputs(outputs)) + .await? + else { + unreachable!(); + }; + + Ok(outputs) +} + +/// [`BlockchainReadRequest::NumberOutputsWithAmount`] +pub(super) async fn number_outputs_with_amount( + mut blockchain_read: BlockchainReadHandle, + output_amounts: Vec, +) -> Result, Error> { + let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::NumberOutputsWithAmount( + output_amounts, + )) + .await? + else { + unreachable!(); + }; + + Ok(map) +} + +/// [`BlockchainReadRequest::KeyImagesSpent`] +pub(super) async fn key_images_spent( + mut blockchain_read: BlockchainReadHandle, + key_images: HashSet<[u8; 32]>, +) -> Result { + let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::KeyImagesSpent(key_images)) + .await? + else { + unreachable!(); + }; + + Ok(is_spent) +} + +/// [`BlockchainReadRequest::CompactChainHistory`] +pub(super) async fn compact_chain_history( + mut blockchain_read: BlockchainReadHandle, +) -> Result<(Vec<[u8; 32]>, u128), Error> { + let BlockchainResponse::CompactChainHistory { + block_ids, + cumulative_difficulty, + } = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::CompactChainHistory) + .await? + else { + unreachable!(); + }; + + Ok((block_ids, cumulative_difficulty)) +} + +/// [`BlockchainReadRequest::FindFirstUnknown`] +pub(super) async fn find_first_unknown( + mut blockchain_read: BlockchainReadHandle, + hashes: Vec<[u8; 32]>, +) -> Result, Error> { + let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::FindFirstUnknown(hashes)) + .await? + else { + unreachable!(); + }; + + Ok(resp.map(|(index, height)| (index, usize_to_u64(height)))) +} + +/// [`BlockchainReadRequest::TotalTxCount`] +pub(super) async fn total_tx_count( + mut blockchain_read: BlockchainReadHandle, +) -> Result { + let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::TotalTxCount) + .await? + else { + unreachable!(); + }; + + Ok(usize_to_u64(tx_count)) +} + +/// [`BlockchainReadRequest::DatabaseSize`] +pub(super) async fn database_size( + mut blockchain_read: BlockchainReadHandle, +) -> Result<(u64, u64), Error> { + let BlockchainResponse::DatabaseSize { + database_size, + free_space, + } = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::DatabaseSize) + .await? + else { + unreachable!(); + }; + + Ok((database_size, free_space)) +} + +/// [`BlockchainReadRequest::OutputHistogram`] +pub(super) async fn output_histogram( + mut blockchain_read: BlockchainReadHandle, + input: OutputHistogramInput, +) -> Result, Error> { + let BlockchainResponse::OutputHistogram(histogram) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::OutputHistogram(input)) + .await? + else { + unreachable!(); + }; + + Ok(histogram) +} + +/// [`BlockchainReadRequest::CoinbaseTxSum`] +pub(super) async fn coinbase_tx_sum( + mut blockchain_read: BlockchainReadHandle, + height: u64, + count: u64, +) -> Result { + let BlockchainResponse::CoinbaseTxSum(sum) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::CoinbaseTxSum { + height: u64_to_usize(height), + count, + }) + .await? + else { + unreachable!(); + }; + + Ok(sum) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs new file mode 100644 index 000000000..b616593d4 --- /dev/null +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -0,0 +1,69 @@ +//! Functions for [`BlockChainContextRequest`] and [`BlockChainContextResponse`]. + +use std::convert::Infallible; + +use anyhow::Error; +use tower::{Service, ServiceExt}; + +use cuprate_consensus::context::{ + BlockChainContext, BlockChainContextRequest, BlockChainContextResponse, + BlockChainContextService, +}; +use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; + +/// [`BlockChainContextRequest::Context`]. +pub(super) async fn context( + service: &mut BlockChainContextService, + height: u64, +) -> Result { + let BlockChainContextResponse::Context(context) = service + .ready() + .await + .expect("TODO") + .call(BlockChainContextRequest::Context) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(context) +} + +/// [`BlockChainContextRequest::HardForkInfo`]. +pub(super) async fn hard_fork_info( + service: &mut BlockChainContextService, + hard_fork: HardFork, +) -> Result { + let BlockChainContextResponse::HardForkInfo(hf_info) = service + .ready() + .await + .expect("TODO") + .call(BlockChainContextRequest::HardForkInfo(hard_fork)) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(hf_info) +} + +/// [`BlockChainContextRequest::FeeEstimate`]. +pub(super) async fn fee_estimate( + service: &mut BlockChainContextService, + grace_blocks: u64, +) -> Result { + let BlockChainContextResponse::FeeEstimate(fee) = service + .ready() + .await + .expect("TODO") + .call(BlockChainContextRequest::FeeEstimate { grace_blocks }) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(fee) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs new file mode 100644 index 000000000..4dc91c821 --- /dev/null +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -0,0 +1,141 @@ +//! Functions for [`BlockchainManagerRequest`] & [`BlockchainManagerResponse`]. + +use anyhow::Error; +use monero_serai::block::Block; +use tower::{Service, ServiceExt}; + +use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; + +use crate::rpc::handler::{ + BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, +}; + +/// [`BlockchainManagerRequest::PopBlocks`] +pub(super) async fn pop_blocks( + blockchain_manager: &mut BlockchainManagerHandle, + amount: u64, +) -> Result { + let BlockchainManagerResponse::PopBlocks { new_height } = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::PopBlocks { + amount: u64_to_usize(amount), + }) + .await? + else { + unreachable!(); + }; + + Ok(usize_to_u64(new_height)) +} + +/// [`BlockchainManagerRequest::Prune`] +pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { + let BlockchainManagerResponse::Ok = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Prune) + .await? + else { + unreachable!(); + }; + + Ok(()) +} + +/// [`BlockchainManagerRequest::Pruned`] +pub(super) async fn pruned( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Pruned) + .await? + else { + unreachable!(); + }; + + Ok(pruned) +} + +/// [`BlockchainManagerRequest::RelayBlock`] +pub(super) async fn relay_block( + blockchain_manager: &mut BlockchainManagerHandle, + block: Block, +) -> Result<(), Error> { + let BlockchainManagerResponse::Ok = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::RelayBlock(block)) + .await? + else { + unreachable!(); + }; + + Ok(()) +} + +/// [`BlockchainManagerRequest::Syncing`] +pub(super) async fn syncing( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Syncing) + .await? + else { + unreachable!(); + }; + + Ok(syncing) +} + +/// [`BlockchainManagerRequest::Synced`] +pub(super) async fn synced( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Synced(syncing) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Synced) + .await? + else { + unreachable!(); + }; + + Ok(syncing) +} + +/// [`BlockchainManagerRequest::Target`] +pub(super) async fn target( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Target(target) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Target) + .await? + else { + unreachable!(); + }; + + Ok(target) +} + +/// [`BlockchainManagerRequest::TargetHeight`] +pub(super) async fn target_height( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::TargetHeight) + .await? + else { + unreachable!(); + }; + + Ok(usize_to_u64(height)) +} diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs new file mode 100644 index 000000000..a36778eb4 --- /dev/null +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -0,0 +1,57 @@ +//! Functions for [`TxpoolReadRequest`]. + +use std::convert::Infallible; + +use anyhow::Error; +use tower::{Service, ServiceExt}; + +use cuprate_helper::cast::usize_to_u64; +use cuprate_txpool::{ + service::{ + interface::{TxpoolReadRequest, TxpoolReadResponse}, + TxpoolReadHandle, + }, + TxEntry, +}; + +/// [`TxpoolReadRequest::Backlog`] +pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { + let TxpoolReadResponse::Backlog(tx_entries) = txpool_read + .ready() + .await + .expect("TODO") + .call(TxpoolReadRequest::Backlog) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(tx_entries) +} + +/// [`TxpoolReadRequest::Size`] +pub(super) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result { + let TxpoolReadResponse::Size(size) = txpool_read + .ready() + .await + .expect("TODO") + .call(TxpoolReadRequest::Size) + .await + .expect("TODO") + else { + unreachable!(); + }; + + Ok(usize_to_u64(size)) +} + +/// TODO +#[expect(clippy::needless_pass_by_ref_mut, reason = "TODO: remove after impl")] +pub(super) async fn flush( + txpool_read: &mut TxpoolReadHandle, + tx_hashes: Vec<[u8; 32]>, +) -> Result<(), Error> { + todo!(); + Ok(()) +} diff --git a/consensus/fast-sync/src/fast_sync.rs b/consensus/fast-sync/src/fast_sync.rs index b4fc12b09..ec4ea297c 100644 --- a/consensus/fast-sync/src/fast_sync.rs +++ b/consensus/fast-sync/src/fast_sync.rs @@ -230,7 +230,7 @@ where let BlockChainContextResponse::Context(checked_context) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await? else { panic!("Context service returned wrong response!"); diff --git a/consensus/src/block.rs b/consensus/src/block.rs index ada46aa42..ceb2cbab8 100644 --- a/consensus/src/block.rs +++ b/consensus/src/block.rs @@ -351,7 +351,7 @@ where let BlockChainContextResponse::Context(checked_context) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await? else { panic!("Context service returned wrong response!"); @@ -374,7 +374,7 @@ where let BlockChainContextResponse::RxVms(rx_vms) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetCurrentRxVm) + .call(BlockChainContextRequest::CurrentRxVms) .await? else { panic!("Blockchain context service returned wrong response!"); @@ -433,7 +433,7 @@ where context } else { let BlockChainContextResponse::Context(checked_context) = context_svc - .oneshot(BlockChainContextRequest::GetContext) + .oneshot(BlockChainContextRequest::Context) .await? else { panic!("Context service returned wrong response!"); diff --git a/consensus/src/block/batch_prepare.rs b/consensus/src/block/batch_prepare.rs index 9c778481b..029a5ae6c 100644 --- a/consensus/src/block/batch_prepare.rs +++ b/consensus/src/block/batch_prepare.rs @@ -93,7 +93,7 @@ where let BlockChainContextResponse::Context(checked_context) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetContext) + .call(BlockChainContextRequest::Context) .await? else { panic!("Context service returned wrong response!"); @@ -136,7 +136,7 @@ where let BlockChainContextResponse::RxVms(rx_vms) = context_svc .ready() .await? - .call(BlockChainContextRequest::GetCurrentRxVm) + .call(BlockChainContextRequest::CurrentRxVms) .await? else { panic!("Blockchain context service returned wrong response!"); diff --git a/consensus/src/context.rs b/consensus/src/context.rs index 5bdb1ce4b..3c944a926 100644 --- a/consensus/src/context.rs +++ b/consensus/src/context.rs @@ -31,7 +31,7 @@ mod alt_chains; mod task; mod tokens; -use cuprate_types::Chain; +use cuprate_types::{Chain, ChainInfo, FeeEstimate, HardForkInfo}; use difficulty::DifficultyCache; use rx_vms::RandomXVm; use weight::BlockWeightsCache; @@ -221,15 +221,18 @@ pub struct NewBlockData { #[derive(Debug, Clone)] pub enum BlockChainContextRequest { /// Get the current blockchain context. - GetContext, - /// Gets the current `RandomX` VM. - GetCurrentRxVm, + Context, + + /// Gets all the current `RandomX` VMs. + CurrentRxVms, + /// Get the next difficulties for these blocks. /// /// Inputs: a list of block timestamps and hfs /// /// The number of difficulties returned will be one more than the number of timestamps/ hfs. BatchGetDifficulties(Vec<(u64, HardFork)>), + /// Add a VM that has been created outside of the blockchain context service to the blockchain context. /// This is useful when batch calculating POW as you may need to create a new VM if you batch a lot of blocks together, /// it would be wasteful to then not give this VM to the context service to then use when it needs to init a VM with the same @@ -237,8 +240,10 @@ pub enum BlockChainContextRequest { /// /// This should include the seed used to init this VM and the VM. 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. PopBlocks { /// The number of blocks to pop from the top of the chain. @@ -248,8 +253,22 @@ pub enum BlockChainContextRequest { /// This will panic if the number of blocks will pop the genesis block. numb_blocks: usize, }, + + /// Get information on a certain hardfork. + HardForkInfo(HardFork), + + /// Get the current fee estimate. + FeeEstimate { + /// TODO + grace_blocks: u64, + }, + /// Clear the alt chain context caches. ClearAltCache, + + /// Get information on all the current alternate chains. + AltChains, + //----------------------------------------------------------------------------------------------------------- AltChainRequests /// A request for an alt chain context cache. /// @@ -261,6 +280,7 @@ pub enum BlockChainContextRequest { /// An internal token to prevent external crates calling this request. _token: AltChainRequestToken, }, + /// A request for a difficulty cache of an alternative chin. /// /// This variant is private and is not callable from outside this crate, the block verifier service will @@ -271,6 +291,7 @@ pub enum BlockChainContextRequest { /// An internal token to prevent external crates calling this request. _token: AltChainRequestToken, }, + /// A request for a block weight cache of an alternative chin. /// /// This variant is private and is not callable from outside this crate, the block verifier service will @@ -281,6 +302,7 @@ pub enum BlockChainContextRequest { /// An internal token to prevent external crates calling this request. _token: AltChainRequestToken, }, + /// A request for a RX VM for an alternative chin. /// /// Response variant: [`BlockChainContextResponse::AltChainRxVM`]. @@ -295,6 +317,7 @@ pub enum BlockChainContextRequest { /// An internal token to prevent external crates calling this request. _token: AltChainRequestToken, }, + /// A request to add an alt chain context cache to the context cache. /// /// This variant is private and is not callable from outside this crate, the block verifier service will @@ -310,22 +333,49 @@ pub enum BlockChainContextRequest { } pub enum BlockChainContextResponse { - /// Blockchain context response. + /// A generic Ok response. + /// + /// Response to: + /// - [`BlockChainContextRequest::NewRXVM`] + /// - [`BlockChainContextRequest::Update`] + /// - [`BlockChainContextRequest::PopBlocks`] + /// - [`BlockChainContextRequest::ClearAltCache`] + /// - [`BlockChainContextRequest::AddAltChainContextCache`] + Ok, + + /// Response to [`BlockChainContextRequest::Context`] Context(BlockChainContext), + + /// Response to [`BlockChainContextRequest::CurrentRxVms`] + /// /// A map of seed height to `RandomX` VMs. RxVms(HashMap>), + /// A list of difficulties. BatchDifficulties(Vec), + + /// Response to [`BlockChainContextRequest::HardForkInfo`] + HardForkInfo(HardForkInfo), + + /// Response to [`BlockChainContextRequest::FeeEstimate`] + FeeEstimate(FeeEstimate), + + /// Response to [`BlockChainContextRequest::AltChains`] + /// + /// If the inner [`Vec::is_empty`], there were no alternate chains. + AltChains(Vec), + /// An alt chain context cache. AltChainContextCache(Box), + /// A difficulty cache for an alt chain. AltChainDifficultyCache(DifficultyCache), + /// A randomX VM for an alt chain. AltChainRxVM(Arc), + /// A weight cache for an alt chain AltChainWeightCache(BlockWeightsCache), - /// A generic Ok response. - Ok, } /// The blockchain context service. diff --git a/consensus/src/context/task.rs b/consensus/src/context/task.rs index 82b466c4b..c51c795ea 100644 --- a/consensus/src/context/task.rs +++ b/consensus/src/context/task.rs @@ -153,7 +153,7 @@ impl ContextTask { req: BlockChainContextRequest, ) -> Result { Ok(match req { - BlockChainContextRequest::GetContext => { + BlockChainContextRequest::Context => { tracing::debug!("Getting blockchain context"); let current_hf = self.hardfork_state.current_hardfork(); @@ -183,7 +183,7 @@ impl ContextTask { }, }) } - BlockChainContextRequest::GetCurrentRxVm => { + BlockChainContextRequest::CurrentRxVms => { BlockChainContextResponse::RxVms(self.rx_vm_cache.get_vms().await) } BlockChainContextRequest::BatchGetDifficulties(blocks) => { @@ -325,6 +325,11 @@ impl ContextTask { self.alt_chain_cache_map.add_alt_cache(prev_id, cache); BlockChainContextResponse::Ok } + BlockChainContextRequest::HardForkInfo(_) + | BlockChainContextRequest::FeeEstimate { .. } + | BlockChainContextRequest::AltChains => { + todo!("finish https://github.com/Cuprate/cuprate/pull/297") + } }) } diff --git a/consensus/src/tests/context.rs b/consensus/src/tests/context.rs index bbf7bb0d7..fdef0ac8d 100644 --- a/consensus/src/tests/context.rs +++ b/consensus/src/tests/context.rs @@ -41,7 +41,7 @@ async fn context_invalidated_on_new_block() -> Result<(), tower::BoxError> { let BlockChainContextResponse::Context(context) = ctx_svc .clone() - .oneshot(BlockChainContextRequest::GetContext) + .oneshot(BlockChainContextRequest::Context) .await? else { panic!("Context service returned wrong response!"); @@ -81,9 +81,8 @@ async fn context_height_correct() -> Result<(), tower::BoxError> { let ctx_svc = initialize_blockchain_context(TEST_CONTEXT_CONFIG, db).await?; - let BlockChainContextResponse::Context(context) = ctx_svc - .oneshot(BlockChainContextRequest::GetContext) - .await? + let BlockChainContextResponse::Context(context) = + ctx_svc.oneshot(BlockChainContextRequest::Context).await? else { panic!("context service returned incorrect response!") }; diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs index 9c2298161..907d69115 100644 --- a/p2p/address-book/src/book.rs +++ b/p2p/address-book/src/book.rs @@ -229,6 +229,15 @@ impl AddressBook { self.banned_peers.contains_key(&peer.ban_id()) } + /// Checks when a peer will be unbanned. + /// + /// - If the peer is banned, this returns [`Some`] containing + /// the [`Instant`] the peer will be unbanned + /// - If the peer is not banned, this returns [`None`] + fn peer_unban_instant(&self, peer: &Z::Addr) -> Option { + self.banned_peers.get(&peer.ban_id()).copied() + } + fn handle_incoming_peer_list( &mut self, mut peer_list: Vec>, @@ -408,9 +417,15 @@ impl Service> for AddressBook { AddressBookRequest::GetWhitePeers(len) => { Ok(AddressBookResponse::Peers(self.get_white_peers(len))) } - AddressBookRequest::IsPeerBanned(addr) => Ok(AddressBookResponse::IsPeerBanned( - self.is_peer_banned(&addr), - )), + AddressBookRequest::GetBan(addr) => Ok(AddressBookResponse::GetBan { + unban_instant: self.peer_unban_instant(&addr).map(Instant::into_std), + }), + AddressBookRequest::PeerlistSize + | AddressBookRequest::ConnectionCount + | AddressBookRequest::SetBan(_) + | AddressBookRequest::GetBans => { + todo!("finish https://github.com/Cuprate/cuprate/pull/297") + } }; ready(response) diff --git a/p2p/p2p-core/src/ban.rs b/p2p/p2p-core/src/ban.rs new file mode 100644 index 000000000..76fd3ebf7 --- /dev/null +++ b/p2p/p2p-core/src/ban.rs @@ -0,0 +1,23 @@ +//! Data structures related to bans. + +use std::time::{Duration, Instant}; + +use crate::NetZoneAddress; + +/// Data within [`crate::services::AddressBookRequest::SetBan`]. +pub struct SetBan { + /// Address of the peer. + pub address: A, + /// - If [`Some`], how long this peer should be banned for + /// - If [`None`], the peer will be unbanned + pub ban: Option, +} + +/// Data within [`crate::services::AddressBookResponse::GetBans`]. +pub struct BanState { + /// Address of the peer. + pub address: A, + /// - If [`Some`], the peer is banned until this [`Instant`] + /// - If [`None`], the peer is not currently banned + pub unban_instant: Option, +} diff --git a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs index 1dcc2bee8..8bb966dbf 100644 --- a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs +++ b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs @@ -105,7 +105,15 @@ impl Service> for DummyAddressBook { AddressBookRequest::NewConnection { .. } | AddressBookRequest::IncomingPeerList(_) => { AddressBookResponse::Ok } - AddressBookRequest::IsPeerBanned(_) => AddressBookResponse::IsPeerBanned(false), + AddressBookRequest::GetBan(_) => AddressBookResponse::GetBan { + unban_instant: None, + }, + AddressBookRequest::PeerlistSize + | AddressBookRequest::ConnectionCount + | AddressBookRequest::SetBan(_) + | AddressBookRequest::GetBans => { + todo!("finish https://github.com/Cuprate/cuprate/pull/297") + } })) } } diff --git a/p2p/p2p-core/src/lib.rs b/p2p/p2p-core/src/lib.rs index c7c607b34..5b93b59ce 100644 --- a/p2p/p2p-core/src/lib.rs +++ b/p2p/p2p-core/src/lib.rs @@ -75,6 +75,7 @@ use cuprate_wire::{ NetworkAddress, }; +pub mod ban; pub mod client; mod constants; pub mod error; diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index b858f33e2..495b71928 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -1,9 +1,13 @@ +use std::time::Instant; + use cuprate_pruning::{PruningError, PruningSeed}; use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use crate::{ - client::InternalPeerID, handles::ConnectionHandle, NetZoneAddress, NetworkAddressIncorrectZone, - NetworkZone, + ban::{BanState, SetBan}, + client::InternalPeerID, + handles::ConnectionHandle, + NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, }; /// A request to the core sync service for our node's [`CoreSyncData`]. @@ -86,16 +90,20 @@ pub enum AddressBookRequest { /// The peers rpc credits per hash rpc_credits_per_hash: u32, }, + /// Tells the address book about a peer list received from a peer. IncomingPeerList(Vec>), + /// Takes a random white peer from the peer list. If height is specified /// then the peer list should retrieve a peer that should have a full /// block at that height according to it's pruning seed TakeRandomWhitePeer { height: Option }, + /// Takes a random gray peer from the peer list. If height is specified /// then the peer list should retrieve a peer that should have a full /// block at that height according to it's pruning seed TakeRandomGrayPeer { height: Option }, + /// Takes a random peer from the peer list. If height is specified /// then the peer list should retrieve a peer that should have a full /// block at that height according to it's pruning seed. @@ -103,17 +111,56 @@ pub enum AddressBookRequest { /// The address book will look in the white peer list first, then the gray /// one if no peer is found. TakeRandomPeer { height: Option }, + /// Gets the specified number of white peers, or less if we don't have enough. GetWhitePeers(usize), + + /// Get the amount of white & grey peers. + PeerlistSize, + + /// Get the amount of incoming & outgoing connections. + ConnectionCount, + + /// (Un)ban a peer. + SetBan(SetBan), + /// Checks if the given peer is banned. - IsPeerBanned(Z::Addr), + GetBan(Z::Addr), + + /// Get the state of all bans. + GetBans, } /// A response from the address book service. pub enum AddressBookResponse { + /// Generic OK response. + /// + /// Response to: + /// - [`AddressBookRequest::NewConnection`] + /// - [`AddressBookRequest::IncomingPeerList`] Ok, + + /// Response to: + /// - [`AddressBookRequest::TakeRandomWhitePeer`] + /// - [`AddressBookRequest::TakeRandomGrayPeer`] + /// - [`AddressBookRequest::TakeRandomPeer`] Peer(ZoneSpecificPeerListEntryBase), + + /// Response to [`AddressBookRequest::GetWhitePeers`]. Peers(Vec>), - /// Contains `true` if the peer is banned. - IsPeerBanned(bool), + + /// Response to [`AddressBookRequest::PeerlistSize`]. + PeerlistSize { white: usize, grey: usize }, + + /// Response to [`AddressBookRequest::ConnectionCount`]. + ConnectionCount { incoming: usize, outgoing: usize }, + + /// Response to [`AddressBookRequest::GetBan`]. + /// + /// This returns [`None`] if the peer is not banned, + /// else it returns how long the peer is banned for. + GetBan { unban_instant: Option }, + + /// Response to [`AddressBookRequest::GetBans`]. + GetBans(Vec>), } diff --git a/p2p/p2p/src/inbound_server.rs b/p2p/p2p/src/inbound_server.rs index 0d50d5491..6e793bd19 100644 --- a/p2p/p2p/src/inbound_server.rs +++ b/p2p/p2p/src/inbound_server.rs @@ -79,16 +79,16 @@ where // If peer is banned, drop connection if let Some(addr) = &addr { - let AddressBookResponse::IsPeerBanned(banned) = address_book + let AddressBookResponse::GetBan { unban_instant } = address_book .ready() .await? - .call(AddressBookRequest::IsPeerBanned(*addr)) + .call(AddressBookRequest::GetBan(*addr)) .await? else { panic!("Address book returned incorrect response!"); }; - if banned { + if unban_instant.is_some() { continue; } } diff --git a/storage/blockchain/src/service/mod.rs b/storage/blockchain/src/service/mod.rs index aa322d06e..53bf1dfa3 100644 --- a/storage/blockchain/src/service/mod.rs +++ b/storage/blockchain/src/service/mod.rs @@ -21,8 +21,8 @@ //! //! The 2nd allows any caller to send [`WriteRequest`][req_w]s. //! -//! The `DatabaseReadHandle` can be shared as it is cheaply [`Clone`]able, however, -//! the `DatabaseWriteHandle` cannot be cloned. There is only 1 place in Cuprate that +//! The [`BlockchainReadHandle`] can be shared as it is cheaply [`Clone`]able, however, +//! the [`BlockchainWriteHandle`] cannot be cloned. There is only 1 place in Cuprate that //! writes, so it is passed there and used. //! //! ## Initialization diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index b0e7e044c..a3b82bdb2 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -1,5 +1,13 @@ //! Database reader thread-pool definitions and logic. +#![expect( + unreachable_code, + unused_variables, + clippy::unnecessary_wraps, + clippy::needless_pass_by_value, + reason = "TODO: finish implementing the signatures from " +)] + //---------------------------------------------------------------------------------------------------- Import use std::{ collections::{HashMap, HashSet}, @@ -18,7 +26,7 @@ use cuprate_database_service::{init_thread_pool, DatabaseReadService, ReaderThre use cuprate_helper::map::combine_low_high_bits_to_u128; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, ChainId, ExtendedBlockHeader, OutputOnChain, + Chain, ChainId, ExtendedBlockHeader, OutputHistogramInput, OutputOnChain, }; use crate::{ @@ -107,6 +115,12 @@ fn map_request( R::CompactChainHistory => compact_chain_history(env), R::FindFirstUnknown(block_ids) => find_first_unknown(env, &block_ids), R::AltBlocksInChain(chain_id) => alt_blocks_in_chain(env, chain_id), + R::Block { height } => block(env, height), + R::BlockByHash(hash) => block_by_hash(env, hash), + R::TotalTxCount => total_tx_count(env), + R::DatabaseSize => database_size(env), + R::OutputHistogram(input) => output_histogram(env, input), + R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -601,3 +615,36 @@ fn alt_blocks_in_chain(env: &ConcreteEnv, chain_id: ChainId) -> ResponseResult { Ok(BlockchainResponse::AltBlocksInChain(blocks)) } + +/// [`BlockchainReadRequest::Block`] +fn block(env: &ConcreteEnv, block_height: BlockHeight) -> ResponseResult { + Ok(BlockchainResponse::Block(todo!())) +} + +/// [`BlockchainReadRequest::BlockByHash`] +fn block_by_hash(env: &ConcreteEnv, block_hash: BlockHash) -> ResponseResult { + Ok(BlockchainResponse::Block(todo!())) +} + +/// [`BlockchainReadRequest::TotalTxCount`] +fn total_tx_count(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::TotalTxCount(todo!())) +} + +/// [`BlockchainReadRequest::DatabaseSize`] +fn database_size(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::DatabaseSize { + database_size: todo!(), + free_space: todo!(), + }) +} + +/// [`BlockchainReadRequest::OutputHistogram`] +fn output_histogram(env: &ConcreteEnv, input: OutputHistogramInput) -> ResponseResult { + Ok(BlockchainResponse::OutputHistogram(todo!())) +} + +/// [`BlockchainReadRequest::CoinbaseTxSum`] +fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResult { + Ok(BlockchainResponse::CoinbaseTxSum(todo!())) +} diff --git a/storage/txpool/src/lib.rs b/storage/txpool/src/lib.rs index 243dc4d97..5fb3b1439 100644 --- a/storage/txpool/src/lib.rs +++ b/storage/txpool/src/lib.rs @@ -10,10 +10,12 @@ pub mod ops; #[cfg(feature = "service")] pub mod service; pub mod tables; +mod tx; pub mod types; pub use config::Config; pub use free::open; +pub use tx::TxEntry; //re-exports pub use cuprate_database; diff --git a/storage/txpool/src/service.rs b/storage/txpool/src/service.rs index d87adcead..91a7060c0 100644 --- a/storage/txpool/src/service.rs +++ b/storage/txpool/src/service.rs @@ -21,9 +21,7 @@ //! //! The 2nd allows any caller to send [`WriteRequest`][req_w]s. //! -//! The `DatabaseReadHandle` can be shared as it is cheaply [`Clone`]able, however, -//! the `DatabaseWriteHandle` cannot be cloned. There is only 1 place in Cuprate that -//! writes, so it is passed there and used. +//! Both the handles are cheaply [`Clone`]able. //! //! ## Initialization //! The database & thread-pool system can be initialized with [`init()`]. diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 450b28d63..88dd02e35 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -5,30 +5,53 @@ use std::sync::Arc; use cuprate_types::TransactionVerificationData; -use crate::types::TransactionHash; +use crate::{tx::TxEntry, types::TransactionHash}; //---------------------------------------------------------------------------------------------------- TxpoolReadRequest /// The transaction pool [`tower::Service`] read request type. pub enum TxpoolReadRequest { /// A request for the blob (raw bytes) of a transaction with the given hash. TxBlob(TransactionHash), + /// A request for the [`TransactionVerificationData`] of a transaction in the tx pool. TxVerificationData(TransactionHash), + + /// Get information on all transactions in the pool. + Backlog, + + /// Get the number of transactions in the pool. + Size, } //---------------------------------------------------------------------------------------------------- TxpoolReadResponse /// The transaction pool [`tower::Service`] read response type. #[expect(clippy::large_enum_variant)] pub enum TxpoolReadResponse { - /// A response containing the raw bytes of a transaction. + /// Response to [`TxpoolReadRequest::TxBlob`]. + /// + /// The inner value is the raw bytes of a transaction. // TODO: use bytes::Bytes. TxBlob(Vec), - /// A response of [`TransactionVerificationData`]. + + /// Response to [`TxpoolReadRequest::TxVerificationData`]. TxVerificationData(TransactionVerificationData), + + /// Response to [`TxpoolReadRequest::Backlog`]. + /// + /// The inner `Vec` contains information on all + /// the transactions currently in the pool. + Backlog(Vec), + + /// Response to [`TxpoolReadRequest::Size`]. + /// + /// The inner value is the amount of + /// transactions currently in the pool. + Size(usize), } //---------------------------------------------------------------------------------------------------- TxpoolWriteRequest /// The transaction pool [`tower::Service`] write request type. +#[derive(Clone)] pub enum TxpoolWriteRequest { /// Add a transaction to the pool. /// @@ -41,6 +64,7 @@ pub enum TxpoolWriteRequest { /// [`true`] if this tx is in the stem state. state_stem: bool, }, + /// Remove a transaction with the given hash from the pool. /// /// Returns [`TxpoolWriteResponse::Ok`]. @@ -49,11 +73,14 @@ pub enum TxpoolWriteRequest { //---------------------------------------------------------------------------------------------------- TxpoolWriteResponse /// The transaction pool [`tower::Service`] write response type. -#[derive(Debug, Ord, PartialOrd, Eq, PartialEq)] +#[derive(Clone, Debug, Ord, PartialOrd, Eq, PartialEq)] pub enum TxpoolWriteResponse { - /// A [`TxpoolWriteRequest::AddTransaction`] response. + /// Response to: + /// - [`TxpoolWriteRequest::RemoveTransaction`] + Ok, + + /// Response to [`TxpoolWriteRequest::AddTransaction`]. /// /// If the inner value is [`Some`] the tx was not added to the pool as it double spends a tx with the given hash. AddTransaction(Option), - Ok, } diff --git a/storage/txpool/src/service/read.rs b/storage/txpool/src/service/read.rs index f0068130f..3135322e3 100644 --- a/storage/txpool/src/service/read.rs +++ b/storage/txpool/src/service/read.rs @@ -1,3 +1,10 @@ +#![expect( + unreachable_code, + unused_variables, + clippy::unnecessary_wraps, + reason = "TODO: finish implementing the signatures from " +)] + use std::sync::Arc; use rayon::ThreadPool; @@ -58,6 +65,8 @@ fn map_request( match request { TxpoolReadRequest::TxBlob(tx_hash) => tx_blob(env, &tx_hash), TxpoolReadRequest::TxVerificationData(tx_hash) => tx_verification_data(env, &tx_hash), + TxpoolReadRequest::Backlog => backlog(env), + TxpoolReadRequest::Size => size(env), } } @@ -101,3 +110,15 @@ fn tx_verification_data(env: &ConcreteEnv, tx_hash: &TransactionHash) -> ReadRes get_transaction_verification_data(tx_hash, &tables).map(TxpoolReadResponse::TxVerificationData) } + +/// [`TxpoolReadRequest::Backlog`]. +#[inline] +fn backlog(env: &ConcreteEnv) -> ReadResponseResult { + Ok(TxpoolReadResponse::Backlog(todo!())) +} + +/// [`TxpoolReadRequest::Size`]. +#[inline] +fn size(env: &ConcreteEnv) -> ReadResponseResult { + Ok(TxpoolReadResponse::Size(todo!())) +} diff --git a/storage/txpool/src/tx.rs b/storage/txpool/src/tx.rs new file mode 100644 index 000000000..6425326a4 --- /dev/null +++ b/storage/txpool/src/tx.rs @@ -0,0 +1,14 @@ +//! Transaction metadata. + +/// Data about a transaction in the pool. +/// +/// Used in [`TxpoolReadResponse::Backlog`](crate::service::interface::TxpoolReadResponse::Backlog). +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct TxEntry { + /// The transaction's weight. + pub weight: u64, + /// The transaction's fee. + pub fee: u64, + /// How long the transaction has been in the pool. + pub time_in_pool: std::time::Duration, +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index f2b96db00..b7436f0a7 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -8,9 +8,11 @@ use std::{ ops::Range, }; +use monero_serai::block::Block; + use crate::{ types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, - AltBlockInformation, ChainId, + AltBlockInformation, ChainId, CoinbaseTxSum, OutputHistogramEntry, OutputHistogramInput, }; //---------------------------------------------------------------------------------------------------- ReadRequest @@ -103,6 +105,29 @@ pub enum BlockchainReadRequest { /// A request for all alt blocks in the chain with the given [`ChainId`]. AltBlocksInChain(ChainId), + + /// Get a [`Block`] by its height. + Block { height: usize }, + + /// Get a [`Block`] by its hash. + BlockByHash([u8; 32]), + + /// Get the total amount of non-coinbase transactions in the chain. + TotalTxCount, + + /// Get the current size of the database. + DatabaseSize, + + /// Get an output histogram. + /// + /// TODO: document fields after impl. + OutputHistogram(OutputHistogramInput), + + /// Get the coinbase amount and the fees amount for + /// `N` last blocks starting at particular height. + /// + /// TODO: document fields after impl. + CoinbaseTxSum { height: usize, count: u64 }, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -147,6 +172,7 @@ pub enum BlockchainWriteRequest { /// This pairs with [`BlockchainReadRequest`] and [`BlockchainWriteRequest`], /// see those two for more info. #[derive(Debug, Clone, PartialEq, Eq)] +#[expect(clippy::large_enum_variant)] pub enum BlockchainResponse { //------------------------------------------------------ Reads /// Response to [`BlockchainReadRequest::BlockExtendedHeader`]. @@ -215,18 +241,41 @@ pub enum BlockchainResponse { cumulative_difficulty: u128, }, - /// The response for [`BlockchainReadRequest::FindFirstUnknown`]. + /// Response to [`BlockchainReadRequest::FindFirstUnknown`]. /// /// Contains the index of the first unknown block and its expected height. /// /// This will be [`None`] if all blocks were known. FindFirstUnknown(Option<(usize, usize)>), - /// The response for [`BlockchainReadRequest::AltBlocksInChain`]. + /// Response to [`BlockchainReadRequest::AltBlocksInChain`]. /// /// Contains all the alt blocks in the alt-chain in chronological order. AltBlocksInChain(Vec), + /// Response to: + /// - [`BlockchainReadRequest::Block`]. + /// - [`BlockchainReadRequest::BlockByHash`]. + Block(Block), + + /// Response to [`BlockchainReadRequest::TotalTxCount`]. + TotalTxCount(usize), + + /// Response to [`BlockchainReadRequest::DatabaseSize`]. + DatabaseSize { + /// The size of the database file in bytes. + database_size: u64, + /// The amount of free bytes there are + /// the disk where the database is located. + free_space: u64, + }, + + /// Response to [`BlockchainReadRequest::OutputHistogram`]. + OutputHistogram(Vec), + + /// Response to [`BlockchainReadRequest::CoinbaseTxSum`]. + CoinbaseTxSum(CoinbaseTxSum), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// @@ -236,7 +285,8 @@ pub enum BlockchainResponse { /// - [`BlockchainWriteRequest::ReverseReorg`] /// - [`BlockchainWriteRequest::FlushAltBlocks`] Ok, - /// The response for [`BlockchainWriteRequest::PopBlocks`]. + + /// Response to [`BlockchainWriteRequest::PopBlocks`]. /// /// The inner value is the alt-chain ID for the old main chain blocks. PopBlocks(ChainId), diff --git a/types/src/lib.rs b/types/src/lib.rs index e9b1e1ade..0fd1ec7b5 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -20,8 +20,9 @@ pub use transaction_verification_data::{ CachedVerificationState, TransactionVerificationData, TxVersion, }; pub use types::{ - AltBlockInformation, Chain, ChainId, ExtendedBlockHeader, OutputOnChain, - VerifiedBlockInformation, VerifiedTransactionInformation, + AltBlockInformation, Chain, ChainId, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, + FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, OutputHistogramEntry, + OutputHistogramInput, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation, }; //---------------------------------------------------------------------------------------------------- Feature-gated diff --git a/types/src/types.rs b/types/src/types.rs index a60ce6c60..7d5c377f6 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -1,6 +1,5 @@ //! Various shared data types in Cuprate. -//---------------------------------------------------------------------------------------------------- Import use std::num::NonZero; use curve25519_dalek::edwards::EdwardsPoint; @@ -11,7 +10,6 @@ use monero_serai::{ use crate::HardFork; -//---------------------------------------------------------------------------------------------------- ExtendedBlockHeader /// Extended header data of a block. /// /// This contains various metadata of a block, but not the block blob itself. @@ -37,7 +35,6 @@ pub struct ExtendedBlockHeader { pub long_term_weight: usize, } -//---------------------------------------------------------------------------------------------------- VerifiedTransactionInformation /// Verified information of a transaction. /// /// This represents a valid transaction @@ -61,7 +58,6 @@ pub struct VerifiedTransactionInformation { pub tx_hash: [u8; 32], } -//---------------------------------------------------------------------------------------------------- VerifiedBlockInformation /// Verified information of a block. /// /// This represents a block that has already been verified to be correct. @@ -94,14 +90,12 @@ pub struct VerifiedBlockInformation { pub cumulative_difficulty: u128, } -//---------------------------------------------------------------------------------------------------- ChainID /// A unique ID for an alt chain. /// /// The inner value is meaningless. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct ChainId(pub NonZero); -//---------------------------------------------------------------------------------------------------- Chain /// An identifier for a chain. #[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] pub enum Chain { @@ -111,7 +105,6 @@ pub enum Chain { Alt(ChainId), } -//---------------------------------------------------------------------------------------------------- AltBlockInformation /// A block on an alternative chain. #[derive(Clone, Debug, PartialEq, Eq)] pub struct AltBlockInformation { @@ -141,7 +134,6 @@ pub struct AltBlockInformation { pub chain_id: ChainId, } -//---------------------------------------------------------------------------------------------------- OutputOnChain /// An already existing transaction output. #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct OutputOnChain { @@ -155,6 +147,104 @@ pub struct OutputOnChain { pub commitment: EdwardsPoint, } +/// Input required to generate an output histogram. +/// +/// Used in RPC's `get_output_histogram`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OutputHistogramInput { + pub amounts: Vec, + pub min_count: u64, + pub max_count: u64, + pub unlocked: bool, + pub recent_cutoff: u64, +} + +/// A single entry in an output histogram. +/// +/// Used in RPC's `get_output_histogram`. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct OutputHistogramEntry { + pub amount: u64, + pub total_instances: u64, + pub unlocked_instances: u64, + pub recent_instances: u64, +} + +/// Data of summed coinbase transactions. +/// +/// Used in RPC's `get_coinbase_tx_sum`. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct CoinbaseTxSum { + pub emission_amount: u128, + pub fee_amount: u128, + pub wide_emission_amount: u128, + pub wide_fee_amount: u128, +} + +/// Data to create a custom block template. +/// +/// Used in RPC's `get_miner_data`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct MinerData { + pub major_version: u8, + pub height: u64, + pub prev_id: [u8; 32], + pub seed_hash: [u8; 32], + pub difficulty: u128, + pub median_weight: u64, + pub already_generated_coins: u64, + pub tx_backlog: Vec, +} + +/// A transaction in the txpool. +/// +/// Used in [`MinerData::tx_backlog`]. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct MinerDataTxBacklogEntry { + pub id: [u8; 32], + pub weight: u64, + pub fee: u64, +} + +/// Information on a [`HardFork`]. +/// +/// Used in RPC's `hard_fork_info`. +#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct HardForkInfo { + pub earliest_height: u64, + pub enabled: bool, + pub state: u32, + pub threshold: u32, + pub version: u8, + pub votes: u32, + pub voting: u8, + pub window: u32, +} + +/// Estimated fee data. +/// +/// Used in RPC's `get_fee_estimate`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct FeeEstimate { + pub fee: u64, + pub fees: Vec, + pub quantization_mask: u64, +} + +/// Information on a (maybe alternate) chain. +/// +/// Used in RPC's `get_alternate_chains`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct ChainInfo { + pub block_hash: [u8; 32], + pub block_hashes: Vec<[u8; 32]>, + pub difficulty: u128, + pub height: u64, + pub length: u64, + pub main_chain_parent_block: [u8; 32], + pub wide_difficulty: u128, +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test {