From d170b46180ad190e684d0174b64061a122e9e9ff Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 9 Oct 2024 20:47:17 -0400 Subject: [PATCH 01/47] import diffs --- Cargo.lock | 1 + binaries/cuprated/Cargo.toml | 1 + binaries/cuprated/src/rpc.rs | 1 + binaries/cuprated/src/rpc/helper.rs | 168 +++++++ binaries/cuprated/src/rpc/json.rs | 444 +++++++++++++++--- binaries/cuprated/src/rpc/request.rs | 10 +- .../cuprated/src/rpc/request/blockchain.rs | 103 ++-- 7 files changed, 628 insertions(+), 100 deletions(-) create mode 100644 binaries/cuprated/src/rpc/helper.rs diff --git a/Cargo.lock b/Cargo.lock index 5fea18d04..e45f7e42c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -972,6 +972,7 @@ dependencies = [ "cuprate-blockchain", "cuprate-consensus", "cuprate-consensus-rules", + "cuprate-constants", "cuprate-cryptonight", "cuprate-dandelion-tower", "cuprate-database", diff --git a/binaries/cuprated/Cargo.toml b/binaries/cuprated/Cargo.toml index 325406bf7..7ec857963 100644 --- a/binaries/cuprated/Cargo.toml +++ b/binaries/cuprated/Cargo.toml @@ -12,6 +12,7 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/binaries/cuprated" cuprate-consensus = { path = "../../consensus" } cuprate-fast-sync = { path = "../../consensus/fast-sync" } cuprate-consensus-rules = { path = "../../consensus/rules" } +cuprate-constants = { path = "../../constants", features = ["build", "rpc"] } cuprate-cryptonight = { path = "../../cryptonight" } cuprate-helper = { path = "../../helper" } cuprate-epee-encoding = { path = "../../net/epee-encoding" } diff --git a/binaries/cuprated/src/rpc.rs b/binaries/cuprated/src/rpc.rs index fe8e5f214..a52fc98c9 100644 --- a/binaries/cuprated/src/rpc.rs +++ b/binaries/cuprated/src/rpc.rs @@ -7,5 +7,6 @@ mod handler; 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 new file mode 100644 index 000000000..7c95b1b34 --- /dev/null +++ b/binaries/cuprated/src/rpc/helper.rs @@ -0,0 +1,168 @@ +//! These are internal helper functions used by the actual RPC handlers. +//! +//! Many of the handlers have bodies with only small differences, +//! the identical code is extracted and reused here in these functions. +//! +//! These build on-top of [`crate::rpc::request`] functions. + +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; +use cuprate_constants::rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}; +use cuprate_helper::{ + cast::{u64_to_usize, usize_to_u64}, + map::split_u128_into_low_high_bits, +}; +use cuprate_types::{ + blockchain::BlockchainReadRequest, Chain, ExtendedBlockHeader, VerifiedBlockInformation, +}; + +use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler}; + +fn into_block_header( + height: u64, + top_height: u64, + fill_pow_hash: bool, + block: Block, + header: ExtendedBlockHeader, +) -> BlockHeader { + let block_weight = usize_to_u64(header.block_weight); + let depth = top_height.saturating_sub(height); + let (cumulative_difficulty_top64, cumulative_difficulty) = + split_u128_into_low_high_bits(header.cumulative_difficulty); + + BlockHeader { + block_size: block_weight, + block_weight, + cumulative_difficulty_top64, + cumulative_difficulty, + depth, + difficulty_top64: todo!(), + difficulty: todo!(), + hash: hex::encode(block.hash()), + height, + long_term_weight: usize_to_u64(header.long_term_weight), + major_version: header.version.as_u8(), + miner_tx_hash: hex::encode(block.miner_transaction.hash()), + minor_version: header.vote, + nonce: block.header.nonce, + num_txes: usize_to_u64(block.transactions.len()), + orphan_status: todo!(), + pow_hash: if fill_pow_hash { + todo!() + } else { + String::new() + }, + prev_hash: hex::encode(block.header.previous), + reward: todo!(), + timestamp: block.header.timestamp, + wide_cumulative_difficulty: hex::encode(u128::to_le_bytes(header.cumulative_difficulty)), + wide_difficulty: todo!(), + } +} + +/// Get a [`VerifiedBlockInformation`] and map it to a [`BlockHeader`]. +pub(super) async fn block_header( + state: &mut CupratedRpcHandler, + height: u64, + fill_pow_hash: bool, +) -> Result { + let (top_height, _) = top_height(state).await?; + let block = blockchain::block(&mut state.blockchain_read, height).await?; + let header = blockchain::block_extended_header(&mut state.blockchain_read, height).await?; + + let block_header = into_block_header(height, top_height, fill_pow_hash, block, header); + + Ok(block_header) +} + +/// Same as [`block_header`] but with the block's hash. +pub(super) async fn block_header_by_hash( + state: &mut CupratedRpcHandler, + hash: [u8; 32], + fill_pow_hash: bool, +) -> Result { + let (top_height, _) = top_height(state).await?; + 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); + + Ok(block_header) +} + +/// TODO +pub(super) async fn top_block_header( + state: &mut CupratedRpcHandler, + fill_pow_hash: bool, +) -> Result { + let block: Block = todo!(); + let header: ExtendedBlockHeader = todo!(); + + let block_header = + into_block_header(header.height, header.height, fill_pow_hash, block, header); + + Ok(block_header) +} + +/// Check if `height` is greater than the [`top_height`]. +/// +/// # Errors +/// This returns the [`top_height`] on [`Ok`] and +/// returns [`Error`] if `height` is greater than [`top_height`]. +pub(super) async fn check_height( + state: &mut CupratedRpcHandler, + height: u64, +) -> Result { + let (top_height, _) = top_height(state).await?; + + if height > top_height { + return Err(anyhow!( + "Requested block height: {height} greater than current top block height: {top_height}", + )); + } + + Ok(top_height) +} + +/// Parse a hexadecimal [`String`] as a 32-byte hash. +pub(super) fn hex_to_hash(hex: String) -> Result<[u8; 32], Error> { + let error = || anyhow!("Failed to parse hex representation of hash. Hex = {hex}."); + + let Ok(bytes) = hex::decode(&hex) else { + return Err(error()); + }; + + let Ok(hash) = bytes.try_into() else { + return Err(error()); + }; + + Ok(hash) +} + +/// [`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 height = chain_height.saturating_sub(1); + Ok((height, hash)) +} + +/// TODO +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) + } +} diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 88b38b92f..2ba6796be 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,29 +1,43 @@ use std::sync::Arc; -use anyhow::Error; -use tower::ServiceExt; - -use cuprate_rpc_types::json::{ - AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest, - CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest, - FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse, - GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse, - GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest, - GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest, GetBlockHeaderByHeightResponse, - GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse, GetBlockRequest, GetBlockResponse, - GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, GetConnectionsRequest, - GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest, - GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse, GetMinerDataRequest, - GetMinerDataResponse, GetOutputHistogramRequest, GetOutputHistogramResponse, - GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, - GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest, - HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, - OnGetBlockHashResponse, PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, - RelayTxResponse, SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, - SyncInfoRequest, SyncInfoResponse, +use anyhow::{anyhow, Error}; +use cuprate_types::HardFork; +use monero_serai::block::Block; +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}, +}; +use cuprate_helper::cast::u64_to_usize; +use cuprate_rpc_types::{ + base::{AccessResponseBase, ResponseBase}, + json::{ + AddAuxPowRequest, AddAuxPowResponse, BannedRequest, BannedResponse, CalcPowRequest, + CalcPowResponse, FlushCacheRequest, FlushCacheResponse, FlushTransactionPoolRequest, + FlushTransactionPoolResponse, GenerateBlocksRequest, GenerateBlocksResponse, + GetAlternateChainsRequest, GetAlternateChainsResponse, GetBansRequest, GetBansResponse, + GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest, + GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest, + GetBlockHeaderByHeightResponse, GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse, + GetBlockRequest, GetBlockResponse, GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, + GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest, + GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest, + GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse, + GetOutputHistogramRequest, GetOutputHistogramResponse, GetTransactionPoolBacklogRequest, + GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse, + GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse, + JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse, + PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, RelayTxResponse, + SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, + SyncInfoResponse, + }, + misc::{BlockHeader, Status}, + CORE_RPC_VERSION, }; -use crate::rpc::CupratedRpcHandler; +use crate::rpc::{helper, request::blockchain, CupratedRpcHandler}; /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( @@ -83,212 +97,518 @@ pub(super) async fn map_request( }) } +/// async fn get_block_count( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetBlockCountRequest, ) -> Result { - todo!() + Ok(GetBlockCountResponse { + base: ResponseBase::ok(), + count: helper::top_height(&mut state).await?.0, + }) } +/// async fn on_get_block_hash( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: OnGetBlockHashRequest, ) -> Result { - todo!() + let [height] = request.block_height; + let hash = blockchain::block_hash(&mut state, height).await?; + let block_hash = hex::encode(hash); + + Ok(OnGetBlockHashResponse { block_hash }) } +/// async fn submit_block( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: SubmitBlockRequest, ) -> Result { - todo!() + 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, + }) } +/// async fn generate_blocks( state: CupratedRpcHandler, request: GenerateBlocksRequest, ) -> Result { - todo!() + Ok(GenerateBlocksResponse { + base: ResponseBase::ok(), + blocks: todo!(), + height: todo!(), + }) } +/// async fn get_last_block_header( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetLastBlockHeaderRequest, ) -> Result { - todo!() + let (height, _) = helper::top_height(&mut state).await?; + let block_header = helper::block_header(&mut state, height, request.fill_pow_hash).await?; + + Ok(GetLastBlockHeaderResponse { + base: AccessResponseBase::ok(), + block_header, + }) } +/// async fn get_block_header_by_hash( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetBlockHeaderByHashRequest, ) -> Result { - todo!() + if state.restricted && request.hashes.len() > RESTRICTED_BLOCK_COUNT { + return Err(anyhow!( + "Too many block headers requested in restricted mode" + )); + } + + async fn get( + state: &mut CupratedRpcHandler, + hex: String, + fill_pow_hash: bool, + ) -> Result { + let hash = helper::hex_to_hash(hex)?; + let block_header = helper::block_header_by_hash(state, hash, fill_pow_hash).await?; + Ok(block_header) + } + + let block_header = get(&mut state, request.hash, request.fill_pow_hash).await?; + + // FIXME PERF: could make a `Vec` on await on all tasks at the same time. + let mut block_headers = Vec::with_capacity(request.hashes.len()); + for hash in request.hashes { + let hash = get(&mut state, hash, request.fill_pow_hash).await?; + block_headers.push(hash); + } + + Ok(GetBlockHeaderByHashResponse { + base: AccessResponseBase::ok(), + block_header, + block_headers, + }) } +/// async fn get_block_header_by_height( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetBlockHeaderByHeightRequest, ) -> Result { - todo!() + helper::check_height(&mut state, request.height).await?; + let block_header = + helper::block_header(&mut state, request.height, request.fill_pow_hash).await?; + + Ok(GetBlockHeaderByHeightResponse { + base: AccessResponseBase::ok(), + block_header, + }) } +/// async fn get_block_headers_range( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetBlockHeadersRangeRequest, ) -> Result { - todo!() + let (top_height, _) = helper::top_height(&mut state).await?; + + if request.start_height >= top_height + || request.end_height >= top_height + || request.start_height > request.end_height + { + return Err(anyhow!("Invalid start/end heights")); + } + + if state.restricted + && request.end_height.saturating_sub(request.start_height) + 1 + > RESTRICTED_BLOCK_HEADER_RANGE + { + return Err(anyhow!("Too many block headers requested.")); + } + + let block_len = u64_to_usize(request.end_height.saturating_sub(request.start_height)); + let mut tasks = Vec::with_capacity(block_len); + let mut headers = Vec::with_capacity(block_len); + + { + let ready = state.blockchain_read.ready().await?; + for height in request.start_height..=request.end_height { + let height = u64_to_usize(height); + let task = tokio::task::spawn(ready.call(BlockchainReadRequest::Block { height })); + tasks.push(task); + } + } + + for task in tasks { + let BlockchainResponse::Block(header) = task.await?? else { + unreachable!(); + }; + // headers.push((&header).into()); + headers.push(todo!()); + } + + Ok(GetBlockHeadersRangeResponse { + base: AccessResponseBase::ok(), + headers, + }) } +/// async fn get_block( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetBlockRequest, ) -> Result { - todo!() + let block = if request.hash.is_empty() { + helper::check_height(&mut state, request.height).await?; + blockchain::block(&mut state, request.height).await? + } else { + let hash = helper::hex_to_hash(request.hash)?; + blockchain::block_by_hash(&mut state, hash).await? + }; + + Ok(todo!()) + + // let block_header = (&block).into(); + // let blob = hex::encode(block.block_blob); + // let miner_tx_hash = hex::encode(block.block.miner_transaction.hash()); + // let tx_hashes = block + // .txs + // .into_iter() + // .map(|tx| hex::encode(tx.tx_hash)) + // .collect(); + + // Ok(GetBlockResponse { + // base: AccessResponseBase::ok(), + // blob, + // json: todo!(), // TODO: make `JSON` type in `cuprate_rpc_types` + // miner_tx_hash, + // tx_hashes, + // block_header, + // }) } +/// async fn get_connections( state: CupratedRpcHandler, request: GetConnectionsRequest, ) -> Result { - todo!() + Ok(GetConnectionsResponse { + base: ResponseBase::ok(), + connections: todo!(), + }) } +/// async fn get_info( state: CupratedRpcHandler, request: GetInfoRequest, ) -> Result { - todo!() + Ok(GetInfoResponse { + base: AccessResponseBase::ok(), + adjusted_time: todo!(), + alt_blocks_count: todo!(), + block_size_limit: todo!(), + block_size_median: todo!(), + block_weight_limit: todo!(), + block_weight_median: todo!(), + bootstrap_daemon_address: todo!(), + busy_syncing: todo!(), + cumulative_difficulty_top64: todo!(), + cumulative_difficulty: todo!(), + database_size: todo!(), + difficulty_top64: todo!(), + difficulty: todo!(), + free_space: todo!(), + grey_peerlist_size: todo!(), + height: todo!(), + height_without_bootstrap: todo!(), + incoming_connections_count: todo!(), + mainnet: todo!(), + nettype: todo!(), + offline: todo!(), + outgoing_connections_count: todo!(), + restricted: todo!(), + rpc_connections_count: todo!(), + stagenet: todo!(), + start_time: todo!(), + synchronized: todo!(), + target_height: todo!(), + target: todo!(), + testnet: todo!(), + top_block_hash: todo!(), + tx_count: todo!(), + tx_pool_size: todo!(), + update_available: todo!(), + version: todo!(), + was_bootstrap_ever_used: todo!(), + white_peerlist_size: todo!(), + wide_cumulative_difficulty: todo!(), + wide_difficulty: todo!(), + }) } +/// async fn hard_fork_info( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: HardForkInfoRequest, ) -> Result { - todo!() + let hard_fork = if request.version > 0 { + HardFork::from_version(request.version)? + } else { + blockchain::current_hard_fork(&mut state).await? + }; + + Ok(HardForkInfoResponse { + base: AccessResponseBase::ok(), + earliest_height: todo!(), + enabled: hard_fork.is_current(), + state: todo!(), + threshold: todo!(), + version: hard_fork.as_u8(), + votes: todo!(), + voting: todo!(), + window: todo!(), + }) } +/// async fn set_bans( state: CupratedRpcHandler, request: SetBansRequest, ) -> Result { - todo!() + todo!(); + + Ok(SetBansResponse { + base: ResponseBase::ok(), + }) } +/// async fn get_bans( state: CupratedRpcHandler, request: GetBansRequest, ) -> Result { - todo!() + Ok(GetBansResponse { + base: ResponseBase::ok(), + bans: todo!(), + }) } +/// async fn banned( state: CupratedRpcHandler, request: BannedRequest, ) -> Result { - todo!() + Ok(BannedResponse { + banned: todo!(), + seconds: todo!(), + status: todo!(), + }) } +/// async fn flush_transaction_pool( state: CupratedRpcHandler, request: FlushTransactionPoolRequest, ) -> Result { - todo!() + todo!(); + Ok(FlushTransactionPoolResponse { status: Status::Ok }) } +/// async fn get_output_histogram( state: CupratedRpcHandler, request: GetOutputHistogramRequest, ) -> Result { - todo!() + Ok(GetOutputHistogramResponse { + base: AccessResponseBase::ok(), + histogram: todo!(), + }) } +/// async fn get_coinbase_tx_sum( state: CupratedRpcHandler, request: GetCoinbaseTxSumRequest, ) -> Result { - todo!() + Ok(GetCoinbaseTxSumResponse { + base: AccessResponseBase::ok(), + emission_amount: todo!(), + emission_amount_top64: todo!(), + fee_amount: todo!(), + fee_amount_top64: todo!(), + wide_emission_amount: todo!(), + wide_fee_amount: todo!(), + }) } +/// async fn get_version( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetVersionRequest, ) -> Result { - todo!() + Ok(GetVersionResponse { + base: ResponseBase::ok(), + version: CORE_RPC_VERSION, + release: RELEASE, + current_height: helper::top_height(&mut state).await?.0, + target_height: todo!(), + hard_forks: todo!(), + }) } +/// async fn get_fee_estimate( state: CupratedRpcHandler, request: GetFeeEstimateRequest, ) -> Result { - todo!() + Ok(GetFeeEstimateResponse { + base: AccessResponseBase::ok(), + fee: todo!(), + fees: todo!(), + quantization_mask: todo!(), + }) } +/// async fn get_alternate_chains( state: CupratedRpcHandler, request: GetAlternateChainsRequest, ) -> Result { - todo!() + Ok(GetAlternateChainsResponse { + base: ResponseBase::ok(), + chains: todo!(), + }) } +/// async fn relay_tx( state: CupratedRpcHandler, request: RelayTxRequest, ) -> Result { - todo!() + todo!(); + Ok(RelayTxResponse { status: Status::Ok }) } +/// async fn sync_info( state: CupratedRpcHandler, request: SyncInfoRequest, ) -> Result { - todo!() + Ok(SyncInfoResponse { + base: AccessResponseBase::ok(), + height: todo!(), + next_needed_pruning_seed: todo!(), + overview: todo!(), + peers: todo!(), + spans: todo!(), + target_height: todo!(), + }) } +/// async fn get_transaction_pool_backlog( state: CupratedRpcHandler, request: GetTransactionPoolBacklogRequest, ) -> Result { - todo!() + Ok(GetTransactionPoolBacklogResponse { + base: ResponseBase::ok(), + backlog: todo!(), + }) } +/// async fn get_miner_data( state: CupratedRpcHandler, request: GetMinerDataRequest, ) -> Result { - todo!() + Ok(GetMinerDataResponse { + base: ResponseBase::ok(), + major_version: todo!(), + height: todo!(), + prev_id: todo!(), + seed_hash: todo!(), + difficulty: todo!(), + median_weight: todo!(), + already_generated_coins: todo!(), + tx_backlog: todo!(), + }) } +/// async fn prune_blockchain( state: CupratedRpcHandler, request: PruneBlockchainRequest, ) -> Result { - todo!() + Ok(PruneBlockchainResponse { + base: ResponseBase::ok(), + pruned: todo!(), + pruning_seed: todo!(), + }) } +/// async fn calc_pow( state: CupratedRpcHandler, request: CalcPowRequest, ) -> Result { - todo!() + Ok(CalcPowResponse { pow_hash: todo!() }) } +/// async fn flush_cache( state: CupratedRpcHandler, request: FlushCacheRequest, ) -> Result { - todo!() + todo!(); + + Ok(FlushCacheResponse { + base: ResponseBase::ok(), + }) } +/// async fn add_aux_pow( state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { - todo!() + Ok(AddAuxPowResponse { + base: ResponseBase::ok(), + blocktemplate_blob: todo!(), + blockhashing_blob: todo!(), + merkle_root: todo!(), + merkle_tree_depth: todo!(), + aux_pow: todo!(), + }) } +/// async fn get_tx_ids_loose( state: CupratedRpcHandler, request: GetTxIdsLooseRequest, ) -> Result { - todo!() + Ok(GetTxIdsLooseResponse { + base: ResponseBase::ok(), + txids: todo!(), + }) } diff --git a/binaries/cuprated/src/rpc/request.rs b/binaries/cuprated/src/rpc/request.rs index 17e12b956..d1d9a21c6 100644 --- a/binaries/cuprated/src/rpc/request.rs +++ b/binaries/cuprated/src/rpc/request.rs @@ -12,8 +12,8 @@ //! 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; +pub(super) mod address_book; +pub(super) mod blockchain; +pub(super) mod blockchain_context; +pub(super) mod blockchain_manager; +pub(super) mod txpool; diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 8af80e509..7705320f3 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -6,9 +6,10 @@ use std::{ }; use anyhow::Error; -use cuprate_blockchain::service::BlockchainReadHandle; +use monero_serai::block::Block; use tower::{Service, ServiceExt}; +use cuprate_blockchain::service::BlockchainReadHandle; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, @@ -16,9 +17,45 @@ use cuprate_types::{ OutputHistogramInput, OutputOnChain, }; +/// [`BlockchainReadRequest::Block`]. +pub(crate) async fn block( + blockchain_read: &mut BlockchainReadHandle, + height: u64, +) -> Result { + let BlockchainResponse::Block(block) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::Block { + height: u64_to_usize(height), + }) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + +/// [`BlockchainReadRequest::BlockByHash`]. +pub(crate) async fn block_by_hash( + blockchain_read: &mut BlockchainReadHandle, + hash: [u8; 32], +) -> Result { + let BlockchainResponse::Block(block) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::BlockByHash(hash)) + .await? + else { + unreachable!(); + }; + + Ok(block) +} + /// [`BlockchainReadRequest::BlockExtendedHeader`]. -pub(super) async fn block_extended_header( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_extended_header( + blockchain_read: &mut BlockchainReadHandle, height: u64, ) -> Result { let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read @@ -36,8 +73,8 @@ pub(super) async fn block_extended_header( } /// [`BlockchainReadRequest::BlockHash`]. -pub(super) async fn block_hash( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_hash( + blockchain_read: &mut BlockchainReadHandle, height: u64, chain: Chain, ) -> Result<[u8; 32], Error> { @@ -57,8 +94,8 @@ pub(super) async fn block_hash( } /// [`BlockchainReadRequest::FindBlock`]. -pub(super) async fn find_block( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn find_block( + blockchain_read: &mut BlockchainReadHandle, block_hash: [u8; 32], ) -> Result, Error> { let BlockchainResponse::FindBlock(option) = blockchain_read @@ -74,8 +111,8 @@ pub(super) async fn find_block( } /// [`BlockchainReadRequest::FilterUnknownHashes`]. -pub(super) async fn filter_unknown_hashes( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn filter_unknown_hashes( + blockchain_read: &mut BlockchainReadHandle, block_hashes: HashSet<[u8; 32]>, ) -> Result, Error> { let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read @@ -91,8 +128,8 @@ pub(super) async fn filter_unknown_hashes( } /// [`BlockchainReadRequest::BlockExtendedHeaderInRange`] -pub(super) async fn block_extended_header_in_range( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn block_extended_header_in_range( + blockchain_read: &mut BlockchainReadHandle, range: Range, chain: Chain, ) -> Result, Error> { @@ -111,8 +148,8 @@ pub(super) async fn block_extended_header_in_range( } /// [`BlockchainReadRequest::ChainHeight`]. -pub(super) async fn chain_height( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn chain_height( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(u64, [u8; 32]), Error> { let BlockchainResponse::ChainHeight(height, hash) = blockchain_read .ready() @@ -127,8 +164,8 @@ pub(super) async fn chain_height( } /// [`BlockchainReadRequest::GeneratedCoins`]. -pub(super) async fn generated_coins( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn generated_coins( + blockchain_read: &mut BlockchainReadHandle, block_height: u64, ) -> Result { let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read @@ -146,8 +183,8 @@ pub(super) async fn generated_coins( } /// [`BlockchainReadRequest::Outputs`] -pub(super) async fn outputs( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn outputs( + blockchain_read: &mut BlockchainReadHandle, outputs: HashMap>, ) -> Result>, Error> { let BlockchainResponse::Outputs(outputs) = blockchain_read @@ -163,8 +200,8 @@ pub(super) async fn outputs( } /// [`BlockchainReadRequest::NumberOutputsWithAmount`] -pub(super) async fn number_outputs_with_amount( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn number_outputs_with_amount( + blockchain_read: &mut BlockchainReadHandle, output_amounts: Vec, ) -> Result, Error> { let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read @@ -182,8 +219,8 @@ pub(super) async fn number_outputs_with_amount( } /// [`BlockchainReadRequest::KeyImagesSpent`] -pub(super) async fn key_images_spent( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn key_images_spent( + blockchain_read: &mut BlockchainReadHandle, key_images: HashSet<[u8; 32]>, ) -> Result { let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read @@ -199,8 +236,8 @@ pub(super) async fn key_images_spent( } /// [`BlockchainReadRequest::CompactChainHistory`] -pub(super) async fn compact_chain_history( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn compact_chain_history( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(Vec<[u8; 32]>, u128), Error> { let BlockchainResponse::CompactChainHistory { block_ids, @@ -218,8 +255,8 @@ pub(super) async fn compact_chain_history( } /// [`BlockchainReadRequest::FindFirstUnknown`] -pub(super) async fn find_first_unknown( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn find_first_unknown( + blockchain_read: &mut BlockchainReadHandle, hashes: Vec<[u8; 32]>, ) -> Result, Error> { let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read @@ -235,8 +272,8 @@ pub(super) async fn find_first_unknown( } /// [`BlockchainReadRequest::TotalTxCount`] -pub(super) async fn total_tx_count( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn total_tx_count( + blockchain_read: &mut BlockchainReadHandle, ) -> Result { let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read .ready() @@ -251,8 +288,8 @@ pub(super) async fn total_tx_count( } /// [`BlockchainReadRequest::DatabaseSize`] -pub(super) async fn database_size( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn database_size( + blockchain_read: &mut BlockchainReadHandle, ) -> Result<(u64, u64), Error> { let BlockchainResponse::DatabaseSize { database_size, @@ -270,8 +307,8 @@ pub(super) async fn database_size( } /// [`BlockchainReadRequest::OutputHistogram`] -pub(super) async fn output_histogram( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn output_histogram( + blockchain_read: &mut BlockchainReadHandle, input: OutputHistogramInput, ) -> Result, Error> { let BlockchainResponse::OutputHistogram(histogram) = blockchain_read @@ -287,8 +324,8 @@ pub(super) async fn output_histogram( } /// [`BlockchainReadRequest::CoinbaseTxSum`] -pub(super) async fn coinbase_tx_sum( - mut blockchain_read: BlockchainReadHandle, +pub(crate) async fn coinbase_tx_sum( + blockchain_read: &mut BlockchainReadHandle, height: u64, count: u64, ) -> Result { From 02e950bf5665a32d13862bd2f70705dca3142536 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 10 Oct 2024 17:37:28 -0400 Subject: [PATCH 02/47] small fixes, hardfork changes --- Cargo.lock | 23 +++++++++ Cargo.toml | 1 + binaries/cuprated/src/rpc.rs | 2 +- binaries/cuprated/src/rpc/helper.rs | 22 ++++----- binaries/cuprated/src/rpc/json.rs | 26 +++++----- rpc/types/src/json.rs | 17 +++++-- test-utils/src/rpc/data/json.rs | 5 +- types/Cargo.toml | 1 + types/src/hard_fork.rs | 73 ++++++++++++++++++++--------- 9 files changed, 120 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e45f7e42c..089236a2d 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 fa348ccdc..6c322fbd8 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 a52fc98c9..9d12c1b52 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 7c95b1b34..5d6477c57 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 2ba6796be..604ed91ee 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 d3426b46c..c28a47f16 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 a05af6700..3d4630623 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 1c7629028..8ac6b25f7 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 8b2cd78cc..92dfb5b73 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) + } } From c18ba6e5b020e2d669e001598190ebf15d7ec324 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 10 Oct 2024 18:15:21 -0400 Subject: [PATCH 03/47] lints --- binaries/cuprated/src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/binaries/cuprated/src/main.rs b/binaries/cuprated/src/main.rs index d3fe1f566..d5c832e2c 100644 --- a/binaries/cuprated/src/main.rs +++ b/binaries/cuprated/src/main.rs @@ -9,6 +9,10 @@ unused_variables, clippy::needless_pass_by_value, clippy::unused_async, + clippy::diverging_sub_expression, + unused_mut, + clippy::let_unit_value, + clippy::needless_pass_by_ref_mut, reason = "TODO: remove after v1.0.0" )] From 93be3be3652465402bd75e1d98be42e0cabc8a5a Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 10 Oct 2024 20:37:35 -0400 Subject: [PATCH 04/47] hard_fork --- types/src/hard_fork.rs | 81 +++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 17 deletions(-) diff --git a/types/src/hard_fork.rs b/types/src/hard_fork.rs index 92dfb5b73..ad1295378 100644 --- a/types/src/hard_fork.rs +++ b/types/src/hard_fork.rs @@ -69,15 +69,14 @@ pub enum HardFork { V13, V14, V15, - // remember to update from_vote! V16, } impl HardFork { - /// TODO + /// The current [`HardFork`]. /// /// ```rust - /// # use crate::hard_fork::HardFork; + /// # use cuprate_types::HardFork; /// assert_eq!(HardFork::CURRENT, HardFork::V16); /// ``` pub const CURRENT: Self = Self::VARIANTS[Self::COUNT - 1]; @@ -87,8 +86,19 @@ impl HardFork { /// ref: /// /// # Errors - /// /// Will return [`Err`] if the version is not a valid [`HardFork`]. + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// assert_eq!(HardFork::from_version(0), Err(HardForkError::HardForkUnknown)); + /// assert_eq!(HardFork::from_version(17), Err(HardForkError::HardForkUnknown)); + /// + /// for (version, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(*hf, HardFork::from_version(version as u8 + 1).unwrap()); + /// } + /// ``` #[inline] pub const fn from_version(version: u8) -> Result { #[expect( @@ -101,30 +111,45 @@ impl HardFork { COUNT as u8 }; - if version != 0 && version <= COUNT_AS_U8 { - Ok(Self::VARIANTS[(version - 1) as usize]) - } else { + if version == 0 || version > COUNT_AS_U8 { Err(HardForkError::HardForkUnknown) + } else { + // INVARIANT: we've proved above that `version` is in a valid range. + Ok(Self::VARIANTS[(version - 1) as usize]) } } /// Returns the hard-fork for a blocks [`BlockHeader::hardfork_signal`] (vote) field. /// /// + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// // 0 is interpreted as 1. + /// assert_eq!(HardFork::from_vote(0), HardFork::V1); + /// // Unknown defaults to `CURRENT`. + /// assert_eq!(HardFork::from_vote(17), HardFork::V16); + /// + /// for (vote, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(*hf, HardFork::from_vote(vote as u8 + 1)); + /// } + /// ``` #[inline] pub fn from_vote(vote: u8) -> Self { if vote == 0 { // A vote of 0 is interpreted as 1 as that's what Monero used to default to. - return Self::V1; + Self::V1 + } else { + // This must default to the latest hard-fork! + Self::from_version(vote).unwrap_or(Self::CURRENT) } - // This must default to the latest hard-fork! - Self::from_version(vote).unwrap_or(Self::CURRENT) } /// Returns the [`HardFork`] version and vote from this block header. /// /// # Errors - /// /// Will return [`Err`] if the [`BlockHeader::hardfork_version`] is not a valid [`HardFork`]. #[inline] pub fn from_block_header(header: &BlockHeader) -> Result<(Self, Self), HardForkError> { @@ -135,26 +160,48 @@ impl HardFork { } /// Returns the raw hard-fork value, as it would appear in [`BlockHeader::hardfork_version`]. - pub const fn as_u8(&self) -> u8 { - *self as u8 + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// for (i, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(hf.as_u8(), i as u8 + 1); + /// } + /// ``` + pub const fn as_u8(self) -> u8 { + self as u8 } /// Returns the next hard-fork. - pub fn next_fork(&self) -> Option { - Self::from_version(*self as u8 + 1).ok() + pub fn next_fork(self) -> Option { + Self::from_version(self as u8 + 1).ok() } /// Returns the target block time for this hardfork. /// /// ref: - pub const fn block_time(&self) -> Duration { + pub const fn block_time(self) -> Duration { match self { Self::V1 => BLOCK_TIME_V1, _ => BLOCK_TIME_V2, } } - /// TODO + /// Returns `true` if `self` is [`Self::CURRENT`]. + /// + /// ```rust + /// # use cuprate_types::HardFork; + /// # use strum::VariantArray; + /// + /// for hf in HardFork::VARIANTS.iter() { + /// if *hf == HardFork::CURRENT { + /// assert!(hf.is_current()); + /// } else { + /// assert!(!hf.is_current()); + /// } + /// } + /// ``` pub const fn is_current(self) -> bool { matches!(self, Self::CURRENT) } From c590bbb8d7eab9aa13e4642ea1b61e49a768e9a0 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 10 Oct 2024 20:39:44 -0400 Subject: [PATCH 05/47] apply diffs --- Cargo.lock | 23 +++++++ Cargo.toml | 1 + types/Cargo.toml | 1 + types/src/hard_fork.rs | 140 ++++++++++++++++++++++++++++++++--------- 4 files changed, 134 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5fea18d04..1b05efadb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -933,6 +933,7 @@ dependencies = [ "proptest-derive", "serde", "serde_json", + "strum", "thiserror", ] @@ -2673,6 +2674,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 fa348ccdc..6c322fbd8 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/types/Cargo.toml b/types/Cargo.toml index 1c7629028..8ac6b25f7 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 8b2cd78cc..ad1295378 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 { @@ -47,58 +69,87 @@ pub enum HardFork { V13, V14, V15, - // remember to update from_vote! V16, } impl HardFork { + /// The current [`HardFork`]. + /// + /// ```rust + /// # use cuprate_types::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: /// /// # Errors - /// /// Will return [`Err`] if the version is not a valid [`HardFork`]. + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// assert_eq!(HardFork::from_version(0), Err(HardForkError::HardForkUnknown)); + /// assert_eq!(HardFork::from_version(17), Err(HardForkError::HardForkUnknown)); + /// + /// for (version, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(*hf, HardFork::from_version(version as u8 + 1).unwrap()); + /// } + /// ``` #[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 { + Err(HardForkError::HardForkUnknown) + } else { + // INVARIANT: we've proved above that `version` is in a valid range. + Ok(Self::VARIANTS[(version - 1) as usize]) + } } /// Returns the hard-fork for a blocks [`BlockHeader::hardfork_signal`] (vote) field. /// /// + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// // 0 is interpreted as 1. + /// assert_eq!(HardFork::from_vote(0), HardFork::V1); + /// // Unknown defaults to `CURRENT`. + /// assert_eq!(HardFork::from_vote(17), HardFork::V16); + /// + /// for (vote, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(*hf, HardFork::from_vote(vote as u8 + 1)); + /// } + /// ``` #[inline] pub fn from_vote(vote: u8) -> Self { if vote == 0 { // A vote of 0 is interpreted as 1 as that's what Monero used to default to. - return Self::V1; + Self::V1 + } else { + // This must default to the latest hard-fork! + Self::from_version(vote).unwrap_or(Self::CURRENT) } - // This must default to the latest hard-fork! - Self::from_version(vote).unwrap_or(Self::V16) } /// Returns the [`HardFork`] version and vote from this block header. /// /// # Errors - /// /// Will return [`Err`] if the [`BlockHeader::hardfork_version`] is not a valid [`HardFork`]. #[inline] pub fn from_block_header(header: &BlockHeader) -> Result<(Self, Self), HardForkError> { @@ -109,22 +160,49 @@ impl HardFork { } /// Returns the raw hard-fork value, as it would appear in [`BlockHeader::hardfork_version`]. - pub const fn as_u8(&self) -> u8 { - *self as u8 + /// + /// ```rust + /// # use cuprate_types::{HardFork, HardForkError}; + /// # use strum::VariantArray; + /// for (i, hf) in HardFork::VARIANTS.iter().enumerate() { + /// // +1 because enumerate starts at 0, hf starts at 1. + /// assert_eq!(hf.as_u8(), i as u8 + 1); + /// } + /// ``` + pub const fn as_u8(self) -> u8 { + self as u8 } /// Returns the next hard-fork. - pub fn next_fork(&self) -> Option { - Self::from_version(*self as u8 + 1).ok() + pub fn next_fork(self) -> Option { + Self::from_version(self as u8 + 1).ok() } /// Returns the target block time for this hardfork. /// /// ref: - pub const fn block_time(&self) -> Duration { + pub const fn block_time(self) -> Duration { match self { Self::V1 => BLOCK_TIME_V1, _ => BLOCK_TIME_V2, } } + + /// Returns `true` if `self` is [`Self::CURRENT`]. + /// + /// ```rust + /// # use cuprate_types::HardFork; + /// # use strum::VariantArray; + /// + /// for hf in HardFork::VARIANTS.iter() { + /// if *hf == HardFork::CURRENT { + /// assert!(hf.is_current()); + /// } else { + /// assert!(!hf.is_current()); + /// } + /// } + /// ``` + pub const fn is_current(self) -> bool { + matches!(self, Self::CURRENT) + } } From cec746bdde996db22f9d0176a3ce70d388966766 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 11 Oct 2024 17:15:10 -0400 Subject: [PATCH 06/47] review fixes --- types/src/hard_fork.rs | 40 ++++++++++++++-------------------------- 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/types/src/hard_fork.rs b/types/src/hard_fork.rs index ad1295378..d16032f57 100644 --- a/types/src/hard_fork.rs +++ b/types/src/hard_fork.rs @@ -73,13 +73,13 @@ pub enum HardFork { } impl HardFork { - /// The current [`HardFork`]. + /// The latest [`HardFork`]. /// /// ```rust /// # use cuprate_types::HardFork; - /// assert_eq!(HardFork::CURRENT, HardFork::V16); + /// assert_eq!(HardFork::LATEST, HardFork::V16); /// ``` - pub const CURRENT: Self = Self::VARIANTS[Self::COUNT - 1]; + pub const LATEST: Self = Self::VARIANTS[Self::COUNT - 1]; /// Returns the hard-fork for a blocks [`BlockHeader::hardfork_version`] field. /// @@ -101,21 +101,9 @@ impl HardFork { /// ``` #[inline] pub const fn from_version(version: u8) -> Result { - #[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 { - Err(HardForkError::HardForkUnknown) - } else { - // INVARIANT: we've proved above that `version` is in a valid range. - Ok(Self::VARIANTS[(version - 1) as usize]) + match Self::from_repr(version) { + Some(this) => Ok(this), + None => Err(HardForkError::HardForkUnknown), } } @@ -128,7 +116,7 @@ impl HardFork { /// # use strum::VariantArray; /// // 0 is interpreted as 1. /// assert_eq!(HardFork::from_vote(0), HardFork::V1); - /// // Unknown defaults to `CURRENT`. + /// // Unknown defaults to `LATEST`. /// assert_eq!(HardFork::from_vote(17), HardFork::V16); /// /// for (vote, hf) in HardFork::VARIANTS.iter().enumerate() { @@ -143,7 +131,7 @@ impl HardFork { Self::V1 } else { // This must default to the latest hard-fork! - Self::from_version(vote).unwrap_or(Self::CURRENT) + Self::from_version(vote).unwrap_or(Self::LATEST) } } @@ -188,21 +176,21 @@ impl HardFork { } } - /// Returns `true` if `self` is [`Self::CURRENT`]. + /// Returns `true` if `self` is [`Self::LATEST`]. /// /// ```rust /// # use cuprate_types::HardFork; /// # use strum::VariantArray; /// /// for hf in HardFork::VARIANTS.iter() { - /// if *hf == HardFork::CURRENT { - /// assert!(hf.is_current()); + /// if *hf == HardFork::LATEST { + /// assert!(hf.is_latest()); /// } else { - /// assert!(!hf.is_current()); + /// assert!(!hf.is_latest()); /// } /// } /// ``` - pub const fn is_current(self) -> bool { - matches!(self, Self::CURRENT) + pub const fn is_latest(self) -> bool { + matches!(self, Self::LATEST) } } From 2522bb8836a55dcd44fa7056f63566261eb70b39 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 11 Oct 2024 18:06:18 -0400 Subject: [PATCH 07/47] binaries/cuprated/src/rpc/request: `pub(super)` -> `pub(crate)` --- .../cuprated/src/rpc/request/address_book.rs | 10 +++++----- .../src/rpc/request/blockchain_context.rs | 7 +++---- .../src/rpc/request/blockchain_manager.rs | 16 ++++++++-------- binaries/cuprated/src/rpc/request/txpool.rs | 6 +++--- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 2aa58e84b..9a16c0fd1 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -12,7 +12,7 @@ use cuprate_p2p_core::{ }; /// [`AddressBookRequest::PeerlistSize`] -pub(super) async fn peerlist_size( +pub(crate) async fn peerlist_size( address_book: &mut impl AddressBook, ) -> Result<(u64, u64), Error> { let AddressBookResponse::PeerlistSize { white, grey } = address_book @@ -30,7 +30,7 @@ pub(super) async fn peerlist_size( } /// [`AddressBookRequest::ConnectionCount`] -pub(super) async fn connection_count( +pub(crate) async fn connection_count( address_book: &mut impl AddressBook, ) -> Result<(u64, u64), Error> { let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book @@ -48,7 +48,7 @@ pub(super) async fn connection_count( } /// [`AddressBookRequest::SetBan`] -pub(super) async fn set_ban( +pub(crate) async fn set_ban( address_book: &mut impl AddressBook, peer: cuprate_p2p_core::ban::SetBan, ) -> Result<(), Error> { @@ -67,7 +67,7 @@ pub(super) async fn set_ban( } /// [`AddressBookRequest::GetBan`] -pub(super) async fn get_ban( +pub(crate) async fn get_ban( address_book: &mut impl AddressBook, peer: Z::Addr, ) -> Result, Error> { @@ -86,7 +86,7 @@ pub(super) async fn get_ban( } /// [`AddressBookRequest::GetBans`] -pub(super) async fn get_bans( +pub(crate) async fn get_bans( address_book: &mut impl AddressBook, ) -> Result<(), Error> { let AddressBookResponse::GetBans(bans) = address_book diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index b616593d4..e0fa67b24 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -12,9 +12,8 @@ use cuprate_consensus::context::{ use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; /// [`BlockChainContextRequest::Context`]. -pub(super) async fn context( +pub(crate) async fn context( service: &mut BlockChainContextService, - height: u64, ) -> Result { let BlockChainContextResponse::Context(context) = service .ready() @@ -31,7 +30,7 @@ pub(super) async fn context( } /// [`BlockChainContextRequest::HardForkInfo`]. -pub(super) async fn hard_fork_info( +pub(crate) async fn hard_fork_info( service: &mut BlockChainContextService, hard_fork: HardFork, ) -> Result { @@ -50,7 +49,7 @@ pub(super) async fn hard_fork_info( } /// [`BlockChainContextRequest::FeeEstimate`]. -pub(super) async fn fee_estimate( +pub(crate) async fn fee_estimate( service: &mut BlockChainContextService, grace_blocks: u64, ) -> Result { diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 4dc91c821..569c7e144 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -11,7 +11,7 @@ use crate::rpc::handler::{ }; /// [`BlockchainManagerRequest::PopBlocks`] -pub(super) async fn pop_blocks( +pub(crate) async fn pop_blocks( blockchain_manager: &mut BlockchainManagerHandle, amount: u64, ) -> Result { @@ -30,7 +30,7 @@ pub(super) async fn pop_blocks( } /// [`BlockchainManagerRequest::Prune`] -pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { +pub(crate) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { let BlockchainManagerResponse::Ok = blockchain_manager .ready() .await? @@ -44,7 +44,7 @@ pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> R } /// [`BlockchainManagerRequest::Pruned`] -pub(super) async fn pruned( +pub(crate) async fn pruned( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager @@ -60,7 +60,7 @@ pub(super) async fn pruned( } /// [`BlockchainManagerRequest::RelayBlock`] -pub(super) async fn relay_block( +pub(crate) async fn relay_block( blockchain_manager: &mut BlockchainManagerHandle, block: Block, ) -> Result<(), Error> { @@ -77,7 +77,7 @@ pub(super) async fn relay_block( } /// [`BlockchainManagerRequest::Syncing`] -pub(super) async fn syncing( +pub(crate) async fn syncing( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager @@ -93,7 +93,7 @@ pub(super) async fn syncing( } /// [`BlockchainManagerRequest::Synced`] -pub(super) async fn synced( +pub(crate) async fn synced( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Synced(syncing) = blockchain_manager @@ -109,7 +109,7 @@ pub(super) async fn synced( } /// [`BlockchainManagerRequest::Target`] -pub(super) async fn target( +pub(crate) async fn target( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::Target(target) = blockchain_manager @@ -125,7 +125,7 @@ pub(super) async fn target( } /// [`BlockchainManagerRequest::TargetHeight`] -pub(super) async fn target_height( +pub(crate) async fn target_height( blockchain_manager: &mut BlockchainManagerHandle, ) -> Result { let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index a36778eb4..dca439ba1 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -15,7 +15,7 @@ use cuprate_txpool::{ }; /// [`TxpoolReadRequest::Backlog`] -pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { +pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { let TxpoolReadResponse::Backlog(tx_entries) = txpool_read .ready() .await @@ -31,7 +31,7 @@ pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result Result { +pub(crate) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result { let TxpoolReadResponse::Size(size) = txpool_read .ready() .await @@ -48,7 +48,7 @@ pub(super) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result, ) -> Result<(), Error> { From fd136b23f60bcd7cb4534a53268e93456fba7729 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 11 Oct 2024 18:07:11 -0400 Subject: [PATCH 08/47] add `BlockChainContextService`, `on_get_block_hash` --- binaries/cuprated/src/rpc/handler.rs | 6 ++++++ binaries/cuprated/src/rpc/json.rs | 26 ++++++++++++-------------- rpc/types/src/json.rs | 4 ++-- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index af2e3f2c0..2019beb4d 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -3,6 +3,7 @@ use std::task::{Context, Poll}; use anyhow::Error; +use cuprate_consensus::BlockChainContextService; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; @@ -102,6 +103,9 @@ pub struct CupratedRpcHandler { /// Read handle to the blockchain database. pub blockchain_read: BlockchainReadHandle, + /// Handle to the blockchain context service. + pub blockchain_context: BlockChainContextService, + /// Handle to the blockchain manager. pub blockchain_manager: BlockchainManagerHandle, @@ -117,6 +121,7 @@ impl CupratedRpcHandler { pub const fn new( restricted: bool, blockchain_read: BlockchainReadHandle, + blockchain_context: BlockChainContextService, blockchain_manager: BlockchainManagerHandle, txpool_read: TxpoolReadHandle, txpool_manager: std::convert::Infallible, @@ -124,6 +129,7 @@ impl CupratedRpcHandler { Self { restricted, blockchain_read, + blockchain_context, blockchain_manager, txpool_read, txpool_manager, diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 604ed91ee..ffbac282c 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -38,7 +38,11 @@ use cuprate_rpc_types::{ CORE_RPC_VERSION, }; -use crate::rpc::{helper, request::blockchain, CupratedRpcHandler}; +use crate::rpc::{ + helper, + request::{blockchain, blockchain_context, blockchain_manager}, + CupratedRpcHandler, +}; /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( @@ -115,7 +119,8 @@ async fn on_get_block_hash( request: OnGetBlockHashRequest, ) -> Result { let [height] = request.block_height; - let hash = blockchain::block_hash(&mut state.blockchain_read, height, todo!()).await?; + let hash = blockchain::block_hash(&mut state.blockchain_read, height, todo!("access to chain")) + .await?; let block_hash = hex::encode(hash); Ok(OnGetBlockHashResponse { block_hash }) @@ -126,21 +131,14 @@ async fn submit_block( mut state: CupratedRpcHandler, request: SubmitBlockRequest, ) -> Result { + // Parse hex into block. let [blob] = request.block_blob; - - 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")); - // } - let bytes = hex::decode(blob)?; let block = Block::read(&mut bytes.as_slice())?; + let block_id = hex::encode(block.hash()); - // - let block_id = todo!("submit block to DB"); - todo!("relay to P2P"); - todo!("send to txpool"); + // Attempt to relay the block. + blockchain_manager::relay_block(&mut state.blockchain_manager, block).await?; Ok(SubmitBlockResponse { base: ResponseBase::ok(), @@ -383,7 +381,7 @@ async fn hard_fork_info( Ok(HardForkInfoResponse { base: AccessResponseBase::ok(), earliest_height: todo!(), - enabled: hard_fork.is_current(), + enabled: todo!("hard_fork.is_latest() is not always correct"), state: todo!(), threshold: todo!(), version: hard_fork.as_u8(), diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index 7e9700b38..fd9ffa32b 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -836,9 +836,9 @@ define_request_and_response! { enabled: true, state: 0, threshold: 0, - version: 3, + version: 16, votes: 10080, - voting: 3, + voting: 16, window: 10080 } )] From b82ff278def5c45b8488d3d198d067524fd6983f Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 11 Oct 2024 20:57:32 -0400 Subject: [PATCH 09/47] map `tower::BoxError` to `anyhow::Error` --- .../cuprated/src/rpc/request/address_book.rs | 24 ++++++++++--------- .../src/rpc/request/blockchain_context.rs | 16 +++++++------ binaries/cuprated/src/rpc/request/txpool.rs | 12 ++++++---- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 9a16c0fd1..6c6658203 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; use tower::ServiceExt; use cuprate_helper::cast::usize_to_u64; @@ -11,6 +11,8 @@ use cuprate_p2p_core::{ AddressBook, NetworkZone, }; +// FIXME: use `anyhow::Error` over `tower::BoxError` in address book. + /// [`AddressBookRequest::PeerlistSize`] pub(crate) async fn peerlist_size( address_book: &mut impl AddressBook, @@ -18,10 +20,10 @@ pub(crate) async fn peerlist_size( let AddressBookResponse::PeerlistSize { white, grey } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::PeerlistSize) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -36,10 +38,10 @@ pub(crate) async fn connection_count( let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::ConnectionCount) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -55,10 +57,10 @@ pub(crate) async fn set_ban( let AddressBookResponse::Ok = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::SetBan(peer)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -74,10 +76,10 @@ pub(crate) async fn get_ban( let AddressBookResponse::GetBan { unban_instant } = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::GetBan(peer)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -92,10 +94,10 @@ pub(crate) async fn get_bans( let AddressBookResponse::GetBans(bans) = address_book .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(AddressBookRequest::GetBans) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index e0fa67b24..43f5fc594 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; use tower::{Service, ServiceExt}; use cuprate_consensus::context::{ @@ -11,6 +11,8 @@ use cuprate_consensus::context::{ }; use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; +// FIXME: use `anyhow::Error` over `tower::BoxError` in blockchain context. + /// [`BlockChainContextRequest::Context`]. pub(crate) async fn context( service: &mut BlockChainContextService, @@ -18,10 +20,10 @@ pub(crate) async fn context( let BlockChainContextResponse::Context(context) = service .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::Context) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -37,10 +39,10 @@ pub(crate) async fn hard_fork_info( let BlockChainContextResponse::HardForkInfo(hf_info) = service .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::HardForkInfo(hard_fork)) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -56,10 +58,10 @@ pub(crate) async fn fee_estimate( let BlockChainContextResponse::FeeEstimate(fee) = service .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::FeeEstimate { grace_blocks }) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index dca439ba1..eef2a474c 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -2,7 +2,7 @@ use std::convert::Infallible; -use anyhow::Error; +use anyhow::{anyhow, Error}; use tower::{Service, ServiceExt}; use cuprate_helper::cast::usize_to_u64; @@ -14,15 +14,17 @@ use cuprate_txpool::{ TxEntry, }; +// FIXME: use `anyhow::Error` over `tower::BoxError` in txpool. + /// [`TxpoolReadRequest::Backlog`] pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result, Error> { let TxpoolReadResponse::Backlog(tx_entries) = txpool_read .ready() .await - .expect("TODO") + .map_err(|e| anyhow!(e))? .call(TxpoolReadRequest::Backlog) .await - .expect("TODO") + .map_err(|e| anyhow!(e))? else { unreachable!(); }; @@ -35,10 +37,10 @@ pub(crate) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result Date: Fri, 11 Oct 2024 21:07:32 -0400 Subject: [PATCH 10/47] get_block --- binaries/cuprated/src/rpc/json.rs | 47 ++++++++++++++++--------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index ffbac282c..ab742d1c2 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -277,33 +277,36 @@ async fn get_block( mut state: CupratedRpcHandler, request: GetBlockRequest, ) -> Result { - let block = if request.hash.is_empty() { + let (block, block_header) = if request.hash.is_empty() { helper::check_height(&mut state, request.height).await?; - blockchain::block(&mut state.blockchain_read, request.height).await? + let block = blockchain::block(&mut state.blockchain_read, request.height).await?; + let block_header = + helper::block_header(&mut state, request.height, request.fill_pow_hash).await?; + (block, block_header) } else { let hash = helper::hex_to_hash(request.hash)?; - blockchain::block_by_hash(&mut state.blockchain_read, hash).await? + let block = blockchain::block_by_hash(&mut state.blockchain_read, hash).await?; + let block_header = + helper::block_header_by_hash(&mut state, hash, request.fill_pow_hash).await?; + (block, block_header) }; - Ok(todo!()) - - // let block_header = (&block).into(); - // let blob = hex::encode(block.block_blob); - // let miner_tx_hash = hex::encode(block.block.miner_transaction.hash()); - // let tx_hashes = block - // .txs - // .into_iter() - // .map(|tx| hex::encode(tx.tx_hash)) - // .collect(); - - // Ok(GetBlockResponse { - // base: AccessResponseBase::ok(), - // blob, - // json: todo!(), // TODO: make `JSON` type in `cuprate_rpc_types` - // miner_tx_hash, - // tx_hashes, - // block_header, - // }) + let blob = hex::encode(block.serialize()); + let miner_tx_hash = hex::encode(block.miner_transaction.hash()); + let tx_hashes = block.transactions.iter().map(hex::encode).collect(); + let json = { + let block = cuprate_types::json::block::Block::from(block); + serde_json::to_string_pretty(&block)? + }; + + Ok(GetBlockResponse { + base: AccessResponseBase::ok(), + blob, + json, + miner_tx_hash, + tx_hashes, + block_header, + }) } /// From 9422c07cc82a75bc2ef50ebc2d405cbfe7b8dc7c Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 16:44:59 -0400 Subject: [PATCH 11/47] connection_info --- binaries/cuprated/src/rpc/json.rs | 7 ++- .../cuprated/src/rpc/request/address_book.rs | 53 +++++++++++++++++- p2p/address-book/src/book.rs | 3 +- p2p/p2p-core/src/ban.rs | 23 -------- .../src/client/handshaker/builder/dummy.rs | 3 +- p2p/p2p-core/src/lib.rs | 2 +- p2p/p2p-core/src/services.rs | 8 ++- p2p/p2p-core/src/types.rs | 54 +++++++++++++++++++ 8 files changed, 123 insertions(+), 30 deletions(-) delete mode 100644 p2p/p2p-core/src/ban.rs create mode 100644 p2p/p2p-core/src/types.rs diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index ab742d1c2..0dc60aee9 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,6 +1,7 @@ use std::sync::Arc; use anyhow::{anyhow, Error}; +use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; use cuprate_types::HardFork; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -40,7 +41,7 @@ use cuprate_rpc_types::{ use crate::rpc::{ helper, - request::{blockchain, blockchain_context, blockchain_manager}, + request::{address_book, blockchain, blockchain_context, blockchain_manager}, CupratedRpcHandler, }; @@ -314,9 +315,11 @@ async fn get_connections( state: CupratedRpcHandler, request: GetConnectionsRequest, ) -> Result { + let connections = address_book::connection_info::(&mut DummyAddressBook).await?; + Ok(GetConnectionsResponse { base: ResponseBase::ok(), - connections: todo!(), + connections, }) } diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 6c6658203..3fe4de32e 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -3,6 +3,7 @@ use std::convert::Infallible; use anyhow::{anyhow, Error}; +use cuprate_rpc_types::misc::ConnectionInfo; use tower::ServiceExt; use cuprate_helper::cast::usize_to_u64; @@ -31,6 +32,56 @@ pub(crate) async fn peerlist_size( Ok((usize_to_u64(white), usize_to_u64(grey))) } +/// [`AddressBookRequest::ConnectionInfo`] +pub(crate) async fn connection_info( + address_book: &mut impl AddressBook, +) -> Result, Error> { + let AddressBookResponse::ConnectionInfo(vec) = address_book + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::ConnectionInfo) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + // FIXME: impl this map somewhere instead of inline. + let vec = vec + .into_iter() + .map(|info| ConnectionInfo { + address: info.address.to_string(), + address_type: info.address_type, + avg_download: info.avg_download, + avg_upload: info.avg_upload, + connection_id: info.connection_id, + current_download: info.current_download, + current_upload: info.current_upload, + height: info.height, + host: info.host, + incoming: info.incoming, + ip: info.ip, + live_time: info.live_time, + localhost: info.localhost, + local_ip: info.local_ip, + peer_id: info.peer_id, + port: info.port, + pruning_seed: info.pruning_seed, + recv_count: info.recv_count, + recv_idle_time: info.recv_idle_time, + rpc_credits_per_hash: info.rpc_credits_per_hash, + rpc_port: info.rpc_port, + send_count: info.send_count, + send_idle_time: info.send_idle_time, + state: info.state, + support_flags: info.support_flags, + }) + .collect(); + + Ok(vec) +} + /// [`AddressBookRequest::ConnectionCount`] pub(crate) async fn connection_count( address_book: &mut impl AddressBook, @@ -52,7 +103,7 @@ pub(crate) async fn connection_count( /// [`AddressBookRequest::SetBan`] pub(crate) async fn set_ban( address_book: &mut impl AddressBook, - peer: cuprate_p2p_core::ban::SetBan, + peer: cuprate_p2p_core::types::SetBan, ) -> Result<(), Error> { let AddressBookResponse::Ok = address_book .ready() diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs index 907d69115..3e5269f5d 100644 --- a/p2p/address-book/src/book.rs +++ b/p2p/address-book/src/book.rs @@ -423,7 +423,8 @@ impl Service> for AddressBook { AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) - | AddressBookRequest::GetBans => { + | AddressBookRequest::GetBans + | AddressBookRequest::ConnectionInfo => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } }; diff --git a/p2p/p2p-core/src/ban.rs b/p2p/p2p-core/src/ban.rs deleted file mode 100644 index 76fd3ebf7..000000000 --- a/p2p/p2p-core/src/ban.rs +++ /dev/null @@ -1,23 +0,0 @@ -//! 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 8bb966dbf..48b3daf5e 100644 --- a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs +++ b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs @@ -111,7 +111,8 @@ impl Service> for DummyAddressBook { AddressBookRequest::PeerlistSize | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) - | AddressBookRequest::GetBans => { + | AddressBookRequest::GetBans + | AddressBookRequest::ConnectionInfo => { 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 5b93b59ce..26e10686c 100644 --- a/p2p/p2p-core/src/lib.rs +++ b/p2p/p2p-core/src/lib.rs @@ -75,7 +75,6 @@ use cuprate_wire::{ NetworkAddress, }; -pub mod ban; pub mod client; mod constants; pub mod error; @@ -83,6 +82,7 @@ pub mod handles; mod network_zones; pub mod protocol; pub mod services; +pub mod types; pub use error::*; pub use network_zones::{ClearNet, ClearNetServerCfg}; diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index 495b71928..6d1089ce1 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -4,9 +4,9 @@ use cuprate_pruning::{PruningError, PruningSeed}; use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use crate::{ - ban::{BanState, SetBan}, client::InternalPeerID, handles::ConnectionHandle, + types::{BanState, ConnectionInfo, SetBan}, NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, }; @@ -118,6 +118,9 @@ pub enum AddressBookRequest { /// Get the amount of white & grey peers. PeerlistSize, + /// Get information on all connections. + ConnectionInfo, + /// Get the amount of incoming & outgoing connections. ConnectionCount, @@ -152,6 +155,9 @@ pub enum AddressBookResponse { /// Response to [`AddressBookRequest::PeerlistSize`]. PeerlistSize { white: usize, grey: usize }, + /// Response to [`AddressBookRequest::ConnectionInfo`]. + ConnectionInfo(Vec>), + /// Response to [`AddressBookRequest::ConnectionCount`]. ConnectionCount { incoming: usize, outgoing: usize }, diff --git a/p2p/p2p-core/src/types.rs b/p2p/p2p-core/src/types.rs new file mode 100644 index 000000000..e53491bd1 --- /dev/null +++ b/p2p/p2p-core/src/types.rs @@ -0,0 +1,54 @@ +//! General data structures. + +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, +} + +// TODO: reduce fields and map to RPC type. +// +/// Data within [`crate::services::AddressBookResponse::ConnectionInfo`]. +pub struct ConnectionInfo { + pub address: A, + pub address_type: u8, + pub avg_download: u64, + pub avg_upload: u64, + pub connection_id: String, + pub current_download: u64, + pub current_upload: u64, + pub height: u64, + pub host: String, + pub incoming: bool, + pub ip: String, + pub live_time: u64, + pub localhost: bool, + pub local_ip: bool, + pub peer_id: String, + pub port: String, + pub pruning_seed: u32, + pub recv_count: u64, + pub recv_idle_time: u64, + pub rpc_credits_per_hash: u32, + pub rpc_port: u16, + pub send_count: u64, + pub send_idle_time: u64, + pub state: String, + pub support_flags: u32, +} From 50bd576bb1a878d3eb6be961623601b418ca8676 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 16:57:10 -0400 Subject: [PATCH 12/47] hard_fork_info --- binaries/cuprated/src/rpc/json.rs | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 0dc60aee9..fe2b597fd 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -380,20 +380,24 @@ 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? - todo!() + blockchain_context::context(&mut state.blockchain_context) + .await? + .unchecked_blockchain_context() + .current_hf }; + let info = blockchain_context::hard_fork_info(&mut state.blockchain_context, hard_fork).await?; + Ok(HardForkInfoResponse { base: AccessResponseBase::ok(), - earliest_height: todo!(), - enabled: todo!("hard_fork.is_latest() is not always correct"), - state: todo!(), - threshold: todo!(), - version: hard_fork.as_u8(), - votes: todo!(), - voting: todo!(), - window: todo!(), + earliest_height: info.earliest_height, + enabled: info.enabled, + state: info.state, + threshold: info.threshold, + version: info.version, + votes: info.votes, + voting: info.voting, + window: info.window, }) } From f677b1ae2aa10bf64c0828ef385d86dadecd2ba1 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 17:04:25 -0400 Subject: [PATCH 13/47] set_bans --- binaries/cuprated/src/rpc/json.rs | 19 +++++++++++++++++-- .../cuprated/src/rpc/request/address_book.rs | 4 ++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index fe2b597fd..1c82df117 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,4 +1,7 @@ -use std::sync::Arc; +use std::{ + sync::Arc, + time::{Duration, Instant}, +}; use anyhow::{anyhow, Error}; use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; @@ -406,7 +409,19 @@ async fn set_bans( state: CupratedRpcHandler, request: SetBansRequest, ) -> Result { - todo!(); + for peer in request.bans { + let address = todo!(); + + let ban = if peer.ban { + Some(Duration::from_secs(peer.seconds.into())) + } else { + None + }; + + let set_ban = cuprate_p2p_core::types::SetBan { address, ban }; + + address_book::set_ban::(&mut DummyAddressBook, set_ban).await?; + } Ok(SetBansResponse { base: ResponseBase::ok(), diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 3fe4de32e..5458c4956 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -103,13 +103,13 @@ pub(crate) async fn connection_count( /// [`AddressBookRequest::SetBan`] pub(crate) async fn set_ban( address_book: &mut impl AddressBook, - peer: cuprate_p2p_core::types::SetBan, + set_ban: cuprate_p2p_core::types::SetBan, ) -> Result<(), Error> { let AddressBookResponse::Ok = address_book .ready() .await .map_err(|e| anyhow!(e))? - .call(AddressBookRequest::SetBan(peer)) + .call(AddressBookRequest::SetBan(set_ban)) .await .map_err(|e| anyhow!(e))? else { From 37bcbb5ea03f9de94975f7c9cd858b8ea0471f09 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 17:16:55 -0400 Subject: [PATCH 14/47] get_bans --- binaries/cuprated/src/rpc/json.rs | 29 +++++++++++++++++-- .../cuprated/src/rpc/request/address_book.rs | 5 ++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 1c82df117..ff7db6ddb 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -38,7 +38,7 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, Status}, + misc::{BlockHeader, GetBan, Status}, CORE_RPC_VERSION, }; @@ -433,9 +433,34 @@ async fn get_bans( state: CupratedRpcHandler, request: GetBansRequest, ) -> Result { + let now = Instant::now(); + + let bans = address_book::get_bans::(&mut DummyAddressBook) + .await? + .into_iter() + .map(|ban| { + let seconds = if let Some(instant) = ban.unban_instant { + instant + .checked_duration_since(now) + .unwrap_or_default() + .as_secs() + .try_into() + .unwrap_or(0) + } else { + 0 + }; + + GetBan { + host: ban.address.to_string(), + ip: todo!(), + seconds, + } + }) + .collect(); + Ok(GetBansResponse { base: ResponseBase::ok(), - bans: todo!(), + bans, }) } diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 5458c4956..b991dce44 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -9,6 +9,7 @@ use tower::ServiceExt; use cuprate_helper::cast::usize_to_u64; use cuprate_p2p_core::{ services::{AddressBookRequest, AddressBookResponse}, + types::BanState, AddressBook, NetworkZone, }; @@ -141,7 +142,7 @@ pub(crate) async fn get_ban( /// [`AddressBookRequest::GetBans`] pub(crate) async fn get_bans( address_book: &mut impl AddressBook, -) -> Result<(), Error> { +) -> Result>, Error> { let AddressBookResponse::GetBans(bans) = address_book .ready() .await @@ -153,5 +154,5 @@ pub(crate) async fn get_bans( unreachable!(); }; - Ok(todo!()) + Ok(bans) } From c7ae795837382db6b8be793bbc2a90a5862aecdc Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 17:57:07 -0400 Subject: [PATCH 15/47] banned --- binaries/cuprated/src/rpc/json.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index ff7db6ddb..359486b9d 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -469,10 +469,26 @@ async fn banned( state: CupratedRpcHandler, request: BannedRequest, ) -> Result { + let peer = todo!("create Z::Addr from request.address"); + let ban = address_book::get_ban::(&mut DummyAddressBook, peer).await?; + + let (banned, seconds) = if let Some(instant) = ban { + let seconds = instant + .checked_duration_since(Instant::now()) + .unwrap_or_default() + .as_secs() + .try_into() + .unwrap_or(0); + + (true, seconds) + } else { + (false, 0) + }; + Ok(BannedResponse { - banned: todo!(), - seconds: todo!(), - status: todo!(), + banned, + seconds, + status: Status::Ok, }) } From 6af977f0a50981509214727dd99a8846f9d501ec Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 18:01:16 -0400 Subject: [PATCH 16/47] flush_transaction_pool --- binaries/cuprated/src/rpc/json.rs | 11 ++++++++++- binaries/cuprated/src/rpc/request/txpool.rs | 6 +----- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 359486b9d..a370156f4 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -48,6 +48,8 @@ use crate::rpc::{ CupratedRpcHandler, }; +use super::request::txpool; + /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( state: CupratedRpcHandler, @@ -497,7 +499,14 @@ async fn flush_transaction_pool( state: CupratedRpcHandler, request: FlushTransactionPoolRequest, ) -> Result { - todo!(); + let tx_hashes = request + .txids + .into_iter() + .map(helper::hex_to_hash) + .collect::, _>>()?; + + txpool::flush(tx_hashes).await?; + Ok(FlushTransactionPoolResponse { status: Status::Ok }) } diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index eef2a474c..952cbbcc8 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -49,11 +49,7 @@ pub(crate) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result, -) -> Result<(), Error> { +pub(crate) async fn flush(tx_hashes: Vec<[u8; 32]>) -> Result<(), Error> { todo!(); Ok(()) } From 1a76934aac5f7d8b3ab834e9627e797c44f7a0c0 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 18:05:59 -0400 Subject: [PATCH 17/47] get_output_histogram --- binaries/cuprated/src/rpc/json.rs | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index a370156f4..883a83346 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -38,7 +38,7 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, GetBan, Status}, + misc::{BlockHeader, GetBan, HistogramEntry, Status}, CORE_RPC_VERSION, }; @@ -512,12 +512,31 @@ async fn flush_transaction_pool( /// async fn get_output_histogram( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetOutputHistogramRequest, ) -> Result { + let input = cuprate_types::OutputHistogramInput { + amounts: request.amounts, + min_count: request.min_count, + max_count: request.max_count, + unlocked: request.unlocked, + recent_cutoff: request.recent_cutoff, + }; + + let histogram = blockchain::output_histogram(&mut state.blockchain_read, input) + .await? + .into_iter() + .map(|entry| HistogramEntry { + amount: entry.amount, + total_instances: entry.total_instances, + unlocked_instances: entry.unlocked_instances, + recent_instances: entry.recent_instances, + }) + .collect(); + Ok(GetOutputHistogramResponse { base: AccessResponseBase::ok(), - histogram: todo!(), + histogram, }) } From 1d435cc1f81dc01ed9adec2914c9e78f77321654 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:01:14 -0400 Subject: [PATCH 18/47] get_coinbase_tx_sum --- binaries/cuprated/src/rpc/json.rs | 28 ++++++++++++++++++++-------- types/src/types.rs | 2 -- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 883a83346..c97fa932f 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -14,7 +14,7 @@ use cuprate_constants::{ build::RELEASE, rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}, }; -use cuprate_helper::cast::u64_to_usize; +use cuprate_helper::{cast::u64_to_usize, map::split_u128_into_low_high_bits}; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, @@ -542,17 +542,29 @@ async fn get_output_histogram( /// async fn get_coinbase_tx_sum( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetCoinbaseTxSumRequest, ) -> Result { + let sum = + blockchain::coinbase_tx_sum(&mut state.blockchain_read, request.height, request.count) + .await?; + + // Formats `u128` as hexadecimal strings. + let wide_emission_amount = format!("{:#x}", sum.fee_amount); + let wide_fee_amount = format!("{:#x}", sum.emission_amount); + + let (emission_amount, emission_amount_top64) = + split_u128_into_low_high_bits(sum.emission_amount); + let (fee_amount, fee_amount_top64) = split_u128_into_low_high_bits(sum.fee_amount); + Ok(GetCoinbaseTxSumResponse { base: AccessResponseBase::ok(), - emission_amount: todo!(), - emission_amount_top64: todo!(), - fee_amount: todo!(), - fee_amount_top64: todo!(), - wide_emission_amount: todo!(), - wide_fee_amount: todo!(), + emission_amount, + emission_amount_top64, + fee_amount, + fee_amount_top64, + wide_emission_amount, + wide_fee_amount, }) } diff --git a/types/src/types.rs b/types/src/types.rs index 7d5c377f6..669ec5daa 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -177,8 +177,6 @@ pub struct OutputHistogramEntry { 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. From d7fef15cd696af51c1c1f77b713907a68f4b3278 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:13:21 -0400 Subject: [PATCH 19/47] get_version --- binaries/cuprated/src/rpc/json.rs | 25 +++++++++++++++---- .../cuprated/src/rpc/request/blockchain.rs | 20 +++++++++++++-- storage/blockchain/src/service/read.rs | 6 +++++ types/src/blockchain.rs | 22 +++++++++++++--- 4 files changed, 62 insertions(+), 11 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index c97fa932f..5bed13c77 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -14,7 +14,10 @@ use cuprate_constants::{ build::RELEASE, rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}, }; -use cuprate_helper::{cast::u64_to_usize, map::split_u128_into_low_high_bits}; +use cuprate_helper::{ + cast::{u64_to_usize, usize_to_u64}, + map::split_u128_into_low_high_bits, +}; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, @@ -38,7 +41,7 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, GetBan, HistogramEntry, Status}, + misc::{BlockHeader, GetBan, HardforkEntry, HistogramEntry, Status}, CORE_RPC_VERSION, }; @@ -573,13 +576,25 @@ async fn get_version( mut state: CupratedRpcHandler, request: GetVersionRequest, ) -> Result { + let current_height = helper::top_height(&mut state).await?.0; + let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?; + + let hard_forks = blockchain::hard_forks(&mut state.blockchain_read) + .await? + .into_iter() + .map(|(height, hf)| HardforkEntry { + height: usize_to_u64(height), + hf_version: hf.as_u8(), + }) + .collect(); + Ok(GetVersionResponse { base: ResponseBase::ok(), version: CORE_RPC_VERSION, release: RELEASE, - current_height: helper::top_height(&mut state).await?.0, - target_height: todo!(), - hard_forks: todo!(), + current_height, + target_height, + hard_forks, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 7705320f3..8f71827fd 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -1,7 +1,7 @@ //! Functions for [`BlockchainReadRequest`]. use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, ops::Range, }; @@ -13,7 +13,7 @@ use cuprate_blockchain::service::BlockchainReadHandle; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, CoinbaseTxSum, ExtendedBlockHeader, MinerData, OutputHistogramEntry, + Chain, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData, OutputHistogramEntry, OutputHistogramInput, OutputOnChain, }; @@ -343,3 +343,19 @@ pub(crate) async fn coinbase_tx_sum( Ok(sum) } + +/// [`BlockchainReadRequest::HardForks`] +pub(crate) async fn hard_forks( + blockchain_read: &mut BlockchainReadHandle, +) -> Result, Error> { + let BlockchainResponse::HardForks(hfs) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::HardForks) + .await? + else { + unreachable!(); + }; + + Ok(hfs) +} diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index a3b82bdb2..95d21b3ca 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -121,6 +121,7 @@ fn map_request( R::DatabaseSize => database_size(env), R::OutputHistogram(input) => output_histogram(env, input), R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), + R::HardForks => hard_forks(env), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -648,3 +649,8 @@ fn output_histogram(env: &ConcreteEnv, input: OutputHistogramInput) -> ResponseR fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResult { Ok(BlockchainResponse::CoinbaseTxSum(todo!())) } + +/// [`BlockchainReadRequest::HardForks`] +fn hard_forks(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::HardForks(todo!())) +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index b7436f0a7..441fb1492 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -4,7 +4,7 @@ //! responses are also tested in Cuprate's blockchain database crate. //---------------------------------------------------------------------------------------------------- Import use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeMap, HashMap, HashSet}, ops::Range, }; @@ -12,7 +12,8 @@ use monero_serai::block::Block; use crate::{ types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, - AltBlockInformation, ChainId, CoinbaseTxSum, OutputHistogramEntry, OutputHistogramInput, + AltBlockInformation, ChainId, CoinbaseTxSum, HardFork, OutputHistogramEntry, + OutputHistogramInput, }; //---------------------------------------------------------------------------------------------------- ReadRequest @@ -107,7 +108,9 @@ pub enum BlockchainReadRequest { AltBlocksInChain(ChainId), /// Get a [`Block`] by its height. - Block { height: usize }, + Block { + height: usize, + }, /// Get a [`Block`] by its hash. BlockByHash([u8; 32]), @@ -127,7 +130,12 @@ pub enum BlockchainReadRequest { /// `N` last blocks starting at particular height. /// /// TODO: document fields after impl. - CoinbaseTxSum { height: usize, count: u64 }, + CoinbaseTxSum { + height: usize, + count: u64, + }, + + HardForks, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -276,6 +284,12 @@ pub enum BlockchainResponse { /// Response to [`BlockchainReadRequest::CoinbaseTxSum`]. CoinbaseTxSum(CoinbaseTxSum), + /// Response to [`BlockchainReadRequest::HardForks`]. + /// + /// - Key = height at which the hardfork activated + /// - Value = hardfork version + HardForks(BTreeMap), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// From 1e0ab56a5e26ae9ed9c7cf9c87831deab8cd0118 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:15:51 -0400 Subject: [PATCH 20/47] get_fee_estimate --- binaries/cuprated/src/rpc/json.rs | 12 ++++++++---- rpc/types/src/json.rs | 8 ++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 5bed13c77..3bc5beded 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -600,14 +600,18 @@ async fn get_version( /// async fn get_fee_estimate( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetFeeEstimateRequest, ) -> Result { + let estimate = + blockchain_context::fee_estimate(&mut state.blockchain_context, request.grace_blocks) + .await?; + Ok(GetFeeEstimateResponse { base: AccessResponseBase::ok(), - fee: todo!(), - fees: todo!(), - quantization_mask: todo!(), + fee: estimate.fee, + fees: estimate.fees, + quantization_mask: estimate.quantization_mask, }) } diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index fd9ffa32b..f0846d34e 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -1143,8 +1143,12 @@ define_request_and_response! { get_fee_estimate, cc73fe71162d564ffda8e549b79a350bca53c454 => core_rpc_server_commands_defs.h => 2250..=2277, - GetFeeEstimate (empty), - Request {}, + + GetFeeEstimate, + + Request { + grace_blocks: u64 = default_zero::(), "default_zero", + }, #[doc = serde_doc_test!( GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse { From 294df3f16373dfcf4c14a6ef8d873ce45fc800fe Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:27:27 -0400 Subject: [PATCH 21/47] get_alternate_chains --- binaries/cuprated/src/rpc/json.rs | 26 ++++++++++++++++--- .../cuprated/src/rpc/request/blockchain.rs | 22 +++++++++++++--- storage/blockchain/src/service/read.rs | 6 +++++ types/src/blockchain.rs | 17 ++++++------ types/src/types.rs | 1 - 5 files changed, 57 insertions(+), 15 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 3bc5beded..989a7d672 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -41,7 +41,7 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, GetBan, HardforkEntry, HistogramEntry, Status}, + misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status}, CORE_RPC_VERSION, }; @@ -617,12 +617,32 @@ async fn get_fee_estimate( /// async fn get_alternate_chains( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetAlternateChainsRequest, ) -> Result { + let chains = blockchain::alt_chains(&mut state.blockchain_read) + .await? + .into_iter() + .map(|info| { + let block_hashes = info.block_hashes.into_iter().map(hex::encode).collect(); + let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(info.difficulty); + + ChainInfo { + block_hash: hex::encode(info.block_hash), + block_hashes, + difficulty, + difficulty_top64, + height: info.height, + length: info.length, + main_chain_parent_block: hex::encode(info.main_chain_parent_block), + wide_difficulty: hex::encode(u128::to_ne_bytes(info.difficulty)), + } + }) + .collect(); + Ok(GetAlternateChainsResponse { base: ResponseBase::ok(), - chains: todo!(), + chains, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 8f71827fd..40654234d 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -9,12 +9,12 @@ use anyhow::Error; use monero_serai::block::Block; use tower::{Service, ServiceExt}; -use cuprate_blockchain::service::BlockchainReadHandle; +use cuprate_blockchain::{service::BlockchainReadHandle, types::AltChainInfo}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData, OutputHistogramEntry, - OutputHistogramInput, OutputOnChain, + Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData, + OutputHistogramEntry, OutputHistogramInput, OutputOnChain, }; /// [`BlockchainReadRequest::Block`]. @@ -359,3 +359,19 @@ pub(crate) async fn hard_forks( Ok(hfs) } + +/// [`BlockchainReadRequest::AltChains`] +pub(crate) async fn alt_chains( + blockchain_read: &mut BlockchainReadHandle, +) -> Result, Error> { + let BlockchainResponse::AltChains(vec) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::AltChains) + .await? + else { + unreachable!(); + }; + + Ok(vec) +} diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 95d21b3ca..c04a6f227 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -122,6 +122,7 @@ fn map_request( R::OutputHistogram(input) => output_histogram(env, input), R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), R::HardForks => hard_forks(env), + R::AltChains => alt_chains(env), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -654,3 +655,8 @@ fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResu fn hard_forks(env: &ConcreteEnv) -> ResponseResult { Ok(BlockchainResponse::HardForks(todo!())) } + +/// [`BlockchainReadRequest::AltChains`] +fn alt_chains(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::AltChains(todo!())) +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 441fb1492..e53619bcf 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -12,7 +12,7 @@ use monero_serai::block::Block; use crate::{ types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, - AltBlockInformation, ChainId, CoinbaseTxSum, HardFork, OutputHistogramEntry, + AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, HardFork, OutputHistogramEntry, OutputHistogramInput, }; @@ -108,9 +108,7 @@ pub enum BlockchainReadRequest { AltBlocksInChain(ChainId), /// Get a [`Block`] by its height. - Block { - height: usize, - }, + Block { height: usize }, /// Get a [`Block`] by its hash. BlockByHash([u8; 32]), @@ -130,12 +128,13 @@ pub enum BlockchainReadRequest { /// `N` last blocks starting at particular height. /// /// TODO: document fields after impl. - CoinbaseTxSum { - height: usize, - count: u64, - }, + CoinbaseTxSum { height: usize, count: u64 }, + /// TODO HardForks, + + /// TODO + AltChains, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -290,6 +289,8 @@ pub enum BlockchainResponse { /// - Value = hardfork version HardForks(BTreeMap), + AltChains(Vec), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// diff --git a/types/src/types.rs b/types/src/types.rs index 669ec5daa..a6833758e 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -240,7 +240,6 @@ pub struct ChainInfo { pub height: u64, pub length: u64, pub main_chain_parent_block: [u8; 32], - pub wide_difficulty: u128, } //---------------------------------------------------------------------------------------------------- Tests From 08b5ff2f05ce6de9d636ce5ce198f9ab93682806 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:31:33 -0400 Subject: [PATCH 22/47] relay_tx --- binaries/cuprated/src/rpc/json.rs | 15 +++++++++++---- binaries/cuprated/src/rpc/request/txpool.rs | 14 +++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 989a7d672..486e330b4 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -499,7 +499,7 @@ async fn banned( /// async fn flush_transaction_pool( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: FlushTransactionPoolRequest, ) -> Result { let tx_hashes = request @@ -508,7 +508,7 @@ async fn flush_transaction_pool( .map(helper::hex_to_hash) .collect::, _>>()?; - txpool::flush(tx_hashes).await?; + txpool::flush(&mut state.txpool_manager, tx_hashes).await?; Ok(FlushTransactionPoolResponse { status: Status::Ok }) } @@ -648,10 +648,17 @@ async fn get_alternate_chains( /// async fn relay_tx( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: RelayTxRequest, ) -> Result { - todo!(); + let tx_hashes = request + .txids + .into_iter() + .map(helper::hex_to_hash) + .collect::, _>>()?; + + txpool::relay(&mut state.txpool_manager, tx_hashes).await?; + Ok(RelayTxResponse { status: Status::Ok }) } diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index 952cbbcc8..e2caccd1d 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -49,7 +49,19 @@ pub(crate) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result) -> Result<(), Error> { +pub(crate) async fn flush( + txpool_manager: &mut Infallible, + tx_hashes: Vec<[u8; 32]>, +) -> Result<(), Error> { + todo!(); + Ok(()) +} + +/// TODO +pub(crate) async fn relay( + txpool_manager: &mut Infallible, + tx_hashes: Vec<[u8; 32]>, +) -> Result<(), Error> { todo!(); Ok(()) } From 2daf2555bb3079e5596b24b1930f604485a460b8 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:40:03 -0400 Subject: [PATCH 23/47] response_base: `fn` -> `const` --- binaries/cuprated/src/rpc/json.rs | 50 +++++++++--------- rpc/types/src/base.rs | 88 ++++++++++--------------------- rpc/types/src/json.rs | 50 +++++++++--------- rpc/types/src/other.rs | 42 +++++++-------- 4 files changed, 100 insertions(+), 130 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 486e330b4..146cfacef 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -117,7 +117,7 @@ async fn get_block_count( request: GetBlockCountRequest, ) -> Result { Ok(GetBlockCountResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, count: helper::top_height(&mut state).await?.0, }) } @@ -150,7 +150,7 @@ async fn submit_block( blockchain_manager::relay_block(&mut state.blockchain_manager, block).await?; Ok(SubmitBlockResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, block_id, }) } @@ -161,7 +161,7 @@ async fn generate_blocks( request: GenerateBlocksRequest, ) -> Result { Ok(GenerateBlocksResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blocks: todo!(), height: todo!(), }) @@ -176,7 +176,7 @@ async fn get_last_block_header( let block_header = helper::block_header(&mut state, height, request.fill_pow_hash).await?; Ok(GetLastBlockHeaderResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header, }) } @@ -212,7 +212,7 @@ async fn get_block_header_by_hash( } Ok(GetBlockHeaderByHashResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header, block_headers, }) @@ -228,7 +228,7 @@ async fn get_block_header_by_height( helper::block_header(&mut state, request.height, request.fill_pow_hash).await?; Ok(GetBlockHeaderByHeightResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header, }) } @@ -276,7 +276,7 @@ async fn get_block_headers_range( } Ok(GetBlockHeadersRangeResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, headers, }) } @@ -309,7 +309,7 @@ async fn get_block( }; Ok(GetBlockResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, blob, json, miner_tx_hash, @@ -326,7 +326,7 @@ async fn get_connections( let connections = address_book::connection_info::(&mut DummyAddressBook).await?; Ok(GetConnectionsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, connections, }) } @@ -337,7 +337,7 @@ async fn get_info( request: GetInfoRequest, ) -> Result { Ok(GetInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, adjusted_time: todo!(), alt_blocks_count: todo!(), block_size_limit: todo!(), @@ -397,7 +397,7 @@ async fn hard_fork_info( let info = blockchain_context::hard_fork_info(&mut state.blockchain_context, hard_fork).await?; Ok(HardForkInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, earliest_height: info.earliest_height, enabled: info.enabled, state: info.state, @@ -429,7 +429,7 @@ async fn set_bans( } Ok(SetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, }) } @@ -464,7 +464,7 @@ async fn get_bans( .collect(); Ok(GetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, bans, }) } @@ -538,7 +538,7 @@ async fn get_output_histogram( .collect(); Ok(GetOutputHistogramResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, histogram, }) } @@ -561,7 +561,7 @@ async fn get_coinbase_tx_sum( let (fee_amount, fee_amount_top64) = split_u128_into_low_high_bits(sum.fee_amount); Ok(GetCoinbaseTxSumResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, emission_amount, emission_amount_top64, fee_amount, @@ -589,7 +589,7 @@ async fn get_version( .collect(); Ok(GetVersionResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, version: CORE_RPC_VERSION, release: RELEASE, current_height, @@ -608,7 +608,7 @@ async fn get_fee_estimate( .await?; Ok(GetFeeEstimateResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, fee: estimate.fee, fees: estimate.fees, quantization_mask: estimate.quantization_mask, @@ -641,7 +641,7 @@ async fn get_alternate_chains( .collect(); Ok(GetAlternateChainsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, chains, }) } @@ -668,7 +668,7 @@ async fn sync_info( request: SyncInfoRequest, ) -> Result { Ok(SyncInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, height: todo!(), next_needed_pruning_seed: todo!(), overview: todo!(), @@ -684,7 +684,7 @@ async fn get_transaction_pool_backlog( request: GetTransactionPoolBacklogRequest, ) -> Result { Ok(GetTransactionPoolBacklogResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, backlog: todo!(), }) } @@ -695,7 +695,7 @@ async fn get_miner_data( request: GetMinerDataRequest, ) -> Result { Ok(GetMinerDataResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, major_version: todo!(), height: todo!(), prev_id: todo!(), @@ -713,7 +713,7 @@ async fn prune_blockchain( request: PruneBlockchainRequest, ) -> Result { Ok(PruneBlockchainResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, pruned: todo!(), pruning_seed: todo!(), }) @@ -735,7 +735,7 @@ async fn flush_cache( todo!(); Ok(FlushCacheResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, }) } @@ -745,7 +745,7 @@ async fn add_aux_pow( request: AddAuxPowRequest, ) -> Result { Ok(AddAuxPowResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blocktemplate_blob: todo!(), blockhashing_blob: todo!(), merkle_root: todo!(), @@ -760,7 +760,7 @@ async fn get_tx_ids_loose( request: GetTxIdsLooseRequest, ) -> Result { Ok(GetTxIdsLooseResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, txids: todo!(), }) } diff --git a/rpc/types/src/base.rs b/rpc/types/src/base.rs index c131e41ec..407b8c11c 100644 --- a/rpc/types/src/base.rs +++ b/rpc/types/src/base.rs @@ -58,61 +58,37 @@ pub struct ResponseBase { } impl ResponseBase { - /// `const` version of [`Default::default`]. - /// - /// ```rust - /// use cuprate_rpc_types::{misc::*, base::*}; - /// - /// let new = ResponseBase::new(); - /// assert_eq!(new, ResponseBase { - /// status: Status::Ok, - /// untrusted: false, - /// }); - /// ``` - pub const fn new() -> Self { - Self { - status: Status::Ok, - untrusted: false, - } - } - - /// Returns OK and trusted [`Self`]. + /// [`Status::Ok`] and trusted [`Self`]. /// /// This is the most common version of [`Self`]. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok = ResponseBase::ok(); - /// assert_eq!(ok, ResponseBase { + /// assert_eq!(ResponseBase::OK, ResponseBase { /// status: Status::Ok, /// untrusted: false, /// }); /// ``` - pub const fn ok() -> Self { - Self { - status: Status::Ok, - untrusted: false, - } - } + pub const OK: Self = Self { + status: Status::Ok, + untrusted: false, + }; - /// Same as [`Self::ok`] but with [`Self::untrusted`] set to `true`. + /// Same as [`Self::OK`] but with [`Self::untrusted`] set to `true`. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok_untrusted = ResponseBase::ok_untrusted(); - /// assert_eq!(ok_untrusted, ResponseBase { + /// assert_eq!(ResponseBase::OK_UNTRUSTED, ResponseBase { /// status: Status::Ok, /// untrusted: true, /// }); /// ``` - pub const fn ok_untrusted() -> Self { - Self { - status: Status::Ok, - untrusted: true, - } - } + pub const OK_UNTRUSTED: Self = Self { + status: Status::Ok, + untrusted: true, + }; } #[cfg(feature = "epee")] @@ -148,9 +124,9 @@ impl AccessResponseBase { /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let new = AccessResponseBase::new(ResponseBase::ok()); + /// let new = AccessResponseBase::new(ResponseBase::OK); /// assert_eq!(new, AccessResponseBase { - /// response_base: ResponseBase::ok(), + /// response_base: ResponseBase::OK, /// credits: 0, /// top_hash: "".into(), /// }); @@ -163,47 +139,41 @@ impl AccessResponseBase { } } - /// Returns OK and trusted [`Self`]. + /// [`Status::Ok`] and trusted [`Self`]. /// /// This is the most common version of [`Self`]. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok = AccessResponseBase::ok(); - /// assert_eq!(ok, AccessResponseBase { - /// response_base: ResponseBase::ok(), + /// assert_eq!(AccessResponseBase::OK, AccessResponseBase { + /// response_base: ResponseBase::OK, /// credits: 0, /// top_hash: "".into(), /// }); /// ``` - pub const fn ok() -> Self { - Self { - response_base: ResponseBase::ok(), - credits: 0, - top_hash: String::new(), - } - } + pub const OK: Self = Self { + response_base: ResponseBase::OK, + credits: 0, + top_hash: String::new(), + }; - /// Same as [`Self::ok`] but with `untrusted` set to `true`. + /// Same as [`Self::OK`] but with `untrusted` set to `true`. /// /// ```rust /// use cuprate_rpc_types::{misc::*, base::*}; /// - /// let ok_untrusted = AccessResponseBase::ok_untrusted(); - /// assert_eq!(ok_untrusted, AccessResponseBase { + /// assert_eq!(AccessResponseBase::OK_UNTRUSTED, AccessResponseBase { /// response_base: ResponseBase::ok_untrusted(), /// credits: 0, /// top_hash: "".into(), /// }); /// ``` - pub const fn ok_untrusted() -> Self { - Self { - response_base: ResponseBase::ok_untrusted(), - credits: 0, - top_hash: String::new(), - } - } + pub const OK_UNTRUSTED: Self = Self { + response_base: ResponseBase::OK_UNTRUSTED, + credits: 0, + top_hash: String::new(), + }; } #[cfg(feature = "epee")] diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index f0846d34e..2b1e378c2 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -184,7 +184,7 @@ define_request_and_response! { // . #[doc = serde_doc_test!( GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(), blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), difficulty_top64: 0, @@ -240,7 +240,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, count: 3195019, } )] @@ -332,7 +332,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()], height: 9783, } @@ -357,7 +357,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header: BlockHeader { block_size: 200419, block_weight: 200419, @@ -409,7 +409,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_headers: vec![], block_header: BlockHeader { block_size: 210, @@ -464,7 +464,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, block_header: BlockHeader { block_size: 210, block_weight: 210, @@ -519,7 +519,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, headers: vec![ BlockHeader { block_size: 301413, @@ -601,7 +601,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BLOCK_RESPONSE => GetBlockResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(), block_header: BlockHeader { block_size: 106, @@ -654,7 +654,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_CONNECTIONS_RESPONSE => GetConnectionsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, connections: vec![ ConnectionInfo { address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(), @@ -728,7 +728,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_INFO_RESPONSE => GetInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, adjusted_time: 1721245289, alt_blocks_count: 16, block_size_limit: 600000, @@ -831,7 +831,7 @@ define_request_and_response! { #[doc = serde_doc_test!( HARD_FORK_INFO_RESPONSE => HardForkInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, earliest_height: 2689608, enabled: true, state: 0, @@ -877,7 +877,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_BANS_RESPONSE => SetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -892,7 +892,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_BANS_RESPONSE => GetBansResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, bans: vec![ GetBan { host: "104.248.206.131".into(), @@ -994,7 +994,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, histogram: vec![HistogramEntry { amount: 20000000000, recent_instances: 0, @@ -1028,7 +1028,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, emission_amount: 9387854817320, emission_amount_top64: 0, fee_amount: 83981380000, @@ -1057,7 +1057,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_VERSION_RESPONSE => GetVersionResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, current_height: 3195051, hard_forks: vec![ HardforkEntry { @@ -1152,7 +1152,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, fee: 20000, fees: vec![20000,80000,320000,4000000], quantization_mask: 10000, @@ -1174,7 +1174,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, chains: vec![ ChainInfo { block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(), @@ -1242,7 +1242,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SYNC_INFO_RESPONSE => SyncInfoResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, height: 3195157, next_needed_pruning_seed: 0, overview: "[]".into(), @@ -1332,7 +1332,7 @@ define_request_and_response! { // TODO: enable test after binary string impl. // #[doc = serde_doc_test!( // GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse { - // base: ResponseBase::ok(), + // base: ResponseBase::OK, // backlog: "...Binary...".into(), // } // )] @@ -1374,7 +1374,7 @@ define_request_and_response! { // TODO: enable test after binary string impl. // #[doc = serde_doc_test!( // GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse { - // base: AccessResponseBase::ok(), + // base: AccessResponseBase::OK, // distributions: vec![Distribution::Uncompressed(DistributionUncompressed { // start_height: 1462078, // base: 0, @@ -1398,7 +1398,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_MINER_DATA_RESPONSE => GetMinerDataResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, already_generated_coins: 18186022843595960691, difficulty: "0x48afae42de".into(), height: 2731375, @@ -1451,7 +1451,7 @@ define_request_and_response! { #[doc = serde_doc_test!( PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, pruned: true, pruning_seed: 387, } @@ -1517,7 +1517,7 @@ define_request_and_response! { #[doc = serde_doc_test!( FLUSH_CACHE_RESPONSE => FlushCacheResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -1546,7 +1546,7 @@ define_request_and_response! { #[doc = serde_doc_test!( ADD_AUX_POW_RESPONSE => AddAuxPowResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, aux_pow: vec![AuxPow { hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(), id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(), diff --git a/rpc/types/src/other.rs b/rpc/types/src/other.rs index e7f3394c9..6c4c021c9 100644 --- a/rpc/types/src/other.rs +++ b/rpc/types/src/other.rs @@ -102,7 +102,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_HEIGHT_RESPONSE => GetHeightResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), height: 3195160, } @@ -157,7 +157,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()], } )] @@ -187,7 +187,7 @@ define_request_and_response! { #[doc = serde_doc_test!( IS_KEY_IMAGE_SPENT_RESPONSE => IsKeyImageSpentResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, spent_status: vec![1, 1], } )] @@ -283,7 +283,7 @@ define_request_and_response! { #[doc = serde_doc_test!( START_MINING_RESPONSE => StartMiningResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -298,7 +298,7 @@ define_request_and_response! { #[doc = serde_doc_test!( STOP_MINING_RESPONSE => StopMiningResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -313,7 +313,7 @@ define_request_and_response! { #[doc = serde_doc_test!( MINING_STATUS_RESPONSE => MiningStatusResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, active: false, address: "".into(), bg_idle_threshold: 0, @@ -359,7 +359,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SAVE_BC_RESPONSE => SaveBcResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -385,7 +385,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_PEER_LIST_RESPONSE => GetPeerListResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, gray_list: vec![ Peer { host: "161.97.193.0".into(), @@ -467,7 +467,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -492,7 +492,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_LEVEL_RESPONSE => SetLogLevelResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, } )] ResponseBase {} @@ -516,7 +516,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LOG_CATEGORIES_RESPONSE => SetLogCategoriesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, categories: "*:INFO".into(), } )] @@ -582,7 +582,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_TRANSACTION_POOL_STATS_RESPONSE => GetTransactionPoolStatsResponse { - base: AccessResponseBase::ok(), + base: AccessResponseBase::OK, pool_stats: TxpoolStats { bytes_max: 11843, bytes_med: 2219, @@ -644,7 +644,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_LIMIT_RESPONSE => GetLimitResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, limit_down: 1280000, limit_up: 1280000, } @@ -676,7 +676,7 @@ define_request_and_response! { #[doc = serde_doc_test!( SET_LIMIT_RESPONSE => SetLimitResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, limit_down: 1024, limit_up: 128, } @@ -707,7 +707,7 @@ define_request_and_response! { #[doc = serde_doc_test!( OUT_PEERS_RESPONSE => OutPeersResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, out_peers: 3232235535, } )] @@ -740,7 +740,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_NET_STATS_RESPONSE => GetNetStatsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, start_time: 1721251858, total_bytes_in: 16283817214, total_bytes_out: 34225244079, @@ -779,7 +779,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_OUTS_RESPONSE => GetOutsResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, outs: vec![ OutKey { height: 51941, @@ -823,7 +823,7 @@ define_request_and_response! { #[doc = serde_doc_test!( UPDATE_RESPONSE => UpdateResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, auto_uri: "".into(), hash: "".into(), path: "".into(), @@ -860,7 +860,7 @@ define_request_and_response! { #[doc = serde_doc_test!( POP_BLOCKS_RESPONSE => PopBlocksResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, height: 76482, } )] @@ -879,7 +879,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_TRANSACTION_POOL_HASHES_RESPONSE => GetTransactionPoolHashesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, tx_hashes: vec![ "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(), "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(), @@ -929,7 +929,7 @@ define_request_and_response! { #[doc = serde_doc_test!( GET_PUBLIC_NODES_RESPONSE => GetPublicNodesResponse { - base: ResponseBase::ok(), + base: ResponseBase::OK, gray: vec![], white: vec![ PublicNode { From a10ed59201b1cad2e1b88171de3e85a55776fd8d Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:43:24 -0400 Subject: [PATCH 24/47] get_transaction_pool_backlog --- binaries/cuprated/src/rpc/json.rs | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 146cfacef..e9cd80c38 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -41,7 +41,7 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status}, + misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, TxBacklogEntry}, CORE_RPC_VERSION, }; @@ -680,12 +680,22 @@ async fn sync_info( /// async fn get_transaction_pool_backlog( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetTransactionPoolBacklogRequest, ) -> Result { + let backlog = txpool::backlog(&mut state.txpool_read) + .await? + .into_iter() + .map(|entry| TxBacklogEntry { + weight: entry.weight, + fee: entry.fee, + time_in_pool: entry.time_in_pool.as_secs(), + }) + .collect(); + Ok(GetTransactionPoolBacklogResponse { base: ResponseBase::OK, - backlog: todo!(), + backlog, }) } From d7d8b3509e1ca94b19062a9407f4ab24d4422e0e Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Mon, 14 Oct 2024 20:48:47 -0400 Subject: [PATCH 25/47] prune --- binaries/cuprated/src/rpc/handler.rs | 4 ++++ binaries/cuprated/src/rpc/json.rs | 17 ++++++++++------- .../src/rpc/request/blockchain_manager.rs | 9 ++++++--- 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index 2019beb4d..a9bbba6c0 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -4,6 +4,7 @@ use std::task::{Context, Poll}; use anyhow::Error; use cuprate_consensus::BlockChainContextService; +use cuprate_pruning::PruningSeed; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; @@ -70,6 +71,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::PopBlocks`] PopBlocks { new_height: usize }, + /// Response to [`BlockchainManagerRequest::Prune`] + Prune(PruningSeed), + /// Response to [`BlockchainManagerRequest::Pruned`] Pruned(bool), diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index e9cd80c38..65bc64e7b 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -5,7 +5,6 @@ use std::{ use anyhow::{anyhow, Error}; use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; -use cuprate_types::HardFork; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -44,15 +43,14 @@ use cuprate_rpc_types::{ misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, TxBacklogEntry}, CORE_RPC_VERSION, }; +use cuprate_types::HardFork; use crate::rpc::{ helper, - request::{address_book, blockchain, blockchain_context, blockchain_manager}, + request::{address_book, blockchain, blockchain_context, blockchain_manager, txpool}, CupratedRpcHandler, }; -use super::request::txpool; - /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( state: CupratedRpcHandler, @@ -719,13 +717,18 @@ async fn get_miner_data( /// async fn prune_blockchain( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: PruneBlockchainRequest, ) -> Result { + let pruned = blockchain_manager::pruned(&mut state.blockchain_manager).await?; + let pruning_seed = blockchain_manager::prune(&mut state.blockchain_manager) + .await? + .compress(); + Ok(PruneBlockchainResponse { base: ResponseBase::OK, - pruned: todo!(), - pruning_seed: todo!(), + pruned, + pruning_seed, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 569c7e144..96547ba55 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -5,6 +5,7 @@ use monero_serai::block::Block; use tower::{Service, ServiceExt}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; +use cuprate_pruning::PruningSeed; use crate::rpc::handler::{ BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, @@ -30,8 +31,10 @@ pub(crate) async fn pop_blocks( } /// [`BlockchainManagerRequest::Prune`] -pub(crate) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { - let BlockchainManagerResponse::Ok = blockchain_manager +pub(crate) async fn prune( + blockchain_manager: &mut BlockchainManagerHandle, +) -> Result { + let BlockchainManagerResponse::Prune(seed) = blockchain_manager .ready() .await? .call(BlockchainManagerRequest::Prune) @@ -40,7 +43,7 @@ pub(crate) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> R unreachable!(); }; - Ok(()) + Ok(seed) } /// [`BlockchainManagerRequest::Pruned`] From 5926f24d22965e222192e17b8b7405317049ba26 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 15 Oct 2024 16:19:35 -0400 Subject: [PATCH 26/47] calc_pow --- binaries/cuprated/src/rpc/handler.rs | 16 ++++++++++++ binaries/cuprated/src/rpc/json.rs | 22 +++++++++++++--- .../src/rpc/request/blockchain_manager.rs | 26 +++++++++++++++++++ 3 files changed, 61 insertions(+), 3 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index a9bbba6c0..e5f316e5e 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -5,6 +5,7 @@ use std::task::{Context, Poll}; use anyhow::Error; use cuprate_consensus::BlockChainContextService; use cuprate_pruning::PruningSeed; +use cuprate_types::HardFork; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; @@ -56,6 +57,18 @@ pub enum BlockchainManagerRequest { /// The height of the next block in the chain. TargetHeight, + + /// Calculate proof-of-work for this block. + CalculatePow { + /// The hardfork of the protocol at this block height. + hardfork: HardFork, + /// The height of the block. + height: usize, + /// The block data. + block: Block, + /// The seed hash for the proof-of-work. + seed_hash: [u8; 32], + }, } /// TODO: use real type when public. @@ -88,6 +101,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::TargetHeight`] TargetHeight { height: usize }, + + /// Response to [`BlockchainManagerRequest::CalculatePow`] + CalculatePow([u8; 32]), } /// TODO: use real type when public. diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 65bc64e7b..ba42af70a 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -734,10 +734,26 @@ async fn prune_blockchain( /// async fn calc_pow( - state: CupratedRpcHandler, - request: CalcPowRequest, + mut state: CupratedRpcHandler, + mut request: CalcPowRequest, ) -> Result { - Ok(CalcPowResponse { pow_hash: todo!() }) + let hardfork = HardFork::from_version(request.major_version)?; + let mut block_blob: Vec = hex::decode(request.block_blob)?; + let block = Block::read(&mut block_blob.as_slice())?; + let seed_hash = helper::hex_to_hash(request.seed_hash)?; + + let pow_hash = blockchain_manager::calculate_pow( + &mut state.blockchain_manager, + hardfork, + request.height, + block, + seed_hash, + ) + .await?; + + let hex = hex::encode(pow_hash); + + Ok(CalcPowResponse { pow_hash: hex }) } /// diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 96547ba55..bd81cc01f 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -1,6 +1,7 @@ //! Functions for [`BlockchainManagerRequest`] & [`BlockchainManagerResponse`]. use anyhow::Error; +use cuprate_types::HardFork; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -142,3 +143,28 @@ pub(crate) async fn target_height( Ok(usize_to_u64(height)) } + +/// [`BlockchainManagerRequest::CalculatePow`] +pub(crate) async fn calculate_pow( + blockchain_manager: &mut BlockchainManagerHandle, + hardfork: HardFork, + height: u64, + block: Block, + seed_hash: [u8; 32], +) -> Result<[u8; 32], Error> { + let BlockchainManagerResponse::CalculatePow(hash) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::CalculatePow { + hardfork, + height: u64_to_usize(height), + block, + seed_hash, + }) + .await? + else { + unreachable!(); + }; + + Ok(hash) +} From 7148ba16687c488925c9bc3ecd3fd8f9cdd94731 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 15 Oct 2024 16:45:54 -0400 Subject: [PATCH 27/47] add_aux_pow --- binaries/cuprated/src/rpc/handler.rs | 15 ++++-- binaries/cuprated/src/rpc/json.rs | 46 +++++++++++++++---- .../src/rpc/request/blockchain_manager.rs | 23 +++++++++- types/src/blockchain.rs | 1 + types/src/lib.rs | 7 +-- types/src/types.rs | 17 +++++++ 6 files changed, 94 insertions(+), 15 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index e5f316e5e..b952bd859 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -3,14 +3,13 @@ use std::task::{Context, Poll}; use anyhow::Error; -use cuprate_consensus::BlockChainContextService; -use cuprate_pruning::PruningSeed; -use cuprate_types::HardFork; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle}; +use cuprate_consensus::BlockChainContextService; +use cuprate_pruning::PruningSeed; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ bin::{BinRequest, BinResponse}, @@ -18,6 +17,7 @@ use cuprate_rpc_types::{ other::{OtherRequest, OtherResponse}, }; use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle}; +use cuprate_types::{AddAuxPow, AuxPow, HardFork}; use crate::rpc::{bin, json, other}; @@ -69,6 +69,12 @@ pub enum BlockchainManagerRequest { /// The seed hash for the proof-of-work. seed_hash: [u8; 32], }, + + /// TODO + AddAuxPow { + blocktemplate_blob: Vec, + aux_pow: Vec, + }, } /// TODO: use real type when public. @@ -104,6 +110,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::CalculatePow`] CalculatePow([u8; 32]), + + /// Response to [`BlockchainManagerRequest::AddAuxPow`] + AddAuxPow(AddAuxPow), } /// TODO: use real type when public. diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index ba42af70a..b3cb1f2c0 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -40,7 +40,10 @@ use cuprate_rpc_types::{ SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest, SyncInfoResponse, }, - misc::{BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, TxBacklogEntry}, + misc::{ + AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, + TxBacklogEntry, + }, CORE_RPC_VERSION, }; use cuprate_types::HardFork; @@ -761,7 +764,7 @@ async fn flush_cache( state: CupratedRpcHandler, request: FlushCacheRequest, ) -> Result { - todo!(); + // TODO: cuprated doesn't need this call; decide behavior. Ok(FlushCacheResponse { base: ResponseBase::OK, @@ -770,16 +773,43 @@ async fn flush_cache( /// async fn add_aux_pow( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { + let blocktemplate_blob = hex::decode(request.blocktemplate_blob)?; + let aux_pow = request + .aux_pow + .into_iter() + .map(|aux| { + let id = helper::hex_to_hash(aux.id)?; + let hash = helper::hex_to_hash(aux.hash)?; + Ok(cuprate_types::AuxPow { id, hash }) + }) + .collect::, Error>>()?; + + let resp = + blockchain_manager::add_aux_pow(&mut state.blockchain_manager, blocktemplate_blob, aux_pow) + .await?; + + let blocktemplate_blob = hex::encode(resp.blocktemplate_blob); + let blockhashing_blob = hex::encode(resp.blockhashing_blob); + let merkle_root = hex::encode(resp.merkle_root); + let aux_pow = resp + .aux_pow + .into_iter() + .map(|aux| AuxPow { + id: hex::encode(aux.id), + hash: hex::encode(aux.hash), + }) + .collect::>(); + Ok(AddAuxPowResponse { base: ResponseBase::OK, - blocktemplate_blob: todo!(), - blockhashing_blob: todo!(), - merkle_root: todo!(), - merkle_tree_depth: todo!(), - aux_pow: todo!(), + blocktemplate_blob, + blockhashing_blob, + merkle_root, + merkle_tree_depth: resp.merkle_tree_depth, + aux_pow, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index bd81cc01f..da84b08d3 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -1,7 +1,7 @@ //! Functions for [`BlockchainManagerRequest`] & [`BlockchainManagerResponse`]. use anyhow::Error; -use cuprate_types::HardFork; +use cuprate_types::{AddAuxPow, AuxPow, HardFork}; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -168,3 +168,24 @@ pub(crate) async fn calculate_pow( Ok(hash) } + +/// [`BlockchainManagerRequest::AddAuxPow`] +pub(crate) async fn add_aux_pow( + blockchain_manager: &mut BlockchainManagerHandle, + blocktemplate_blob: Vec, + aux_pow: Vec, +) -> Result { + let BlockchainManagerResponse::AddAuxPow(response) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::AddAuxPow { + blocktemplate_blob, + aux_pow, + }) + .await? + else { + unreachable!(); + }; + + Ok(response) +} diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index e53619bcf..5b408dea7 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -289,6 +289,7 @@ pub enum BlockchainResponse { /// - Value = hardfork version HardForks(BTreeMap), + /// TODO AltChains(Vec), //------------------------------------------------------ Writes diff --git a/types/src/lib.rs b/types/src/lib.rs index 0fd1ec7b5..fa35153bb 100644 --- a/types/src/lib.rs +++ b/types/src/lib.rs @@ -20,9 +20,10 @@ pub use transaction_verification_data::{ CachedVerificationState, TransactionVerificationData, TxVersion, }; pub use types::{ - AltBlockInformation, Chain, ChainId, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, - FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, OutputHistogramEntry, - OutputHistogramInput, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation, + AddAuxPow, AltBlockInformation, AuxPow, 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 a6833758e..720ad0a73 100644 --- a/types/src/types.rs +++ b/types/src/types.rs @@ -242,6 +242,23 @@ pub struct ChainInfo { pub main_chain_parent_block: [u8; 32], } +/// Used in RPC's `add_aux_pow`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AuxPow { + pub id: [u8; 32], + pub hash: [u8; 32], +} + +/// Used in RPC's `add_aux_pow`. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct AddAuxPow { + pub blocktemplate_blob: Vec, + pub blockhashing_blob: Vec, + pub merkle_root: [u8; 32], + pub merkle_tree_depth: u64, + pub aux_pow: Vec, +} + //---------------------------------------------------------------------------------------------------- Tests #[cfg(test)] mod test { From d56477cd61b1004afea74d5b403abcbf682c3984 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 15 Oct 2024 16:58:14 -0400 Subject: [PATCH 28/47] get_tx_ids_loose --- binaries/cuprated/src/rpc/json.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index b3cb1f2c0..e8872dfec 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -818,6 +818,9 @@ async fn get_tx_ids_loose( state: CupratedRpcHandler, request: GetTxIdsLooseRequest, ) -> Result { + // TODO: this RPC call is not yet in the v0.18 branch. + return Err(anyhow!("not implemented")); + Ok(GetTxIdsLooseResponse { base: ResponseBase::OK, txids: todo!(), From 548639b2f697e376a58ea3f15284c19a2d98d6a5 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 15 Oct 2024 20:14:15 -0400 Subject: [PATCH 29/47] generate_blocks --- binaries/cuprated/src/rpc/handler.rs | 23 ++++++++++++++++- binaries/cuprated/src/rpc/json.rs | 25 ++++++++++++++++--- .../src/rpc/request/blockchain_manager.rs | 25 +++++++++++++++++++ 3 files changed, 69 insertions(+), 4 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index b952bd859..befecfe47 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -23,7 +23,6 @@ use crate::rpc::{bin, json, other}; /// TODO: use real type when public. #[derive(Clone)] -#[expect(clippy::large_enum_variant)] pub enum BlockchainManagerRequest { /// Pop blocks off the top of the blockchain. /// @@ -72,9 +71,23 @@ pub enum BlockchainManagerRequest { /// TODO AddAuxPow { + /// TODO blocktemplate_blob: Vec, + /// TODO aux_pow: Vec, }, + + /// TODO + GenerateBlocks { + /// TODO + amount_of_blocks: u64, + /// TODO + prev_block: [u8; 32], + /// TODO + starting_nonce: u32, + /// TODO + wallet_address: String, + }, } /// TODO: use real type when public. @@ -113,6 +126,14 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::AddAuxPow`] AddAuxPow(AddAuxPow), + + /// Response to [`BlockchainManagerRequest::GenerateBlocks`] + GenerateBlocks { + /// TODO + blocks: Vec<[u8; 32]>, + /// TODO + height: usize, + }, } /// TODO: use real type when public. diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index e8872dfec..24798b30a 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -46,7 +46,7 @@ use cuprate_rpc_types::{ }, CORE_RPC_VERSION, }; -use cuprate_types::HardFork; +use cuprate_types::{Chain, HardFork}; use crate::rpc::{ helper, @@ -161,10 +161,29 @@ async fn generate_blocks( state: CupratedRpcHandler, request: GenerateBlocksRequest, ) -> Result { + if todo!("active cuprated chain") != todo!("regtest chain") { + return Err(anyhow!("Regtest required when generating blocks")); + } + + // TODO: is this value only used as a local variable in the handler? + // it may not be needed in the request type. + let prev_block = helper::hex_to_hash(request.prev_block)?; + + let (blocks, height) = blockchain_manager::generate_blocks( + &mut state.blockchain_manager, + request.amount_of_blocks, + prev_block, + request.starting_nonce, + request.wallet_address, + ) + .await?; + + let blocks = blocks.into_iter().map(hex::encode).collect(); + Ok(GenerateBlocksResponse { base: ResponseBase::OK, - blocks: todo!(), - height: todo!(), + blocks, + height, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index da84b08d3..ba2811219 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -189,3 +189,28 @@ pub(crate) async fn add_aux_pow( Ok(response) } + +/// [`BlockchainManagerRequest::GenerateBlocks`] +pub(crate) async fn generate_blocks( + blockchain_manager: &mut BlockchainManagerHandle, + amount_of_blocks: u64, + prev_block: [u8; 32], + starting_nonce: u32, + wallet_address: String, +) -> Result<(Vec<[u8; 32]>, u64), Error> { + let BlockchainManagerResponse::GenerateBlocks { blocks, height } = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::GenerateBlocks { + amount_of_blocks, + prev_block, + starting_nonce, + wallet_address, + }) + .await? + else { + unreachable!(); + }; + + Ok((blocks, usize_to_u64(height))) +} From e2f25bd52decba7716ddd588030f0caf6079ec47 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 15 Oct 2024 20:58:44 -0400 Subject: [PATCH 30/47] get_info --- binaries/cuprated/src/rpc/json.rs | 162 +++++++++++++----- .../cuprated/src/rpc/request/blockchain.rs | 16 ++ binaries/cuprated/src/rpc/request/txpool.rs | 9 +- storage/blockchain/src/service/read.rs | 6 + storage/txpool/src/service/interface.rs | 5 +- storage/txpool/src/service/read.rs | 6 +- types/src/blockchain.rs | 6 + 7 files changed, 161 insertions(+), 49 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 24798b30a..21e146cf2 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -48,10 +48,14 @@ use cuprate_rpc_types::{ }; use cuprate_types::{Chain, HardFork}; -use crate::rpc::{ - helper, - request::{address_book, blockchain, blockchain_context, blockchain_manager, txpool}, - CupratedRpcHandler, +use crate::{ + constants::VERSION_BUILD, + rpc::{ + helper, + request::{address_book, blockchain, blockchain_context, blockchain_manager, txpool}, + CupratedRpcHandler, + }, + statics::START_INSTANT_UNIX, }; /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. @@ -353,50 +357,120 @@ async fn get_connections( /// async fn get_info( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetInfoRequest, ) -> Result { + let restricted = state.restricted(); + let context = blockchain_context::context(&mut state.blockchain_context).await?; + + let c = context.unchecked_blockchain_context(); + let cumulative_difficulty = c.cumulative_difficulty; + let adjusted_time = c.current_adjusted_timestamp_for_time_lock(); // TODO: is this correct? + + let c = &c.context_to_verify_block; + + let alt_blocks_count = if restricted { + 0 + } else { + blockchain::alt_chain_count(&mut state.blockchain_read).await? + }; + let block_weight_limit = usize_to_u64(c.effective_median_weight); // TODO: is this correct? + let block_weight_median = usize_to_u64(c.median_weight_for_block_reward); // TODO: is this correct? + let block_size_limit = block_weight_limit; + let block_size_median = block_weight_median; + let (bootstrap_daemon_address, was_bootstrap_ever_used) = if restricted { + (String::new(), false) + } else { + todo!() + }; + let busy_syncing = blockchain_manager::syncing(&mut state.blockchain_manager).await?; + let (cumulative_difficulty, cumulative_difficulty_top64) = + split_u128_into_low_high_bits(cumulative_difficulty); + let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?; + let (database_size, free_space) = if restricted { + let database_size = todo!(); // round_up(res.database_size, 5ull* 1024 * 1024 * 1024) */ + (database_size, u64::MAX) + } else { + (database_size, free_space) + }; + let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(c.next_difficulty); + let height = usize_to_u64(c.chain_height); + let height_without_bootstrap = if restricted { 0 } else { height }; + let (incoming_connections_count, outgoing_connections_count) = if restricted { + (0, 0) + } else { + address_book::connection_count::(&mut DummyAddressBook).await? + }; + let mainnet = todo!(); + let nettype = todo!(); + let offline = todo!(); + let rpc_connections_count = if restricted { 0 } else { todo!() }; + let stagenet = todo!(); + let start_time = if restricted { 0 } else { *START_INSTANT_UNIX }; + let synchronized = blockchain_manager::synced(&mut state.blockchain_manager).await?; + let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?; + let target = blockchain_manager::target(&mut state.blockchain_manager) + .await? + .as_secs(); + let testnet = todo!(); + let top_block_hash = hex::encode(c.top_hash); + let tx_count = blockchain::total_tx_count(&mut state.blockchain_read).await?; + let tx_pool_size = txpool::size(&mut state.txpool_read, !restricted).await?; + let update_available = if restricted { false } else { todo!() }; + let version = if restricted { + String::new() + } else { + VERSION_BUILD.to_string() + }; + let (white_peerlist_size, grey_peerlist_size) = if restricted { + (0, 0) + } else { + address_book::peerlist_size::(&mut DummyAddressBook).await? + }; + let wide_cumulative_difficulty = format!("{cumulative_difficulty:#x}"); + let wide_difficulty = format!("{:#x}", c.next_difficulty); + Ok(GetInfoResponse { base: AccessResponseBase::OK, - adjusted_time: todo!(), - alt_blocks_count: todo!(), - block_size_limit: todo!(), - block_size_median: todo!(), - block_weight_limit: todo!(), - block_weight_median: todo!(), - bootstrap_daemon_address: todo!(), - busy_syncing: todo!(), - cumulative_difficulty_top64: todo!(), - cumulative_difficulty: todo!(), - database_size: todo!(), - difficulty_top64: todo!(), - difficulty: todo!(), - free_space: todo!(), - grey_peerlist_size: todo!(), - height: todo!(), - height_without_bootstrap: todo!(), - incoming_connections_count: todo!(), - mainnet: todo!(), - nettype: todo!(), - offline: todo!(), - outgoing_connections_count: todo!(), - restricted: todo!(), - rpc_connections_count: todo!(), - stagenet: todo!(), - start_time: todo!(), - synchronized: todo!(), - target_height: todo!(), - target: todo!(), - testnet: todo!(), - top_block_hash: todo!(), - tx_count: todo!(), - tx_pool_size: todo!(), - update_available: todo!(), - version: todo!(), - was_bootstrap_ever_used: todo!(), - white_peerlist_size: todo!(), - wide_cumulative_difficulty: todo!(), - wide_difficulty: todo!(), + adjusted_time, + alt_blocks_count, + block_size_limit, + block_size_median, + block_weight_limit, + block_weight_median, + bootstrap_daemon_address, + busy_syncing, + cumulative_difficulty_top64, + cumulative_difficulty, + database_size, + difficulty_top64, + difficulty, + free_space, + grey_peerlist_size, + height, + height_without_bootstrap, + incoming_connections_count, + mainnet, + nettype, + offline, + outgoing_connections_count, + restricted, + rpc_connections_count, + stagenet, + start_time, + synchronized, + target_height, + target, + testnet, + top_block_hash, + tx_count, + tx_pool_size, + update_available, + version, + was_bootstrap_ever_used, + white_peerlist_size, + wide_cumulative_difficulty, + wide_difficulty, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 40654234d..36f43fa98 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -375,3 +375,19 @@ pub(crate) async fn alt_chains( Ok(vec) } + +/// [`BlockchainReadRequest::AltChainCount`] +pub(crate) async fn alt_chain_count( + blockchain_read: &mut BlockchainReadHandle, +) -> Result { + let BlockchainResponse::AltChainCount(count) = blockchain_read + .ready() + .await? + .call(BlockchainReadRequest::AltChainCount) + .await? + else { + unreachable!(); + }; + + Ok(usize_to_u64(count)) +} diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index e2caccd1d..eadbb23d8 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -33,12 +33,17 @@ pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result Result { +pub(crate) async fn size( + txpool_read: &mut TxpoolReadHandle, + include_sensitive_txs: bool, +) -> Result { let TxpoolReadResponse::Size(size) = txpool_read .ready() .await .map_err(|e| anyhow!(e))? - .call(TxpoolReadRequest::Size) + .call(TxpoolReadRequest::Size { + include_sensitive_txs, + }) .await .map_err(|e| anyhow!(e))? else { diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index c04a6f227..76d44a275 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -123,6 +123,7 @@ fn map_request( R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), R::HardForks => hard_forks(env), R::AltChains => alt_chains(env), + R::AltChainCount => alt_chain_count(env), } /* SOMEDAY: post-request handling, run some code for each request? */ @@ -660,3 +661,8 @@ fn hard_forks(env: &ConcreteEnv) -> ResponseResult { fn alt_chains(env: &ConcreteEnv) -> ResponseResult { Ok(BlockchainResponse::AltChains(todo!())) } + +/// [`BlockchainReadRequest::AltChainCount`] +fn alt_chain_count(env: &ConcreteEnv) -> ResponseResult { + Ok(BlockchainResponse::AltChainCount(todo!())) +} diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 88dd02e35..d90b255df 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -20,7 +20,10 @@ pub enum TxpoolReadRequest { Backlog, /// Get the number of transactions in the pool. - Size, + Size { + /// TODO + include_sensitive_txs: bool, + }, } //---------------------------------------------------------------------------------------------------- TxpoolReadResponse diff --git a/storage/txpool/src/service/read.rs b/storage/txpool/src/service/read.rs index 3135322e3..0b75e8a68 100644 --- a/storage/txpool/src/service/read.rs +++ b/storage/txpool/src/service/read.rs @@ -66,7 +66,9 @@ fn map_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), + TxpoolReadRequest::Size { + include_sensitive_txs, + } => size(env, include_sensitive_txs), } } @@ -119,6 +121,6 @@ fn backlog(env: &ConcreteEnv) -> ReadResponseResult { /// [`TxpoolReadRequest::Size`]. #[inline] -fn size(env: &ConcreteEnv) -> ReadResponseResult { +fn size(env: &ConcreteEnv, include_sensitive_txs: bool) -> ReadResponseResult { Ok(TxpoolReadResponse::Size(todo!())) } diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 5b408dea7..49fec0732 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -135,6 +135,9 @@ pub enum BlockchainReadRequest { /// TODO AltChains, + + /// TODO + AltChainCount, } //---------------------------------------------------------------------------------------------------- WriteRequest @@ -292,6 +295,9 @@ pub enum BlockchainResponse { /// TODO AltChains(Vec), + /// Response to [`BlockchainReadRequest::AltChainCount`]. + AltChainCount(usize), + //------------------------------------------------------ Writes /// A generic Ok response to indicate a request was successfully handled. /// From 4b1d7bc8974754443c488f50b7d779582b1bb920 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 16 Oct 2024 16:46:13 -0400 Subject: [PATCH 31/47] sync_info --- binaries/cuprated/src/rpc/handler.rs | 8 +++ binaries/cuprated/src/rpc/json.rs | 38 ++++++++++--- .../cuprated/src/rpc/request/address_book.rs | 53 ++++++++++++++++++- .../src/rpc/request/blockchain_manager.rs | 19 +++++++ p2p/address-book/src/book.rs | 4 +- .../src/client/handshaker/builder/dummy.rs | 4 +- p2p/p2p-core/src/services.rs | 14 ++++- p2p/p2p-core/src/types.rs | 14 +++++ 8 files changed, 142 insertions(+), 12 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index befecfe47..bfa6a8229 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -88,6 +88,11 @@ pub enum BlockchainManagerRequest { /// TODO wallet_address: String, }, + + /// TODO + /// + /// + Overview { height: usize }, } /// TODO: use real type when public. @@ -134,6 +139,9 @@ pub enum BlockchainManagerResponse { /// TODO height: usize, }, + + /// Response to [`BlockchainManagerRequest::Overview`] + Overview(String), } /// TODO: use real type when public. diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 21e146cf2..11ef85a32 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -42,7 +42,7 @@ use cuprate_rpc_types::{ }, misc::{ AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, - TxBacklogEntry, + SyncInfoPeer, TxBacklogEntry, }, CORE_RPC_VERSION, }; @@ -758,17 +758,39 @@ async fn relay_tx( /// async fn sync_info( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: SyncInfoRequest, ) -> Result { + let height = usize_to_u64( + blockchain_context::context(&mut state.blockchain_context) + .await? + .unchecked_blockchain_context() + .chain_height, + ); + + let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?; + + let peers = address_book::connection_info::(&mut DummyAddressBook) + .await? + .into_iter() + .map(|info| SyncInfoPeer { info }) + .collect(); + + let next_needed_pruning_seed = + address_book::next_needed_pruning_seed::(&mut DummyAddressBook) + .await? + .compress(); + let overview = blockchain_manager::overview(&mut state.blockchain_manager, height).await?; + let spans = address_book::spans::(&mut DummyAddressBook).await?; + Ok(SyncInfoResponse { base: AccessResponseBase::OK, - height: todo!(), - next_needed_pruning_seed: todo!(), - overview: todo!(), - peers: todo!(), - spans: todo!(), - target_height: todo!(), + height, + next_needed_pruning_seed, + overview, + peers, + spans, + target_height, }) } diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index b991dce44..bd462209c 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -3,7 +3,8 @@ use std::convert::Infallible; use anyhow::{anyhow, Error}; -use cuprate_rpc_types::misc::ConnectionInfo; +use cuprate_pruning::PruningSeed; +use cuprate_rpc_types::misc::{ConnectionInfo, Span}; use tower::ServiceExt; use cuprate_helper::cast::usize_to_u64; @@ -156,3 +157,53 @@ pub(crate) async fn get_bans( Ok(bans) } + +/// [`AddressBookRequest::Spans`] +pub(crate) async fn spans( + address_book: &mut impl AddressBook, +) -> Result, Error> { + let AddressBookResponse::Spans(vec) = address_book + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::Spans) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + // FIXME: impl this map somewhere instead of inline. + let vec = vec + .into_iter() + .map(|span| Span { + connection_id: span.connection_id, + nblocks: span.nblocks, + rate: span.rate, + remote_address: span.remote_address, + size: span.size, + speed: span.speed, + start_block_height: span.start_block_height, + }) + .collect(); + + Ok(vec) +} + +/// [`AddressBookRequest::NextNeededPruningSeed`] +pub(crate) async fn next_needed_pruning_seed( + address_book: &mut impl AddressBook, +) -> Result { + let AddressBookResponse::NextNeededPruningSeed(seed) = address_book + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(AddressBookRequest::NextNeededPruningSeed) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + Ok(seed) +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index ba2811219..1ee702d6c 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -214,3 +214,22 @@ pub(crate) async fn generate_blocks( Ok((blocks, usize_to_u64(height))) } + +/// [`BlockchainManagerRequest::Overview`] +pub(crate) async fn overview( + blockchain_manager: &mut BlockchainManagerHandle, + height: u64, +) -> Result { + let BlockchainManagerResponse::Overview(overview) = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Overview { + height: u64_to_usize(height), + }) + .await? + else { + unreachable!(); + }; + + Ok(overview) +} diff --git a/p2p/address-book/src/book.rs b/p2p/address-book/src/book.rs index 3e5269f5d..bc7109bc6 100644 --- a/p2p/address-book/src/book.rs +++ b/p2p/address-book/src/book.rs @@ -424,7 +424,9 @@ impl Service> for AddressBook { | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) | AddressBookRequest::GetBans - | AddressBookRequest::ConnectionInfo => { + | AddressBookRequest::ConnectionInfo + | AddressBookRequest::NextNeededPruningSeed + | AddressBookRequest::Spans => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } }; diff --git a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs index 48b3daf5e..4c039bb66 100644 --- a/p2p/p2p-core/src/client/handshaker/builder/dummy.rs +++ b/p2p/p2p-core/src/client/handshaker/builder/dummy.rs @@ -112,7 +112,9 @@ impl Service> for DummyAddressBook { | AddressBookRequest::ConnectionCount | AddressBookRequest::SetBan(_) | AddressBookRequest::GetBans - | AddressBookRequest::ConnectionInfo => { + | AddressBookRequest::ConnectionInfo + | AddressBookRequest::NextNeededPruningSeed + | AddressBookRequest::Spans => { todo!("finish https://github.com/Cuprate/cuprate/pull/297") } })) diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index 6d1089ce1..6124e3e07 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -6,7 +6,7 @@ use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use crate::{ client::InternalPeerID, handles::ConnectionHandle, - types::{BanState, ConnectionInfo, SetBan}, + types::{BanState, ConnectionInfo, SetBan, Span}, NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, }; @@ -132,6 +132,12 @@ pub enum AddressBookRequest { /// Get the state of all bans. GetBans, + + /// TODO + Spans, + + /// TODO + NextNeededPruningSeed, } /// A response from the address book service. @@ -169,4 +175,10 @@ pub enum AddressBookResponse { /// Response to [`AddressBookRequest::GetBans`]. GetBans(Vec>), + + /// Response to [`AddressBookRequest::Spans`]. + Spans(Vec), + + /// Response to [`AddressBookRequest::NextNeededPruningSeed`]. + NextNeededPruningSeed(PruningSeed), } diff --git a/p2p/p2p-core/src/types.rs b/p2p/p2p-core/src/types.rs index e53491bd1..4714f9e2c 100644 --- a/p2p/p2p-core/src/types.rs +++ b/p2p/p2p-core/src/types.rs @@ -52,3 +52,17 @@ pub struct ConnectionInfo { pub state: String, pub support_flags: u32, } + +/// Used in RPC's `sync_info`. +/// +/// Data within [`crate::services::AddressBookResponse::Spans`]. +#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct Span { + pub connection_id: String, + pub nblocks: u64, + pub rate: u32, + pub remote_address: String, + pub size: u64, + pub speed: u32, + pub start_block_height: u64, +} From bd3a844cc5af38dc0718285645b69509867e3880 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 16 Oct 2024 16:57:48 -0400 Subject: [PATCH 32/47] get_miner_data --- binaries/cuprated/src/rpc/json.rs | 41 ++++++++++++++----- .../src/rpc/request/blockchain_context.rs | 12 +++--- binaries/cuprated/src/rpc/request/txpool.rs | 20 ++++++++- storage/txpool/src/lib.rs | 2 +- storage/txpool/src/service/interface.rs | 13 +++++- storage/txpool/src/service/read.rs | 7 ++++ storage/txpool/src/tx.rs | 13 ++++++ 7 files changed, 88 insertions(+), 20 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 11ef85a32..204b36ff2 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -41,8 +41,8 @@ use cuprate_rpc_types::{ SyncInfoResponse, }, misc::{ - AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, - SyncInfoPeer, TxBacklogEntry, + AuxPow, BlockHeader, ChainInfo, GetBan, GetMinerDataTxBacklogEntry, HardforkEntry, + HistogramEntry, Status, SyncInfoPeer, TxBacklogEntry, }, CORE_RPC_VERSION, }; @@ -817,19 +817,38 @@ async fn get_transaction_pool_backlog( /// async fn get_miner_data( - state: CupratedRpcHandler, + mut state: CupratedRpcHandler, request: GetMinerDataRequest, ) -> Result { + let context = blockchain_context::context(&mut state.blockchain_context).await?; + let context = context.unchecked_blockchain_context(); + let major_version = context.current_hf.as_u8(); + let height = usize_to_u64(context.chain_height); + let prev_id = hex::encode(context.top_hash); + let seed_hash = todo!(); + let difficulty = format!("{:#x}", context.next_difficulty); + let median_weight = usize_to_u64(context.median_weight_for_block_reward); + let already_generated_coins = context.already_generated_coins; + let tx_backlog = txpool::block_template_backlog(&mut state.txpool_read) + .await? + .into_iter() + .map(|entry| GetMinerDataTxBacklogEntry { + id: hex::encode(entry.id), + weight: entry.weight, + fee: entry.fee, + }) + .collect(); + Ok(GetMinerDataResponse { base: ResponseBase::OK, - major_version: todo!(), - height: todo!(), - prev_id: todo!(), - seed_hash: todo!(), - difficulty: todo!(), - median_weight: todo!(), - already_generated_coins: todo!(), - tx_backlog: todo!(), + major_version, + height, + prev_id, + seed_hash, + difficulty, + median_weight, + already_generated_coins, + tx_backlog, }) } diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index 43f5fc594..9001b32d5 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -15,9 +15,9 @@ use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; /// [`BlockChainContextRequest::Context`]. pub(crate) async fn context( - service: &mut BlockChainContextService, + blockchain_context: &mut BlockChainContextService, ) -> Result { - let BlockChainContextResponse::Context(context) = service + let BlockChainContextResponse::Context(context) = blockchain_context .ready() .await .map_err(|e| anyhow!(e))? @@ -33,10 +33,10 @@ pub(crate) async fn context( /// [`BlockChainContextRequest::HardForkInfo`]. pub(crate) async fn hard_fork_info( - service: &mut BlockChainContextService, + blockchain_context: &mut BlockChainContextService, hard_fork: HardFork, ) -> Result { - let BlockChainContextResponse::HardForkInfo(hf_info) = service + let BlockChainContextResponse::HardForkInfo(hf_info) = blockchain_context .ready() .await .map_err(|e| anyhow!(e))? @@ -52,10 +52,10 @@ pub(crate) async fn hard_fork_info( /// [`BlockChainContextRequest::FeeEstimate`]. pub(crate) async fn fee_estimate( - service: &mut BlockChainContextService, + blockchain_context: &mut BlockChainContextService, grace_blocks: u64, ) -> Result { - let BlockChainContextResponse::FeeEstimate(fee) = service + let BlockChainContextResponse::FeeEstimate(fee) = blockchain_context .ready() .await .map_err(|e| anyhow!(e))? diff --git a/binaries/cuprated/src/rpc/request/txpool.rs b/binaries/cuprated/src/rpc/request/txpool.rs index eadbb23d8..3ef456cd8 100644 --- a/binaries/cuprated/src/rpc/request/txpool.rs +++ b/binaries/cuprated/src/rpc/request/txpool.rs @@ -11,7 +11,7 @@ use cuprate_txpool::{ interface::{TxpoolReadRequest, TxpoolReadResponse}, TxpoolReadHandle, }, - TxEntry, + BlockTemplateTxEntry, TxEntry, }; // FIXME: use `anyhow::Error` over `tower::BoxError` in txpool. @@ -32,6 +32,24 @@ pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result Result, Error> { + let TxpoolReadResponse::BlockTemplateBacklog(tx_entries) = txpool_read + .ready() + .await + .map_err(|e| anyhow!(e))? + .call(TxpoolReadRequest::BlockTemplateBacklog) + .await + .map_err(|e| anyhow!(e))? + else { + unreachable!(); + }; + + Ok(tx_entries) +} + /// [`TxpoolReadRequest::Size`] pub(crate) async fn size( txpool_read: &mut TxpoolReadHandle, diff --git a/storage/txpool/src/lib.rs b/storage/txpool/src/lib.rs index 5fb3b1439..200013604 100644 --- a/storage/txpool/src/lib.rs +++ b/storage/txpool/src/lib.rs @@ -15,7 +15,7 @@ pub mod types; pub use config::Config; pub use free::open; -pub use tx::TxEntry; +pub use tx::{BlockTemplateTxEntry, TxEntry}; //re-exports pub use cuprate_database; diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index d90b255df..394162a04 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -5,7 +5,10 @@ use std::sync::Arc; use cuprate_types::TransactionVerificationData; -use crate::{tx::TxEntry, types::TransactionHash}; +use crate::{ + tx::{BlockTemplateTxEntry, TxEntry}, + types::TransactionHash, +}; //---------------------------------------------------------------------------------------------------- TxpoolReadRequest /// The transaction pool [`tower::Service`] read request type. @@ -19,6 +22,9 @@ pub enum TxpoolReadRequest { /// Get information on all transactions in the pool. Backlog, + /// TODO + BlockTemplateBacklog, + /// Get the number of transactions in the pool. Size { /// TODO @@ -45,6 +51,11 @@ pub enum TxpoolReadResponse { /// the transactions currently in the pool. Backlog(Vec), + /// Response to [`TxpoolReadRequest::BlockTemplateBacklog`]. + /// + /// TODO + BlockTemplateBacklog(Vec), + /// Response to [`TxpoolReadRequest::Size`]. /// /// The inner value is the amount of diff --git a/storage/txpool/src/service/read.rs b/storage/txpool/src/service/read.rs index 0b75e8a68..229bf2bef 100644 --- a/storage/txpool/src/service/read.rs +++ b/storage/txpool/src/service/read.rs @@ -66,6 +66,7 @@ fn map_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::BlockTemplateBacklog => block_template_backlog(env), TxpoolReadRequest::Size { include_sensitive_txs, } => size(env, include_sensitive_txs), @@ -119,6 +120,12 @@ fn backlog(env: &ConcreteEnv) -> ReadResponseResult { Ok(TxpoolReadResponse::Backlog(todo!())) } +/// [`TxpoolReadRequest::BlockTemplateBacklog`]. +#[inline] +fn block_template_backlog(env: &ConcreteEnv) -> ReadResponseResult { + Ok(TxpoolReadResponse::BlockTemplateBacklog(todo!())) +} + /// [`TxpoolReadRequest::Size`]. #[inline] fn size(env: &ConcreteEnv, include_sensitive_txs: bool) -> ReadResponseResult { diff --git a/storage/txpool/src/tx.rs b/storage/txpool/src/tx.rs index 6425326a4..7daff1562 100644 --- a/storage/txpool/src/tx.rs +++ b/storage/txpool/src/tx.rs @@ -12,3 +12,16 @@ pub struct TxEntry { /// How long the transaction has been in the pool. pub time_in_pool: std::time::Duration, } + +/// TODO +/// +/// Used in [`TxpoolReadResponse::BlockTemplateBacklog`](crate::service::interface::TxpoolReadResponse::BlockTemplateBacklog). +#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] +pub struct BlockTemplateTxEntry { + /// TODO + pub id: [u8; 32], + /// TODO + pub weight: u64, + /// TODO + pub fee: u64, +} From bf07f2c84c196e46849c921fc0302692f751e8f6 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 16 Oct 2024 20:46:24 -0400 Subject: [PATCH 33/47] `BlockchainManagerRequest` docs --- binaries/cuprated/src/rpc/handler.rs | 46 +++++++++++++------ binaries/cuprated/src/rpc/json.rs | 6 ++- .../src/rpc/request/blockchain_manager.rs | 4 +- 3 files changed, 38 insertions(+), 18 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index bfa6a8229..13e8924ea 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -69,30 +69,48 @@ pub enum BlockchainManagerRequest { seed_hash: [u8; 32], }, - /// TODO + /// Add auxirilly proof-of-work to a block. + /// + /// From the RPC `add_aux_pow` usecase's documentation: + /// ```` + /// This enables merge mining with Monero without requiring + /// software that manually alters the extra field in the coinbase + /// tx to include the merkle root of the aux blocks. + /// ```` AddAuxPow { - /// TODO - blocktemplate_blob: Vec, - /// TODO + /// The block template to add to. + block_template: Block, + /// The auxirilly proof-of-work to add. aux_pow: Vec, }, - /// TODO + /// Generate new blocks. + /// + /// This request is only for regtest, see RPC's `generateblocks`. GenerateBlocks { - /// TODO + /// Number of the blocks to be generated. amount_of_blocks: u64, - /// TODO + /// The previous block's hash. prev_block: [u8; 32], - /// TODO + /// The starting value for the nonce. starting_nonce: u32, - /// TODO + /// The address that will receive the coinbase reward. wallet_address: String, }, - /// TODO + /// Get a visual [`String`] overview of blockchain progress. + /// + /// This is a highly implementation specific format used by + /// `monerod` in the `sync_info` RPC call's `overview` field; + /// it is essentially an ASCII visual of blocks. /// - /// - Overview { height: usize }, + /// See also: + /// - + /// - + Overview { + /// TODO: the current blockchain height? do we need to pass this? + height: usize, + }, } /// TODO: use real type when public. @@ -134,9 +152,9 @@ pub enum BlockchainManagerResponse { /// Response to [`BlockchainManagerRequest::GenerateBlocks`] GenerateBlocks { - /// TODO + /// Hashes of the blocks generated. blocks: Vec<[u8; 32]>, - /// TODO + /// The new top height. (TODO: is this correct?) height: usize, }, diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 204b36ff2..a8ee552be 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -910,7 +910,9 @@ async fn add_aux_pow( mut state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { - let blocktemplate_blob = hex::decode(request.blocktemplate_blob)?; + let hex = hex::decode(request.blocktemplate_blob)?; + let block_template = Block::read(&mut hex.as_slice())?; + let aux_pow = request .aux_pow .into_iter() @@ -922,7 +924,7 @@ async fn add_aux_pow( .collect::, Error>>()?; let resp = - blockchain_manager::add_aux_pow(&mut state.blockchain_manager, blocktemplate_blob, aux_pow) + blockchain_manager::add_aux_pow(&mut state.blockchain_manager, block_template, aux_pow) .await?; let blocktemplate_blob = hex::encode(resp.blocktemplate_blob); diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 1ee702d6c..62eecdae3 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -172,14 +172,14 @@ pub(crate) async fn calculate_pow( /// [`BlockchainManagerRequest::AddAuxPow`] pub(crate) async fn add_aux_pow( blockchain_manager: &mut BlockchainManagerHandle, - blocktemplate_blob: Vec, + block_template: Block, aux_pow: Vec, ) -> Result { let BlockchainManagerResponse::AddAuxPow(response) = blockchain_manager .ready() .await? .call(BlockchainManagerRequest::AddAuxPow { - blocktemplate_blob, + block_template, aux_pow, }) .await? From 98dfaa4870f23b185239cbc83a5398395b896c8f Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 17 Oct 2024 17:13:37 -0400 Subject: [PATCH 34/47] docs, `ConnectionInfo`, `AddressType` --- .../cuprated/src/rpc/request/address_book.rs | 69 +++++++------ p2p/p2p-core/src/services.rs | 9 +- p2p/p2p-core/src/types.rs | 73 ++++++++++++-- rpc/types/src/misc/address_type.rs | 97 +++++++++++++++++++ rpc/types/src/misc/misc.rs | 2 +- rpc/types/src/misc/mod.rs | 2 + 6 files changed, 213 insertions(+), 39 deletions(-) create mode 100644 rpc/types/src/misc/address_type.rs diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index bd462209c..c3ffbd3c6 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -52,32 +52,45 @@ pub(crate) async fn connection_info( // FIXME: impl this map somewhere instead of inline. let vec = vec .into_iter() - .map(|info| ConnectionInfo { - address: info.address.to_string(), - address_type: info.address_type, - avg_download: info.avg_download, - avg_upload: info.avg_upload, - connection_id: info.connection_id, - current_download: info.current_download, - current_upload: info.current_upload, - height: info.height, - host: info.host, - incoming: info.incoming, - ip: info.ip, - live_time: info.live_time, - localhost: info.localhost, - local_ip: info.local_ip, - peer_id: info.peer_id, - port: info.port, - pruning_seed: info.pruning_seed, - recv_count: info.recv_count, - recv_idle_time: info.recv_idle_time, - rpc_credits_per_hash: info.rpc_credits_per_hash, - rpc_port: info.rpc_port, - send_count: info.send_count, - send_idle_time: info.send_idle_time, - state: info.state, - support_flags: info.support_flags, + .map(|info| { + use cuprate_p2p_core::types::AddressType as A1; + use cuprate_rpc_types::misc::AddressType as A2; + + let address_type = match info.address_type { + A1::Invalid => A2::Invalid, + A1::Ipv4 => A2::Ipv4, + A1::Ipv6 => A2::Ipv6, + A1::I2p => A2::I2p, + A1::Tor => A2::Tor, + }; + + ConnectionInfo { + address: info.address.to_string(), + address_type, + avg_download: info.avg_download, + avg_upload: info.avg_upload, + connection_id: hex::encode(info.connection_id.to_ne_bytes()), + current_download: info.current_download, + current_upload: info.current_upload, + height: info.height, + host: info.host, + incoming: info.incoming, + ip: info.ip, + live_time: info.live_time, + localhost: info.localhost, + local_ip: info.local_ip, + peer_id: info.peer_id, + port: info.port, + pruning_seed: info.pruning_seed.compress(), + recv_count: info.recv_count, + recv_idle_time: info.recv_idle_time, + rpc_credits_per_hash: info.rpc_credits_per_hash, + rpc_port: info.rpc_port, + send_count: info.send_count, + send_idle_time: info.send_idle_time, + state: info.state, + support_flags: info.support_flags, + } }) .collect(); @@ -177,10 +190,10 @@ pub(crate) async fn spans( let vec = vec .into_iter() .map(|span| Span { - connection_id: span.connection_id, + connection_id: hex::encode(span.connection_id.to_ne_bytes()), nblocks: span.nblocks, rate: span.rate, - remote_address: span.remote_address, + remote_address: span.remote_address.to_string(), size: span.size, speed: span.speed, start_block_height: span.start_block_height, diff --git a/p2p/p2p-core/src/services.rs b/p2p/p2p-core/src/services.rs index 6124e3e07..481f0243d 100644 --- a/p2p/p2p-core/src/services.rs +++ b/p2p/p2p-core/src/services.rs @@ -133,10 +133,13 @@ pub enum AddressBookRequest { /// Get the state of all bans. GetBans, - /// TODO + /// Get [`Span`] data. + /// + /// This is data that describes an active downloading process, + /// if we are fully synced, this will return an empty [`Vec`]. Spans, - /// TODO + /// Get the next [`PruningSeed`] needed for a pruned sync. NextNeededPruningSeed, } @@ -177,7 +180,7 @@ pub enum AddressBookResponse { GetBans(Vec>), /// Response to [`AddressBookRequest::Spans`]. - Spans(Vec), + Spans(Vec>), /// Response to [`AddressBookRequest::NextNeededPruningSeed`]. NextNeededPruningSeed(PruningSeed), diff --git a/p2p/p2p-core/src/types.rs b/p2p/p2p-core/src/types.rs index 4714f9e2c..eef3cb85d 100644 --- a/p2p/p2p-core/src/types.rs +++ b/p2p/p2p-core/src/types.rs @@ -2,6 +2,8 @@ use std::time::{Duration, Instant}; +use cuprate_pruning::PruningSeed; + use crate::NetZoneAddress; /// Data within [`crate::services::AddressBookRequest::SetBan`]. @@ -22,15 +24,72 @@ pub struct BanState { pub unban_instant: Option, } +/// An enumeration of address types. +/// +/// Used [`ConnectionInfo::address_type`]. +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(u8)] +pub enum AddressType { + #[default] + Invalid, + Ipv4, + Ipv6, + I2p, + Tor, +} + +impl AddressType { + /// Convert [`Self`] to a [`u8`]. + /// + /// ```rust + /// use cuprate_p2p_core::AddressType as A; + /// + /// assert_eq!(A::Invalid.to_u8(), 0); + /// assert_eq!(A::Ipv4.to_u8(), 1); + /// assert_eq!(A::Ipv6.to_u8(), 2); + /// assert_eq!(A::I2p.to_u8(), 3); + /// assert_eq!(A::Tor.to_u8(), 4); + /// ``` + pub const fn to_u8(self) -> u8 { + self as u8 + } + + /// Convert a [`u8`] to a [`Self`]. + /// + /// # Errors + /// This returns [`None`] if `u > 4`. + /// + /// ```rust + /// use cuprate_p2p_core::AddressType as A; + /// + /// assert_eq!(A::from_u8(0), Some(A::Invalid)); + /// assert_eq!(A::from_u8(1), Some(A::Ipv4)); + /// assert_eq!(A::from_u8(2), Some(A::Ipv6)); + /// assert_eq!(A::from_u8(3), Some(A::I2p)); + /// assert_eq!(A::from_u8(4), Some(A::Tor)); + /// assert_eq!(A::from_u8(5), None); + /// ``` + pub const fn from_u8(u: u8) -> Option { + Some(match u { + 0 => Self::Invalid, + 1 => Self::Ipv4, + 2 => Self::Ipv6, + 3 => Self::I2p, + 4 => Self::Tor, + _ => return None, + }) + } +} + // TODO: reduce fields and map to RPC type. // /// Data within [`crate::services::AddressBookResponse::ConnectionInfo`]. pub struct ConnectionInfo { pub address: A, - pub address_type: u8, + pub address_type: AddressType, pub avg_download: u64, pub avg_upload: u64, - pub connection_id: String, + pub connection_id: u64, // TODO: boost::uuids::uuid pub current_download: u64, pub current_upload: u64, pub height: u64, @@ -42,14 +101,14 @@ pub struct ConnectionInfo { pub local_ip: bool, pub peer_id: String, pub port: String, - pub pruning_seed: u32, + pub pruning_seed: PruningSeed, pub recv_count: u64, pub recv_idle_time: u64, pub rpc_credits_per_hash: u32, pub rpc_port: u16, pub send_count: u64, pub send_idle_time: u64, - pub state: String, + pub state: String, // TODO: what type is this? pub support_flags: u32, } @@ -57,11 +116,11 @@ pub struct ConnectionInfo { /// /// Data within [`crate::services::AddressBookResponse::Spans`]. #[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] -pub struct Span { - pub connection_id: String, +pub struct Span { + pub connection_id: u64, // TODO: boost::uuids::uuid pub nblocks: u64, pub rate: u32, - pub remote_address: String, + pub remote_address: A, pub size: u64, pub speed: u32, pub start_block_height: u64, diff --git a/rpc/types/src/misc/address_type.rs b/rpc/types/src/misc/address_type.rs new file mode 100644 index 000000000..ca9f83709 --- /dev/null +++ b/rpc/types/src/misc/address_type.rs @@ -0,0 +1,97 @@ +//! Types of network addresses; used in P2P. + +use cuprate_epee_encoding::Marker; + +#[cfg(feature = "serde")] +use serde::{Deserialize, Serialize}; + +#[cfg(feature = "epee")] +use cuprate_epee_encoding::{ + error, + macros::bytes::{Buf, BufMut}, + EpeeValue, +}; + +/// Used in [`crate::misc::ConnectionInfo::address_type`]. +#[doc = crate::macros::monero_definition_link!( + cc73fe71162d564ffda8e549b79a350bca53c454, + "epee/include/net/enums.h", + 39..=47 +)] +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", serde(untagged))] +#[repr(u8)] +pub enum AddressType { + #[default] + Invalid, + Ipv4, + Ipv6, + I2p, + Tor, +} + +impl AddressType { + /// Convert [`Self`] to a [`u8`]. + /// + /// ```rust + /// use cuprate_rpc_types::misc::AddressType as A; + /// + /// assert_eq!(A::Invalid.to_u8(), 0); + /// assert_eq!(A::Ipv4.to_u8(), 1); + /// assert_eq!(A::Ipv6.to_u8(), 2); + /// assert_eq!(A::I2p.to_u8(), 3); + /// assert_eq!(A::Tor.to_u8(), 4); + /// ``` + pub const fn to_u8(self) -> u8 { + self as u8 + } + + /// Convert a [`u8`] to a [`Self`]. + /// + /// # Errors + /// This returns [`None`] if `u > 4`. + /// + /// ```rust + /// use cuprate_rpc_types::misc::AddressType as A; + /// + /// assert_eq!(A::from_u8(0), Some(A::Invalid)); + /// assert_eq!(A::from_u8(1), Some(A::Ipv4)); + /// assert_eq!(A::from_u8(2), Some(A::Ipv6)); + /// assert_eq!(A::from_u8(3), Some(A::I2p)); + /// assert_eq!(A::from_u8(4), Some(A::Tor)); + /// assert_eq!(A::from_u8(5), None); + /// ``` + pub const fn from_u8(u: u8) -> Option { + Some(match u { + 0 => Self::Invalid, + 1 => Self::Ipv4, + 2 => Self::Ipv6, + 3 => Self::I2p, + 4 => Self::Tor, + _ => return None, + }) + } +} + +impl From for u8 { + fn from(value: AddressType) -> Self { + value.to_u8() + } +} + +#[cfg(feature = "epee")] +impl EpeeValue for AddressType { + const MARKER: Marker = u8::MARKER; + + fn read(r: &mut B, marker: &Marker) -> error::Result { + let u = u8::read(r, marker)?; + Self::from_u8(u).ok_or(error::Error::Format("u8 was greater than 4")) + } + + fn write(self, w: &mut B) -> error::Result<()> { + let u = self.to_u8(); + u8::write(u, w)?; + Ok(()) + } +} diff --git a/rpc/types/src/misc/misc.rs b/rpc/types/src/misc/misc.rs index 842997bc5..49fed6f78 100644 --- a/rpc/types/src/misc/misc.rs +++ b/rpc/types/src/misc/misc.rs @@ -110,7 +110,7 @@ define_struct_and_impl_epee! { /// Used in [`crate::json::GetConnectionsResponse`]. ConnectionInfo { address: String, - address_type: u8, + address_type: crate::misc::AddressType, avg_download: u64, avg_upload: u64, connection_id: String, diff --git a/rpc/types/src/misc/mod.rs b/rpc/types/src/misc/mod.rs index e09f84778..672d49354 100644 --- a/rpc/types/src/misc/mod.rs +++ b/rpc/types/src/misc/mod.rs @@ -12,6 +12,7 @@ )] //---------------------------------------------------------------------------------------------------- Mod +mod address_type; mod binary_string; mod distribution; mod key_image_spent_status; @@ -21,6 +22,7 @@ mod pool_info_extent; mod status; mod tx_entry; +pub use address_type::AddressType; pub use binary_string::BinaryString; pub use distribution::{Distribution, DistributionCompressedBinary, DistributionUncompressed}; pub use key_image_spent_status::KeyImageSpentStatus; From 13eedc6d800ed9d0857dd442ceffb6ca6cdaa5dd Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 17 Oct 2024 18:32:47 -0400 Subject: [PATCH 35/47] sig docs, remove `HardForks` request --- Cargo.lock | 1 + binaries/cuprated/Cargo.toml | 1 + binaries/cuprated/src/rpc/json.rs | 24 ++++++++++++------- .../cuprated/src/rpc/request/blockchain.rs | 16 ------------- storage/blockchain/src/service/read.rs | 6 ----- storage/txpool/src/service/interface.rs | 12 ++++++---- storage/txpool/src/tx.rs | 9 +++---- types/src/blockchain.rs | 19 ++++----------- 8 files changed, 36 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 089236a2d..76ad13f03 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1010,6 +1010,7 @@ dependencies = [ "serde", "serde_bytes", "serde_json", + "strum", "thiserror", "thread_local", "tokio", diff --git a/binaries/cuprated/Cargo.toml b/binaries/cuprated/Cargo.toml index 7ec857963..dc504d8d8 100644 --- a/binaries/cuprated/Cargo.toml +++ b/binaries/cuprated/Cargo.toml @@ -65,6 +65,7 @@ rayon = { workspace = true } serde_bytes = { workspace = true } serde_json = { workspace = true } serde = { workspace = true } +strum = { workspace = true } thiserror = { workspace = true } thread_local = { workspace = true } tokio-util = { workspace = true } diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index a8ee552be..ed0802960 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -5,7 +5,9 @@ use std::{ use anyhow::{anyhow, Error}; use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; +use futures::TryFutureExt; use monero_serai::block::Block; +use strum::{EnumCount, VariantArray}; use tower::{Service, ServiceExt}; use cuprate_consensus::{BlockchainReadRequest, BlockchainResponse}; @@ -673,14 +675,20 @@ async fn get_version( let current_height = helper::top_height(&mut state).await?.0; let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?; - let hard_forks = blockchain::hard_forks(&mut state.blockchain_read) - .await? - .into_iter() - .map(|(height, hf)| HardforkEntry { - height: usize_to_u64(height), - hf_version: hf.as_u8(), - }) - .collect(); + let mut hard_forks = Vec::with_capacity(HardFork::COUNT); + + // FIXME: use an iterator `collect()` version. + for hf in HardFork::VARIANTS { + if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await + { + let entry = HardforkEntry { + height: hf.earliest_height, + hf_version: hf.version, + }; + + hard_forks.push(entry); + } + } Ok(GetVersionResponse { base: ResponseBase::OK, diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 36f43fa98..97c7f48be 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -344,22 +344,6 @@ pub(crate) async fn coinbase_tx_sum( Ok(sum) } -/// [`BlockchainReadRequest::HardForks`] -pub(crate) async fn hard_forks( - blockchain_read: &mut BlockchainReadHandle, -) -> Result, Error> { - let BlockchainResponse::HardForks(hfs) = blockchain_read - .ready() - .await? - .call(BlockchainReadRequest::HardForks) - .await? - else { - unreachable!(); - }; - - Ok(hfs) -} - /// [`BlockchainReadRequest::AltChains`] pub(crate) async fn alt_chains( blockchain_read: &mut BlockchainReadHandle, diff --git a/storage/blockchain/src/service/read.rs b/storage/blockchain/src/service/read.rs index 76d44a275..e3c01802c 100644 --- a/storage/blockchain/src/service/read.rs +++ b/storage/blockchain/src/service/read.rs @@ -121,7 +121,6 @@ fn map_request( R::DatabaseSize => database_size(env), R::OutputHistogram(input) => output_histogram(env, input), R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), - R::HardForks => hard_forks(env), R::AltChains => alt_chains(env), R::AltChainCount => alt_chain_count(env), } @@ -652,11 +651,6 @@ fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResu Ok(BlockchainResponse::CoinbaseTxSum(todo!())) } -/// [`BlockchainReadRequest::HardForks`] -fn hard_forks(env: &ConcreteEnv) -> ResponseResult { - Ok(BlockchainResponse::HardForks(todo!())) -} - /// [`BlockchainReadRequest::AltChains`] fn alt_chains(env: &ConcreteEnv) -> ResponseResult { Ok(BlockchainResponse::AltChains(todo!())) diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 394162a04..931154e11 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -22,12 +22,16 @@ pub enum TxpoolReadRequest { /// Get information on all transactions in the pool. Backlog, - /// TODO + /// Get information on all transactions in + /// the pool for block template purposes. + /// + /// This is only slightly different to [`TxpoolReadRequest::Backlog`]. BlockTemplateBacklog, /// Get the number of transactions in the pool. Size { - /// TODO + /// If this is [`true`], the size returned will + /// include private transactions in the pool. include_sensitive_txs: bool, }, } @@ -47,13 +51,13 @@ pub enum TxpoolReadResponse { /// Response to [`TxpoolReadRequest::Backlog`]. /// - /// The inner `Vec` contains information on all + /// The inner [`Vec`] contains information on all /// the transactions currently in the pool. Backlog(Vec), /// Response to [`TxpoolReadRequest::BlockTemplateBacklog`]. /// - /// TODO + /// The inner [`Vec`] contains information on transactions BlockTemplateBacklog(Vec), /// Response to [`TxpoolReadRequest::Size`]. diff --git a/storage/txpool/src/tx.rs b/storage/txpool/src/tx.rs index 7daff1562..03cc48c48 100644 --- a/storage/txpool/src/tx.rs +++ b/storage/txpool/src/tx.rs @@ -13,15 +13,16 @@ pub struct TxEntry { pub time_in_pool: std::time::Duration, } -/// TODO +/// Data about a transaction in the pool +/// for use in a block template. /// /// Used in [`TxpoolReadResponse::BlockTemplateBacklog`](crate::service::interface::TxpoolReadResponse::BlockTemplateBacklog). #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] pub struct BlockTemplateTxEntry { - /// TODO + /// The transaction's ID (hash). pub id: [u8; 32], - /// TODO + /// The transaction's weight. pub weight: u64, - /// TODO + /// The transaction's fee. pub fee: u64, } diff --git a/types/src/blockchain.rs b/types/src/blockchain.rs index 49fec0732..c39c0bd8b 100644 --- a/types/src/blockchain.rs +++ b/types/src/blockchain.rs @@ -4,7 +4,7 @@ //! responses are also tested in Cuprate's blockchain database crate. //---------------------------------------------------------------------------------------------------- Import use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{HashMap, HashSet}, ops::Range, }; @@ -12,7 +12,7 @@ use monero_serai::block::Block; use crate::{ types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, - AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, HardFork, OutputHistogramEntry, + AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, OutputHistogramEntry, OutputHistogramInput, }; @@ -130,13 +130,10 @@ pub enum BlockchainReadRequest { /// TODO: document fields after impl. CoinbaseTxSum { height: usize, count: u64 }, - /// TODO - HardForks, - - /// TODO + /// Get information on all alternative chains. AltChains, - /// TODO + /// Get the amount of alternative chains that exist. AltChainCount, } @@ -286,13 +283,7 @@ pub enum BlockchainResponse { /// Response to [`BlockchainReadRequest::CoinbaseTxSum`]. CoinbaseTxSum(CoinbaseTxSum), - /// Response to [`BlockchainReadRequest::HardForks`]. - /// - /// - Key = height at which the hardfork activated - /// - Value = hardfork version - HardForks(BTreeMap), - - /// TODO + /// Response to [`BlockchainReadRequest::AltChains`]. AltChains(Vec), /// Response to [`BlockchainReadRequest::AltChainCount`]. From 0cb6a76fc282d34b314509966626305fc989b273 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Tue, 12 Nov 2024 20:06:13 -0500 Subject: [PATCH 36/47] clean imports --- Cargo.lock | 312 +++++++++--------- binaries/cuprated/src/rpc/handler.rs | 5 +- binaries/cuprated/src/rpc/helper.rs | 17 +- binaries/cuprated/src/rpc/json.rs | 12 +- .../cuprated/src/rpc/request/address_book.rs | 9 +- .../cuprated/src/rpc/request/blockchain.rs | 8 +- .../src/rpc/request/blockchain_context.rs | 2 - .../src/rpc/request/blockchain_manager.rs | 6 +- 8 files changed, 170 insertions(+), 201 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 25ebf0967..61c4725f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.24.2" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -46,15 +46,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.10" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anyhow" -version = "1.0.92" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" [[package]] name = "arrayref" @@ -70,9 +70,9 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "async-stream" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", @@ -81,9 +81,9 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.6" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", @@ -92,9 +92,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.83" +version = "0.1.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +checksum = "a27b8a3a6e1a44fa4c8baf1f653e4172e81486d4941f2237e20dc2d0cf4ddff1" dependencies = [ "proc-macro2", "quote", @@ -109,15 +109,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.4.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "axum" -version = "0.7.7" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" dependencies = [ "async-trait", "axum-core", @@ -141,7 +141,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper 1.0.1", "tokio", - "tower 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tower 0.4.13", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -149,9 +149,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.4.5" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" dependencies = [ "async-trait", "bytes", @@ -162,7 +162,7 @@ dependencies = [ "mime", "pin-project-lite", "rustversion", - "sync_wrapper 1.0.1", + "sync_wrapper 0.1.2", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", @@ -304,18 +304,18 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "94bbb0ad554ad961ddc5da507a12a29b14e4ae5bda06b19f575a3e6079d2e2ae" dependencies = [ "bytemuck_derive", ] [[package]] name = "bytemuck_derive" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcfcc3cd946cb52f0bbfdbbcfa2f4e24f75ebb6c0e1002f7c25904fada18b9ec" +checksum = "0cc8b54b395f2fcfbb3d90c47b01c7f444d94d05bdeb775811dec868ac3bbc26" dependencies = [ "proc-macro2", "quote", @@ -330,18 +330,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.8.0" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.1.31" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "shlex", ] @@ -372,9 +372,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3e5a21b8495e732f1b3c364c9949b201ca7bae518c502c80256c96ad79eaf6ac" dependencies = [ "clap_builder", "clap_derive", @@ -382,9 +382,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "8cf2dd12af7a047ad9d6da2b6b249759a22a7abc0f474c1dae1777afa4b21a73" dependencies = [ "anstyle", "clap_lex", @@ -392,9 +392,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.18" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck", "proc-macro2", @@ -559,7 +559,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -598,7 +598,7 @@ dependencies = [ "tempfile", "thread_local", "tokio", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", ] [[package]] @@ -624,7 +624,7 @@ dependencies = [ "thread_local", "tokio", "tokio-test", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -644,7 +644,7 @@ dependencies = [ "thread_local", "tokio", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -701,7 +701,7 @@ dependencies = [ "thiserror", "tokio", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -731,7 +731,7 @@ dependencies = [ "futures", "rayon", "serde", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", ] [[package]] @@ -764,7 +764,7 @@ dependencies = [ "sha3", "thiserror", "tokio", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", ] [[package]] @@ -851,7 +851,7 @@ dependencies = [ "tokio-stream", "tokio-test", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -883,7 +883,7 @@ dependencies = [ "tokio-stream", "tokio-test", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", ] @@ -912,7 +912,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "ureq", ] @@ -974,7 +974,7 @@ dependencies = [ "tempfile", "thiserror", "tokio", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", ] [[package]] @@ -1078,7 +1078,7 @@ dependencies = [ "tokio", "tokio-stream", "tokio-util", - "tower 0.5.1 (git+https://github.com/Cuprate/tower.git?rev=6c7faf0)", + "tower 0.5.1", "tracing", "tracing-subscriber", ] @@ -1136,7 +1136,7 @@ checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ "cfg-if", "crossbeam-utils", - "hashbrown 0.14.5", + "hashbrown", "lock_api", "once_cell", "parking_lot_core", @@ -1249,9 +1249,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "324a1be68054ef05ad64b861cc9eaf1d623d2d8cb25b4bf2cb9cdd902b4bf253" dependencies = [ "crc32fast", "miniz_oxide", @@ -1293,9 +1293,9 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futures" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1307,9 +1307,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1317,21 +1317,21 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", @@ -1340,21 +1340,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1391,9 +1391,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.31.1" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "groestl" @@ -1443,12 +1443,6 @@ dependencies = [ "ahash", ] -[[package]] -name = "hashbrown" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" - [[package]] name = "heck" version = "0.5.0" @@ -1550,9 +1544,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.9.5" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -1562,9 +1556,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "1.5.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", @@ -1601,9 +1595,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "da62f120a8a37763efb0cf8fdf264b884c7b8b9ac8660b900c8661030c00e6ba" dependencies = [ "bytes", "futures-channel", @@ -1614,6 +1608,7 @@ dependencies = [ "pin-project-lite", "socket2", "tokio", + "tower 0.4.13", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tracing", ] @@ -1653,12 +1648,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown", ] [[package]] @@ -1680,9 +1675,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" dependencies = [ "wasm-bindgen", ] @@ -1704,15 +1699,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libm" -version = "0.2.11" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "libredox" @@ -1999,18 +1994,18 @@ dependencies = [ [[package]] name = "object" -version = "0.36.5" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.20.2" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl-probe" @@ -2119,18 +2114,18 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.7" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.7" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", @@ -2139,9 +2134,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.15" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2202,9 +2197,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -2342,18 +2337,18 @@ dependencies = [ [[package]] name = "redb" -version = "2.2.0" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b1de48a7cf7ba193e81e078d17ee2b786236eed1d3f7c60f8a09545efc4925" +checksum = "e4760ad04a88ef77075ba86ba9ea79b919e6bab29c1764c5747237cd6eaedcaa" dependencies = [ "libc", ] [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "0884ad60e090bf1345b93da0a5de8923c93884cd03f40dfcfddd3b4bee661853" dependencies = [ "bitflags 2.6.0", ] @@ -2391,9 +2386,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.5" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "ring" @@ -2427,9 +2422,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -2440,9 +2435,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.16" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "log", "once_cell", @@ -2468,18 +2463,19 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.2.0" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +checksum = "196fe16b00e106300d3e45ecfcb764fa292a535d7326a29a5875c579c7417425" dependencies = [ + "base64", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.10.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16f1201b3c9a7ee8039bcadc17b7e605e2945b27eee7631788c1bd2b0643674b" +checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" @@ -2494,9 +2490,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.18" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -2518,9 +2514,9 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "schannel" -version = "0.1.26" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01227be5826fa0690321a2ba6c5cd57a19cf3f6a09e76973b58e61de6ab9d1c1" +checksum = "e9aaafd5a2b6e3d657ff009d82fbd630b6bd54dd4eb06f21693925cdf80f9b8b" dependencies = [ "windows-sys 0.59.0", ] @@ -2546,9 +2542,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.12.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea4a292869320c0272d7bc55a5a6aafaff59b4f63404a003887b679a2e05b4b6" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" dependencies = [ "core-foundation-sys", "libc", @@ -2568,9 +2564,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" dependencies = [ "serde_derive", ] @@ -2586,9 +2582,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.210" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" dependencies = [ "proc-macro2", "quote", @@ -2597,9 +2593,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" dependencies = [ "itoa", "memchr", @@ -2739,7 +2735,7 @@ name = "std-shims" version = "0.1.1" source = "git+https://github.com/Cuprate/serai.git?rev=d5205ce#d5205ce2319e09414eb91d12cf38e83a08165f79" dependencies = [ - "hashbrown 0.14.5", + "hashbrown", "spin", ] @@ -2773,9 +2769,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.86" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89275301d38033efb81a6e60e3497e734dfcc62571f2854bf4b16690398824c" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -2823,9 +2819,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.13.0" +version = "3.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" dependencies = [ "cfg-if", "fastrand", @@ -2836,18 +2832,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -2887,9 +2883,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.41.0" +version = "1.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" dependencies = [ "backtrace", "bytes", @@ -2973,9 +2969,9 @@ checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" [[package]] name = "toml_edit" -version = "0.22.22" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "toml_datetime", @@ -2984,14 +2980,14 @@ dependencies = [ [[package]] name = "tower" -version = "0.5.1" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "pin-project", "pin-project-lite", - "sync_wrapper 0.1.2", "tokio", "tower-layer 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tower-service 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3114,9 +3110,9 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-bidi" -version = "0.3.17" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3212,9 +3208,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" dependencies = [ "cfg-if", "once_cell", @@ -3223,9 +3219,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" dependencies = [ "bumpalo", "log", @@ -3238,9 +3234,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3248,9 +3244,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" dependencies = [ "proc-macro2", "quote", @@ -3261,15 +3257,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" [[package]] name = "webpki-roots" -version = "0.26.6" +version = "0.26.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841c67bff177718f1d4dfefde8d8f0e78f9b6589319ba88312f567fc5841a958" +checksum = "0bd24728e5af82c6c4ec1b66ac4844bdf8156257fccda846ec58b42cd0cdbe6a" dependencies = [ "rustls-pki-types", ] @@ -3519,9 +3515,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.20" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index b0d54ab83..b2bcc0237 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -7,7 +7,7 @@ use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; -use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle}; +use cuprate_blockchain::service::BlockchainReadHandle; use cuprate_consensus::BlockChainContextService; use cuprate_pruning::PruningSeed; use cuprate_rpc_interface::RpcHandler; @@ -16,8 +16,7 @@ use cuprate_rpc_types::{ json::{JsonRpcRequest, JsonRpcResponse}, other::{OtherRequest, OtherResponse}, }; -use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle}; -use cuprate_types::{AddAuxPow, AuxPow, HardFork}; +use cuprate_txpool::service::TxpoolReadHandle; use crate::rpc::{bin, json, other}; diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index dec5d79eb..fe79c08e0 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -5,23 +5,12 @@ //! //! These build on-top of [`crate::rpc::request`] functions. -use std::sync::Arc; - use anyhow::{anyhow, Error}; -use futures::StreamExt; use monero_serai::block::Block; -use tower::{Service, ServiceExt}; - -use cuprate_consensus::BlockchainResponse; -use cuprate_constants::rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}; -use cuprate_helper::{ - cast::{u64_to_usize, usize_to_u64}, - map::split_u128_into_low_high_bits, -}; + +use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits}; use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus}; -use cuprate_types::{ - blockchain::BlockchainReadRequest, Chain, ExtendedBlockHeader, VerifiedBlockInformation, -}; +use cuprate_types::ExtendedBlockHeader; use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler}; diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index c66025708..3a3297a5d 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,10 +1,6 @@ -use std::{ - sync::Arc, - time::{Duration, Instant}, -}; +use std::time::{Duration, Instant}; use anyhow::{anyhow, Error}; -use futures::TryFutureExt; use monero_serai::block::Block; use strum::{EnumCount, VariantArray}; use tower::{Service, ServiceExt}; @@ -43,12 +39,12 @@ use cuprate_rpc_types::{ SyncInfoResponse, }, misc::{ - AuxPow, BlockHeader, ChainInfo, GetBan, GetMinerDataTxBacklogEntry, HardforkEntry, - HistogramEntry, Status, SyncInfoPeer, TxBacklogEntry, + AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, + SyncInfoPeer, TxBacklogEntry, }, CORE_RPC_VERSION, }; -use cuprate_types::{Chain, HardFork}; +use cuprate_types::HardFork; use crate::{ constants::VERSION_BUILD, diff --git a/binaries/cuprated/src/rpc/request/address_book.rs b/binaries/cuprated/src/rpc/request/address_book.rs index 9d71b51cc..fd2c0b1a6 100644 --- a/binaries/cuprated/src/rpc/request/address_book.rs +++ b/binaries/cuprated/src/rpc/request/address_book.rs @@ -1,7 +1,5 @@ //! Functions for TODO: doc enum message. -use std::convert::Infallible; - use anyhow::{anyhow, Error}; use tower::ServiceExt; @@ -11,12 +9,7 @@ use cuprate_p2p_core::{ types::{BanState, ConnectionId}, AddressBook, NetworkZone, }; -use cuprate_pruning::PruningSeed; -use cuprate_rpc_types::misc::{ConnectionInfo, Span}; - -use crate::rpc::constants::FIELD_NOT_SUPPORTED; - -// FIXME: use `anyhow::Error` over `tower::BoxError` in address book. +use cuprate_rpc_types::misc::ConnectionInfo; // FIXME: use `anyhow::Error` over `tower::BoxError` in address book. diff --git a/binaries/cuprated/src/rpc/request/blockchain.rs b/binaries/cuprated/src/rpc/request/blockchain.rs index 97c7f48be..537994401 100644 --- a/binaries/cuprated/src/rpc/request/blockchain.rs +++ b/binaries/cuprated/src/rpc/request/blockchain.rs @@ -1,7 +1,7 @@ //! Functions for [`BlockchainReadRequest`]. use std::{ - collections::{BTreeMap, HashMap, HashSet}, + collections::{HashMap, HashSet}, ops::Range, }; @@ -9,12 +9,12 @@ use anyhow::Error; use monero_serai::block::Block; use tower::{Service, ServiceExt}; -use cuprate_blockchain::{service::BlockchainReadHandle, types::AltChainInfo}; +use cuprate_blockchain::service::BlockchainReadHandle; use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_types::{ blockchain::{BlockchainReadRequest, BlockchainResponse}, - Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData, - OutputHistogramEntry, OutputHistogramInput, OutputOnChain, + Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, OutputHistogramEntry, + OutputHistogramInput, OutputOnChain, }; /// [`BlockchainReadRequest::Block`]. diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index c6f0f2259..73ae3c0c5 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -1,7 +1,5 @@ //! Functions for [`BlockChainContextRequest`] and [`BlockChainContextResponse`]. -use std::convert::Infallible; - use anyhow::{anyhow, Error}; use monero_serai::block::Block; use tower::{Service, ServiceExt}; diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 18b75debd..4b5912147 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -8,11 +8,9 @@ use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_p2p_core::{types::ConnectionId, NetworkZone}; use cuprate_pruning::PruningSeed; use cuprate_rpc_types::misc::Span; -use cuprate_types::{AddAuxPow, AuxPow, HardFork}; -use crate::rpc::{ - constants::FIELD_NOT_SUPPORTED, - handler::{BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse}, +use crate::rpc::handler::{ + BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, }; /// [`BlockchainManagerRequest::PopBlocks`] From e30eeb8a358ef54f17b3a47d6e1e7165fcc45b48 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 13 Nov 2024 16:53:28 -0500 Subject: [PATCH 37/47] fix `on_get_block_hash`, `generate_blocks`, `get_block_headers_range` --- binaries/cuprated/src/rpc/bin.rs | 2 + binaries/cuprated/src/rpc/handler.rs | 2 +- binaries/cuprated/src/rpc/helper.rs | 2 +- binaries/cuprated/src/rpc/json.rs | 64 +++++++++++++++++----------- binaries/cuprated/src/rpc/other.rs | 2 + 5 files changed, 45 insertions(+), 27 deletions(-) diff --git a/binaries/cuprated/src/rpc/bin.rs b/binaries/cuprated/src/rpc/bin.rs index b4e676dcc..70d8c63ff 100644 --- a/binaries/cuprated/src/rpc/bin.rs +++ b/binaries/cuprated/src/rpc/bin.rs @@ -1,3 +1,5 @@ +//! RPC request handler functions (binary endpoints). + use anyhow::Error; use cuprate_rpc_types::{ diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index b2bcc0237..fd9be38f0 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -1,4 +1,4 @@ -//! Dummy implementation of [`RpcHandler`]. +//! `cuprated`'s implementation of [`RpcHandler`]. use std::task::{Context, Poll}; diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index fe79c08e0..f3b7164c9 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -14,7 +14,7 @@ use cuprate_types::ExtendedBlockHeader; use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler}; -fn into_block_header( +pub(super) fn into_block_header( height: u64, top_height: u64, fill_pow_hash: bool, diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 3a3297a5d..91b9b0b33 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,3 +1,5 @@ +//! RPC request handler functions (JSON-RPC). + use std::time::{Duration, Instant}; use anyhow::{anyhow, Error}; @@ -131,8 +133,12 @@ async fn on_get_block_hash( request: OnGetBlockHashRequest, ) -> Result { let [height] = request.block_height; - let hash = blockchain::block_hash(&mut state.blockchain_read, height, todo!("access to chain")) - .await?; + let hash = blockchain::block_hash( + &mut state.blockchain_read, + height, + todo!("access to `cuprated`'s Chain"), + ) + .await?; let block_hash = hex::encode(hash); Ok(OnGetBlockHashResponse { block_hash }) @@ -167,8 +173,9 @@ async fn generate_blocks( return Err(anyhow!("Regtest required when generating blocks")); } - // TODO: is this value only used as a local variable in the handler? - // it may not be needed in the request type. + // FIXME: + // is this field only used as a local variable in the handler in `monerod`? + // It may not be needed in the request type. let prev_block = helper::hex_to_hash(request.prev_block)?; let (blocks, height) = blockchain_manager::generate_blocks( @@ -269,32 +276,39 @@ async fn get_block_headers_range( return Err(anyhow!("Invalid start/end heights")); } - if state.restricted() - && request.end_height.saturating_sub(request.start_height) + 1 - > RESTRICTED_BLOCK_HEADER_RANGE - { + let too_many_blocks = || { + request.end_height.saturating_sub(request.start_height) + 1 > RESTRICTED_BLOCK_HEADER_RANGE + }; + + if state.restricted() && too_many_blocks() { return Err(anyhow!("Too many block headers requested.")); } - let block_len = u64_to_usize(request.end_height.saturating_sub(request.start_height)); - let mut tasks = Vec::with_capacity(block_len); - let mut headers = Vec::with_capacity(block_len); + // FIXME: + // This code currently: + // 1. requests a specific `(Block, BlockHeader)` + // 2. maps them to the RPC type + // 3. pushes them to the a `Vec` sequentially + // + // It could be more efficient by: + // 1. requesting all `(Block, Header)`s in the range at once + // 2. mapping all at once and collect into a `Vec` + // + // This isn't currently possible because there + // is no internal request for a range of blocks. + + let (range, expected_len) = { + let start = u64_to_usize(request.start_height); + let end = u64_to_usize(request.end_height).saturating_add(1); + (start..end, end.saturating_sub(start)) + }; - { - let ready = state.blockchain_read.ready().await?; - for height in request.start_height..=request.end_height { - let height = u64_to_usize(height); - let task = tokio::task::spawn(ready.call(BlockchainReadRequest::Block { height })); - tasks.push(task); - } - } + let mut headers = Vec::with_capacity(expected_len); - for task in tasks { - let BlockchainResponse::Block(header) = task.await?? else { - unreachable!(); - }; - // headers.push((&header).into()); - headers.push(todo!()); + for height in range { + let height = usize_to_u64(height); + let header = helper::block_header(&mut state, height, request.fill_pow_hash).await?; + headers.push(header); } Ok(GetBlockHeadersRangeResponse { diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs index 16b58c41e..a67774fbd 100644 --- a/binaries/cuprated/src/rpc/other.rs +++ b/binaries/cuprated/src/rpc/other.rs @@ -1,3 +1,5 @@ +//! RPC request handler functions (other JSON endpoints). + use anyhow::Error; use cuprate_rpc_types::other::{ From 228a718e04922663fa2831e17c0883619e40970c Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 13 Nov 2024 17:35:35 -0500 Subject: [PATCH 38/47] fix `get_info`, `banned` --- binaries/cuprated/src/rpc/json.rs | 48 ++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 91b9b0b33..ecb60b85f 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -16,7 +16,7 @@ use cuprate_helper::{ cast::{u64_to_usize, usize_to_u64}, map::split_u128_into_low_high_bits, }; -use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet}; +use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet, Network}; use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_types::{ base::{AccessResponseBase, ResponseBase}, @@ -400,7 +400,11 @@ async fn get_info( split_u128_into_low_high_bits(cumulative_difficulty); let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?; let (database_size, free_space) = if restricted { - let database_size = todo!(); // round_up(res.database_size, 5ull* 1024 * 1024 * 1024) */ + // + fn round_up(value: u64, quantum: u64) -> u64 { + (value + quantum - 1) / quantum * quantum + } + let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024); (database_size, u64::MAX) } else { (database_size, free_space) @@ -413,22 +417,37 @@ async fn get_info( } else { address_book::connection_count::(&mut DummyAddressBook).await? }; - let mainnet = todo!(); - let nettype = todo!(); - let offline = todo!(); - let rpc_connections_count = if restricted { 0 } else { todo!() }; - let stagenet = todo!(); + let (mainnet, testnet, stagenet) = match todo!("access to `cuprated`'s `Network`") { + Network::Mainnet => (true, false, false), + Network::Testnet => (false, true, false), + Network::Stagenet => (false, false, true), + }; + // TODO: make sure this is: + // - the same case as `monerod` + // - untagged (no `Network::`) + let nettype = todo!("access to `cuprated`'s `Network`").to_string(); + let offline = todo!("access to CLI/config's `--offline`"); + let rpc_connections_count = if restricted { + 0 + } else { + todo!( + "implement a connection counter in axum/RPC, maybe `AtomicU64` any handler activating" + ) + }; let start_time = if restricted { 0 } else { *START_INSTANT_UNIX }; let synchronized = blockchain_manager::synced(&mut state.blockchain_manager).await?; let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?; let target = blockchain_manager::target(&mut state.blockchain_manager) .await? .as_secs(); - let testnet = todo!(); let top_block_hash = hex::encode(c.top_hash); let tx_count = blockchain::total_tx_count(&mut state.blockchain_read).await?; let tx_pool_size = txpool::size(&mut state.txpool_read, !restricted).await?; - let update_available = if restricted { false } else { todo!() }; + let update_available = if restricted { + false + } else { + todo!("implement an update checker for `cuprated`") + }; let version = if restricted { String::new() } else { @@ -580,7 +599,16 @@ async fn banned( state: CupratedRpcHandler, request: BannedRequest, ) -> Result { - let peer = todo!("create Z::Addr from request.address"); + let peer = match request.address.parse::() { + Ok(p) => p, + Err(e) => { + return Err(anyhow!( + "Failed to parse address: {} ({e})", + request.address + )) + } + }; + let ban = address_book::get_ban::(&mut DummyAddressBook, peer).await?; let (banned, seconds) = if let Some(instant) = ban { From 9374d08a07b0f58aa7251f42268a62f8d22fd7fe Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 13 Nov 2024 17:44:45 -0500 Subject: [PATCH 39/47] fix `sync_info` --- binaries/cuprated/src/rpc/json.rs | 25 ++++++++++--------- .../src/rpc/request/blockchain_manager.rs | 3 ++- 2 files changed, 15 insertions(+), 13 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index ecb60b85f..07b96a621 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -58,6 +58,8 @@ use crate::{ statics::START_INSTANT_UNIX, }; +use super::constants::FIELD_NOT_SUPPORTED; + /// Map a [`JsonRpcRequest`] to the function that will lead to a [`JsonRpcResponse`]. pub(super) async fn map_request( state: CupratedRpcHandler, @@ -715,7 +717,7 @@ async fn get_version( let mut hard_forks = Vec::with_capacity(HardFork::COUNT); - // FIXME: use an iterator `collect()` version. + // FIXME: use an async iterator `collect()` version. for hf in HardFork::VARIANTS { if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await { @@ -822,16 +824,15 @@ async fn sync_info( .map(|info| SyncInfoPeer { info }) .collect(); - // TODO - // let next_needed_pruning_seed = - // address_book::next_needed_pruning_seed::(&mut DummyAddressBook) - // .await? - // .compress(); - // let overview = blockchain_manager::overview(&mut state.blockchain_manager, height).await?; - // let spans = address_book::spans::(&mut DummyAddressBook).await?; - let next_needed_pruning_seed = todo!(); - let overview = todo!(); - let spans = todo!(); + let next_needed_pruning_seed = + blockchain_manager::next_needed_pruning_seed(&mut state.blockchain_manager) + .await? + .compress(); + + let spans = blockchain_manager::spans::(&mut state.blockchain_manager).await?; + + // + let overview = String::from(FIELD_NOT_SUPPORTED); Ok(SyncInfoResponse { base: AccessResponseBase::OK, @@ -1009,7 +1010,7 @@ async fn get_tx_ids_loose( request: GetTxIdsLooseRequest, ) -> Result { // TODO: this RPC call is not yet in the v0.18 branch. - return Err(anyhow!("not implemented")); + return Err(anyhow!("Not implemented")); Ok(GetTxIdsLooseResponse { base: ResponseBase::OK, diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index 4b5912147..ed72284a3 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -183,7 +183,8 @@ pub(crate) async fn spans( // unreachable!(); // }; - let vec: Vec> = todo!(); + let vec: Vec> = + todo!("waiting on blockchain downloader/syncer: "); // FIXME: impl this map somewhere instead of inline. let vec = vec From fd84940ee69c971b6d7427f4467817719390e16e Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Wed, 13 Nov 2024 18:01:30 -0500 Subject: [PATCH 40/47] fix `get_miner_data` --- binaries/cuprated/src/rpc/json.rs | 40 +++++++++++++++---------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 07b96a621..09c3b435e 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -41,8 +41,8 @@ use cuprate_rpc_types::{ SyncInfoResponse, }, misc::{ - AuxPow, BlockHeader, ChainInfo, GetBan, HardforkEntry, HistogramEntry, Status, - SyncInfoPeer, TxBacklogEntry, + AuxPow, BlockHeader, ChainInfo, GetBan, GetMinerDataTxBacklogEntry, HardforkEntry, + HistogramEntry, Status, SyncInfoPeer, TxBacklogEntry, }, CORE_RPC_VERSION, }; @@ -872,24 +872,24 @@ async fn get_miner_data( request: GetMinerDataRequest, ) -> Result { let context = blockchain_context::context(&mut state.blockchain_context).await?; - let context = context.unchecked_blockchain_context(); - let major_version = context.current_hf.as_u8(); - let height = usize_to_u64(context.chain_height); - let prev_id = hex::encode(context.top_hash); - let seed_hash = todo!(); - let difficulty = format!("{:#x}", context.next_difficulty); - let median_weight = usize_to_u64(context.median_weight_for_block_reward); - let already_generated_coins = context.already_generated_coins; - let tx_backlog = todo!(); - // let tx_backlog = txpool::block_template_backlog(&mut state.txpool_read) - // .await? - // .into_iter() - // .map(|entry| GetMinerDataTxBacklogEntry { - // id: hex::encode(entry.id), - // weight: entry.weight, - // fee: entry.fee, - // }) - // .collect(); + let c = context.unchecked_blockchain_context(); + + let major_version = c.current_hf.as_u8(); + let height = usize_to_u64(c.chain_height); + let prev_id = hex::encode(c.top_hash); + let seed_hash = hex::encode(c.top_hash); + let difficulty = format!("{:#x}", c.next_difficulty); + let median_weight = usize_to_u64(c.median_weight_for_block_reward); + let already_generated_coins = c.already_generated_coins; + let tx_backlog = txpool::backlog(&mut state.txpool_read) + .await? + .into_iter() + .map(|entry| GetMinerDataTxBacklogEntry { + id: hex::encode(entry.id), + weight: entry.weight, + fee: entry.fee, + }) + .collect(); Ok(GetMinerDataResponse { base: ResponseBase::OK, From 46bf19861a01e1cf785bd610b774509d0958f8e7 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 14 Nov 2024 17:03:15 -0500 Subject: [PATCH 41/47] initial `add_aux_pow` impl --- binaries/cuprated/src/rpc/json.rs | 168 +++++++++++++++++++++++++++--- 1 file changed, 152 insertions(+), 16 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 09c3b435e..faccde05b 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -13,7 +13,7 @@ use cuprate_constants::{ rpc::{RESTRICTED_BLOCK_COUNT, RESTRICTED_BLOCK_HEADER_RANGE}, }; use cuprate_helper::{ - cast::{u64_to_usize, usize_to_u64}, + cast::{u32_to_usize, u64_to_usize, usize_to_u64}, map::split_u128_into_low_high_bits, }; use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet, Network}; @@ -403,7 +403,7 @@ async fn get_info( let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?; let (database_size, free_space) = if restricted { // - fn round_up(value: u64, quantum: u64) -> u64 { + const fn round_up(value: u64, quantum: u64) -> u64 { (value + quantum - 1) / quantum * quantum } let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024); @@ -964,8 +964,9 @@ async fn add_aux_pow( mut state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { - let hex = hex::decode(request.blocktemplate_blob)?; - let block_template = Block::read(&mut hex.as_slice())?; + if request.aux_pow.is_empty() { + return Err(anyhow!("Empty `aux_pow` vector")); + } let aux_pow = request .aux_pow @@ -975,31 +976,166 @@ async fn add_aux_pow( let hash = helper::hex_to_hash(aux.hash)?; Ok(cuprate_types::AuxPow { id, hash }) }) - .collect::, Error>>()?; + .collect::, Error>>()?; + // Some of the code below requires that the + // `.len()` of certain containers are the same. + // Boxed slices are used over `Vec` to slightly + // safe-guard against accidently pushing to it. - let resp = todo!(); - // let resp = - // blockchain_manager::add_aux_pow(&mut state.blockchain_manager, block_template, aux_pow) - // .await?; + // --- BEGIN AUX POW IMPL --- - let blocktemplate_blob = hex::encode(resp.blocktemplate_blob); - let blockhashing_blob = hex::encode(resp.blockhashing_blob); - let merkle_root = hex::encode(resp.merkle_root); - let aux_pow = resp - .aux_pow - .into_iter() + // Original impl: + // + + let len = aux_pow.len(); + + let mut path_domain = 1_usize; + while 1 << path_domain < len { + path_domain += 1; + } + + let nonce = 0_u32; + let mut collision = true; + let mut slots: Box<[u32]> = vec![0; len].into_boxed_slice(); // INVARIANT: this must be the same `.len()` as `aux_pow` + + for nonce in 0..u32::MAX { + let slot_seen: Vec = vec![false; len]; + + collision = false; + + slots.iter_mut().for_each(|i| *i = u32::MAX); + + for i in &mut slots { + let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());"); + let slot = u32_to_usize(slot_u32); + + if slot >= len { + return Err(anyhow!("Computed slot is out of range")); + } + + if slot_seen[slot] { + collision = true; + break; + } + + slot_seen[slot] = true; + *i = slot_u32; + } + + if !collision { + break; + } + } + + if collision { + return Err(anyhow!("Failed to find a suitable nonce")); + } + + let slots = slots; + + // FIXME: use iterator version. + let (aux_pow_id_raw, aux_pow_raw) = { + let mut aux_pow_id_raw = Vec::<[u8; 32]>::with_capacity(len); + let mut aux_pow_raw = Vec::<[u8; 32]>::with_capacity(len); + + assert_eq!( + aux_pow.len(), + slots.len(), + "these need to be the same or else the below .zip() doesn't make sense" + ); + + for (aux_pow, slot) in aux_pow.iter().zip(&slots) { + if u32_to_usize(*slot) >= len { + return Err(anyhow!("Slot value out of range")); + } + + aux_pow_id_raw.push(aux_pow.id); + aux_pow_raw.push(aux_pow.hash); + } + + assert_eq!( + slots.len(), + aux_pow_raw.len(), + "these need to be the same or else the below .zip() doesn't make sense" + ); + assert_eq!( + aux_pow_raw.len(), + aux_pow_id_raw.len(), + "these need to be the same or else the below .zip() doesn't make sense" + ); + + for (slot, aux_pow) in slots.iter().zip(&aux_pow) { + let slot = u32_to_usize(*slot); + + if slot >= len { + return Err(anyhow!("Slot value out of range")); + } + + aux_pow_raw[slot] = aux_pow.hash; + aux_pow_id_raw[slot] = aux_pow.id; + } + + ( + aux_pow_id_raw.into_boxed_slice(), + aux_pow_raw.into_boxed_slice(), + ) + }; + + // let crypto_tree_hash = || todo!(&aux_pow_raw, aux_pow_raw.len()); + let crypto_tree_hash = todo!(); + + let block_template = { + let hex = hex::decode(request.blocktemplate_blob)?; + Block::read(&mut hex.as_slice())? + }; + + fn remove_field_from_tx_extra() -> Result<(), ()> { + todo!() + } + + if remove_field_from_tx_extra().is_err() { + return Err(anyhow!("Error removing existing merkle root")); + } + + fn add_mm_merkle_root_to_tx_extra() -> Result<(), ()> { + todo!() + } + + if add_mm_merkle_root_to_tx_extra().is_err() { + return Err(anyhow!("Error adding merkle root")); + } + + fn invalidate_hashes() { + // block_template.invalidate_hashes(); + // block_template.miner_tx.invalidate_hashes(); + todo!(); + } + + invalidate_hashes(); + + let blocktemplate_blob = block_template.serialize(); + let blockhashing_blob = block_template.serialize_pow_hash(); + let merkle_root: [u8; 32] = todo!(); + let merkle_tree_depth = todo!(); + + let blocktemplate_blob = hex::encode(blocktemplate_blob); + let blockhashing_blob = hex::encode(blockhashing_blob); + let merkle_root = hex::encode(merkle_root); + let aux_pow = IntoIterator::into_iter(aux_pow) // must be explicit due to `boxed_slice_into_iter` .map(|aux| AuxPow { id: hex::encode(aux.id), hash: hex::encode(aux.hash), }) .collect::>(); + // --- END AUX POW IMPL --- + Ok(AddAuxPowResponse { base: ResponseBase::OK, blocktemplate_blob, blockhashing_blob, merkle_root, - merkle_tree_depth: resp.merkle_tree_depth, + merkle_tree_depth, aux_pow, }) } From 1f3b5ed1278c54ef61b198996dc39548dc09c568 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 14 Nov 2024 17:44:08 -0500 Subject: [PATCH 42/47] fix `calculate_pow` --- binaries/cuprated/src/rpc/helper.rs | 6 +++- binaries/cuprated/src/rpc/json.rs | 33 ++++++++++++------- .../src/rpc/request/blockchain_context.rs | 11 +++++-- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index f3b7164c9..48434a450 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -8,11 +8,15 @@ use anyhow::{anyhow, Error}; use monero_serai::block::Block; +use cuprate_consensus::{BlockChainContext, BlockChainContextService}; use cuprate_helper::{cast::usize_to_u64, map::split_u128_into_low_high_bits}; use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus}; use cuprate_types::ExtendedBlockHeader; -use crate::{rpc::request::blockchain, rpc::CupratedRpcHandler}; +use crate::{ + rpc::request::{blockchain, blockchain_context}, + rpc::CupratedRpcHandler, +}; pub(super) fn into_block_header( height: u64, diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index faccde05b..656bc6fa4 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -931,20 +931,31 @@ async fn calc_pow( let block = Block::read(&mut block_blob.as_slice())?; let seed_hash = helper::hex_to_hash(request.seed_hash)?; - // let pow_hash = blockchain_manager::calculate_pow( - // &mut state.blockchain_manager, - // hardfork, - // request.height, - // block, - // seed_hash, - // ) - // .await?; + let block_weight = todo!(); - // let hex = hex::encode(pow_hash); + let median_for_block_reward = blockchain_context::context(&mut state.blockchain_context) + .await? + .unchecked_blockchain_context() + .context_to_verify_block + .median_weight_for_block_reward; + + if cuprate_consensus_rules::blocks::check_block_weight(block_weight, median_for_block_reward) + .is_err() + { + return Err(anyhow!("Block blob size is too big, rejecting block")); + } + + let pow_hash = blockchain_context::calculate_pow( + &mut state.blockchain_context, + hardfork, + block, + seed_hash, + ) + .await?; - let hex = todo!(); + let pow_hash = hex::encode(pow_hash); - Ok(CalcPowResponse { pow_hash: hex }) + Ok(CalcPowResponse { pow_hash }) } /// diff --git a/binaries/cuprated/src/rpc/request/blockchain_context.rs b/binaries/cuprated/src/rpc/request/blockchain_context.rs index 73ae3c0c5..f0990afbb 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_context.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_context.rs @@ -73,17 +73,22 @@ pub(crate) async fn fee_estimate( pub(crate) async fn calculate_pow( blockchain_context: &mut BlockChainContextService, hardfork: HardFork, - height: u64, - block: Box, + block: Block, seed_hash: [u8; 32], ) -> Result<[u8; 32], Error> { + let Some(height) = block.number() else { + return Err(anyhow!("block is missing height")); + }; + + let block = Box::new(block); + let BlockChainContextResponse::CalculatePow(hash) = blockchain_context .ready() .await .map_err(|e| anyhow!(e))? .call(BlockChainContextRequest::CalculatePow { hardfork, - height: u64_to_usize(height), + height, block, seed_hash, }) From e975c420d96e6f5250a3d89ad89221ab79eb18f4 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Thu, 14 Nov 2024 19:58:24 -0500 Subject: [PATCH 43/47] add_aux_pow --- binaries/cuprated/src/rpc/json.rs | 33 ++++++++++++++++++++----------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 656bc6fa4..00bbaea0a 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -931,7 +931,7 @@ async fn calc_pow( let block = Block::read(&mut block_blob.as_slice())?; let seed_hash = helper::hex_to_hash(request.seed_hash)?; - let block_weight = todo!(); + let block_weight = todo!("calculate block weight"); let median_for_block_reward = blockchain_context::context(&mut state.blockchain_context) .await? @@ -1005,11 +1005,13 @@ async fn add_aux_pow( path_domain += 1; } - let nonce = 0_u32; + let mut nonce = 0_u32; let mut collision = true; let mut slots: Box<[u32]> = vec![0; len].into_boxed_slice(); // INVARIANT: this must be the same `.len()` as `aux_pow` - for nonce in 0..u32::MAX { + for n in 0..u32::MAX { + nonce = n; + let slot_seen: Vec = vec![false; len]; collision = false; @@ -1038,12 +1040,13 @@ async fn add_aux_pow( } } + let nonce = nonce; + let slots = slots; + if collision { return Err(anyhow!("Failed to find a suitable nonce")); } - let slots = slots; - // FIXME: use iterator version. let (aux_pow_id_raw, aux_pow_raw) = { let mut aux_pow_id_raw = Vec::<[u8; 32]>::with_capacity(len); @@ -1092,8 +1095,16 @@ async fn add_aux_pow( ) }; - // let crypto_tree_hash = || todo!(&aux_pow_raw, aux_pow_raw.len()); - let crypto_tree_hash = todo!(); + fn tree_hash(aux_pow_raw: &[[u8; 32]]) -> [u8; 32] { + todo!("https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2163") + } + + fn encode_mm_depth(aux_pow_len: usize, nonce: u32) -> u64 { + todo!("https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/cryptonote_basic/merge_mining.cpp#L74") + } + + let merkle_root = tree_hash(aux_pow_raw.as_ref()); + let merkle_tree_depth = encode_mm_depth(len, nonce); let block_template = { let hex = hex::decode(request.blocktemplate_blob)?; @@ -1101,7 +1112,7 @@ async fn add_aux_pow( }; fn remove_field_from_tx_extra() -> Result<(), ()> { - todo!() + todo!("https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L767") } if remove_field_from_tx_extra().is_err() { @@ -1109,7 +1120,8 @@ async fn add_aux_pow( } fn add_mm_merkle_root_to_tx_extra() -> Result<(), ()> { - todo!() + todo!("https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2189 + ") } if add_mm_merkle_root_to_tx_extra().is_err() { @@ -1119,6 +1131,7 @@ async fn add_aux_pow( fn invalidate_hashes() { // block_template.invalidate_hashes(); // block_template.miner_tx.invalidate_hashes(); + // todo!(); } @@ -1126,8 +1139,6 @@ async fn add_aux_pow( let blocktemplate_blob = block_template.serialize(); let blockhashing_blob = block_template.serialize_pow_hash(); - let merkle_root: [u8; 32] = todo!(); - let merkle_tree_depth = todo!(); let blocktemplate_blob = hex::encode(blocktemplate_blob); let blockhashing_blob = hex::encode(blockhashing_blob); From d634bea297a7b65b276ab903b07bb5220191a52c Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 15 Nov 2024 15:51:06 -0500 Subject: [PATCH 44/47] `get_output_distribution` --- binaries/cuprated/src/rpc/handler.rs | 2 +- binaries/cuprated/src/rpc/json.rs | 49 ++++++++++++++++++++++---- rpc/interface/src/route/bin.rs | 2 +- rpc/interface/src/route/json_rpc.rs | 2 +- rpc/interface/src/route/other.rs | 2 +- rpc/interface/src/rpc_handler.rs | 2 +- rpc/interface/src/rpc_handler_dummy.rs | 3 +- rpc/types/src/json.rs | 4 +++ 8 files changed, 54 insertions(+), 12 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index fd9be38f0..5db473d52 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -180,7 +180,7 @@ impl CupratedRpcHandler { } impl RpcHandler for CupratedRpcHandler { - fn restricted(&self) -> bool { + fn is_restricted(&self) -> bool { self.restricted } } diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 00bbaea0a..b445931b4 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -32,7 +32,8 @@ use cuprate_rpc_types::{ GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse, - GetOutputHistogramRequest, GetOutputHistogramResponse, GetTransactionPoolBacklogRequest, + GetOutputDistributionRequest, GetOutputDistributionResponse, GetOutputHistogramRequest, + GetOutputHistogramResponse, GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse, @@ -41,8 +42,8 @@ use cuprate_rpc_types::{ SyncInfoResponse, }, misc::{ - AuxPow, BlockHeader, ChainInfo, GetBan, GetMinerDataTxBacklogEntry, HardforkEntry, - HistogramEntry, Status, SyncInfoPeer, TxBacklogEntry, + AuxPow, BlockHeader, ChainInfo, Distribution, GetBan, GetMinerDataTxBacklogEntry, + HardforkEntry, HistogramEntry, Status, SyncInfoPeer, TxBacklogEntry, }, CORE_RPC_VERSION, }; @@ -109,6 +110,9 @@ pub(super) async fn map_request( Req::GetTransactionPoolBacklog(r) => { Resp::GetTransactionPoolBacklog(get_transaction_pool_backlog(state, r).await?) } + Req::GetOutputDistribution(r) => { + Resp::GetOutputDistribution(get_output_distribution(state, r).await?) + } Req::GetMinerData(r) => Resp::GetMinerData(get_miner_data(state, r).await?), Req::PruneBlockchain(r) => Resp::PruneBlockchain(prune_blockchain(state, r).await?), Req::CalcPow(r) => Resp::CalcPow(calc_pow(state, r).await?), @@ -217,7 +221,7 @@ async fn get_block_header_by_hash( mut state: CupratedRpcHandler, request: GetBlockHeaderByHashRequest, ) -> Result { - if state.restricted() && request.hashes.len() > RESTRICTED_BLOCK_COUNT { + if state.is_restricted() && request.hashes.len() > RESTRICTED_BLOCK_COUNT { return Err(anyhow!( "Too many block headers requested in restricted mode" )); @@ -282,7 +286,7 @@ async fn get_block_headers_range( request.end_height.saturating_sub(request.start_height) + 1 > RESTRICTED_BLOCK_HEADER_RANGE }; - if state.restricted() && too_many_blocks() { + if state.is_restricted() && too_many_blocks() { return Err(anyhow!("Too many block headers requested.")); } @@ -374,7 +378,7 @@ async fn get_info( mut state: CupratedRpcHandler, request: GetInfoRequest, ) -> Result { - let restricted = state.restricted(); + let restricted = state.is_restricted(); let context = blockchain_context::context(&mut state.blockchain_context).await?; let c = context.unchecked_blockchain_context(); @@ -866,6 +870,39 @@ async fn get_transaction_pool_backlog( }) } +/// +async fn get_output_distribution( + mut state: CupratedRpcHandler, + request: GetOutputDistributionRequest, +) -> Result { + if state.is_restricted() && request.amounts != [1, 0] { + return Err(anyhow!( + "Restricted RPC can only get output distribution for RCT outputs. Use your own node." + )); + } + + // 0 is placeholder for the whole chain + let req_to_height = if request.to_height == 0 { + helper::top_height(&mut state).await?.0.saturating_sub(1) + } else { + request.to_height + }; + + let distributions = request.amounts.into_iter().map(|amount| { + fn get_output_distribution() -> Result { + todo!("https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/rpc/rpc_handler.cpp#L29"); + Err(anyhow!("Failed to get output distribution")) + } + + get_output_distribution() + }).collect::, _>>()?; + + Ok(GetOutputDistributionResponse { + base: AccessResponseBase::OK, + distributions, + }) +} + /// async fn get_miner_data( mut state: CupratedRpcHandler, diff --git a/rpc/interface/src/route/bin.rs b/rpc/interface/src/route/bin.rs index f7e3a01c0..6d4fb9a3f 100644 --- a/rpc/interface/src/route/bin.rs +++ b/rpc/interface/src/route/bin.rs @@ -72,7 +72,7 @@ macro_rules! generate_endpoints_inner { paste::paste! { { // Check if restricted. - if [<$variant Request>]::IS_RESTRICTED && $handler.restricted() { + if [<$variant Request>]::IS_RESTRICTED && $handler.is_restricted() { // TODO: mimic `monerod` behavior. return Err(StatusCode::FORBIDDEN); } diff --git a/rpc/interface/src/route/json_rpc.rs b/rpc/interface/src/route/json_rpc.rs index 7efb85137..bb8658603 100644 --- a/rpc/interface/src/route/json_rpc.rs +++ b/rpc/interface/src/route/json_rpc.rs @@ -37,7 +37,7 @@ pub(crate) async fn json_rpc( // Return early if this RPC server is restricted and // the requested method is only for non-restricted RPC. - if request.body.is_restricted() && handler.restricted() { + if request.body.is_restricted() && handler.is_restricted() { let error_object = ErrorObject { code: ErrorCode::ServerError(-1 /* TODO */), message: Cow::Borrowed("Restricted. TODO: mimic monerod message"), diff --git a/rpc/interface/src/route/other.rs b/rpc/interface/src/route/other.rs index 3ff84487e..3993bd0fe 100644 --- a/rpc/interface/src/route/other.rs +++ b/rpc/interface/src/route/other.rs @@ -75,7 +75,7 @@ macro_rules! generate_endpoints_inner { paste::paste! { { // Check if restricted. - if [<$variant Request>]::IS_RESTRICTED && $handler.restricted() { + if [<$variant Request>]::IS_RESTRICTED && $handler.is_restricted() { // TODO: mimic `monerod` behavior. return Err(StatusCode::FORBIDDEN); } diff --git a/rpc/interface/src/rpc_handler.rs b/rpc/interface/src/rpc_handler.rs index 1d2676c76..c5c576863 100644 --- a/rpc/interface/src/rpc_handler.rs +++ b/rpc/interface/src/rpc_handler.rs @@ -46,5 +46,5 @@ pub trait RpcHandler: /// /// will automatically be denied access when using the /// [`axum::Router`] provided by [`RouterBuilder`](crate::RouterBuilder). - fn restricted(&self) -> bool; + fn is_restricted(&self) -> bool; } diff --git a/rpc/interface/src/rpc_handler_dummy.rs b/rpc/interface/src/rpc_handler_dummy.rs index 9d5009e45..ac48ceca2 100644 --- a/rpc/interface/src/rpc_handler_dummy.rs +++ b/rpc/interface/src/rpc_handler_dummy.rs @@ -39,7 +39,7 @@ pub struct RpcHandlerDummy { } impl RpcHandler for RpcHandlerDummy { - fn restricted(&self) -> bool { + fn is_restricted(&self) -> bool { self.restricted } } @@ -85,6 +85,7 @@ impl Service for RpcHandlerDummy { Req::GetTransactionPoolBacklog(_) => { Resp::GetTransactionPoolBacklog(Default::default()) } + Req::GetOutputDistribution(_) => Resp::GetOutputDistribution(Default::default()), Req::GetMinerData(_) => Resp::GetMinerData(Default::default()), Req::PruneBlockchain(_) => Resp::PruneBlockchain(Default::default()), Req::CalcPow(_) => Resp::CalcPow(Default::default()), diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index cb55e64a4..d4087da33 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -1623,6 +1623,7 @@ pub enum JsonRpcRequest { RelayTx(RelayTxRequest), SyncInfo(SyncInfoRequest), GetTransactionPoolBacklog(GetTransactionPoolBacklogRequest), + GetOutputDistribution(GetOutputDistributionRequest), GetMinerData(GetMinerDataRequest), PruneBlockchain(PruneBlockchainRequest), CalcPow(CalcPowRequest), @@ -1648,6 +1649,7 @@ impl RpcCallValue for JsonRpcRequest { Self::GetVersion(x) => x.is_restricted(), Self::GetFeeEstimate(x) => x.is_restricted(), Self::GetTransactionPoolBacklog(x) => x.is_restricted(), + Self::GetOutputDistribution(x) => x.is_restricted(), Self::GetMinerData(x) => x.is_restricted(), Self::AddAuxPow(x) => x.is_restricted(), Self::GetTxIdsLoose(x) => x.is_restricted(), @@ -1683,6 +1685,7 @@ impl RpcCallValue for JsonRpcRequest { Self::GetVersion(x) => x.is_empty(), Self::GetFeeEstimate(x) => x.is_empty(), Self::GetTransactionPoolBacklog(x) => x.is_empty(), + Self::GetOutputDistribution(x) => x.is_empty(), Self::GetMinerData(x) => x.is_empty(), Self::AddAuxPow(x) => x.is_empty(), Self::GetTxIdsLoose(x) => x.is_empty(), @@ -1755,6 +1758,7 @@ pub enum JsonRpcResponse { RelayTx(RelayTxResponse), SyncInfo(SyncInfoResponse), GetTransactionPoolBacklog(GetTransactionPoolBacklogResponse), + GetOutputDistribution(GetOutputDistributionResponse), GetMinerData(GetMinerDataResponse), PruneBlockchain(PruneBlockchainResponse), CalcPow(CalcPowResponse), From 854b1752b1f4f8b9d6ec469746057f9851ee6123 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 15 Nov 2024 20:11:56 -0500 Subject: [PATCH 45/47] checkup --- binaries/cuprated/src/rpc/json.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index b445931b4..0b273fa3f 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1,4 +1,8 @@ //! RPC request handler functions (JSON-RPC). +//! +//! TODO: +//! Many handlers have `todo!()`s for internals that must be completed, see: +//! use std::time::{Duration, Instant}; @@ -436,9 +440,7 @@ async fn get_info( let rpc_connections_count = if restricted { 0 } else { - todo!( - "implement a connection counter in axum/RPC, maybe `AtomicU64` any handler activating" - ) + todo!("implement a connection counter in axum/RPC") }; let start_time = if restricted { 0 } else { *START_INSTANT_UNIX }; let synchronized = blockchain_manager::synced(&mut state.blockchain_manager).await?; @@ -1037,6 +1039,8 @@ async fn add_aux_pow( let len = aux_pow.len(); + // TODO: why is this here? it does nothing: + // let mut path_domain = 1_usize; while 1 << path_domain < len { path_domain += 1; @@ -1053,7 +1057,7 @@ async fn add_aux_pow( collision = false; - slots.iter_mut().for_each(|i| *i = u32::MAX); + slots.fill(u32::MAX); for i in &mut slots { let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());"); From 2d2d4931f82029304c4fa378b66abb0727fb3495 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Fri, 15 Nov 2024 20:48:34 -0500 Subject: [PATCH 46/47] `find_nonce()` + `add_aux_pow` async wrapper --- binaries/cuprated/src/rpc/json.rs | 60 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 0b273fa3f..5cf7c14e0 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -1009,8 +1009,16 @@ async fn flush_cache( }) } -/// +/// An async-friendly wrapper for [`add_aux_pow_inner`]. async fn add_aux_pow( + state: CupratedRpcHandler, + request: AddAuxPowRequest, +) -> Result { + tokio::task::spawn_blocking(|| add_aux_pow_inner(state, request)).await? +} + +/// +fn add_aux_pow_inner( mut state: CupratedRpcHandler, request: AddAuxPowRequest, ) -> Result { @@ -1046,47 +1054,35 @@ async fn add_aux_pow( path_domain += 1; } - let mut nonce = 0_u32; - let mut collision = true; - let mut slots: Box<[u32]> = vec![0; len].into_boxed_slice(); // INVARIANT: this must be the same `.len()` as `aux_pow` - - for n in 0..u32::MAX { - nonce = n; + fn find_nonce(aux_pow_len: usize) -> Result<(u32, Box<[u32]>), Error> { + // INVARIANT: this must be the same `.len()` as `aux_pow` + let mut slots: Box<[u32]> = vec![u32::MAX; aux_pow_len].into_boxed_slice(); + let mut slot_seen: Box<[bool]> = vec![false; aux_pow_len].into_boxed_slice(); - let slot_seen: Vec = vec![false; len]; + for nonce in 0..u32::MAX { + for i in &mut slots { + let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());"); + let slot = u32_to_usize(slot_u32); - collision = false; + if slot >= aux_pow_len { + return Err(anyhow!("Computed slot is out of range")); + } - slots.fill(u32::MAX); + if slot_seen[slot] { + return Ok((nonce, slots)); + } - for i in &mut slots { - let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());"); - let slot = u32_to_usize(slot_u32); - - if slot >= len { - return Err(anyhow!("Computed slot is out of range")); - } - - if slot_seen[slot] { - collision = true; - break; + slot_seen[slot] = true; + *i = slot_u32; } - slot_seen[slot] = true; - *i = slot_u32; + slots.fill(u32::MAX); } - if !collision { - break; - } + Err(anyhow!("Failed to find a suitable nonce")) } - let nonce = nonce; - let slots = slots; - - if collision { - return Err(anyhow!("Failed to find a suitable nonce")); - } + let (nonce, slots) = find_nonce(len)?; // FIXME: use iterator version. let (aux_pow_id_raw, aux_pow_raw) = { From 86f2dd15866f11e5b6ea97d69187beade872ab71 Mon Sep 17 00:00:00 2001 From: "hinto.janai" Date: Sun, 17 Nov 2024 21:00:27 -0500 Subject: [PATCH 47/47] fixes --- binaries/cuprated/src/rpc/handler.rs | 5 ++++- binaries/cuprated/src/rpc/json.rs | 6 ++++-- binaries/cuprated/src/rpc/request/blockchain_manager.rs | 2 +- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index 5db473d52..f3eb8314f 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -35,7 +35,10 @@ pub enum BlockchainManagerRequest { Pruned, /// Relay a block to the network. - RelayBlock(Block), + RelayBlock( + /// This is [`Box`]ed due to `clippy::large_enum_variant`. + Box, + ), /// Is the blockchain in the middle of syncing? /// diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 5cf7c14e0..0bd412558 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -166,7 +166,7 @@ async fn submit_block( let block_id = hex::encode(block.hash()); // Attempt to relay the block. - blockchain_manager::relay_block(&mut state.blockchain_manager, block).await?; + blockchain_manager::relay_block(&mut state.blockchain_manager, Box::new(block)).await?; Ok(SubmitBlockResponse { base: ResponseBase::OK, @@ -1059,7 +1059,9 @@ fn add_aux_pow_inner( let mut slots: Box<[u32]> = vec![u32::MAX; aux_pow_len].into_boxed_slice(); let mut slot_seen: Box<[bool]> = vec![false; aux_pow_len].into_boxed_slice(); - for nonce in 0..u32::MAX { + const MAX_NONCE: u32 = 65535; + + for nonce in 0..=MAX_NONCE { for i in &mut slots { let slot_u32: u32 = todo!("const uint32_t slot = cryptonote::get_aux_slot(aux_pow[idx].first, nonce, aux_pow.size());"); let slot = u32_to_usize(slot_u32); diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index ed72284a3..fe3f55729 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -67,7 +67,7 @@ pub(crate) async fn pruned( /// [`BlockchainManagerRequest::RelayBlock`] pub(crate) async fn relay_block( blockchain_manager: &mut BlockchainManagerHandle, - block: Block, + block: Box, ) -> Result<(), Error> { let BlockchainManagerResponse::Ok = blockchain_manager .ready()