mirror of
https://github.com/Cuprate/cuprate.git
synced 2024-12-23 20:19:31 +00:00
bin: get_blocks_by_height
, get_hashes
This commit is contained in:
parent
4f738eef38
commit
6dc85c606f
5 changed files with 209 additions and 5 deletions
|
@ -1,4 +1,4 @@
|
|||
use anyhow::Error;
|
||||
use anyhow::{anyhow, Error};
|
||||
|
||||
use cuprate_rpc_types::{
|
||||
base::{AccessResponseBase, ResponseBase},
|
||||
|
@ -9,9 +9,13 @@ use cuprate_rpc_types::{
|
|||
GetTransactionPoolHashesRequest, GetTransactionPoolHashesResponse,
|
||||
},
|
||||
json::{GetOutputDistributionRequest, GetOutputDistributionResponse},
|
||||
misc::RequestedInfo,
|
||||
};
|
||||
use cuprate_types::BlockCompleteEntry;
|
||||
|
||||
use crate::rpc::CupratedRpcHandlerState;
|
||||
use crate::rpc::{blockchain, helper, CupratedRpcHandlerState, RESTRICTED_TRANSACTIONS_COUNT};
|
||||
|
||||
use super::RESTRICTED_BLOCK_COUNT;
|
||||
|
||||
/// Map a [`BinRequest`] to the function that will lead to a [`BinResponse`].
|
||||
pub(super) async fn map_request(
|
||||
|
@ -41,6 +45,38 @@ async fn get_blocks(
|
|||
state: CupratedRpcHandlerState,
|
||||
request: GetBlocksRequest,
|
||||
) -> Result<GetBlocksResponse, Error> {
|
||||
// Time should be set early:
|
||||
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L628-L631>
|
||||
let daemon_time = cuprate_helper::time::current_unix_timestamp();
|
||||
|
||||
let Some(requested_info) = RequestedInfo::from_u8(request.requested_info) else {
|
||||
return Err(anyhow!("Failed, wrong requested info"));
|
||||
};
|
||||
|
||||
let (get_blocks, get_pool) = match requested_info {
|
||||
RequestedInfo::BlocksOnly => (true, false),
|
||||
RequestedInfo::BlocksAndPool => (true, true),
|
||||
RequestedInfo::PoolOnly => (false, true),
|
||||
};
|
||||
|
||||
if get_pool {
|
||||
let max_tx_count = if state.restricted {
|
||||
RESTRICTED_TRANSACTIONS_COUNT
|
||||
} else {
|
||||
usize::MAX
|
||||
};
|
||||
|
||||
todo!();
|
||||
}
|
||||
|
||||
if get_blocks {
|
||||
if !request.block_ids.is_empty() {
|
||||
todo!();
|
||||
}
|
||||
|
||||
todo!();
|
||||
}
|
||||
|
||||
// Ok(GetBlocksResponse {
|
||||
// base: ResponseBase::ok(),
|
||||
// ..todo!()
|
||||
|
@ -53,20 +89,55 @@ async fn get_blocks_by_height(
|
|||
state: CupratedRpcHandlerState,
|
||||
request: GetBlocksByHeightRequest,
|
||||
) -> Result<GetBlocksByHeightResponse, Error> {
|
||||
if state.restricted && request.heights.len() > RESTRICTED_BLOCK_COUNT {
|
||||
return Err(anyhow!("Too many blocks requested in restricted mode"));
|
||||
}
|
||||
|
||||
let blocks = request
|
||||
.heights
|
||||
.into_iter()
|
||||
.map(|height| Ok(todo!()))
|
||||
.collect::<Result<Vec<BlockCompleteEntry>, Error>>()?;
|
||||
|
||||
Ok(GetBlocksByHeightResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
..todo!()
|
||||
blocks,
|
||||
})
|
||||
}
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L859-L880>
|
||||
async fn get_hashes(
|
||||
state: CupratedRpcHandlerState,
|
||||
mut state: CupratedRpcHandlerState,
|
||||
request: GetHashesRequest,
|
||||
) -> Result<GetHashesResponse, Error> {
|
||||
let Some(last) = request.block_ids.last() else {
|
||||
return Err(anyhow!("block_ids empty"));
|
||||
};
|
||||
|
||||
const GENESIS_BLOCK_HASH: [u8; 32] = [0; 32]; // TODO
|
||||
if last != GENESIS_BLOCK_HASH {
|
||||
return Err(anyhow!(
|
||||
"genesis block mismatch, found: {last:?}, expected: {GENESIS_BLOCK_HASH:?}"
|
||||
));
|
||||
}
|
||||
|
||||
let mut bytes = request.block_ids;
|
||||
let hashes: Vec<[u8; 32]> = bytes.clone().into();
|
||||
|
||||
let (current_height, _) = helper::top_height(&mut state).await?;
|
||||
|
||||
let Some((index, start_height)) = blockchain::find_first_unknown(&mut state, hashes).await?
|
||||
else {
|
||||
return Err(anyhow!("Failed"));
|
||||
};
|
||||
|
||||
let m_blocks_ids = bytes.split_off(index);
|
||||
|
||||
Ok(GetHashesResponse {
|
||||
base: AccessResponseBase::ok(),
|
||||
..todo!()
|
||||
m_blocks_ids,
|
||||
start_height,
|
||||
current_height,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -188,6 +188,24 @@ pub(super) async fn pop_blocks(
|
|||
Ok(usize_to_u64(height))
|
||||
}
|
||||
|
||||
/// [`BlockchainResponse::FindFirstUnknown`]
|
||||
pub(super) async fn find_first_unknown(
|
||||
state: &mut CupratedRpcHandlerState,
|
||||
hashes: Vec<[u8; 32]>,
|
||||
) -> Result<Option<(usize, u64)>, Error> {
|
||||
let BlockchainResponse::FindFirstUnknown(resp) = state
|
||||
.blockchain_read
|
||||
.ready()
|
||||
.await?
|
||||
.call(BlockchainReadRequest::FindFirstUnknown(hashes))
|
||||
.await?
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
|
||||
Ok(resp.map(|(index, height)| (index, usize_to_u64(height))))
|
||||
}
|
||||
|
||||
// FindBlock([u8; 32]),
|
||||
// FilterUnknownHashes(HashSet<[u8; 32]>),
|
||||
// BlockExtendedHeaderInRange(Range<usize>, Chain),
|
||||
|
|
|
@ -154,6 +154,26 @@ impl<const N: usize> ByteArrayVec<N> {
|
|||
self.0
|
||||
}
|
||||
|
||||
pub fn first(&self) -> Option<[u8; N]> {
|
||||
let len = self.len();
|
||||
|
||||
if len == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self[0])
|
||||
}
|
||||
|
||||
pub fn last(&self) -> Option<[u8; N]> {
|
||||
let len = self.len();
|
||||
|
||||
if len == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(self[len - 1])
|
||||
}
|
||||
|
||||
/// Splits the byte array vec into two at the given index.
|
||||
///
|
||||
/// Afterwards self contains elements [0, at), and the returned [`ByteArrayVec`] contains elements [at, len).
|
||||
|
@ -246,6 +266,13 @@ impl<const N: usize> Index<usize> for ByteArrayVec<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<ByteArrayVec<N>> for Vec<[u8; N]> {
|
||||
fn from(value: ByteArrayVec<N>) -> Self {
|
||||
let len = value.len();
|
||||
(0..len).map(|i| value[i]).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde_json::{from_str, to_string};
|
||||
|
|
|
@ -18,6 +18,7 @@ mod key_image_spent_status;
|
|||
#[allow(clippy::module_inception)]
|
||||
mod misc;
|
||||
mod pool_info_extent;
|
||||
mod requested_info;
|
||||
mod status;
|
||||
mod tx_entry;
|
||||
|
||||
|
@ -31,5 +32,6 @@ pub use misc::{
|
|||
SyncInfoPeer, TxBacklogEntry, TxInfo, TxOutputIndices, TxpoolHisto, TxpoolStats,
|
||||
};
|
||||
pub use pool_info_extent::PoolInfoExtent;
|
||||
pub use requested_info::RequestedInfo;
|
||||
pub use status::Status;
|
||||
pub use tx_entry::TxEntry;
|
||||
|
|
86
rpc/types/src/misc/requested_info.rs
Normal file
86
rpc/types/src/misc/requested_info.rs
Normal file
|
@ -0,0 +1,86 @@
|
|||
//! TODO
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
use cuprate_epee_encoding::{
|
||||
error,
|
||||
macros::bytes::{Buf, BufMut},
|
||||
EpeeValue, Marker,
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- RequestedInfo
|
||||
#[doc = crate::macros::monero_definition_link!(
|
||||
cc73fe71162d564ffda8e549b79a350bca53c454,
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
178..=183
|
||||
)]
|
||||
/// Used in [`crate::bin::GetBlocksRequest`].
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[repr(u8)]
|
||||
pub enum RequestedInfo {
|
||||
#[default]
|
||||
BlocksOnly = 0,
|
||||
BlocksAndPool = 1,
|
||||
PoolOnly = 2,
|
||||
}
|
||||
|
||||
impl RequestedInfo {
|
||||
/// Convert [`Self`] to a [`u8`].
|
||||
///
|
||||
/// ```rust
|
||||
/// use cuprate_rpc_types::misc::RequestedInfo as R;
|
||||
///
|
||||
/// assert_eq!(R::BlocksOnly.to_u8(), 0);
|
||||
/// assert_eq!(R::BlocksAndPool.to_u8(), 1);
|
||||
/// assert_eq!(R::PoolOnly.to_u8(), 2);
|
||||
/// ```
|
||||
pub const fn to_u8(self) -> u8 {
|
||||
match self {
|
||||
Self::BlocksOnly => 0,
|
||||
Self::BlocksAndPool => 1,
|
||||
Self::PoolOnly => 2,
|
||||
}
|
||||
}
|
||||
|
||||
/// Convert a [`u8`] to a [`Self`].
|
||||
///
|
||||
/// # Errors
|
||||
/// This returns [`None`] if `u > 2`.
|
||||
///
|
||||
/// ```rust
|
||||
/// use cuprate_rpc_types::misc::RequestedInfo as R;
|
||||
///
|
||||
/// assert_eq!(R::from_u8(0), Some(R::BlocksOnly));
|
||||
/// assert_eq!(R::from_u8(1), Some(R::BlocksAndPool));
|
||||
/// assert_eq!(R::from_u8(2), Some(R::PoolOnly));
|
||||
/// assert_eq!(R::from_u8(3), None);
|
||||
/// ```
|
||||
pub const fn from_u8(u: u8) -> Option<Self> {
|
||||
Some(match u {
|
||||
0 => Self::BlocksOnly,
|
||||
1 => Self::BlocksAndPool,
|
||||
2 => Self::PoolOnly,
|
||||
_ => return None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
impl EpeeValue for RequestedInfo {
|
||||
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 2"))
|
||||
}
|
||||
|
||||
fn write<B: BufMut>(self, w: &mut B) -> error::Result<()> {
|
||||
let u = self.to_u8();
|
||||
u8::write(u, w)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue