apply diffs

This commit is contained in:
hinto.janai 2024-10-17 20:25:23 -04:00
parent 978d72b6c1
commit 09640fb4ea
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
28 changed files with 954 additions and 268 deletions

View file

@ -9,31 +9,31 @@ repository = "https://github.com/Cuprate/cuprate/tree/main/binaries/cuprated"
[dependencies] [dependencies]
# TODO: after v1.0.0, remove unneeded dependencies. # TODO: after v1.0.0, remove unneeded dependencies.
cuprate-consensus = { path = "../../consensus" } cuprate-consensus = { path = "../../consensus" }
cuprate-fast-sync = { path = "../../consensus/fast-sync" }
cuprate-consensus-context = { path = "../../consensus/context" } cuprate-consensus-context = { path = "../../consensus/context" }
cuprate-consensus-rules = { path = "../../consensus/rules" } cuprate-consensus-rules = { path = "../../consensus/rules" }
cuprate-cryptonight = { path = "../../cryptonight" } cuprate-fast-sync = { path = "../../consensus/fast-sync" }
cuprate-helper = { path = "../../helper" } cuprate-cryptonight = { path = "../../cryptonight" }
cuprate-epee-encoding = { path = "../../net/epee-encoding" } cuprate-helper = { path = "../../helper" }
cuprate-fixed-bytes = { path = "../../net/fixed-bytes" } cuprate-epee-encoding = { path = "../../net/epee-encoding" }
cuprate-levin = { path = "../../net/levin" } cuprate-fixed-bytes = { path = "../../net/fixed-bytes" }
cuprate-wire = { path = "../../net/wire" } cuprate-levin = { path = "../../net/levin" }
cuprate-p2p = { path = "../../p2p/p2p" } cuprate-wire = { path = "../../net/wire" }
cuprate-p2p-core = { path = "../../p2p/p2p-core" } cuprate-p2p = { path = "../../p2p/p2p" }
cuprate-dandelion-tower = { path = "../../p2p/dandelion-tower" } cuprate-p2p-core = { path = "../../p2p/p2p-core" }
cuprate-async-buffer = { path = "../../p2p/async-buffer" } cuprate-dandelion-tower = { path = "../../p2p/dandelion-tower" }
cuprate-address-book = { path = "../../p2p/address-book" } cuprate-async-buffer = { path = "../../p2p/async-buffer" }
cuprate-blockchain = { path = "../../storage/blockchain", features = ["service"] } cuprate-address-book = { path = "../../p2p/address-book" }
cuprate-database-service = { path = "../../storage/service" } cuprate-blockchain = { path = "../../storage/blockchain", features = ["service"] }
cuprate-txpool = { path = "../../storage/txpool" } cuprate-database-service = { path = "../../storage/service" }
cuprate-database = { path = "../../storage/database" } cuprate-txpool = { path = "../../storage/txpool" }
cuprate-pruning = { path = "../../pruning" } cuprate-database = { path = "../../storage/database" }
cuprate-test-utils = { path = "../../test-utils" } cuprate-pruning = { path = "../../pruning" }
cuprate-types = { path = "../../types" } cuprate-test-utils = { path = "../../test-utils" }
cuprate-json-rpc = { path = "../../rpc/json-rpc" } cuprate-types = { path = "../../types" }
cuprate-rpc-interface = { path = "../../rpc/interface" } cuprate-json-rpc = { path = "../../rpc/json-rpc" }
cuprate-rpc-types = { path = "../../rpc/types" } cuprate-rpc-interface = { path = "../../rpc/interface" }
cuprate-rpc-types = { path = "../../rpc/types" }
# TODO: after v1.0.0, remove unneeded dependencies. # TODO: after v1.0.0, remove unneeded dependencies.
anyhow = { workspace = true } anyhow = { workspace = true }

View file

@ -9,6 +9,10 @@
unused_variables, unused_variables,
clippy::needless_pass_by_value, clippy::needless_pass_by_value,
clippy::unused_async, 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" reason = "TODO: remove after v1.0.0"
)] )]

View file

