diff --git a/binaries/cuprated/src/rpc/bin.rs b/binaries/cuprated/src/rpc/bin.rs index c07cca8..84405fe 100644 --- a/binaries/cuprated/src/rpc/bin.rs +++ b/binaries/cuprated/src/rpc/bin.rs @@ -110,7 +110,7 @@ async fn get_blocks( } Ok(GetBlocksResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), blocks: todo!(), start_height: todo!(), current_height: todo!(), @@ -136,7 +136,7 @@ async fn get_blocks_by_height( .collect::, Error>>()?; Ok(GetBlocksByHeightResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), blocks, }) } @@ -178,7 +178,7 @@ async fn get_hashes( let m_blocks_ids = bytes.split_off(index); Ok(GetHashesResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), m_blocks_ids, start_height, current_height, @@ -191,7 +191,7 @@ async fn get_output_indexes( request: GetOutputIndexesRequest, ) -> Result { Ok(GetOutputIndexesResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } @@ -202,7 +202,7 @@ async fn get_outs( request: GetOutsRequest, ) -> Result { Ok(GetOutsResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } @@ -213,7 +213,7 @@ async fn get_transaction_pool_hashes( request: GetTransactionPoolHashesRequest, ) -> Result { Ok(GetTransactionPoolHashesResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } @@ -224,7 +224,7 @@ async fn get_output_distribution( request: GetOutputDistributionRequest, ) -> Result { Ok(GetOutputDistributionResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } diff --git a/binaries/cuprated/src/rpc/handler.rs b/binaries/cuprated/src/rpc/handler.rs index 57863db..66b8549 100644 --- a/binaries/cuprated/src/rpc/handler.rs +++ b/binaries/cuprated/src/rpc/handler.rs @@ -41,6 +41,9 @@ pub enum BlockchainManagerRequest { Box, ), + /// TODO + Sync, + /// Is the blockchain in the middle of syncing? /// /// This returning `false` does not necessarily @@ -102,6 +105,7 @@ pub enum BlockchainManagerResponse { /// Response to: /// - [`BlockchainManagerRequest::Prune`] /// - [`BlockchainManagerRequest::RelayBlock`] + /// - [`BlockchainManagerRequest::Sync`] Ok, /// Response to [`BlockchainManagerRequest::PopBlocks`] diff --git a/binaries/cuprated/src/rpc/helper.rs b/binaries/cuprated/src/rpc/helper.rs index 0d79316..cad3382 100644 --- a/binaries/cuprated/src/rpc/helper.rs +++ b/binaries/cuprated/src/rpc/helper.rs @@ -11,7 +11,10 @@ use cuprate_helper::{ cast::{u64_to_usize, usize_to_u64}, map::split_u128_into_low_high_bits, }; -use cuprate_rpc_types::misc::BlockHeader; +use cuprate_rpc_types::{ + base::{AccessResponseBase, ResponseBase}, + misc::BlockHeader, +}; use cuprate_types::HardFork; use crate::{ @@ -166,3 +169,21 @@ pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [ let height = chain_height.saturating_sub(1); Ok((height, hash)) } + +/// TODO +pub const fn response_base(is_bootstrap: bool) -> ResponseBase { + if is_bootstrap { + ResponseBase::OK_UNTRUSTED + } else { + ResponseBase::OK + } +} + +/// TODO +pub const fn access_response_base(is_bootstrap: bool) -> AccessResponseBase { + if is_bootstrap { + AccessResponseBase::OK_UNTRUSTED + } else { + AccessResponseBase::OK + } +} diff --git a/binaries/cuprated/src/rpc/json.rs b/binaries/cuprated/src/rpc/json.rs index 8dff6e7..598cdbe 100644 --- a/binaries/cuprated/src/rpc/json.rs +++ b/binaries/cuprated/src/rpc/json.rs @@ -193,7 +193,7 @@ async fn get_block_template( let wide_difficulty = (difficulty, difficulty_top64).hex_prefix(); Ok(GetBlockTemplateResponse { - base: ResponseBase::OK, + base: helper::response_base(false), blockhashing_blob, blocktemplate_blob, difficulty_top64, @@ -215,7 +215,7 @@ async fn get_block_count( _: GetBlockCountRequest, ) -> Result { Ok(GetBlockCountResponse { - base: ResponseBase::OK, + base: helper::response_base(false), count: helper::top_height(&mut state).await?.0, }) } @@ -253,7 +253,7 @@ async fn submit_block( blockchain_manager::relay_block(&mut state.blockchain_manager, Box::new(block)).await?; Ok(SubmitBlockResponse { - base: ResponseBase::OK, + base: helper::response_base(false), block_id, }) } @@ -288,7 +288,7 @@ async fn generate_blocks( let blocks = blocks.into_iter().map(Hex).collect(); Ok(GenerateBlocksResponse { - base: ResponseBase::OK, + base: helper::response_base(false), blocks, height, }) @@ -303,7 +303,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: helper::access_response_base(false), block_header, }) } @@ -338,7 +338,7 @@ async fn get_block_header_by_hash( } Ok(GetBlockHeaderByHashResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), block_header, block_headers, }) @@ -354,7 +354,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: helper::access_response_base(false), block_header, }) } @@ -409,7 +409,7 @@ async fn get_block_headers_range( } Ok(GetBlockHeadersRangeResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), headers, }) } @@ -442,7 +442,7 @@ async fn get_block( }; Ok(GetBlockResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), blob, json, miner_tx_hash, @@ -459,7 +459,7 @@ async fn get_connections( let connections = address_book::connection_info::(&mut DummyAddressBook).await?; Ok(GetConnectionsResponse { - base: ResponseBase::OK, + base: helper::response_base(false), connections, }) } @@ -557,7 +557,7 @@ async fn get_info( let wide_difficulty = format!("{:#x}", c.next_difficulty); Ok(GetInfoResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), adjusted_time, alt_blocks_count, block_size_limit, @@ -617,7 +617,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: helper::access_response_base(false), earliest_height: info.earliest_height, enabled: info.enabled, state: info.state, @@ -654,7 +654,7 @@ async fn set_bans( } Ok(SetBansResponse { - base: ResponseBase::OK, + base: helper::response_base(false), }) } @@ -694,7 +694,7 @@ async fn get_bans(state: CupratedRpcHandler, _: GetBansRequest) -> Result, _>>()?; Ok(GetOutputDistributionResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), distributions, }) } @@ -1015,7 +1015,7 @@ async fn get_miner_data( .collect(); Ok(GetMinerDataResponse { - base: ResponseBase::OK, + base: helper::response_base(false), major_version, height, prev_id, @@ -1038,7 +1038,7 @@ async fn prune_blockchain( .compress(); Ok(PruneBlockchainResponse { - base: ResponseBase::OK, + base: helper::response_base(false), pruned, pruning_seed, }) @@ -1090,7 +1090,7 @@ async fn flush_cache( // TODO: cuprated doesn't need this call; decide behavior. Ok(FlushCacheResponse { - base: ResponseBase::OK, + base: helper::response_base(false), }) } @@ -1288,7 +1288,7 @@ fn add_aux_pow_inner( let aux_pow = aux_pow.into_vec(); Ok(AddAuxPowResponse { - base: ResponseBase::OK, + base: helper::response_base(false), blocktemplate_blob, blockhashing_blob, merkle_root, @@ -1306,7 +1306,7 @@ async fn get_tx_ids_loose( return Err(anyhow!("Not implemented")); Ok(GetTxIdsLooseResponse { - base: ResponseBase::OK, + base: helper::response_base(false), txids: todo!(), }) } diff --git a/binaries/cuprated/src/rpc/other.rs b/binaries/cuprated/src/rpc/other.rs index a88633c..a8a1bc0 100644 --- a/binaries/cuprated/src/rpc/other.rs +++ b/binaries/cuprated/src/rpc/other.rs @@ -1,6 +1,9 @@ //! RPC request handler functions (other JSON endpoints). -use std::collections::{BTreeSet, HashMap, HashSet}; +use std::{ + borrow::Cow, + collections::{BTreeSet, HashMap, HashSet}, +}; use anyhow::{anyhow, Error}; @@ -69,9 +72,6 @@ pub(super) async fn map_request( Req::GetPeerList(r) => Resp::GetPeerList(get_peer_list(state, r).await?), Req::SetLogLevel(r) => Resp::SetLogLevel(set_log_level(state, r).await?), Req::SetLogCategories(r) => Resp::SetLogCategories(set_log_categories(state, r).await?), - Req::SetBootstrapDaemon(r) => { - Resp::SetBootstrapDaemon(set_bootstrap_daemon(state, r).await?) - } Req::GetTransactionPool(r) => { Resp::GetTransactionPool(get_transaction_pool(state, r).await?) } @@ -92,7 +92,8 @@ pub(super) async fn map_request( Req::GetPublicNodes(r) => Resp::GetPublicNodes(get_public_nodes(state, r).await?), // Unsupported requests. - Req::Update(_) + Req::SetBootstrapDaemon(_) + | Req::Update(_) | Req::StartMining(_) | Req::StopMining(_) | Req::MiningStatus(_) @@ -103,13 +104,13 @@ pub(super) async fn map_request( /// async fn get_height( mut state: CupratedRpcHandler, - request: GetHeightRequest, + _: GetHeightRequest, ) -> Result { let (height, hash) = helper::top_height(&mut state).await?; let hash = Hex(hash); Ok(GetHeightResponse { - base: ResponseBase::OK, + base: helper::response_base(false), height, hash, }) @@ -254,7 +255,7 @@ async fn get_transactions( }; Ok(GetTransactionsResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), txs_as_hex, txs_as_json, missed_tx, @@ -265,7 +266,7 @@ async fn get_transactions( /// async fn get_alt_blocks_hashes( mut state: CupratedRpcHandler, - request: GetAltBlocksHashesRequest, + _: GetAltBlocksHashesRequest, ) -> Result { let blks_hashes = blockchain::alt_chains(&mut state.blockchain_read) .await? @@ -274,7 +275,7 @@ async fn get_alt_blocks_hashes( .collect(); Ok(GetAltBlocksHashesResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), blks_hashes, }) } @@ -321,7 +322,7 @@ async fn is_key_image_spent( }); Ok(IsKeyImageSpentResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), spent_status, }) } @@ -332,7 +333,7 @@ async fn send_raw_transaction( request: SendRawTransactionRequest, ) -> Result { let mut resp = SendRawTransactionResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), double_spend: false, fee_too_low: false, invalid_input: false, @@ -354,20 +355,20 @@ async fn send_raw_transaction( }; if request.do_sanity_checks { - // FIXME: these checks could be defined elsewhere. - // - // - fn tx_sanity_check(tx: &Transaction, rct_outs_available: u64) -> Result<(), &'static str> { - let Some(input) = tx.prefix().inputs.get(0) else { - return Err("No inputs"); + /// FIXME: these checks could be defined elsewhere. + /// + /// + fn tx_sanity_check(tx: &Transaction, rct_outs_available: u64) -> Result<(), String> { + let Some(input) = tx.prefix().inputs.first() else { + return Err("No inputs".to_string()); }; - let mut rct_indices = BTreeSet::new(); - let n_indices: usize = 0; + let mut rct_indices = vec![]; + let mut n_indices: usize = 0; - for input in tx.prefix().inputs { + for input in &tx.prefix().inputs { match input { - Input::Gen(_) => return Err("Transaction is coinbase"), + Input::Gen(_) => return Err("Transaction is coinbase".to_string()), Input::ToKey { amount, key_offsets, @@ -377,8 +378,19 @@ async fn send_raw_transaction( continue; }; + /// + fn relative_output_offsets_to_absolute(mut offsets: Vec) -> Vec { + assert!(!offsets.is_empty()); + + for i in 1..offsets.len() { + offsets[i] += offsets[i - 1]; + } + + offsets + } + n_indices += key_offsets.len(); - let absolute = todo!(); + let absolute = relative_output_offsets_to_absolute(key_offsets.clone()); rct_indices.extend(absolute); } } @@ -394,13 +406,12 @@ async fn send_raw_transaction( let rct_indices_len = rct_indices.len(); if rct_indices_len < n_indices * 8 / 10 { - return Err("amount of unique indices is too low (amount of rct indices is {rct_indices_len} out of total {n_indices} indices."); + return Err(format!("amount of unique indices is too low (amount of rct indices is {rct_indices_len} out of total {n_indices} indices.")); } - let offsets = Vec::with_capacity(rct_indices_len); - let median = todo!(); + let median = cuprate_helper::num::median(rct_indices); if median < rct_outs_available * 6 / 10 { - return Err("median offset index is too low (median is {median} out of total {rct_outs_available} offsets). Transactions should contain a higher fraction of recent outputs."); + return Err(format!("median offset index is too low (median is {median} out of total {rct_outs_available} offsets). Transactions should contain a higher fraction of recent outputs.")); } Ok(()) @@ -458,46 +469,10 @@ async fn send_raw_transaction( Ok(resp) } -/// -async fn start_mining( - state: CupratedRpcHandler, - request: StartMiningRequest, -) -> Result { - unreachable!(); - Ok(StartMiningResponse { - base: ResponseBase::OK, - }) -} - -/// -async fn stop_mining( - state: CupratedRpcHandler, - request: StopMiningRequest, -) -> Result { - unreachable!(); - Ok(StopMiningResponse { - base: ResponseBase::OK, - }) -} - -/// -async fn mining_status( - state: CupratedRpcHandler, - request: MiningStatusRequest, -) -> Result { - unreachable!(); - Ok(MiningStatusResponse { - base: ResponseBase::OK, - ..todo!() - }) -} - /// -async fn save_bc( - state: CupratedRpcHandler, - request: SaveBcRequest, -) -> Result { - todo!(); +async fn save_bc(mut state: CupratedRpcHandler, _: SaveBcRequest) -> Result { + blockchain_manager::sync(&mut state.blockchain_manager).await?; + Ok(SaveBcResponse { base: ResponseBase::OK, }) @@ -509,7 +484,7 @@ async fn get_peer_list( request: GetPeerListRequest, ) -> Result { Ok(GetPeerListResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -521,7 +496,7 @@ async fn set_log_hash_rate( ) -> Result { unreachable!(); Ok(SetLogHashRateResponse { - base: ResponseBase::OK, + base: helper::response_base(false), }) } @@ -532,7 +507,7 @@ async fn set_log_level( ) -> Result { todo!(); Ok(SetLogLevelResponse { - base: ResponseBase::OK, + base: helper::response_base(false), }) } @@ -542,27 +517,18 @@ async fn set_log_categories( request: SetLogCategoriesRequest, ) -> Result { Ok(SetLogCategoriesResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } -/// -async fn set_bootstrap_daemon( - state: CupratedRpcHandler, - request: SetBootstrapDaemonRequest, -) -> Result { - todo!(); - Ok(SetBootstrapDaemonResponse { status: Status::Ok }) -} - /// async fn get_transaction_pool( state: CupratedRpcHandler, request: GetTransactionPoolRequest, ) -> Result { Ok(GetTransactionPoolResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } @@ -573,7 +539,7 @@ async fn get_transaction_pool_stats( request: GetTransactionPoolStatsRequest, ) -> Result { Ok(GetTransactionPoolStatsResponse { - base: AccessResponseBase::OK, + base: helper::access_response_base(false), ..todo!() }) } @@ -593,7 +559,7 @@ async fn get_limit( request: GetLimitRequest, ) -> Result { Ok(GetLimitResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -604,7 +570,7 @@ async fn set_limit( request: SetLimitRequest, ) -> Result { Ok(SetLimitResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -615,7 +581,7 @@ async fn out_peers( request: OutPeersRequest, ) -> Result { Ok(OutPeersResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -626,7 +592,7 @@ async fn in_peers( request: InPeersRequest, ) -> Result { Ok(InPeersResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -637,7 +603,7 @@ async fn get_net_stats( request: GetNetStatsRequest, ) -> Result { Ok(GetNetStatsResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -678,22 +644,11 @@ async fn get_outs( // TODO: check txpool Ok(GetOutsResponse { - base: ResponseBase::OK, + base: helper::response_base(false), outs, }) } -/// -async fn update( - state: CupratedRpcHandler, - request: UpdateRequest, -) -> Result { - Ok(UpdateResponse { - base: ResponseBase::OK, - ..todo!() - }) -} - /// async fn pop_blocks( mut state: CupratedRpcHandler, @@ -703,7 +658,7 @@ async fn pop_blocks( blockchain_manager::pop_blocks(&mut state.blockchain_manager, request.nblocks).await?; Ok(PopBlocksResponse { - base: ResponseBase::OK, + base: helper::response_base(false), height, }) } @@ -714,7 +669,7 @@ async fn get_transaction_pool_hashes( request: GetTransactionPoolHashesRequest, ) -> Result { Ok(GetTransactionPoolHashesResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } @@ -725,7 +680,49 @@ async fn get_public_nodes( request: GetPublicNodesRequest, ) -> Result { Ok(GetPublicNodesResponse { - base: ResponseBase::OK, + base: helper::response_base(false), ..todo!() }) } + +//---------------------------------------------------------------------------------------------------- Unsupported RPC calls + +/// +async fn set_bootstrap_daemon( + state: CupratedRpcHandler, + request: SetBootstrapDaemonRequest, +) -> Result { + todo!(); +} + +/// +async fn update( + state: CupratedRpcHandler, + request: UpdateRequest, +) -> Result { + todo!(); +} + +/// +async fn start_mining( + state: CupratedRpcHandler, + request: StartMiningRequest, +) -> Result { + unreachable!() +} + +/// +async fn stop_mining( + state: CupratedRpcHandler, + request: StopMiningRequest, +) -> Result { + unreachable!(); +} + +/// +async fn mining_status( + state: CupratedRpcHandler, + request: MiningStatusRequest, +) -> Result { + unreachable!(); +} diff --git a/binaries/cuprated/src/rpc/request/blockchain_manager.rs b/binaries/cuprated/src/rpc/request/blockchain_manager.rs index ec0d4d5..ef4f2f4 100644 --- a/binaries/cuprated/src/rpc/request/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/request/blockchain_manager.rs @@ -242,3 +242,17 @@ pub(crate) async fn create_block_template( Ok(block_template) } + +/// [`BlockchainManagerRequest::Sync`] +pub(crate) async fn sync(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { + let BlockchainManagerResponse::Ok = blockchain_manager + .ready() + .await? + .call(BlockchainManagerRequest::Sync) + .await? + else { + unreachable!(); + }; + + Ok(()) +}