Compare commits

..

2 commits

Author SHA1 Message Date
hinto.janai
13eedc6d80
sig docs, remove HardForks request
Some checks failed
Audit / audit (push) Has been cancelled
Deny / audit (push) Has been cancelled
2024-10-17 18:32:47 -04:00
hinto.janai
98dfaa4870
docs, ConnectionInfo, AddressType 2024-10-17 17:13:37 -04:00
14 changed files with 249 additions and 91 deletions

1
Cargo.lock generated
View file

@ -1010,6 +1010,7 @@ dependencies = [
"serde",
"serde_bytes",
"serde_json",
"strum",
"thiserror",
"thread_local",
"tokio",

View file

@ -65,6 +65,7 @@ rayon = { workspace = true }
serde_bytes = { workspace = true }
serde_json = { workspace = true }
serde = { workspace = true }
strum = { workspace = true }
thiserror = { workspace = true }
thread_local = { workspace = true }
tokio-util = { workspace = true }

View file

@ -5,7 +5,9 @@ use std::{
use anyhow::{anyhow, Error};
use cuprate_p2p_core::{client::handshaker::builder::DummyAddressBook, ClearNet};
use futures::TryFutureExt;
use monero_serai::block::Block;
use strum::{EnumCount, VariantArray};
use tower::{Service, ServiceExt};
use cuprate_consensus::{BlockchainReadRequest, BlockchainResponse};
@ -673,14 +675,20 @@ async fn get_version(
let current_height = helper::top_height(&mut state).await?.0;
let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?;
let hard_forks = blockchain::hard_forks(&mut state.blockchain_read)
.await?
.into_iter()
.map(|(height, hf)| HardforkEntry {
height: usize_to_u64(height),
hf_version: hf.as_u8(),
})
.collect();
let mut hard_forks = Vec::with_capacity(HardFork::COUNT);
// FIXME: use an iterator `collect()` version.
for hf in HardFork::VARIANTS {
if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await
{
let entry = HardforkEntry {
height: hf.earliest_height,
hf_version: hf.version,
};
hard_forks.push(entry);
}
}
Ok(GetVersionResponse {
base: ResponseBase::OK,

View file

@ -52,32 +52,45 @@ pub(crate) async fn connection_info<Z: NetworkZone>(
// FIXME: impl this map somewhere instead of inline.
let vec = vec
.into_iter()
.map(|info| ConnectionInfo {
address: info.address.to_string(),
address_type: info.address_type,
avg_download: info.avg_download,
avg_upload: info.avg_upload,
connection_id: info.connection_id,
current_download: info.current_download,
current_upload: info.current_upload,
height: info.height,
host: info.host,
incoming: info.incoming,
ip: info.ip,
live_time: info.live_time,
localhost: info.localhost,
local_ip: info.local_ip,
peer_id: info.peer_id,
port: info.port,
pruning_seed: info.pruning_seed,
recv_count: info.recv_count,
recv_idle_time: info.recv_idle_time,
rpc_credits_per_hash: info.rpc_credits_per_hash,
rpc_port: info.rpc_port,
send_count: info.send_count,
send_idle_time: info.send_idle_time,
state: info.state,
support_flags: info.support_flags,
.map(|info| {
use cuprate_p2p_core::types::AddressType as A1;
use cuprate_rpc_types::misc::AddressType as A2;
let address_type = match info.address_type {
A1::Invalid => A2::Invalid,
A1::Ipv4 => A2::Ipv4,
A1::Ipv6 => A2::Ipv6,
A1::I2p => A2::I2p,
A1::Tor => A2::Tor,
};
ConnectionInfo {
address: info.address.to_string(),
address_type,
avg_download: info.avg_download,
avg_upload: info.avg_upload,
connection_id: hex::encode(info.connection_id.to_ne_bytes()),
current_download: info.current_download,
current_upload: info.current_upload,
height: info.height,
host: info.host,
incoming: info.incoming,
ip: info.ip,
live_time: info.live_time,
localhost: info.localhost,
local_ip: info.local_ip,
peer_id: info.peer_id,
port: info.port,
pruning_seed: info.pruning_seed.compress(),
recv_count: info.recv_count,
recv_idle_time: info.recv_idle_time,
rpc_credits_per_hash: info.rpc_credits_per_hash,
rpc_port: info.rpc_port,
send_count: info.send_count,
send_idle_time: info.send_idle_time,
state: info.state,
support_flags: info.support_flags,
}
})
.collect();
@ -177,10 +190,10 @@ pub(crate) async fn spans<Z: NetworkZone>(
let vec = vec
.into_iter()
.map(|span| Span {
connection_id: span.connection_id,
connection_id: hex::encode(span.connection_id.to_ne_bytes()),
nblocks: span.nblocks,
rate: span.rate,
remote_address: span.remote_address,
remote_address: span.remote_address.to_string(),
size: span.size,
speed: span.speed,
start_block_height: span.start_block_height,

View file

@ -344,22 +344,6 @@ pub(crate) async fn coinbase_tx_sum(
Ok(sum)
}
/// [`BlockchainReadRequest::HardForks`]
pub(crate) async fn hard_forks(
blockchain_read: &mut BlockchainReadHandle,
) -> Result<BTreeMap<usize, HardFork>, Error> {
let BlockchainResponse::HardForks(hfs) = blockchain_read
.ready()
.await?
.call(BlockchainReadRequest::HardForks)
.await?
else {
unreachable!();
};
Ok(hfs)
}
/// [`BlockchainReadRequest::AltChains`]
pub(crate) async fn alt_chains(
blockchain_read: &mut BlockchainReadHandle,

View file

@ -133,10 +133,13 @@ pub enum AddressBookRequest<Z: NetworkZone> {
/// Get the state of all bans.
GetBans,
/// TODO
/// Get [`Span`] data.
///
/// This is data that describes an active downloading process,
/// if we are fully synced, this will return an empty [`Vec`].
Spans,
/// TODO
/// Get the next [`PruningSeed`] needed for a pruned sync.
NextNeededPruningSeed,
}
@ -177,7 +180,7 @@ pub enum AddressBookResponse<Z: NetworkZone> {
GetBans(Vec<BanState<Z::Addr>>),
/// Response to [`AddressBookRequest::Spans`].
Spans(Vec<Span>),
Spans(Vec<Span<Z::Addr>>),
/// Response to [`AddressBookRequest::NextNeededPruningSeed`].
NextNeededPruningSeed(PruningSeed),

View file

@ -2,6 +2,8 @@
use std::time::{Duration, Instant};
use cuprate_pruning::PruningSeed;
use crate::NetZoneAddress;
/// Data within [`crate::services::AddressBookRequest::SetBan`].
@ -22,15 +24,72 @@ pub struct BanState<A: NetZoneAddress> {
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: u8,
pub address_type: AddressType,
pub avg_download: u64,
pub avg_upload: u64,
pub connection_id: String,
pub connection_id: u64, // TODO: boost::uuids::uuid
pub current_download: u64,
pub current_upload: u64,
pub height: u64,
@ -42,14 +101,14 @@ pub struct ConnectionInfo<A: NetZoneAddress> {
pub local_ip: bool,
pub peer_id: String,
pub port: String,
pub pruning_seed: u32,
pub pruning_seed: PruningSeed,
pub recv_count: u64,
pub recv_idle_time: u64,
pub rpc_credits_per_hash: u32,
pub rpc_port: u16,
pub send_count: u64,
pub send_idle_time: u64,
pub state: String,
pub state: String, // TODO: what type is this?
pub support_flags: u32,
}
@ -57,11 +116,11 @@ pub struct ConnectionInfo<A: NetZoneAddress> {
///
/// Data within [`crate::services::AddressBookResponse::Spans`].
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Span {
pub connection_id: String,
pub struct Span<A: NetZoneAddress> {
pub connection_id: u64, // TODO: boost::uuids::uuid
pub nblocks: u64,
pub rate: u32,
pub remote_address: String,
pub remote_address: A,
pub size: u64,
pub speed: u32,
pub start_block_height: u64,

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`].
ConnectionInfo {
address: String,
address_type: u8,
address_type: crate::misc::AddressType,
avg_download: u64,
avg_upload: u64,
connection_id: String,

View file

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

View file

@ -121,7 +121,6 @@ fn map_request(
R::DatabaseSize => database_size(env),
R::OutputHistogram(input) => output_histogram(env, input),
R::CoinbaseTxSum { height, count } => coinbase_tx_sum(env, height, count),
R::HardForks => hard_forks(env),
R::AltChains => alt_chains(env),
R::AltChainCount => alt_chain_count(env),
}
@ -652,11 +651,6 @@ fn coinbase_tx_sum(env: &ConcreteEnv, height: usize, count: u64) -> ResponseResu
Ok(BlockchainResponse::CoinbaseTxSum(todo!()))
}
/// [`BlockchainReadRequest::HardForks`]
fn hard_forks(env: &ConcreteEnv) -> ResponseResult {
Ok(BlockchainResponse::HardForks(todo!()))
}
/// [`BlockchainReadRequest::AltChains`]
fn alt_chains(env: &ConcreteEnv) -> ResponseResult {
Ok(BlockchainResponse::AltChains(todo!()))

View file

@ -22,12 +22,16 @@ pub enum TxpoolReadRequest {
/// Get information on all transactions in the pool.
Backlog,
/// TODO
/// Get information on all transactions in
/// the pool for block template purposes.
///
/// This is only slightly different to [`TxpoolReadRequest::Backlog`].
BlockTemplateBacklog,
/// Get the number of transactions in the pool.
Size {
/// TODO
/// If this is [`true`], the size returned will
/// include private transactions in the pool.
include_sensitive_txs: bool,
},
}
@ -47,13 +51,13 @@ pub enum TxpoolReadResponse {
/// Response to [`TxpoolReadRequest::Backlog`].
///
/// The inner `Vec` contains information on all
/// The inner [`Vec`] contains information on all
/// the transactions currently in the pool.
Backlog(Vec<TxEntry>),
/// Response to [`TxpoolReadRequest::BlockTemplateBacklog`].
///
/// TODO
/// The inner [`Vec`] contains information on transactions
BlockTemplateBacklog(Vec<BlockTemplateTxEntry>),
/// Response to [`TxpoolReadRequest::Size`].

View file

@ -13,15 +13,16 @@ pub struct TxEntry {
pub time_in_pool: std::time::Duration,
}
/// TODO
/// Data about a transaction in the pool
/// for use in a block template.
///
/// Used in [`TxpoolReadResponse::BlockTemplateBacklog`](crate::service::interface::TxpoolReadResponse::BlockTemplateBacklog).
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct BlockTemplateTxEntry {
/// TODO
/// The transaction's ID (hash).
pub id: [u8; 32],
/// TODO
/// The transaction's weight.
pub weight: u64,
/// TODO
/// The transaction's fee.
pub fee: u64,
}

View file

@ -4,7 +4,7 @@
//! responses are also tested in Cuprate's blockchain database crate.
//---------------------------------------------------------------------------------------------------- Import
use std::{
collections::{BTreeMap, HashMap, HashSet},
collections::{HashMap, HashSet},
ops::Range,
};
@ -12,7 +12,7 @@ use monero_serai::block::Block;
use crate::{
types::{Chain, ExtendedBlockHeader, OutputOnChain, VerifiedBlockInformation},
AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, HardFork, OutputHistogramEntry,
AltBlockInformation, ChainId, ChainInfo, CoinbaseTxSum, OutputHistogramEntry,
OutputHistogramInput,
};
@ -130,13 +130,10 @@ pub enum BlockchainReadRequest {
/// TODO: document fields after impl.
CoinbaseTxSum { height: usize, count: u64 },
/// TODO
HardForks,
/// TODO
/// Get information on all alternative chains.
AltChains,
/// TODO
/// Get the amount of alternative chains that exist.
AltChainCount,
}
@ -286,13 +283,7 @@ pub enum BlockchainResponse {
/// Response to [`BlockchainReadRequest::CoinbaseTxSum`].
CoinbaseTxSum(CoinbaseTxSum),
/// Response to [`BlockchainReadRequest::HardForks`].
///
/// - Key = height at which the hardfork activated
/// - Value = hardfork version
HardForks(BTreeMap<usize, HardFork>),
/// TODO
/// Response to [`BlockchainReadRequest::AltChains`].
AltChains(Vec<ChainInfo>),
/// Response to [`BlockchainReadRequest::AltChainCount`].