@ -8,6 +8,8 @@ use monero_serai::block::Block;
use tower::Service; use tower::Service;
use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle}; use cuprate_blockchain::service::{BlockchainReadHandle, BlockchainWriteHandle};
use cuprate_consensus::BlockChainContextService;
use cuprate_pruning::PruningSeed;
use cuprate_rpc_interface::RpcHandler; use cuprate_rpc_interface::RpcHandler;
use cuprate_rpc_types::{ use cuprate_rpc_types::{
bin::{BinRequest, BinResponse}, bin::{BinRequest, BinResponse},
@ -15,12 +17,12 @@ use cuprate_rpc_types::{
other::{OtherRequest, OtherResponse}, other::{OtherRequest, OtherResponse},
}; };
use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle}; use cuprate_txpool::service::{TxpoolReadHandle, TxpoolWriteHandle};
use cuprate_types::{AddAuxPow, AuxPow, HardFork};
use crate::rpc::{bin, json, other}; use crate::rpc::{bin, json, other};
/// TODO: use real type when public. /// TODO: use real type when public.
#[derive(Clone)] #[derive(Clone)]
#[expect(clippy::large_enum_variant)]
pub enum BlockchainManagerRequest { pub enum BlockchainManagerRequest {
/// Pop blocks off the top of the blockchain. /// Pop blocks off the top of the blockchain.
/// ///
@ -54,6 +56,61 @@ pub enum BlockchainManagerRequest {
/// The height of the next block in the chain. /// The height of the next block in the chain.
TargetHeight, 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],
},
/// 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 {
/// The block template to add to.
block_template: Block,
/// The auxirilly proof-of-work to add.
aux_pow: Vec<AuxPow>,
},
/// Generate new blocks.
///
/// This request is only for regtest, see RPC's `generateblocks`.
GenerateBlocks {
/// Number of the blocks to be generated.
amount_of_blocks: u64,
/// The previous block's hash.
prev_block: [u8; 32],
/// The starting value for the nonce.
starting_nonce: u32,
/// The address that will receive the coinbase reward.
wallet_address: String,
},
/// 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.
///
/// See also:
/// - <https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#sync_info>
/// - <https://github.com/monero-project/monero/blob/master/src/cryptonote_protocol/block_queue.cpp#L178>
Overview {
/// TODO: the current blockchain height? do we need to pass this?
height: usize,
},
} }
/// TODO: use real type when public. /// TODO: use real type when public.
@ -69,6 +126,9 @@ pub enum BlockchainManagerResponse {
/// Response to [`BlockchainManagerRequest::PopBlocks`] /// Response to [`BlockchainManagerRequest::PopBlocks`]
PopBlocks { new_height: usize }, PopBlocks { new_height: usize },
/// Response to [`BlockchainManagerRequest::Prune`]
Prune(PruningSeed),
/// Response to [`BlockchainManagerRequest::Pruned`] /// Response to [`BlockchainManagerRequest::Pruned`]
Pruned(bool), Pruned(bool),
@ -83,6 +143,23 @@ pub enum BlockchainManagerResponse {
/// Response to [`BlockchainManagerRequest::TargetHeight`] /// Response to [`BlockchainManagerRequest::TargetHeight`]
TargetHeight { height: usize }, TargetHeight { height: usize },
/// Response to [`BlockchainManagerRequest::CalculatePow`]
CalculatePow([u8; 32]),
/// Response to [`BlockchainManagerRequest::AddAuxPow`]
AddAuxPow(AddAuxPow),
/// Response to [`BlockchainManagerRequest::GenerateBlocks`]
GenerateBlocks {
/// Hashes of the blocks generated.
blocks: Vec<[u8; 32]>,
/// The new top height. (TODO: is this correct?)
height: usize,
},
/// Response to [`BlockchainManagerRequest::Overview`]
Overview(String),
} }
/// TODO: use real type when public. /// TODO: use real type when public.
@ -102,6 +179,9 @@ pub struct CupratedRpcHandler {
/// Read handle to the blockchain database. /// Read handle to the blockchain database.
pub blockchain_read: BlockchainReadHandle, pub blockchain_read: BlockchainReadHandle,
/// Handle to the blockchain context service.
pub blockchain_context: BlockChainContextService,
/// Handle to the blockchain manager. /// Handle to the blockchain manager.
pub blockchain_manager: BlockchainManagerHandle, pub blockchain_manager: BlockchainManagerHandle,
@ -117,6 +197,7 @@ impl CupratedRpcHandler {
pub const fn new( pub const fn new(
restricted: bool, restricted: bool,
blockchain_read: BlockchainReadHandle, blockchain_read: BlockchainReadHandle,
blockchain_context: BlockChainContextService,
blockchain_manager: BlockchainManagerHandle, blockchain_manager: BlockchainManagerHandle,
txpool_read: TxpoolReadHandle, txpool_read: TxpoolReadHandle,
txpool_manager: std::convert::Infallible, txpool_manager: std::convert::Infallible,
@ -124,6 +205,7 @@ impl CupratedRpcHandler {
Self { Self {
restricted, restricted,
blockchain_read, blockchain_read,
blockchain_context,
blockchain_manager, blockchain_manager,
txpool_read, txpool_read,
txpool_manager, txpool_manager,

View file

@ -2,26 +2,31 @@
use std::convert::Infallible; use std::convert::Infallible;
use anyhow::Error; use anyhow::{anyhow, Error};
use cuprate_pruning::PruningSeed;
use cuprate_rpc_types::misc::{ConnectionInfo, Span};
use tower::ServiceExt; use tower::ServiceExt;
use cuprate_helper::cast::usize_to_u64; use cuprate_helper::cast::usize_to_u64;
use cuprate_p2p_core::{ use cuprate_p2p_core::{
services::{AddressBookRequest, AddressBookResponse}, services::{AddressBookRequest, AddressBookResponse},
types::BanState,
AddressBook, NetworkZone, AddressBook, NetworkZone,
}; };
// FIXME: use `anyhow::Error` over `tower::BoxError` in address book.
/// [`AddressBookRequest::PeerlistSize`] /// [`AddressBookRequest::PeerlistSize`]
pub(super) async fn peerlist_size<Z: NetworkZone>( pub(crate) async fn peerlist_size<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>, address_book: &mut impl AddressBook<Z>,
) -> Result<(u64, u64), Error> { ) -> Result<(u64, u64), Error> {
let AddressBookResponse::PeerlistSize { white, grey } = address_book let AddressBookResponse::PeerlistSize { white, grey } = address_book
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(AddressBookRequest::PeerlistSize) .call(AddressBookRequest::PeerlistSize)
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -29,17 +34,80 @@ pub(super) async fn peerlist_size<Z: NetworkZone>(
Ok((usize_to_u64(white), usize_to_u64(grey))) Ok((usize_to_u64(white), usize_to_u64(grey)))
} }
/// [`AddressBookRequest::ConnectionInfo`]
pub(crate) async fn connection_info<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>,
) -> Result<Vec<ConnectionInfo>, 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| {
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();
Ok(vec)
}
/// [`AddressBookRequest::ConnectionCount`] /// [`AddressBookRequest::ConnectionCount`]
pub(super) async fn connection_count<Z: NetworkZone>( pub(crate) async fn connection_count<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>, address_book: &mut impl AddressBook<Z>,
) -> Result<(u64, u64), Error> { ) -> Result<(u64, u64), Error> {
let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book let AddressBookResponse::ConnectionCount { incoming, outgoing } = address_book
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(AddressBookRequest::ConnectionCount) .call(AddressBookRequest::ConnectionCount)
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -48,17 +116,17 @@ pub(super) async fn connection_count<Z: NetworkZone>(
} }
/// [`AddressBookRequest::SetBan`] /// [`AddressBookRequest::SetBan`]
pub(super) async fn set_ban<Z: NetworkZone>( pub(crate) async fn set_ban<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>, address_book: &mut impl AddressBook<Z>,
peer: cuprate_p2p_core::ban::SetBan<Z::Addr>, set_ban: cuprate_p2p_core::types::SetBan<Z::Addr>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let AddressBookResponse::Ok = address_book let AddressBookResponse::Ok = address_book
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(AddressBookRequest::SetBan(peer)) .call(AddressBookRequest::SetBan(set_ban))
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -67,17 +135,17 @@ pub(super) async fn set_ban<Z: NetworkZone>(
} }
/// [`AddressBookRequest::GetBan`] /// [`AddressBookRequest::GetBan`]
pub(super) async fn get_ban<Z: NetworkZone>( pub(crate) async fn get_ban<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>, address_book: &mut impl AddressBook<Z>,
peer: Z::Addr, peer: Z::Addr,
) -> Result<Option<std::time::Instant>, Error> { ) -> Result<Option<std::time::Instant>, Error> {
let AddressBookResponse::GetBan { unban_instant } = address_book let AddressBookResponse::GetBan { unban_instant } = address_book
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(AddressBookRequest::GetBan(peer)) .call(AddressBookRequest::GetBan(peer))
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -86,19 +154,69 @@ pub(super) async fn get_ban<Z: NetworkZone>(
} }
/// [`AddressBookRequest::GetBans`] /// [`AddressBookRequest::GetBans`]
pub(super) async fn get_bans<Z: NetworkZone>( pub(crate) async fn get_bans<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>, address_book: &mut impl AddressBook<Z>,
) -> Result<(), Error> { ) -> Result<Vec<BanState<Z::Addr>>, Error> {
let AddressBookResponse::GetBans(bans) = address_book let AddressBookResponse::GetBans(bans) = address_book
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(AddressBookRequest::GetBans) .call(AddressBookRequest::GetBans)
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
Ok(todo!()) Ok(bans)
}
/// [`AddressBookRequest::Spans`]
pub(crate) async fn spans<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>,
) -> Result<Vec<Span>, 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: hex::encode(span.connection_id.to_ne_bytes()),
nblocks: span.nblocks,
rate: span.rate,
remote_address: span.remote_address.to_string(),
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<Z: NetworkZone>(
address_book: &mut impl AddressBook<Z>,
) -> Result<PruningSeed, Error> {
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)
} }

View file

@ -1,24 +1,61 @@
//! Functions for [`BlockchainReadRequest`]. //! Functions for [`BlockchainReadRequest`].
use std::{ use std::{
collections::{HashMap, HashSet}, collections::{BTreeMap, HashMap, HashSet},
ops::Range, ops::Range,
}; };
use anyhow::Error; use anyhow::Error;
use cuprate_blockchain::service::BlockchainReadHandle; use monero_serai::block::Block;
use tower::{Service, ServiceExt}; use tower::{Service, ServiceExt};
use cuprate_blockchain::{service::BlockchainReadHandle, types::AltChainInfo};
use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
use cuprate_types::{ use cuprate_types::{
blockchain::{BlockchainReadRequest, BlockchainResponse}, blockchain::{BlockchainReadRequest, BlockchainResponse},
Chain, CoinbaseTxSum, ExtendedBlockHeader, MinerData, OutputHistogramEntry, Chain, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, HardFork, MinerData,
OutputHistogramInput, OutputOnChain, OutputHistogramEntry, OutputHistogramInput, OutputOnChain,
}; };
/// [`BlockchainReadRequest::Block`].
pub(crate) async fn block(
blockchain_read: &mut BlockchainReadHandle,
height: u64,
) -> Result<Block, Error> {
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<Block, Error> {
let BlockchainResponse::Block(block) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::BlockByHash(hash))
.await?
else {
unreachable!();
};
Ok(block)
}
/// [`BlockchainReadRequest::BlockExtendedHeader`]. /// [`BlockchainReadRequest::BlockExtendedHeader`].
pub(super) async fn block_extended_header( pub(crate) async fn block_extended_header(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
height: u64, height: u64,
) -> Result<ExtendedBlockHeader, Error> { ) -> Result<ExtendedBlockHeader, Error> {
let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read let BlockchainResponse::BlockExtendedHeader(header) = blockchain_read
@ -36,8 +73,8 @@ pub(super) async fn block_extended_header(
} }
/// [`BlockchainReadRequest::BlockHash`]. /// [`BlockchainReadRequest::BlockHash`].
pub(super) async fn block_hash( pub(crate) async fn block_hash(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
height: u64, height: u64,
chain: Chain, chain: Chain,
) -> Result<[u8; 32], Error> { ) -> Result<[u8; 32], Error> {
@ -57,8 +94,8 @@ pub(super) async fn block_hash(
} }
/// [`BlockchainReadRequest::FindBlock`]. /// [`BlockchainReadRequest::FindBlock`].
pub(super) async fn find_block( pub(crate) async fn find_block(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
block_hash: [u8; 32], block_hash: [u8; 32],
) -> Result<Option<(Chain, usize)>, Error> { ) -> Result<Option<(Chain, usize)>, Error> {
let BlockchainResponse::FindBlock(option) = blockchain_read let BlockchainResponse::FindBlock(option) = blockchain_read
@ -74,8 +111,8 @@ pub(super) async fn find_block(
} }
/// [`BlockchainReadRequest::FilterUnknownHashes`]. /// [`BlockchainReadRequest::FilterUnknownHashes`].
pub(super) async fn filter_unknown_hashes( pub(crate) async fn filter_unknown_hashes(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
block_hashes: HashSet<[u8; 32]>, block_hashes: HashSet<[u8; 32]>,
) -> Result<HashSet<[u8; 32]>, Error> { ) -> Result<HashSet<[u8; 32]>, Error> {
let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read let BlockchainResponse::FilterUnknownHashes(output) = blockchain_read
@ -91,8 +128,8 @@ pub(super) async fn filter_unknown_hashes(
} }
/// [`BlockchainReadRequest::BlockExtendedHeaderInRange`] /// [`BlockchainReadRequest::BlockExtendedHeaderInRange`]
pub(super) async fn block_extended_header_in_range( pub(crate) async fn block_extended_header_in_range(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
range: Range<usize>, range: Range<usize>,
chain: Chain, chain: Chain,
) -> Result<Vec<ExtendedBlockHeader>, Error> { ) -> Result<Vec<ExtendedBlockHeader>, Error> {
@ -111,8 +148,8 @@ pub(super) async fn block_extended_header_in_range(
} }
/// [`BlockchainReadRequest::ChainHeight`]. /// [`BlockchainReadRequest::ChainHeight`].
pub(super) async fn chain_height( pub(crate) async fn chain_height(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
) -> Result<(u64, [u8; 32]), Error> { ) -> Result<(u64, [u8; 32]), Error> {
let BlockchainResponse::ChainHeight(height, hash) = blockchain_read let BlockchainResponse::ChainHeight(height, hash) = blockchain_read
.ready() .ready()
@ -127,8 +164,8 @@ pub(super) async fn chain_height(
} }
/// [`BlockchainReadRequest::GeneratedCoins`]. /// [`BlockchainReadRequest::GeneratedCoins`].
pub(super) async fn generated_coins( pub(crate) async fn generated_coins(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
block_height: u64, block_height: u64,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read let BlockchainResponse::GeneratedCoins(generated_coins) = blockchain_read
@ -146,8 +183,8 @@ pub(super) async fn generated_coins(
} }
/// [`BlockchainReadRequest::Outputs`] /// [`BlockchainReadRequest::Outputs`]
pub(super) async fn outputs( pub(crate) async fn outputs(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
outputs: HashMap<u64, HashSet<u64>>, outputs: HashMap<u64, HashSet<u64>>,
) -> Result<HashMap<u64, HashMap<u64, OutputOnChain>>, Error> { ) -> Result<HashMap<u64, HashMap<u64, OutputOnChain>>, Error> {
let BlockchainResponse::Outputs(outputs) = blockchain_read let BlockchainResponse::Outputs(outputs) = blockchain_read
@ -163,8 +200,8 @@ pub(super) async fn outputs(
} }
/// [`BlockchainReadRequest::NumberOutputsWithAmount`] /// [`BlockchainReadRequest::NumberOutputsWithAmount`]
pub(super) async fn number_outputs_with_amount( pub(crate) async fn number_outputs_with_amount(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
output_amounts: Vec<u64>, output_amounts: Vec<u64>,
) -> Result<HashMap<u64, usize>, Error> { ) -> Result<HashMap<u64, usize>, Error> {
let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read let BlockchainResponse::NumberOutputsWithAmount(map) = blockchain_read
@ -182,8 +219,8 @@ pub(super) async fn number_outputs_with_amount(
} }
/// [`BlockchainReadRequest::KeyImagesSpent`] /// [`BlockchainReadRequest::KeyImagesSpent`]
pub(super) async fn key_images_spent( pub(crate) async fn key_images_spent(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
key_images: HashSet<[u8; 32]>, key_images: HashSet<[u8; 32]>,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read let BlockchainResponse::KeyImagesSpent(is_spent) = blockchain_read
@ -199,8 +236,8 @@ pub(super) async fn key_images_spent(
} }
/// [`BlockchainReadRequest::CompactChainHistory`] /// [`BlockchainReadRequest::CompactChainHistory`]
pub(super) async fn compact_chain_history( pub(crate) async fn compact_chain_history(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
) -> Result<(Vec<[u8; 32]>, u128), Error> { ) -> Result<(Vec<[u8; 32]>, u128), Error> {
let BlockchainResponse::CompactChainHistory { let BlockchainResponse::CompactChainHistory {
block_ids, block_ids,
@ -218,8 +255,8 @@ pub(super) async fn compact_chain_history(
} }
/// [`BlockchainReadRequest::FindFirstUnknown`] /// [`BlockchainReadRequest::FindFirstUnknown`]
pub(super) async fn find_first_unknown( pub(crate) async fn find_first_unknown(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
hashes: Vec<[u8; 32]>, hashes: Vec<[u8; 32]>,
) -> Result<Option<(usize, u64)>, Error> { ) -> Result<Option<(usize, u64)>, Error> {
let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read let BlockchainResponse::FindFirstUnknown(resp) = blockchain_read
@ -235,8 +272,8 @@ pub(super) async fn find_first_unknown(
} }
/// [`BlockchainReadRequest::TotalTxCount`] /// [`BlockchainReadRequest::TotalTxCount`]
pub(super) async fn total_tx_count( pub(crate) async fn total_tx_count(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read let BlockchainResponse::TotalTxCount(tx_count) = blockchain_read
.ready() .ready()
@ -251,8 +288,8 @@ pub(super) async fn total_tx_count(
} }
/// [`BlockchainReadRequest::DatabaseSize`] /// [`BlockchainReadRequest::DatabaseSize`]
pub(super) async fn database_size( pub(crate) async fn database_size(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
) -> Result<(u64, u64), Error> { ) -> Result<(u64, u64), Error> {
let BlockchainResponse::DatabaseSize { let BlockchainResponse::DatabaseSize {
database_size, database_size,
@ -270,8 +307,8 @@ pub(super) async fn database_size(
} }
/// [`BlockchainReadRequest::OutputHistogram`] /// [`BlockchainReadRequest::OutputHistogram`]
pub(super) async fn output_histogram( pub(crate) async fn output_histogram(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
input: OutputHistogramInput, input: OutputHistogramInput,
) -> Result<Vec<OutputHistogramEntry>, Error> { ) -> Result<Vec<OutputHistogramEntry>, Error> {
let BlockchainResponse::OutputHistogram(histogram) = blockchain_read let BlockchainResponse::OutputHistogram(histogram) = blockchain_read
@ -287,8 +324,8 @@ pub(super) async fn output_histogram(
} }
/// [`BlockchainReadRequest::CoinbaseTxSum`] /// [`BlockchainReadRequest::CoinbaseTxSum`]
pub(super) async fn coinbase_tx_sum( pub(crate) async fn coinbase_tx_sum(
mut blockchain_read: BlockchainReadHandle, blockchain_read: &mut BlockchainReadHandle,
height: u64, height: u64,
count: u64, count: u64,
) -> Result<CoinbaseTxSum, Error> { ) -> Result<CoinbaseTxSum, Error> {
@ -306,3 +343,35 @@ pub(super) async fn coinbase_tx_sum(
Ok(sum) Ok(sum)
} }
/// [`BlockchainReadRequest::AltChains`]
pub(crate) async fn alt_chains(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<Vec<ChainInfo>, Error> {
let BlockchainResponse::AltChains(vec) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::AltChains)
.await?
else {
unreachable!();
};
Ok(vec)
}
/// [`BlockchainReadRequest::AltChainCount`]
pub(crate) async fn alt_chain_count(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<u64, Error> {
let BlockchainResponse::AltChainCount(count) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::AltChainCount)
.await?
else {
unreachable!();
};
Ok(usize_to_u64(count))
}

View file

@ -2,7 +2,7 @@
use std::convert::Infallible; use std::convert::Infallible;
use anyhow::Error; use anyhow::{anyhow, Error};
use tower::{Service, ServiceExt}; use tower::{Service, ServiceExt};
use cuprate_consensus_context::{ use cuprate_consensus_context::{
@ -11,18 +11,19 @@ use cuprate_consensus_context::{
}; };
use cuprate_types::{FeeEstimate, HardFork, HardForkInfo}; use cuprate_types::{FeeEstimate, HardFork, HardForkInfo};
// FIXME: use `anyhow::Error` over `tower::BoxError` in blockchain context.
/// [`BlockChainContextRequest::Context`]. /// [`BlockChainContextRequest::Context`].
pub(super) async fn context( pub(crate) async fn context(
service: &mut BlockChainContextService, blockchain_context: &mut BlockChainContextService,
height: u64,
) -> Result<BlockChainContext, Error> { ) -> Result<BlockChainContext, Error> {
let BlockChainContextResponse::Context(context) = service let BlockChainContextResponse::Context(context) = blockchain_context
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(BlockChainContextRequest::Context) .call(BlockChainContextRequest::Context)
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -31,17 +32,17 @@ pub(super) async fn context(
} }
/// [`BlockChainContextRequest::HardForkInfo`]. /// [`BlockChainContextRequest::HardForkInfo`].
pub(super) async fn hard_fork_info( pub(crate) async fn hard_fork_info(
service: &mut BlockChainContextService, blockchain_context: &mut BlockChainContextService,
hard_fork: HardFork, hard_fork: HardFork,
) -> Result<HardForkInfo, Error> { ) -> Result<HardForkInfo, Error> {
let BlockChainContextResponse::HardForkInfo(hf_info) = service let BlockChainContextResponse::HardForkInfo(hf_info) = blockchain_context
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(BlockChainContextRequest::HardForkInfo(hard_fork)) .call(BlockChainContextRequest::HardForkInfo(hard_fork))
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -50,17 +51,17 @@ pub(super) async fn hard_fork_info(
} }
/// [`BlockChainContextRequest::FeeEstimate`]. /// [`BlockChainContextRequest::FeeEstimate`].
pub(super) async fn fee_estimate( pub(crate) async fn fee_estimate(
service: &mut BlockChainContextService, blockchain_context: &mut BlockChainContextService,
grace_blocks: u64, grace_blocks: u64,
) -> Result<FeeEstimate, Error> { ) -> Result<FeeEstimate, Error> {
let BlockChainContextResponse::FeeEstimate(fee) = service let BlockChainContextResponse::FeeEstimate(fee) = blockchain_context
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(BlockChainContextRequest::FeeEstimate { grace_blocks }) .call(BlockChainContextRequest::FeeEstimate { grace_blocks })
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };

View file

@ -5,13 +5,15 @@ use monero_serai::block::Block;
use tower::{Service, ServiceExt}; use tower::{Service, ServiceExt};
use cuprate_helper::cast::{u64_to_usize, usize_to_u64}; use cuprate_helper::cast::{u64_to_usize, usize_to_u64};
use cuprate_pruning::PruningSeed;
use cuprate_types::{AddAuxPow, AuxPow, HardFork};
use crate::rpc::handler::{ use crate::rpc::handler::{
BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse, BlockchainManagerHandle, BlockchainManagerRequest, BlockchainManagerResponse,
}; };
/// [`BlockchainManagerRequest::PopBlocks`] /// [`BlockchainManagerRequest::PopBlocks`]
pub(super) async fn pop_blocks( pub(crate) async fn pop_blocks(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
amount: u64, amount: u64,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
@ -30,8 +32,10 @@ pub(super) async fn pop_blocks(
} }
/// [`BlockchainManagerRequest::Prune`] /// [`BlockchainManagerRequest::Prune`]
pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> Result<(), Error> { pub(crate) async fn prune(
let BlockchainManagerResponse::Ok = blockchain_manager blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<PruningSeed, Error> {
let BlockchainManagerResponse::Prune(seed) = blockchain_manager
.ready() .ready()
.await? .await?
.call(BlockchainManagerRequest::Prune) .call(BlockchainManagerRequest::Prune)
@ -40,11 +44,11 @@ pub(super) async fn prune(blockchain_manager: &mut BlockchainManagerHandle) -> R
unreachable!(); unreachable!();
}; };
Ok(()) Ok(seed)
} }
/// [`BlockchainManagerRequest::Pruned`] /// [`BlockchainManagerRequest::Pruned`]
pub(super) async fn pruned( pub(crate) async fn pruned(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager let BlockchainManagerResponse::Pruned(pruned) = blockchain_manager
@ -60,7 +64,7 @@ pub(super) async fn pruned(
} }
/// [`BlockchainManagerRequest::RelayBlock`] /// [`BlockchainManagerRequest::RelayBlock`]
pub(super) async fn relay_block( pub(crate) async fn relay_block(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
block: Block, block: Block,
) -> Result<(), Error> { ) -> Result<(), Error> {
@ -77,7 +81,7 @@ pub(super) async fn relay_block(
} }
/// [`BlockchainManagerRequest::Syncing`] /// [`BlockchainManagerRequest::Syncing`]
pub(super) async fn syncing( pub(crate) async fn syncing(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager let BlockchainManagerResponse::Syncing(syncing) = blockchain_manager
@ -93,7 +97,7 @@ pub(super) async fn syncing(
} }
/// [`BlockchainManagerRequest::Synced`] /// [`BlockchainManagerRequest::Synced`]
pub(super) async fn synced( pub(crate) async fn synced(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<bool, Error> { ) -> Result<bool, Error> {
let BlockchainManagerResponse::Synced(syncing) = blockchain_manager let BlockchainManagerResponse::Synced(syncing) = blockchain_manager
@ -109,7 +113,7 @@ pub(super) async fn synced(
} }
/// [`BlockchainManagerRequest::Target`] /// [`BlockchainManagerRequest::Target`]
pub(super) async fn target( pub(crate) async fn target(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<std::time::Duration, Error> { ) -> Result<std::time::Duration, Error> {
let BlockchainManagerResponse::Target(target) = blockchain_manager let BlockchainManagerResponse::Target(target) = blockchain_manager
@ -125,7 +129,7 @@ pub(super) async fn target(
} }
/// [`BlockchainManagerRequest::TargetHeight`] /// [`BlockchainManagerRequest::TargetHeight`]
pub(super) async fn target_height( pub(crate) async fn target_height(
blockchain_manager: &mut BlockchainManagerHandle, blockchain_manager: &mut BlockchainManagerHandle,
) -> Result<u64, Error> { ) -> Result<u64, Error> {
let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager let BlockchainManagerResponse::TargetHeight { height } = blockchain_manager
@ -139,3 +143,93 @@ pub(super) async fn target_height(
Ok(usize_to_u64(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)
}
/// [`BlockchainManagerRequest::AddAuxPow`]
pub(crate) async fn add_aux_pow(
blockchain_manager: &mut BlockchainManagerHandle,
block_template: Block,
aux_pow: Vec<AuxPow>,
) -> Result<AddAuxPow, Error> {
let BlockchainManagerResponse::AddAuxPow(response) = blockchain_manager
.ready()
.await?
.call(BlockchainManagerRequest::AddAuxPow {
block_template,
aux_pow,
})
.await?
else {
unreachable!();
};
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)))
}
/// [`BlockchainManagerRequest::Overview`]
pub(crate) async fn overview(
blockchain_manager: &mut BlockchainManagerHandle,
height: u64,
) -> Result<String, Error> {
let BlockchainManagerResponse::Overview(overview) = blockchain_manager
.ready()
.await?
.call(BlockchainManagerRequest::Overview {
height: u64_to_usize(height),
})
.await?
else {
unreachable!();
};
Ok(overview)
}

View file

@ -2,7 +2,7 @@
use std::convert::Infallible; use std::convert::Infallible;
use anyhow::Error; use anyhow::{anyhow, Error};
use tower::{Service, ServiceExt}; use tower::{Service, ServiceExt};
use cuprate_helper::cast::usize_to_u64; use cuprate_helper::cast::usize_to_u64;
@ -11,18 +11,38 @@ use cuprate_txpool::{
interface::{TxpoolReadRequest, TxpoolReadResponse}, interface::{TxpoolReadRequest, TxpoolReadResponse},
TxpoolReadHandle, TxpoolReadHandle,
}, },
TxEntry, BlockTemplateTxEntry, TxEntry,
}; };
// FIXME: use `anyhow::Error` over `tower::BoxError` in txpool.
/// [`TxpoolReadRequest::Backlog`] /// [`TxpoolReadRequest::Backlog`]
pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result<Vec<TxEntry>, Error> { pub(crate) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result<Vec<TxEntry>, Error> {
let TxpoolReadResponse::Backlog(tx_entries) = txpool_read let TxpoolReadResponse::Backlog(tx_entries) = txpool_read
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(TxpoolReadRequest::Backlog) .call(TxpoolReadRequest::Backlog)
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else {
unreachable!();
};
Ok(tx_entries)
}
/// [`TxpoolReadRequest::BlockTemplateBacklog`]
pub(crate) async fn block_template_backlog(
txpool_read: &mut TxpoolReadHandle,
) -> Result<Vec<BlockTemplateTxEntry>, 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 { else {
unreachable!(); unreachable!();
}; };
@ -31,14 +51,19 @@ pub(super) async fn backlog(txpool_read: &mut TxpoolReadHandle) -> Result<Vec<Tx
} }
/// [`TxpoolReadRequest::Size`] /// [`TxpoolReadRequest::Size`]
pub(super) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result<u64, Error> { pub(crate) async fn size(
txpool_read: &mut TxpoolReadHandle,
include_sensitive_txs: bool,
) -> Result<u64, Error> {
let TxpoolReadResponse::Size(size) = txpool_read let TxpoolReadResponse::Size(size) = txpool_read
.ready() .ready()
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
.call(TxpoolReadRequest::Size) .call(TxpoolReadRequest::Size {
include_sensitive_txs,
})
.await .await
.expect("TODO") .map_err(|e| anyhow!(e))?
else { else {
unreachable!(); unreachable!();
}; };
@ -47,9 +72,17 @@ pub(super) async fn size(txpool_read: &mut TxpoolReadHandle) -> Result<u64, Erro
} }
/// TODO /// TODO
#[expect(clippy::needless_pass_by_ref_mut, reason = "TODO: remove after impl")] pub(crate) async fn flush(
pub(super) async fn flush( txpool_manager: &mut Infallible,
txpool_read: &mut TxpoolReadHandle, tx_hashes: Vec<[u8; 32]>,
) -> Result<(), Error> {
todo!();
Ok(())
}
/// TODO
pub(crate) async fn relay(
txpool_manager: &mut Infallible,
tx_hashes: Vec<[u8; 32]>, tx_hashes: Vec<[u8; 32]>,
) -> Result<(), Error> { ) -> Result<(), Error> {
todo!(); todo!();

View file

@ -423,7 +423,10 @@ impl<Z: BorshNetworkZone> Service<AddressBookRequest<Z>> for AddressBook<Z> {
AddressBookRequest::PeerlistSize AddressBookRequest::PeerlistSize
| AddressBookRequest::ConnectionCount | AddressBookRequest::ConnectionCount
| AddressBookRequest::SetBan(_) | AddressBookRequest::SetBan(_)
| AddressBookRequest::GetBans => { | AddressBookRequest::GetBans
| AddressBookRequest::ConnectionInfo
| AddressBookRequest::NextNeededPruningSeed
| AddressBookRequest::Spans => {
todo!("finish https://github.com/Cuprate/cuprate/pull/297") todo!("finish https://github.com/Cuprate/cuprate/pull/297")
} }
}; };

View file

@ -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<A: NetZoneAddress> {
/// 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<Duration>,
}
/// Data within [`crate::services::AddressBookResponse::GetBans`].
pub struct BanState<A: NetZoneAddress> {
/// 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<Instant>,
}

View file

@ -111,7 +111,10 @@ impl<N: NetworkZone> Service<AddressBookRequest<N>> for DummyAddressBook {
AddressBookRequest::PeerlistSize AddressBookRequest::PeerlistSize
| AddressBookRequest::ConnectionCount | AddressBookRequest::ConnectionCount
| AddressBookRequest::SetBan(_) | AddressBookRequest::SetBan(_)
| AddressBookRequest::GetBans => { | AddressBookRequest::GetBans
| AddressBookRequest::ConnectionInfo
| AddressBookRequest::NextNeededPruningSeed
| AddressBookRequest::Spans => {
todo!("finish https://github.com/Cuprate/cuprate/pull/297") todo!("finish https://github.com/Cuprate/cuprate/pull/297")
} }
})) }))

View file

@ -75,7 +75,6 @@ use cuprate_wire::{
NetworkAddress, NetworkAddress,
}; };
pub mod ban;
pub mod client; pub mod client;
mod constants; mod constants;
pub mod error; pub mod error;
@ -83,6 +82,7 @@ pub mod handles;
mod network_zones; mod network_zones;
pub mod protocol; pub mod protocol;
pub mod services; pub mod services;
pub mod types;
pub use error::*; pub use error::*;
pub use network_zones::{ClearNet, ClearNetServerCfg}; pub use network_zones::{ClearNet, ClearNetServerCfg};

View file

@ -4,9 +4,9 @@ use cuprate_pruning::{PruningError, PruningSeed};
use cuprate_wire::{CoreSyncData, PeerListEntryBase}; use cuprate_wire::{CoreSyncData, PeerListEntryBase};
use crate::{ use crate::{
ban::{BanState, SetBan},
client::InternalPeerID, client::InternalPeerID,
handles::ConnectionHandle, handles::ConnectionHandle,
types::{BanState, ConnectionInfo, SetBan, Span},
NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone, NetZoneAddress, NetworkAddressIncorrectZone, NetworkZone,
}; };
@ -118,6 +118,9 @@ pub enum AddressBookRequest<Z: NetworkZone> {
/// Get the amount of white & grey peers. /// Get the amount of white & grey peers.
PeerlistSize, PeerlistSize,
/// Get information on all connections.
ConnectionInfo,
/// Get the amount of incoming & outgoing connections. /// Get the amount of incoming & outgoing connections.
ConnectionCount, ConnectionCount,
@ -129,6 +132,15 @@ pub enum AddressBookRequest<Z: NetworkZone> {
/// Get the state of all bans. /// Get the state of all bans.
GetBans, GetBans,
/// Get [`Span`] data.
///
/// This is data that describes an active downloading process,
/// if we are fully synced, this will return an empty [`Vec`].
Spans,
/// Get the next [`PruningSeed`] needed for a pruned sync.
NextNeededPruningSeed,
} }
/// A response from the address book service. /// A response from the address book service.
@ -152,6 +164,9 @@ pub enum AddressBookResponse<Z: NetworkZone> {
/// Response to [`AddressBookRequest::PeerlistSize`]. /// Response to [`AddressBookRequest::PeerlistSize`].
PeerlistSize { white: usize, grey: usize }, PeerlistSize { white: usize, grey: usize },
/// Response to [`AddressBookRequest::ConnectionInfo`].
ConnectionInfo(Vec<ConnectionInfo<Z::Addr>>),
/// Response to [`AddressBookRequest::ConnectionCount`]. /// Response to [`AddressBookRequest::ConnectionCount`].
ConnectionCount { incoming: usize, outgoing: usize }, ConnectionCount { incoming: usize, outgoing: usize },
@ -163,4 +178,10 @@ pub enum AddressBookResponse<Z: NetworkZone> {
/// Response to [`AddressBookRequest::GetBans`]. /// Response to [`AddressBookRequest::GetBans`].
GetBans(Vec<BanState<Z::Addr>>), GetBans(Vec<BanState<Z::Addr>>),
/// Response to [`AddressBookRequest::Spans`].
Spans(Vec<Span<Z::Addr>>),
/// Response to [`AddressBookRequest::NextNeededPruningSeed`].
NextNeededPruningSeed(PruningSeed),
} }

127
p2p/p2p-core/src/types.rs Normal file
View file

@ -0,0 +1,127 @@
//! General data structures.
use std::time::{Duration, Instant};
use cuprate_pruning::PruningSeed;
use crate::NetZoneAddress;
/// Data within [`crate::services::AddressBookRequest::SetBan`].
pub struct SetBan<A: NetZoneAddress> {
/// 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<Duration>,
}
/// Data within [`crate::services::AddressBookResponse::GetBans`].
pub struct BanState<A: NetZoneAddress> {
/// 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<Instant>,
}
/// 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<Self> {
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<A: NetZoneAddress> {
pub address: A,
pub address_type: AddressType,
pub avg_download: u64,
pub avg_upload: u64,
pub connection_id: u64, // TODO: boost::uuids::uuid
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: 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, // TODO: what type is this?
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<A: NetZoneAddress> {
pub connection_id: u64, // TODO: boost::uuids::uuid
pub nblocks: u64,
pub rate: u32,
pub remote_address: A,
pub size: u64,
pub speed: u32,
pub start_block_height: u64,
}

View file

@ -58,61 +58,37 @@ pub struct ResponseBase {
} }
impl ResponseBase { impl ResponseBase {
/// `const` version of [`Default::default`]. /// [`Status::Ok`] and trusted [`Self`].
///
/// ```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`].
/// ///
/// This is the most common version of [`Self`]. /// This is the most common version of [`Self`].
/// ///
/// ```rust /// ```rust
/// use cuprate_rpc_types::{misc::*, base::*}; /// use cuprate_rpc_types::{misc::*, base::*};
/// ///
/// let ok = ResponseBase::ok(); /// assert_eq!(ResponseBase::OK, ResponseBase {
/// assert_eq!(ok, ResponseBase {
/// status: Status::Ok, /// status: Status::Ok,
/// untrusted: false, /// untrusted: false,
/// }); /// });
/// ``` /// ```
pub const fn ok() -> Self { pub const OK: Self = Self {
Self { status: Status::Ok,
status: Status::Ok, untrusted: false,
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 /// ```rust
/// use cuprate_rpc_types::{misc::*, base::*}; /// use cuprate_rpc_types::{misc::*, base::*};
/// ///
/// let ok_untrusted = ResponseBase::ok_untrusted(); /// assert_eq!(ResponseBase::OK_UNTRUSTED, ResponseBase {
/// assert_eq!(ok_untrusted, ResponseBase {
/// status: Status::Ok, /// status: Status::Ok,
/// untrusted: true, /// untrusted: true,
/// }); /// });
/// ``` /// ```
pub const fn ok_untrusted() -> Self { pub const OK_UNTRUSTED: Self = Self {
Self { status: Status::Ok,
status: Status::Ok, untrusted: true,
untrusted: true, };
}
}
} }
#[cfg(feature = "epee")] #[cfg(feature = "epee")]
@ -148,9 +124,9 @@ impl AccessResponseBase {
/// ```rust /// ```rust
/// use cuprate_rpc_types::{misc::*, base::*}; /// use cuprate_rpc_types::{misc::*, base::*};
/// ///
/// let new = AccessResponseBase::new(ResponseBase::ok()); /// let new = AccessResponseBase::new(ResponseBase::OK);
/// assert_eq!(new, AccessResponseBase { /// assert_eq!(new, AccessResponseBase {
/// response_base: ResponseBase::ok(), /// response_base: ResponseBase::OK,
/// credits: 0, /// credits: 0,
/// top_hash: "".into(), /// 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`]. /// This is the most common version of [`Self`].
/// ///
/// ```rust /// ```rust
/// use cuprate_rpc_types::{misc::*, base::*}; /// use cuprate_rpc_types::{misc::*, base::*};
/// ///
/// let ok = AccessResponseBase::ok(); /// assert_eq!(AccessResponseBase::OK, AccessResponseBase {
/// assert_eq!(ok, AccessResponseBase { /// response_base: ResponseBase::OK,
/// response_base: ResponseBase::ok(),
/// credits: 0, /// credits: 0,
/// top_hash: "".into(), /// top_hash: "".into(),
/// }); /// });
/// ``` /// ```
pub const fn ok() -> Self { pub const OK: Self = Self {
Self { response_base: ResponseBase::OK,
response_base: ResponseBase::ok(), credits: 0,
credits: 0, top_hash: String::new(),
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 /// ```rust
/// use cuprate_rpc_types::{misc::*, base::*}; /// use cuprate_rpc_types::{misc::*, base::*};
/// ///
/// let ok_untrusted = AccessResponseBase::ok_untrusted(); /// assert_eq!(AccessResponseBase::OK_UNTRUSTED, AccessResponseBase {
/// assert_eq!(ok_untrusted, AccessResponseBase {
/// response_base: ResponseBase::ok_untrusted(), /// response_base: ResponseBase::ok_untrusted(),
/// credits: 0, /// credits: 0,
/// top_hash: "".into(), /// top_hash: "".into(),
/// }); /// });
/// ``` /// ```
pub const fn ok_untrusted() -> Self { pub const OK_UNTRUSTED: Self = Self {
Self { response_base: ResponseBase::OK_UNTRUSTED,
response_base: ResponseBase::ok_untrusted(), credits: 0,
credits: 0, top_hash: String::new(),
top_hash: String::new(), };
}
}
} }
#[cfg(feature = "epee")] #[cfg(feature = "epee")]

View file

@ -184,7 +184,7 @@ define_request_and_response! {
// <https://serde.rs/field-attrs.html#flatten>. // <https://serde.rs/field-attrs.html#flatten>.
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse { GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(), blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(),
blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(), blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(),
difficulty_top64: 0, difficulty_top64: 0,
@ -240,7 +240,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse { GET_BLOCK_COUNT_RESPONSE => GetBlockCountResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
count: 3195019, count: 3195019,
} }
)] )]
@ -332,7 +332,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse { GENERATE_BLOCKS_RESPONSE => GenerateBlocksResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()], blocks: vec!["49b712db7760e3728586f8434ee8bc8d7b3d410dac6bb6e98bf5845c83b917e4".into()],
height: 9783, height: 9783,
} }
@ -357,7 +357,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse { GET_LAST_BLOCK_HEADER_RESPONSE => GetLastBlockHeaderResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
block_header: BlockHeader { block_header: BlockHeader {
block_size: 200419, block_size: 200419,
block_weight: 200419, block_weight: 200419,
@ -409,7 +409,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse { GET_BLOCK_HEADER_BY_HASH_RESPONSE => GetBlockHeaderByHashResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
block_headers: vec![], block_headers: vec![],
block_header: BlockHeader { block_header: BlockHeader {
block_size: 210, block_size: 210,
@ -464,7 +464,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse { GET_BLOCK_HEADER_BY_HEIGHT_RESPONSE => GetBlockHeaderByHeightResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
block_header: BlockHeader { block_header: BlockHeader {
block_size: 210, block_size: 210,
block_weight: 210, block_weight: 210,
@ -519,7 +519,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse { GET_BLOCK_HEADERS_RANGE_RESPONSE => GetBlockHeadersRangeResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
headers: vec![ headers: vec![
BlockHeader { BlockHeader {
block_size: 301413, block_size: 301413,
@ -601,7 +601,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BLOCK_RESPONSE => GetBlockResponse { GET_BLOCK_RESPONSE => GetBlockResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(), blob: "1010c58bab9b06b27bdecfc6cd0a46172d136c08831cf67660377ba992332363228b1b722781e7807e07f502cef8a70101ff92f8a7010180e0a596bb1103d7cbf826b665d7a532c316982dc8dbc24f285cbc18bbcc27c7164cd9b3277a85d034019f629d8b36bd16a2bfce3ea80c31dc4d8762c67165aec21845494e32b7582fe00211000000297a787a000000000000000000000000".into(),
block_header: BlockHeader { block_header: BlockHeader {
block_size: 106, block_size: 106,
@ -654,7 +654,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_CONNECTIONS_RESPONSE => GetConnectionsResponse { GET_CONNECTIONS_RESPONSE => GetConnectionsResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
connections: vec![ connections: vec![
ConnectionInfo { ConnectionInfo {
address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(), address: "3evk3kezfjg44ma6tvesy7rbxwwpgpympj45xar5fo4qajrsmkoaqdqd.onion:18083".into(),
@ -728,7 +728,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_INFO_RESPONSE => GetInfoResponse { GET_INFO_RESPONSE => GetInfoResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
adjusted_time: 1721245289, adjusted_time: 1721245289,
alt_blocks_count: 16, alt_blocks_count: 16,
block_size_limit: 600000, block_size_limit: 600000,
@ -831,7 +831,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
HARD_FORK_INFO_RESPONSE => HardForkInfoResponse { HARD_FORK_INFO_RESPONSE => HardForkInfoResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
earliest_height: 2689608, earliest_height: 2689608,
enabled: true, enabled: true,
state: 0, state: 0,
@ -877,7 +877,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SET_BANS_RESPONSE => SetBansResponse { SET_BANS_RESPONSE => SetBansResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -892,7 +892,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_BANS_RESPONSE => GetBansResponse { GET_BANS_RESPONSE => GetBansResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
bans: vec![ bans: vec![
GetBan { GetBan {
host: "104.248.206.131".into(), host: "104.248.206.131".into(),
@ -994,7 +994,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse { GET_OUTPUT_HISTOGRAM_RESPONSE => GetOutputHistogramResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
histogram: vec![HistogramEntry { histogram: vec![HistogramEntry {
amount: 20000000000, amount: 20000000000,
recent_instances: 0, recent_instances: 0,
@ -1028,7 +1028,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse { GET_COINBASE_TX_SUM_RESPONSE => GetCoinbaseTxSumResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
emission_amount: 9387854817320, emission_amount: 9387854817320,
emission_amount_top64: 0, emission_amount_top64: 0,
fee_amount: 83981380000, fee_amount: 83981380000,
@ -1057,7 +1057,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_VERSION_RESPONSE => GetVersionResponse { GET_VERSION_RESPONSE => GetVersionResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
current_height: 3195051, current_height: 3195051,
hard_forks: vec![ hard_forks: vec![
HardforkEntry { HardforkEntry {
@ -1143,12 +1143,16 @@ define_request_and_response! {
get_fee_estimate, get_fee_estimate,
cc73fe71162d564ffda8e549b79a350bca53c454 => cc73fe71162d564ffda8e549b79a350bca53c454 =>
core_rpc_server_commands_defs.h => 2250..=2277, core_rpc_server_commands_defs.h => 2250..=2277,
GetFeeEstimate (empty),
Request {}, GetFeeEstimate,
Request {
grace_blocks: u64 = default_zero::<u64>(), "default_zero",
},
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse { GET_FEE_ESTIMATE_RESPONSE => GetFeeEstimateResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
fee: 20000, fee: 20000,
fees: vec![20000,80000,320000,4000000], fees: vec![20000,80000,320000,4000000],
quantization_mask: 10000, quantization_mask: 10000,
@ -1170,7 +1174,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse { GET_ALTERNATE_CHAINS_RESPONSE => GetAlternateChainsResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
chains: vec![ chains: vec![
ChainInfo { ChainInfo {
block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(), block_hash: "4826c7d45d7cf4f02985b5c405b0e5d7f92c8d25e015492ce19aa3b209295dce".into(),
@ -1238,7 +1242,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SYNC_INFO_RESPONSE => SyncInfoResponse { SYNC_INFO_RESPONSE => SyncInfoResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
height: 3195157, height: 3195157,
next_needed_pruning_seed: 0, next_needed_pruning_seed: 0,
overview: "[]".into(), overview: "[]".into(),
@ -1328,7 +1332,7 @@ define_request_and_response! {
// TODO: enable test after binary string impl. // TODO: enable test after binary string impl.
// #[doc = serde_doc_test!( // #[doc = serde_doc_test!(
// GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse { // GET_TRANSACTION_POOL_BACKLOG_RESPONSE => GetTransactionPoolBacklogResponse {
// base: ResponseBase::ok(), // base: ResponseBase::OK,
// backlog: "...Binary...".into(), // backlog: "...Binary...".into(),
// } // }
// )] // )]
@ -1370,7 +1374,7 @@ define_request_and_response! {
// TODO: enable test after binary string impl. // TODO: enable test after binary string impl.
// #[doc = serde_doc_test!( // #[doc = serde_doc_test!(
// GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse { // GET_OUTPUT_DISTRIBUTION_RESPONSE => GetOutputDistributionResponse {
// base: AccessResponseBase::ok(), // base: AccessResponseBase::OK,
// distributions: vec![Distribution::Uncompressed(DistributionUncompressed { // distributions: vec![Distribution::Uncompressed(DistributionUncompressed {
// start_height: 1462078, // start_height: 1462078,
// base: 0, // base: 0,
@ -1394,7 +1398,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_MINER_DATA_RESPONSE => GetMinerDataResponse { GET_MINER_DATA_RESPONSE => GetMinerDataResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
already_generated_coins: 18186022843595960691, already_generated_coins: 18186022843595960691,
difficulty: "0x48afae42de".into(), difficulty: "0x48afae42de".into(),
height: 2731375, height: 2731375,
@ -1447,7 +1451,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse { PRUNE_BLOCKCHAIN_RESPONSE => PruneBlockchainResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
pruned: true, pruned: true,
pruning_seed: 387, pruning_seed: 387,
} }
@ -1513,7 +1517,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
FLUSH_CACHE_RESPONSE => FlushCacheResponse { FLUSH_CACHE_RESPONSE => FlushCacheResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -1542,7 +1546,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
ADD_AUX_POW_RESPONSE => AddAuxPowResponse { ADD_AUX_POW_RESPONSE => AddAuxPowResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
aux_pow: vec![AuxPow { aux_pow: vec![AuxPow {
hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(), hash: "7b35762de164b20885e15dbe656b1138db06bb402fa1796f5765a23933d8859a".into(),
id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(), id: "3200b4ea97c3b2081cd4190b58e49572b2319fed00d030ad51809dff06b5d8c8".into(),

View file

@ -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<Self> {
Some(match u {
0 => Self::Invalid,
1 => Self::Ipv4,
2 => Self::Ipv6,
3 => Self::I2p,
4 => Self::Tor,
_ => return None,
})
}
}
impl From<AddressType> for u8 {
fn from(value: AddressType) -> Self {
value.to_u8()
}
}
#[cfg(feature = "epee")]
impl EpeeValue for AddressType {
const MARKER: Marker = u8::MARKER;
fn read<B: Buf>(r: &mut B, marker: &Marker) -> error::Result<Self> {
let u = u8::read(r, marker)?;
Self::from_u8(u).ok_or(error::Error::Format("u8 was greater than 4"))
}
fn write<B: BufMut>(self, w: &mut B) -> error::Result<()> {
let u = self.to_u8();
u8::write(u, w)?;
Ok(())
}
}

View file

@ -110,7 +110,7 @@ define_struct_and_impl_epee! {
/// Used in [`crate::json::GetConnectionsResponse`]. /// Used in [`crate::json::GetConnectionsResponse`].
ConnectionInfo { ConnectionInfo {
address: String, address: String,
address_type: u8, address_type: crate::misc::AddressType,
avg_download: u64, avg_download: u64,
avg_upload: u64, avg_upload: u64,
connection_id: String, connection_id: String,

View file

@ -12,6 +12,7 @@
)] )]
//---------------------------------------------------------------------------------------------------- Mod //---------------------------------------------------------------------------------------------------- Mod
mod address_type;
mod binary_string; mod binary_string;
mod distribution; mod distribution;
mod key_image_spent_status; mod key_image_spent_status;
@ -21,6 +22,7 @@ mod pool_info_extent;
mod status; mod status;
mod tx_entry; mod tx_entry;
pub use address_type::AddressType;
pub use binary_string::BinaryString; pub use binary_string::BinaryString;
pub use distribution::{Distribution, DistributionCompressedBinary, DistributionUncompressed}; pub use distribution::{Distribution, DistributionCompressedBinary, DistributionUncompressed};
pub use key_image_spent_status::KeyImageSpentStatus; pub use key_image_spent_status::KeyImageSpentStatus;

View file

@ -102,7 +102,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_HEIGHT_RESPONSE => GetHeightResponse { GET_HEIGHT_RESPONSE => GetHeightResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(), hash: "68bb1a1cff8e2a44c3221e8e1aff80bc6ca45d06fa8eff4d2a3a7ac31d4efe3f".into(),
height: 3195160, height: 3195160,
} }
@ -157,7 +157,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse { GET_ALT_BLOCKS_HASHES_RESPONSE => GetAltBlocksHashesResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()], blks_hashes: vec!["8ee10db35b1baf943f201b303890a29e7d45437bd76c2bd4df0d2f2ee34be109".into()],
} }
)] )]
@ -187,7 +187,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
IS_KEY_IMAGE_SPENT_RESPONSE => IsKeyImageSpentResponse { IS_KEY_IMAGE_SPENT_RESPONSE => IsKeyImageSpentResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
spent_status: vec![1, 1], spent_status: vec![1, 1],
} }
)] )]
@ -283,7 +283,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
START_MINING_RESPONSE => StartMiningResponse { START_MINING_RESPONSE => StartMiningResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -298,7 +298,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
STOP_MINING_RESPONSE => StopMiningResponse { STOP_MINING_RESPONSE => StopMiningResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -313,7 +313,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
MINING_STATUS_RESPONSE => MiningStatusResponse { MINING_STATUS_RESPONSE => MiningStatusResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
active: false, active: false,
address: "".into(), address: "".into(),
bg_idle_threshold: 0, bg_idle_threshold: 0,
@ -359,7 +359,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SAVE_BC_RESPONSE => SaveBcResponse { SAVE_BC_RESPONSE => SaveBcResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -385,7 +385,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_PEER_LIST_RESPONSE => GetPeerListResponse { GET_PEER_LIST_RESPONSE => GetPeerListResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
gray_list: vec![ gray_list: vec![
Peer { Peer {
host: "161.97.193.0".into(), host: "161.97.193.0".into(),
@ -467,7 +467,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse { SET_LOG_HASH_RATE_RESPONSE => SetLogHashRateResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -492,7 +492,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SET_LOG_LEVEL_RESPONSE => SetLogLevelResponse { SET_LOG_LEVEL_RESPONSE => SetLogLevelResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
} }
)] )]
ResponseBase {} ResponseBase {}
@ -516,7 +516,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SET_LOG_CATEGORIES_RESPONSE => SetLogCategoriesResponse { SET_LOG_CATEGORIES_RESPONSE => SetLogCategoriesResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
categories: "*:INFO".into(), categories: "*:INFO".into(),
} }
)] )]
@ -582,7 +582,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_TRANSACTION_POOL_STATS_RESPONSE => GetTransactionPoolStatsResponse { GET_TRANSACTION_POOL_STATS_RESPONSE => GetTransactionPoolStatsResponse {
base: AccessResponseBase::ok(), base: AccessResponseBase::OK,
pool_stats: TxpoolStats { pool_stats: TxpoolStats {
bytes_max: 11843, bytes_max: 11843,
bytes_med: 2219, bytes_med: 2219,
@ -644,7 +644,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_LIMIT_RESPONSE => GetLimitResponse { GET_LIMIT_RESPONSE => GetLimitResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
limit_down: 1280000, limit_down: 1280000,
limit_up: 1280000, limit_up: 1280000,
} }
@ -676,7 +676,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
SET_LIMIT_RESPONSE => SetLimitResponse { SET_LIMIT_RESPONSE => SetLimitResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
limit_down: 1024, limit_down: 1024,
limit_up: 128, limit_up: 128,
} }
@ -707,7 +707,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
OUT_PEERS_RESPONSE => OutPeersResponse { OUT_PEERS_RESPONSE => OutPeersResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
out_peers: 3232235535, out_peers: 3232235535,
} }
)] )]
@ -740,7 +740,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_NET_STATS_RESPONSE => GetNetStatsResponse { GET_NET_STATS_RESPONSE => GetNetStatsResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
start_time: 1721251858, start_time: 1721251858,
total_bytes_in: 16283817214, total_bytes_in: 16283817214,
total_bytes_out: 34225244079, total_bytes_out: 34225244079,
@ -779,7 +779,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_OUTS_RESPONSE => GetOutsResponse { GET_OUTS_RESPONSE => GetOutsResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
outs: vec![ outs: vec![
OutKey { OutKey {
height: 51941, height: 51941,
@ -823,7 +823,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
UPDATE_RESPONSE => UpdateResponse { UPDATE_RESPONSE => UpdateResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
auto_uri: "".into(), auto_uri: "".into(),
hash: "".into(), hash: "".into(),
path: "".into(), path: "".into(),
@ -860,7 +860,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
POP_BLOCKS_RESPONSE => PopBlocksResponse { POP_BLOCKS_RESPONSE => PopBlocksResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
height: 76482, height: 76482,
} }
)] )]
@ -879,7 +879,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_TRANSACTION_POOL_HASHES_RESPONSE => GetTransactionPoolHashesResponse { GET_TRANSACTION_POOL_HASHES_RESPONSE => GetTransactionPoolHashesResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
tx_hashes: vec![ tx_hashes: vec![
"aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(), "aa928aed888acd6152c60194d50a4df29b0b851be6169acf11b6a8e304dd6c03".into(),
"794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(), "794345f321a98f3135151f3056c0fdf8188646a8dab27de971428acf3551dd11".into(),
@ -929,7 +929,7 @@ define_request_and_response! {
#[doc = serde_doc_test!( #[doc = serde_doc_test!(
GET_PUBLIC_NODES_RESPONSE => GetPublicNodesResponse { GET_PUBLIC_NODES_RESPONSE => GetPublicNodesResponse {
base: ResponseBase::ok(), base: ResponseBase::OK,
gray: vec![], gray: vec![],
white: vec![ white: vec![
PublicNode { PublicNode {

View file

@ -121,6 +121,8 @@ fn map_request(
R::DatabaseSize => database_size(env), R::DatabaseSize => database_size(env),
R::OutputHistogram(input) => output_histogram(env, input), R::OutputHistogram(input) => output_histogram(env, input),
R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count), R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count),
R::AltChains => alt_chains(env),
R::AltChainCount => alt_chain_count(env),
} }
/* SOMEDAY: post-request handling, run some code for each request? */ /* SOMEDAY: post-request handling, run some code for each request? */
@ -648,3 +650,13 @@ fn output_histogram(env: &ConcreteEnv, input: OutputHistogramInput) -> ResponseR
fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResult { fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResult {
Ok(BlockchainResponse::CoinbaseTxSum(todo!())) Ok(BlockchainResponse::CoinbaseTxSum(todo!()))
} }
/// [`BlockchainReadRequest::AltChains`]
fn alt_chains(env: &ConcreteEnv) -> ResponseResult {
Ok(BlockchainResponse::AltChains(todo!()))
}
/// [`BlockchainReadRequest::AltChainCount`]
fn alt_chain_count(env: &ConcreteEnv) -> ResponseResult {
Ok(BlockchainResponse::AltChainCount(todo!()))
}

View file

@ -15,7 +15,7 @@ pub mod types;
pub use config::Config; pub use config::Config;
pub use free::open; pub use free::open;
pub use tx::TxEntry; pub use tx::{BlockTemplateTxEntry, TxEntry};
//re-exports //re-exports
pub use cuprate_database; pub use cuprate_database;

View file

@ -5,7 +5,10 @@ use std::sync::Arc;
use cuprate_types::TransactionVerificationData; use cuprate_types::TransactionVerificationData;
use crate::{tx::TxEntry, types::TransactionHash}; use crate::{
tx::{BlockTemplateTxEntry, TxEntry},
types::TransactionHash,
};
//---------------------------------------------------------------------------------------------------- TxpoolReadRequest //---------------------------------------------------------------------------------------------------- TxpoolReadRequest
/// The transaction pool [`tower::Service`] read request type. /// The transaction pool [`tower::Service`] read request type.
@ -19,8 +22,18 @@ pub enum TxpoolReadRequest {
/// Get information on all transactions in the pool. /// Get information on all transactions in the pool.
Backlog, Backlog,
/// 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. /// Get the number of transactions in the pool.
Size, Size {
/// If this is [`true`], the size returned will
/// include private transactions in the pool.
include_sensitive_txs: bool,
},
} }
//---------------------------------------------------------------------------------------------------- TxpoolReadResponse //---------------------------------------------------------------------------------------------------- TxpoolReadResponse
@ -38,10 +51,15 @@ pub enum TxpoolReadResponse {
/// Response to [`TxpoolReadRequest::Backlog`]. /// Response to [`TxpoolReadRequest::Backlog`].
/// ///
/// The inner `Vec` contains information on all /// The inner [`Vec`] contains information on all
/// the transactions currently in the pool. /// the transactions currently in the pool.
Backlog(Vec<TxEntry>), Backlog(Vec<TxEntry>),
/// Response to [`TxpoolReadRequest::BlockTemplateBacklog`].
///
/// The inner [`Vec`] contains information on transactions
BlockTemplateBacklog(Vec<BlockTemplateTxEntry>),
/// Response to [`TxpoolReadRequest::Size`]. /// Response to [`TxpoolReadRequest::Size`].
/// ///
/// The inner value is the amount of /// The inner value is the amount of

View file

@ -66,7 +66,10 @@ fn map_request(
TxpoolReadRequest::TxBlob(tx_hash) => tx_blob(env, &tx_hash), TxpoolReadRequest::TxBlob(tx_hash) => tx_blob(env, &tx_hash),
TxpoolReadRequest::TxVerificationData(tx_hash) => tx_verification_data(env, &tx_hash), TxpoolReadRequest::TxVerificationData(tx_hash) => tx_verification_data(env, &tx_hash),
TxpoolReadRequest::Backlog => backlog(env), TxpoolReadRequest::Backlog => backlog(env),
TxpoolReadRequest::Size => size(env), TxpoolReadRequest::BlockTemplateBacklog => block_template_backlog(env),
TxpoolReadRequest::Size {
include_sensitive_txs,
} => size(env, include_sensitive_txs),
} }
} }
@ -117,8 +120,14 @@ fn backlog(env: &ConcreteEnv) -> ReadResponseResult {
Ok(TxpoolReadResponse::Backlog(todo!())) Ok(TxpoolReadResponse::Backlog(todo!()))
} }
/// [`TxpoolReadRequest::BlockTemplateBacklog`].
#[inline]
fn block_template_backlog(env: &ConcreteEnv) -> ReadResponseResult {
Ok(TxpoolReadResponse::BlockTemplateBacklog(todo!()))
}
/// [`TxpoolReadRequest::Size`]. /// [`TxpoolReadRequest::Size`].
#[inline] #[inline]
fn size(env: &ConcreteEnv) -> ReadResponseResult { fn size(env: &ConcreteEnv, include_sensitive_txs: bool) -> ReadResponseResult {
Ok(TxpoolReadResponse::Size(todo!())) Ok(TxpoolReadResponse::Size(todo!()))
} }

View file

@ -12,3 +12,17 @@ pub struct TxEntry {
/// How long the transaction has been in the pool. /// How long the transaction has been in the pool.
pub time_in_pool: std::time::Duration, pub time_in_pool: std::time::Duration,
} }
/// 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 {
/// The transaction's ID (hash).
pub id: [u8; 32],
/// The transaction's weight.
pub weight: u64,
/// The transaction's fee.
pub fee: u64,
}

View file

@ -12,7 +12,8 @@ use monero_serai::block::Block;
use crate::{ use crate::{
types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation}, types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation},
AltBlockInformation, ChainId, CoinbaseTxSum, OutputHistogramEntry, OutputHistogramInput, AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, OutputHistogramEntry,
OutputHistogramInput,
}; };
//---------------------------------------------------------------------------------------------------- ReadRequest //---------------------------------------------------------------------------------------------------- ReadRequest
@ -128,6 +129,12 @@ pub enum BlockchainReadRequest {
/// ///
/// TODO: document fields after impl. /// TODO: document fields after impl.
CoinbaseTxSum { height: usize, count: u64 }, CoinbaseTxSum { height: usize, count: u64 },
/// Get information on all alternative chains.
AltChains,
/// Get the amount of alternative chains that exist.
AltChainCount,
} }
//---------------------------------------------------------------------------------------------------- WriteRequest //---------------------------------------------------------------------------------------------------- WriteRequest
@ -276,6 +283,12 @@ pub enum BlockchainResponse {
/// Response to [`BlockchainReadRequest::CoinbaseTxSum`]. /// Response to [`BlockchainReadRequest::CoinbaseTxSum`].
CoinbaseTxSum(CoinbaseTxSum), CoinbaseTxSum(CoinbaseTxSum),
/// Response to [`BlockchainReadRequest::AltChains`].
AltChains(Vec<ChainInfo>),
/// Response to [`BlockchainReadRequest::AltChainCount`].
AltChainCount(usize),
//------------------------------------------------------ Writes //------------------------------------------------------ Writes
/// A generic Ok response to indicate a request was successfully handled. /// A generic Ok response to indicate a request was successfully handled.
/// ///

View file

@ -20,9 +20,10 @@ pub use transaction_verification_data::{
CachedVerificationState, TransactionVerificationData, TxVersion, CachedVerificationState, TransactionVerificationData, TxVersion,
}; };
pub use types::{ pub use types::{
AltBlockInformation, Chain, ChainId, ChainInfo, CoinbaseTxSum, ExtendedBlockHeader, AddAuxPow, AltBlockInformation, AuxPow, Chain, ChainId, ChainInfo, CoinbaseTxSum,
FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry, OutputHistogramEntry, ExtendedBlockHeader, FeeEstimate, HardForkInfo, MinerData, MinerDataTxBacklogEntry,
OutputHistogramInput, OutputOnChain, VerifiedBlockInformation, VerifiedTransactionInformation, OutputHistogramEntry, OutputHistogramInput, OutputOnChain, VerifiedBlockInformation,
VerifiedTransactionInformation,
}; };
//---------------------------------------------------------------------------------------------------- Feature-gated //---------------------------------------------------------------------------------------------------- Feature-gated

View file

@ -177,8 +177,6 @@ pub struct OutputHistogramEntry {
pub struct CoinbaseTxSum { pub struct CoinbaseTxSum {
pub emission_amount: u128, pub emission_amount: u128,
pub fee_amount: u128, pub fee_amount: u128,
pub wide_emission_amount: u128,
pub wide_fee_amount: u128,
} }
/// Data to create a custom block template. /// Data to create a custom block template.
@ -242,7 +240,23 @@ pub struct ChainInfo {
pub height: u64, pub height: u64,
pub length: u64, pub length: u64,
pub main_chain_parent_block: [u8; 32], pub main_chain_parent_block: [u8; 32],
pub wide_difficulty: u128, }
/// 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<u8>,
pub blockhashing_blob: Vec<u8>,
pub merkle_root: [u8; 32],
pub merkle_tree_depth: u64,
pub aux_pow: Vec<AuxPow>,
} }
//---------------------------------------------------------------------------------------------------- Tests //---------------------------------------------------------------------------------------------------- Tests