diff --git a/binaries/cuprated/src/rpc/handlers/bin.rs b/binaries/cuprated/src/rpc/handlers/bin.rs index 8ce8248..239ac8d 100644 --- a/binaries/cuprated/src/rpc/handlers/bin.rs +++ b/binaries/cuprated/src/rpc/handlers/bin.rs @@ -1,4 +1,8 @@ //! RPC request handler functions (binary endpoints). +//! +//! TODO: +//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see: +//! use std::num::NonZero; diff --git a/binaries/cuprated/src/rpc/handlers/helper.rs b/binaries/cuprated/src/rpc/handlers/helper.rs index 1ddd076..5b005f8 100644 --- a/binaries/cuprated/src/rpc/handlers/helper.rs +++ b/binaries/cuprated/src/rpc/handlers/helper.rs @@ -170,7 +170,7 @@ pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [ Ok((height, hash)) } -/// TODO +/// TODO: impl bootstrap pub const fn response_base(is_bootstrap: bool) -> ResponseBase { if is_bootstrap { ResponseBase::OK_UNTRUSTED @@ -179,7 +179,7 @@ pub const fn response_base(is_bootstrap: bool) -> ResponseBase { } } -/// TODO +/// TODO: impl bootstrap pub const fn access_response_base(is_bootstrap: bool) -> AccessResponseBase { if is_bootstrap { AccessResponseBase::OK_UNTRUSTED diff --git a/binaries/cuprated/src/rpc/handlers/json_rpc.rs b/binaries/cuprated/src/rpc/handlers/json_rpc.rs index a93cadb..4f7f00c 100644 --- a/binaries/cuprated/src/rpc/handlers/json_rpc.rs +++ b/binaries/cuprated/src/rpc/handlers/json_rpc.rs @@ -1,8 +1,8 @@ //! RPC request handler functions (JSON-RPC). //! //! TODO: -//! Many handlers have `todo!()`s for other Cuprate internals that must be completed, see: -//! +//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see: +//! use std::{ net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}, @@ -147,23 +147,26 @@ async fn get_block_template( return Err(anyhow!("Too big extra_nonce size")); } - // cryptonote::address_parse_info info; + // TODO: this is hardcoded for the current address scheme + mainnet, + // create/use a more well-defined wallet lib. + let parse_wallet_address = || { + if request.wallet_address.len() == 95 { + Ok(()) + } else { + Err(()) + } + }; + let is_correct_address_type = || !request.wallet_address.starts_with("4"); - if request.wallet_address.is_empty() - || todo!( - "!cryptonote::get_account_address_from_str(info, nettype(), request.wallet_address))" - ) - { + if parse_wallet_address().is_err() { return Err(anyhow!("Failed to parse wallet address")); } - if todo!("info.is_subaddress") { - return Err(anyhow!("Mining to subaddress is not supported yet")); + if is_correct_address_type() { + return Err(anyhow!("Incorrect address type")); } - let blob_reserve = hex::decode(request.extra_nonce)?; - let prev_block: [u8; 32] = request.prev_block.try_into()?; - let extra_nonce = hex::decode(request.extra_nonce)?; + let prev_block = request.prev_block.try_into().unwrap_or([0; 32]); let BlockTemplate { block, @@ -178,14 +181,13 @@ async fn get_block_template( &mut state.blockchain_manager, prev_block, request.wallet_address, - extra_nonce, + request.extra_nonce.0, ) .await?; let blockhashing_blob = HexVec(block.serialize_pow_hash()); let blocktemplate_blob = HexVec(block.serialize()); let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(difficulty); - // let next_seed_hash = Hex(next_seed_hash); let next_seed_hash = HexVec::empty_if_zeroed(next_seed_hash); let prev_hash = Hex(block.header.previous); let seed_hash = Hex(seed_hash); @@ -242,7 +244,7 @@ async fn submit_block( ) -> Result { // Parse hex into block. let [blob] = request.block_blob; - let block = Block::read(&mut blob.0.as_slice())?; + let block = Block::read(&mut blob.as_slice())?; let block_id = Hex(block.hash()); // Attempt to relay the block. @@ -562,8 +564,8 @@ async fn get_info( address_book::peerlist_size::(&mut DummyAddressBook).await? }; - let wide_cumulative_difficulty = format!("{cumulative_difficulty:#x}"); - let wide_difficulty = format!("{:#x}", c.next_difficulty); + let wide_cumulative_difficulty = cumulative_difficulty.hex_prefix(); + let wide_difficulty = c.next_difficulty.hex_prefix(); Ok(GetInfoResponse { base: helper::access_response_base(false), @@ -799,8 +801,8 @@ async fn get_coinbase_tx_sum( .await?; // Formats `u128` as hexadecimal strings. - let wide_emission_amount = format!("{fee_amount:#x}"); - let wide_fee_amount = format!("{emission_amount:#x}"); + let wide_emission_amount = fee_amount.hex_prefix(); + let wide_fee_amount = emission_amount.hex_prefix(); Ok(GetCoinbaseTxSumResponse { base: helper::access_response_base(false), @@ -979,7 +981,7 @@ async fn get_miner_data( let height = usize_to_u64(c.chain_height); let prev_id = Hex(c.top_hash); let seed_hash = Hex(c.top_hash); - let difficulty = format!("{:#x}", c.next_difficulty); + let difficulty = c.next_difficulty.hex_prefix(); 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) @@ -1028,7 +1030,7 @@ async fn calc_pow( request: CalcPowRequest, ) -> Result { let hardfork = HardFork::from_version(request.major_version)?; - let block = Block::read(&mut request.block_blob.0.as_slice())?; + let block = Block::read(&mut request.block_blob.as_slice())?; let seed_hash = request.seed_hash.0; // let block_weight = todo!(); @@ -1219,7 +1221,7 @@ fn add_aux_pow_inner( let merkle_root = tree_hash(aux_pow_raw.as_ref()); let merkle_tree_depth = encode_mm_depth(len, nonce); - let block_template = Block::read(&mut request.blocktemplate_blob.0.as_slice())?; + let block_template = Block::read(&mut request.blocktemplate_blob.as_slice())?; fn remove_field_from_tx_extra() -> Result<(), ()> { todo!("https://github.com/monero-project/monero/blob/master/src/cryptonote_basic/cryptonote_format_utils.cpp#L767") diff --git a/binaries/cuprated/src/rpc/handlers/other_json.rs b/binaries/cuprated/src/rpc/handlers/other_json.rs index ffe078a..bf6a96f 100644 --- a/binaries/cuprated/src/rpc/handlers/other_json.rs +++ b/binaries/cuprated/src/rpc/handlers/other_json.rs @@ -1,4 +1,8 @@ //! RPC request handler functions (other JSON endpoints). +//! +//! TODO: +//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see: +//! use std::{ borrow::Cow, @@ -6,6 +10,7 @@ use std::{ }; use anyhow::{anyhow, Error}; +use monero_serai::transaction::{Input, Timelock, Transaction}; use cuprate_constants::rpc::{ MAX_RESTRICTED_GLOBAL_FAKE_OUTS_COUNT, RESTRICTED_SPENT_KEY_IMAGES_COUNT, @@ -40,7 +45,6 @@ use cuprate_types::{ rpc::{KeyImageSpentStatus, PoolInfo, PoolTxInfo, PublicNode}, TxInPool, TxRelayChecks, }; -use monero_serai::transaction::{Input, Timelock, Transaction}; use crate::{ rpc::{ @@ -173,7 +177,7 @@ async fn get_transactions( txs_as_hex.push(as_hex.clone()); let as_json = if request.decode_as_json { - let tx = Transaction::read(&mut as_hex.0.as_slice())?; + let tx = Transaction::read(&mut as_hex.as_slice())?; let json_type = cuprate_types::json::tx::Transaction::from(tx); let json = serde_json::to_string(&json_type).unwrap(); txs_as_json.push(json.clone()); @@ -351,7 +355,7 @@ async fn send_raw_transaction( tx_extra_too_big: false, }; - let tx = Transaction::read(&mut request.tx_as_hex.0.as_slice())?; + let tx = Transaction::read(&mut request.tx_as_hex.as_slice())?; if request.do_sanity_checks { /// FIXME: these checks could be defined elsewhere. diff --git a/binaries/cuprated/src/rpc/handlers/shared.rs b/binaries/cuprated/src/rpc/handlers/shared.rs index 7181cf6..2f19dc8 100644 --- a/binaries/cuprated/src/rpc/handlers/shared.rs +++ b/binaries/cuprated/src/rpc/handlers/shared.rs @@ -1,4 +1,8 @@ //! RPC handler functions that are shared between different endpoint/methods. +//! +//! TODO: +//! Some handlers have `todo!()`s for other Cuprate internals that must be completed, see: +//! use std::{ collections::{HashMap, HashSet}, diff --git a/binaries/cuprated/src/rpc/rpc_handler.rs b/binaries/cuprated/src/rpc/rpc_handler.rs index 23bf848..b465704 100644 --- a/binaries/cuprated/src/rpc/rpc_handler.rs +++ b/binaries/cuprated/src/rpc/rpc_handler.rs @@ -3,7 +3,6 @@ use std::task::{Context, Poll}; use anyhow::Error; -use cuprate_types::BlockTemplate; use futures::future::BoxFuture; use monero_serai::block::Block; use tower::Service; @@ -18,6 +17,7 @@ use cuprate_rpc_types::{ other::{OtherRequest, OtherResponse}, }; use cuprate_txpool::service::TxpoolReadHandle; +use cuprate_types::BlockTemplate; use crate::rpc::handlers; @@ -41,7 +41,7 @@ pub enum BlockchainManagerRequest { Box, ), - /// TODO + /// Sync/flush the blockchain database to disk. Sync, /// Is the blockchain in the middle of syncing? @@ -89,14 +89,14 @@ pub enum BlockchainManagerRequest { /// Get the next [`PruningSeed`] needed for a pruned sync. NextNeededPruningSeed, - /// TODO + /// Create a block template. CreateBlockTemplate { prev_block: [u8; 32], account_public_address: String, extra_nonce: Vec, }, - /// TODO + /// Safely shutdown `cuprated`. Stop, } @@ -140,8 +140,6 @@ pub enum BlockchainManagerResponse { height: usize, }, - // /// Response to [`BlockchainManagerRequest::Spans`]. - // Spans(Vec>), /// Response to [`BlockchainManagerRequest::NextNeededPruningSeed`]. NextNeededPruningSeed(PruningSeed), diff --git a/binaries/cuprated/src/rpc/service/address_book.rs b/binaries/cuprated/src/rpc/service/address_book.rs index c38fc7e..3d96f0c 100644 --- a/binaries/cuprated/src/rpc/service/address_book.rs +++ b/binaries/cuprated/src/rpc/service/address_book.rs @@ -3,7 +3,6 @@ use std::net::SocketAddrV4; use anyhow::{anyhow, Error}; -use cuprate_types::rpc::Peer; use tower::ServiceExt; use cuprate_helper::{cast::usize_to_u64, map::u32_from_ipv4}; @@ -13,6 +12,7 @@ use cuprate_p2p_core::{ AddressBook, NetworkZone, }; use cuprate_rpc_types::misc::ConnectionInfo; +use cuprate_types::rpc::Peer; // FIXME: use `anyhow::Error` over `tower::BoxError` in address book. diff --git a/binaries/cuprated/src/rpc/service/blockchain_manager.rs b/binaries/cuprated/src/rpc/service/blockchain_manager.rs index fa10279..f7fc92f 100644 --- a/binaries/cuprated/src/rpc/service/blockchain_manager.rs +++ b/binaries/cuprated/src/rpc/service/blockchain_manager.rs @@ -1,7 +1,6 @@ //! Functions to send [`BlockchainManagerRequest`]s. use anyhow::Error; -use cuprate_types::BlockTemplate; use monero_serai::block::Block; use tower::{Service, ServiceExt}; @@ -9,6 +8,7 @@ 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::BlockTemplate; use crate::rpc::rpc_handler::{ BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, diff --git a/helper/src/fmt.rs b/helper/src/fmt.rs index 4a13927..9193687 100644 --- a/helper/src/fmt.rs +++ b/helper/src/fmt.rs @@ -1,6 +1,8 @@ -//! Formatting. +//! String formatting. +/// A type that can be represented in hexadecimal (with a `0x` prefix). pub trait HexPrefix { + /// Turn `self` into a hexadecimal string prefixed with `0x`. fn hex_prefix(self) -> String; } diff --git a/rpc/types/src/from.rs b/rpc/types/src/from.rs index de8daf0..da99dbe 100644 --- a/rpc/types/src/from.rs +++ b/rpc/types/src/from.rs @@ -111,15 +111,6 @@ impl From for crate::misc::HistogramEntry { } } -// impl From for crate::misc::HardforkEntry { -// fn from(x: HardforkEntry) -> Self { -// Self { -// height: x.height, -// hf_version: x.hf_version, -// } -// } -// } - impl From for crate::misc::ChainInfo { fn from(x: ChainInfo) -> Self { Self { @@ -150,18 +141,6 @@ impl From> for crate::misc::Span { } } -// impl From for crate::misc::OutputDistributionData { -// fn from(x: OutputDistributionData) -> Self { -// todo!(); - -// // Self { -// // distribution: Vec, -// // start_height: u64, -// // base: u64, -// // } -// } -// } - impl From for crate::misc::TxInfo { fn from(x: TxInfo) -> Self { Self { diff --git a/rpc/types/src/json.rs b/rpc/types/src/json.rs index d5b7c7b..e379cd1 100644 --- a/rpc/types/src/json.rs +++ b/rpc/types/src/json.rs @@ -76,11 +76,11 @@ define_request_and_response! { // 1. As an expression // 2. As a string literal // - // For example: `extra_nonce: String /* = default_string(), "default_string" */,` + // For example: `extra_nonce: HexVec /* = default::(), "default" */,` // // This is a HACK since `serde`'s default attribute only takes in // string literals and macros (stringify) within attributes do not work. - extra_nonce: String = default::(), "default", + extra_nonce: HexVec = default::(), "default", prev_block: HexVec = default::(), "default", // Another optional expression: @@ -958,7 +958,7 @@ mod test { fn get_block_template_request() { test_json_request(json::GET_BLOCK_TEMPLATE_REQUEST, GetBlockTemplateRequest { reserve_size: 60, - extra_nonce: String::default(), + extra_nonce: HexVec::default(), prev_block: HexVec::default(), wallet_address: "44GBHzv6ZyQdJkjqZje6KLZ3xSyN1hBSFAnLP6EAqJtCRVzMzZmeXTC2AHKDS9aEDTRKmo6a6o9r9j86pYfhCWDkKjbtcns".into(), }); diff --git a/rpc/types/src/misc/requested_info.rs b/rpc/types/src/misc/requested_info.rs index ca0cf3a..7736e91 100644 --- a/rpc/types/src/misc/requested_info.rs +++ b/rpc/types/src/misc/requested_info.rs @@ -1,4 +1,4 @@ -//! TODO +//! [`RequestedInfo`] //---------------------------------------------------------------------------------------------------- Use #[cfg(feature = "serde")] diff --git a/storage/txpool/src/service/interface.rs b/storage/txpool/src/service/interface.rs index 7e6b4d4..18d6e08 100644 --- a/storage/txpool/src/service/interface.rs +++ b/storage/txpool/src/service/interface.rs @@ -19,6 +19,10 @@ use crate::{ //---------------------------------------------------------------------------------------------------- TxpoolReadRequest /// The transaction pool [`tower::Service`] read request type. +/// +/// ### `include_sensitive_txs` +/// This field exists in many requests. +/// If this is [`true`], the request will include private (local) transactions in the response. #[derive(Clone)] pub enum TxpoolReadRequest { /// Get the blob (raw bytes) of a transaction with the given hash. @@ -39,42 +43,38 @@ pub enum TxpoolReadRequest { Backlog, /// Get the number of transactions in the pool. - Size { - /// If this is [`true`], the size returned will - /// include private transactions in the pool. - include_sensitive_txs: bool, - }, + Size { include_sensitive_txs: bool }, /// Get general information on the txpool. PoolInfo { - /// If this is [`true`], the size returned will - /// include private transactions in the pool. include_sensitive_txs: bool, - /// TODO + /// The maximum amount of transactions to retrieve. max_tx_count: usize, - /// TODO + /// Fetch transactions that start from this time. + /// + /// [`None`] means all transactions. start_time: Option>, }, - /// TODO + /// Get transactions by their hashes. TxsByHash { tx_hashes: Vec<[u8; 32]>, include_sensitive_txs: bool, }, - /// TODO + /// Check if certain key images exist in the txpool. KeyImagesSpent { key_images: Vec<[u8; 32]>, include_sensitive_txs: bool, }, - /// TODO + /// Get txpool info. Pool { include_sensitive_txs: bool }, - /// TODO + /// Get txpool stats. PoolStats { include_sensitive_txs: bool }, - /// TODO + /// Get the hashes of all transaction in the pool. AllHashes { include_sensitive_txs: bool }, } diff --git a/types/hex/src/array.rs b/types/hex/src/array.rs index 33bb416..f64266f 100644 --- a/types/hex/src/array.rs +++ b/types/hex/src/array.rs @@ -3,6 +3,11 @@ //! This module provides transparent wrapper types for //! arrays that (de)serialize from hexadecimal input/output. +use std::{ + borrow::Borrow, + ops::{Deref, DerefMut}, +}; + use hex::{FromHex, FromHexError}; use serde::{Deserialize, Deserializer, Serialize}; @@ -74,6 +79,31 @@ impl Default for Hex { } } +impl Deref for Hex { + type Target = [u8; N]; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for Hex { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Borrow<[u8; N]> for Hex { + fn borrow(&self) -> &[u8; N] { + &self.0 + } +} + +impl AsRef<[u8; N]> for Hex { + fn as_ref(&self) -> &[u8; N] { + &self.0 + } +} + impl From> for [u8; N] { fn from(hex: Hex) -> Self { hex.0 diff --git a/types/hex/src/vec.rs b/types/hex/src/vec.rs index c29ccfb..5b378fc 100644 --- a/types/hex/src/vec.rs +++ b/types/hex/src/vec.rs @@ -3,6 +3,11 @@ //! This module provides transparent wrapper types for //! arrays that (de)serialize from hexadecimal input/output. +use std::{ + borrow::Borrow, + ops::{Deref, DerefMut}, +}; + use hex::FromHexError; use serde::{Deserialize, Deserializer, Serialize}; @@ -42,11 +47,6 @@ impl HexVec { Self(Vec::new()) } - /// [`Vec::is_empty`]. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - /// Returns an empty [`Self`] if `array` is all `0`s. /// /// ```rust @@ -73,6 +73,31 @@ impl<'de> Deserialize<'de> for HexVec { } } +impl Deref for HexVec { + type Target = Vec; + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for HexVec { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl Borrow> for HexVec { + fn borrow(&self) -> &Vec { + &self.0 + } +} + +impl AsRef> for HexVec { + fn as_ref(&self) -> &Vec { + &self.0 + } +} + impl From for Vec { fn from(hex: HexVec) -> Self { hex.0 diff --git a/types/types/src/blockchain.rs b/types/types/src/blockchain.rs index 8e6eadf..2556dac 100644 --- a/types/types/src/blockchain.rs +++ b/types/types/src/blockchain.rs @@ -175,13 +175,13 @@ pub enum BlockchainReadRequest { /// Get the amount of alternative chains that exist. AltChainCount, - /// TODO + /// Get transaction blobs by their hashes. Transactions { tx_hashes: HashSet<[u8; 32]> }, - /// TODO + /// Get the total amount of RCT outputs in the blockchain. TotalRctOutputs, - /// TODO + /// Get the output indexes of a transaction. TxOutputIndexes { tx_hash: [u8; 32] }, }