mirror of
https://github.com/hinto-janai/cuprate.git
synced 2024-12-22 11:39:30 +00:00
Compare commits
3 commits
568a276b7f
...
d1c1025238
Author | SHA1 | Date | |
---|---|---|---|
|
d1c1025238 | ||
|
a1903f33b0 | ||
|
20e599fc72 |
20 changed files with 1332 additions and 972 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1072,7 +1072,9 @@ dependencies = [
|
|||
"cuprate-test-utils",
|
||||
"cuprate-types",
|
||||
"hex",
|
||||
"hex-literal",
|
||||
"paste",
|
||||
"pretty_assertions",
|
||||
"serde",
|
||||
"serde_json",
|
||||
]
|
||||
|
|
|
@ -34,7 +34,7 @@ cuprate-test-utils = { workspace = true }
|
|||
cuprate-types = { workspace = true, features = ["json"] }
|
||||
cuprate-json-rpc = { workspace = true }
|
||||
cuprate-rpc-interface = { workspace = true }
|
||||
cuprate-rpc-types = { workspace = true }
|
||||
cuprate-rpc-types = { workspace = true, features = ["from"] }
|
||||
|
||||
|
||||
# TODO: after v1.0.0, remove unneeded dependencies.
|
||||
|
|
|
@ -57,17 +57,17 @@ pub(super) async fn block_header(
|
|||
)
|
||||
.await?;
|
||||
|
||||
let pow_hash = blockchain_context::calculate_pow(
|
||||
&mut state.blockchain_context,
|
||||
hardfork,
|
||||
block,
|
||||
seed_hash,
|
||||
Some(
|
||||
blockchain_context::calculate_pow(
|
||||
&mut state.blockchain_context,
|
||||
hardfork,
|
||||
block,
|
||||
seed_hash,
|
||||
)
|
||||
.await?,
|
||||
)
|
||||
.await?;
|
||||
|
||||
pow_hash
|
||||
} else {
|
||||
[0; 32]
|
||||
None
|
||||
};
|
||||
|
||||
let block_weight = usize_to_u64(header.block_weight);
|
||||
|
@ -76,7 +76,6 @@ pub(super) async fn block_header(
|
|||
let (cumulative_difficulty_top64, cumulative_difficulty) =
|
||||
split_u128_into_low_high_bits(header.cumulative_difficulty);
|
||||
let (difficulty_top64, difficulty) = split_u128_into_low_high_bits(difficulty);
|
||||
let wide_difficulty = hex::encode(difficulty.to_ne_bytes());
|
||||
|
||||
let reward = block
|
||||
.miner_transaction
|
||||
|
|
|
@ -34,24 +34,25 @@ use cuprate_rpc_types::{
|
|||
GetBlockCountRequest, GetBlockCountResponse, GetBlockHeaderByHashRequest,
|
||||
GetBlockHeaderByHashResponse, GetBlockHeaderByHeightRequest,
|
||||
GetBlockHeaderByHeightResponse, GetBlockHeadersRangeRequest, GetBlockHeadersRangeResponse,
|
||||
GetBlockRequest, GetBlockResponse, GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse,
|
||||
GetConnectionsRequest, GetConnectionsResponse, GetFeeEstimateRequest,
|
||||
GetFeeEstimateResponse, GetInfoRequest, GetInfoResponse, GetLastBlockHeaderRequest,
|
||||
GetLastBlockHeaderResponse, GetMinerDataRequest, GetMinerDataResponse,
|
||||
GetOutputDistributionRequest, GetOutputDistributionResponse, GetOutputHistogramRequest,
|
||||
GetOutputHistogramResponse, GetTransactionPoolBacklogRequest,
|
||||
GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest, GetTxIdsLooseResponse,
|
||||
GetVersionRequest, GetVersionResponse, HardForkInfoRequest, HardForkInfoResponse,
|
||||
JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest, OnGetBlockHashResponse,
|
||||
PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest, RelayTxResponse,
|
||||
SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse, SyncInfoRequest,
|
||||
SyncInfoResponse,
|
||||
GetBlockRequest, GetBlockResponse, GetBlockTemplateRequest, GetBlockTemplateResponse,
|
||||
GetCoinbaseTxSumRequest, GetCoinbaseTxSumResponse, GetConnectionsRequest,
|
||||
GetConnectionsResponse, GetFeeEstimateRequest, GetFeeEstimateResponse, GetInfoRequest,
|
||||
GetInfoResponse, GetLastBlockHeaderRequest, GetLastBlockHeaderResponse,
|
||||
GetMinerDataRequest, GetMinerDataResponse, GetOutputDistributionRequest,
|
||||
GetOutputDistributionResponse, GetOutputHistogramRequest, GetOutputHistogramResponse,
|
||||
GetTransactionPoolBacklogRequest, GetTransactionPoolBacklogResponse, GetTxIdsLooseRequest,
|
||||
GetTxIdsLooseResponse, GetVersionRequest, GetVersionResponse, HardForkInfoRequest,
|
||||
HardForkInfoResponse, JsonRpcRequest, JsonRpcResponse, OnGetBlockHashRequest,
|
||||
OnGetBlockHashResponse, PruneBlockchainRequest, PruneBlockchainResponse, RelayTxRequest,
|
||||
RelayTxResponse, SetBansRequest, SetBansResponse, SubmitBlockRequest, SubmitBlockResponse,
|
||||
SyncInfoRequest, SyncInfoResponse,
|
||||
},
|
||||
misc::{BlockHeader, ChainInfo, Distribution, GetBan, HistogramEntry, Status, SyncInfoPeer},
|
||||
CORE_RPC_VERSION,
|
||||
};
|
||||
use cuprate_types::{
|
||||
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardforkEntry, TxBacklogEntry},
|
||||
hex::Hex,
|
||||
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry},
|
||||
HardFork,
|
||||
};
|
||||
|
||||
|
@ -76,6 +77,7 @@ pub(super) async fn map_request(
|
|||
use JsonRpcResponse as Resp;
|
||||
|
||||
Ok(match request {
|
||||
Req::GetBlockTemplate(r) => Resp::GetBlockTemplate(get_block_template(state, r).await?),
|
||||
Req::GetBlockCount(r) => Resp::GetBlockCount(get_block_count(state, r).await?),
|
||||
Req::OnGetBlockHash(r) => Resp::OnGetBlockHash(on_get_block_hash(state, r).await?),
|
||||
Req::SubmitBlock(r) => Resp::SubmitBlock(submit_block(state, r).await?),
|
||||
|
@ -125,6 +127,101 @@ pub(super) async fn map_request(
|
|||
})
|
||||
}
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L1911-L2005>
|
||||
async fn get_block_template(
|
||||
mut state: CupratedRpcHandler,
|
||||
request: GetBlockTemplateRequest,
|
||||
) -> Result<GetBlockTemplateResponse, Error> {
|
||||
if request.reserve_size > 255 {
|
||||
return Err(anyhow!("Too big reserved size, maximum 255"));
|
||||
}
|
||||
|
||||
if request.reserve_size != 0 && !request.extra_nonce.is_empty() {
|
||||
return Err(anyhow!(
|
||||
"Cannot specify both a reserve_size and an extra_nonce"
|
||||
));
|
||||
}
|
||||
|
||||
if request.extra_nonce.len() > 510 {
|
||||
return Err(anyhow!("Too big extra_nonce size"));
|
||||
}
|
||||
|
||||
// cryptonote::address_parse_info info;
|
||||
|
||||
if request.wallet_address.is_empty()
|
||||
|| todo!(
|
||||
"!cryptonote::get_account_address_from_str(info, nettype(), request.wallet_address))"
|
||||
)
|
||||
{
|
||||
return Err(anyhow!("Failed to parse wallet address"));
|
||||
}
|
||||
|
||||
if todo!("info.is_subaddress") {
|
||||
return Err(anyhow!("Mining to subaddress is not supported yet"));
|
||||
}
|
||||
|
||||
// block b;
|
||||
// cryptonote::blobdata blob_reserve;
|
||||
// size_t reserved_offset;
|
||||
// if(!request.extra_nonce.empty())
|
||||
// {
|
||||
// if(!string_tools::parse_hexstr_to_binbuff(request.extra_nonce, blob_reserve))
|
||||
// {
|
||||
// error_resp.code = CORE_RPC_ERROR_CODE_WRONG_PARAM;
|
||||
// error_resp.message = "Parameter extra_nonce should be a hex string";
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// blob_reserve.resize(request.reserve_size, 0);
|
||||
// cryptonote::difficulty_type wdiff;
|
||||
// crypto::hash prev_block;
|
||||
// if (!request.prev_block.empty())
|
||||
// {
|
||||
// if (!epee::string_tools::hex_to_pod(request.prev_block, prev_block))
|
||||
// {
|
||||
// error_resp.code = CORE_RPC_ERROR_CODE_INTERNAL_ERROR;
|
||||
// error_resp.message = "Invalid prev_block";
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// crypto::hash seed_hash, next_seed_hash;
|
||||
// if (!get_block_template(info.address, request.prev_block.empty() ? NULL : &prev_block, blob_reserve, reserved_offset, wdiff, res.height, res.expected_reward, res.cumulative_weight, b, res.seed_height, seed_hash, next_seed_hash, error_resp))
|
||||
// return false;
|
||||
// if (b.major_version >= RX_BLOCK_VERSION)
|
||||
// {
|
||||
// res.seed_hash = string_tools::pod_to_hex(seed_hash);
|
||||
// if (seed_hash != next_seed_hash)
|
||||
// res.next_seed_hash = string_tools::pod_to_hex(next_seed_hash);
|
||||
// }
|
||||
|
||||
// res.reserved_offset = reserved_offset;
|
||||
// store_difficulty(wdiff, res.difficulty, res.wide_difficulty, res.difficulty_top64);
|
||||
// blobdata block_blob = t_serializable_object_to_blob(b);
|
||||
// blobdata hashing_blob = get_block_hashing_blob(b);
|
||||
// res.prev_hash = string_tools::pod_to_hex(b.prev_id);
|
||||
// res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
||||
// res.blockhashing_blob = string_tools::buff_to_hex_nodelimer(hashing_blob);
|
||||
// res.status = CORE_RPC_STATUS_OK;
|
||||
// return true;
|
||||
|
||||
Ok(GetBlockTemplateResponse {
|
||||
base: ResponseBase::OK,
|
||||
blockhashing_blob: todo!(),
|
||||
blocktemplate_blob: todo!(),
|
||||
difficulty_top64: todo!(),
|
||||
difficulty: todo!(),
|
||||
expected_reward: todo!(),
|
||||
height: todo!(),
|
||||
next_seed_hash: todo!(),
|
||||
prev_hash: todo!(),
|
||||
reserved_offset: todo!(),
|
||||
seed_hash: todo!(),
|
||||
seed_height: todo!(),
|
||||
wide_difficulty: todo!(),
|
||||
})
|
||||
}
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L1790-L1804>
|
||||
async fn get_block_count(
|
||||
mut state: CupratedRpcHandler,
|
||||
|
@ -148,9 +245,10 @@ async fn on_get_block_hash(
|
|||
todo!("access to `cuprated`'s Chain"),
|
||||
)
|
||||
.await?;
|
||||
let block_hash = hex::encode(hash);
|
||||
|
||||
Ok(OnGetBlockHashResponse { block_hash })
|
||||
Ok(OnGetBlockHashResponse {
|
||||
block_hash: Hex(hash),
|
||||
})
|
||||
}
|
||||
|
||||
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L2209-L2266>
|
||||
|
@ -232,19 +330,19 @@ async fn get_block_header_by_hash(
|
|||
|
||||
async fn get(
|
||||
state: &mut CupratedRpcHandler,
|
||||
hex: String,
|
||||
hash: [u8; 32],
|
||||
fill_pow_hash: bool,
|
||||
) -> Result<BlockHeader, Error> {
|
||||
let hash = helper::hex_to_hash(hex)?;
|
||||
let block_header = helper::block_header_by_hash(state, hash, fill_pow_hash).await?;
|
||||
Ok(block_header)
|
||||
}
|
||||
|
||||
let block_header = get(&mut state, request.hash, request.fill_pow_hash).await?;
|
||||
let block_header = get(&mut state, request.hash.0, request.fill_pow_hash).await?;
|
||||
|
||||
// FIXME PERF: could make a `Vec` on await on all tasks at the same time.
|
||||
let mut block_headers = Vec::with_capacity(request.hashes.len());
|
||||
for hash in request.hashes {
|
||||
let hash = helper::hex_to_hash(hash)?;
|
||||
let hash = get(&mut state, hash, request.fill_pow_hash).await?;
|
||||
block_headers.push(hash);
|
||||
}
|
||||
|
@ -736,7 +834,7 @@ async fn get_version(
|
|||
for hf in HardFork::VARIANTS {
|
||||
if let Ok(hf) = blockchain_context::hard_fork_info(&mut state.blockchain_context, *hf).await
|
||||
{
|
||||
let entry = HardforkEntry {
|
||||
let entry = HardForkEntry {
|
||||
height: hf.earliest_height,
|
||||
hf_version: HardFork::from_version(hf.version)
|
||||
.expect("blockchain context should not be responding with invalid hardforks"),
|
||||
|
@ -1073,7 +1171,7 @@ fn add_aux_pow_inner(
|
|||
for nonce in 0..=MAX_NONCE {
|
||||
for i in &mut slots {
|
||||
let slot_u32 = get_aux_slot(
|
||||
&aux_pow[u32_to_usize(*i)].id,
|
||||
&aux_pow[u32_to_usize(*i)].id.0,
|
||||
nonce,
|
||||
non_zero_len.try_into().unwrap(),
|
||||
);
|
||||
|
@ -1117,8 +1215,8 @@ fn add_aux_pow_inner(
|
|||
return Err(anyhow!("Slot value out of range"));
|
||||
}
|
||||
|
||||
aux_pow_id_raw.push(aux_pow.id);
|
||||
aux_pow_raw.push(aux_pow.hash);
|
||||
aux_pow_id_raw.push(aux_pow.id.0);
|
||||
aux_pow_raw.push(aux_pow.hash.0);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
|
@ -1139,8 +1237,8 @@ fn add_aux_pow_inner(
|
|||
return Err(anyhow!("Slot value out of range"));
|
||||
}
|
||||
|
||||
aux_pow_raw[slot] = aux_pow.hash;
|
||||
aux_pow_id_raw[slot] = aux_pow.id;
|
||||
aux_pow_raw[slot] = aux_pow.hash.0;
|
||||
aux_pow_id_raw[slot] = aux_pow.id.0;
|
||||
}
|
||||
|
||||
(
|
||||
|
@ -1196,10 +1294,8 @@ fn add_aux_pow_inner(
|
|||
|
||||
let blocktemplate_blob = hex::encode(blocktemplate_blob);
|
||||
let blockhashing_blob = hex::encode(blockhashing_blob);
|
||||
let merkle_root = hex::encode(merkle_root);
|
||||
let aux_pow = IntoIterator::into_iter(aux_pow) // must be explicit due to `boxed_slice_into_iter`
|
||||
.map(Into::into)
|
||||
.collect::<Vec<cuprate_rpc_types::misc::AuxPow>>();
|
||||
let merkle_root = Hex(merkle_root);
|
||||
let aux_pow = aux_pow.into_vec();
|
||||
|
||||
Ok(AddAuxPowResponse {
|
||||
base: ResponseBase::OK,
|
||||
|
|
|
@ -23,6 +23,7 @@ map = ["cast", "dep:monero-serai", "dep:cuprate-constants"]
|
|||
time = ["dep:chrono", "std"]
|
||||
thread = ["std", "dep:target_os_lib"]
|
||||
tx = ["dep:monero-serai"]
|
||||
fmt = ["map", "std"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-constants = { workspace = true, optional = true, features = ["block"] }
|
||||
|
|
19
helper/src/fmt.rs
Normal file
19
helper/src/fmt.rs
Normal file
|
@ -0,0 +1,19 @@
|
|||
//! Formatting.
|
||||
|
||||
use crate::map::combine_low_high_bits_to_u128;
|
||||
|
||||
/// Format two [`u64`]'s as a [`u128`] as a lower-case hexadecimal string prefixed with `0x`.
|
||||
///
|
||||
/// ```rust
|
||||
/// # use cuprate_helper::fmt::hex_prefix_u128;
|
||||
/// assert_eq!(hex_prefix_u128(0, 0), "0x0");
|
||||
/// assert_eq!(hex_prefix_u128(0, u64::MAX), "0xffffffffffffffff0000000000000000");
|
||||
/// assert_eq!(hex_prefix_u128(u64::MAX, 0), "0xffffffffffffffff");
|
||||
/// assert_eq!(hex_prefix_u128(u64::MAX, u64::MAX), "0xffffffffffffffffffffffffffffffff");
|
||||
/// ```
|
||||
pub fn hex_prefix_u128(low_bits: u64, high_bits: u64) -> String {
|
||||
format!("{:#x}", combine_low_high_bits_to_u128(low_bits, high_bits))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {}
|
|
@ -11,7 +11,7 @@ pub mod atomic;
|
|||
#[cfg(feature = "cast")]
|
||||
pub mod cast;
|
||||
|
||||
#[cfg(all(feature = "fs", feature = "std"))]
|
||||
#[cfg(feature = "fs")]
|
||||
pub mod fs;
|
||||
|
||||
pub mod network;
|
||||
|
@ -33,6 +33,6 @@ pub mod tx;
|
|||
|
||||
#[cfg(feature = "crypto")]
|
||||
pub mod crypto;
|
||||
//---------------------------------------------------------------------------------------------------- Private Usage
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
#[cfg(feature = "fmt")]
|
||||
pub mod fmt;
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
//! `#[no_std]` compatible.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Use
|
||||
use core::net::Ipv4Addr;
|
||||
|
||||
use monero_serai::transaction::Timelock;
|
||||
|
||||
use cuprate_constants::block::MAX_BLOCK_HEIGHT;
|
||||
|
@ -28,6 +30,7 @@ use crate::cast::{u64_to_usize, usize_to_u64};
|
|||
/// let high = u64::MAX;
|
||||
///
|
||||
/// assert_eq!(split_u128_into_low_high_bits(value), (low, high));
|
||||
/// assert_eq!(split_u128_into_low_high_bits(0), (0, 0));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn split_u128_into_low_high_bits(value: u128) -> (u64, u64) {
|
||||
|
@ -52,6 +55,7 @@ pub const fn split_u128_into_low_high_bits(value: u128) -> (u64, u64) {
|
|||
/// let high = u64::MAX;
|
||||
///
|
||||
/// assert_eq!(combine_low_high_bits_to_u128(low, high), value);
|
||||
/// assert_eq!(combine_low_high_bits_to_u128(0, 0), 0);
|
||||
/// ```
|
||||
#[inline]
|
||||
pub const fn combine_low_high_bits_to_u128(low_bits: u64, high_bits: u64) -> u128 {
|
||||
|
@ -59,6 +63,24 @@ pub const fn combine_low_high_bits_to_u128(low_bits: u64, high_bits: u64) -> u12
|
|||
res | (low_bits as u128)
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- IPv4
|
||||
/// Convert an [`Ipv4Addr`] to a [`u32`].
|
||||
///
|
||||
/// For why this exists, see: <https://architecture.cuprate.org/oddities/le-ipv4.html>.
|
||||
#[inline]
|
||||
pub const fn ipv4_from_u32(ip: u32) -> Ipv4Addr {
|
||||
let [a, b, c, d] = ip.to_le_bytes();
|
||||
Ipv4Addr::new(a, b, c, d)
|
||||
}
|
||||
|
||||
/// Convert a [`u32`] to an [`Ipv4Addr`].
|
||||
///
|
||||
/// For why this exists, see: <https://architecture.cuprate.org/oddities/le-ipv4.html>.
|
||||
#[inline]
|
||||
pub const fn u32_from_ipv4(ip: Ipv4Addr) -> u32 {
|
||||
u32::from_le_bytes(ip.octets())
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Timelock
|
||||
/// Map a [`u64`] to a [`Timelock`].
|
||||
///
|
||||
|
|
|
@ -59,6 +59,7 @@ impl Service<JsonRpcRequest> for RpcHandlerDummy {
|
|||
|
||||
#[expect(clippy::default_trait_access)]
|
||||
let resp = match req {
|
||||
Req::GetBlockTemplate(_) => Resp::GetBlockTemplate(Default::default()),
|
||||
Req::GetBlockCount(_) => Resp::GetBlockCount(Default::default()),
|
||||
Req::OnGetBlockHash(_) => Resp::OnGetBlockHash(Default::default()),
|
||||
Req::SubmitBlock(_) => Resp::SubmitBlock(Default::default()),
|
||||
|
|
|
@ -12,7 +12,14 @@ keywords = ["cuprate", "rpc", "types", "monero"]
|
|||
default = ["serde", "epee", "from"]
|
||||
serde = ["dep:serde", "cuprate-fixed-bytes/serde", "cuprate-types/serde"]
|
||||
epee = ["dep:cuprate-epee-encoding", "cuprate-types/epee"]
|
||||
from = ["dep:cuprate-helper", "cuprate-helper/map", "dep:cuprate-p2p-core", "dep:hex"]
|
||||
from = [
|
||||
"dep:cuprate-helper",
|
||||
"cuprate-helper/map",
|
||||
"cuprate-helper/fmt",
|
||||
"cuprate-types/rpc",
|
||||
"dep:cuprate-p2p-core",
|
||||
"dep:hex"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { workspace = true, optional = true }
|
||||
|
@ -28,8 +35,10 @@ hex = { workspace = true, optional = true }
|
|||
[dev-dependencies]
|
||||
cuprate-test-utils = { workspace = true }
|
||||
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
hex-literal = { workspace = true }
|
||||
pretty_assertions = { workspace = true }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//! `height`, it will use [`default_height`] to fill that in.
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Import
|
||||
// use cuprate_types::hex::Hex;
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- TODO
|
||||
/// Default [`bool`] type used in request/response types, `false`.
|
||||
|
@ -28,6 +29,12 @@ pub(crate) const fn default_string() -> String {
|
|||
String::new()
|
||||
}
|
||||
|
||||
// /// Default [`Hex`] type used in request/response types.
|
||||
// #[inline]
|
||||
// pub(crate) const fn default_hex<const N: usize>() -> Hex<N> {
|
||||
// Hex([0; N])
|
||||
// }
|
||||
|
||||
/// Default block height used in request/response types.
|
||||
#[inline]
|
||||
pub(crate) const fn default_height() -> u64 {
|
||||
|
|
|
@ -2,39 +2,21 @@
|
|||
//!
|
||||
//! Only non-crate types are imported, all crate types use `crate::`.
|
||||
|
||||
#![allow(unused_variables, unreachable_code, reason = "TODO")]
|
||||
|
||||
use std::{
|
||||
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||
net::{SocketAddr, SocketAddrV4},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use cuprate_helper::map::combine_low_high_bits_to_u128;
|
||||
use cuprate_helper::{fmt::hex_prefix_u128, map::ipv4_from_u32};
|
||||
use cuprate_p2p_core::{
|
||||
types::{BanState, ConnectionId, ConnectionInfo, SetBan, Span},
|
||||
ClearNet, NetZoneAddress, NetworkZone,
|
||||
types::{ConnectionId, ConnectionInfo, SetBan, Span},
|
||||
NetZoneAddress,
|
||||
};
|
||||
use cuprate_types::{
|
||||
hex::Hex,
|
||||
rpc::{
|
||||
AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, GetBan, GetMinerDataTxBacklogEntry,
|
||||
GetOutputsOut, HardforkEntry, HistogramEntry, OutKey, OutKeyBin, OutputDistributionData,
|
||||
Peer, PublicNode, SpentKeyImageInfo, TxBacklogEntry, TxInfo, TxOutputIndices, TxpoolHisto,
|
||||
TxpoolStats,
|
||||
},
|
||||
rpc::{BlockHeader, ChainInfo, HistogramEntry, TxInfo},
|
||||
};
|
||||
|
||||
/// <https://architecture.cuprate.org/oddities/le-ipv4.html>
|
||||
const fn ipv4_from_u32(ip: u32) -> Ipv4Addr {
|
||||
let [a, b, c, d] = ip.to_le_bytes();
|
||||
Ipv4Addr::new(a, b, c, d)
|
||||
}
|
||||
|
||||
/// Format two [`u64`]'s as a [`u128`] as a hexadecimal string prefixed with `0x`.
|
||||
fn hex_prefix_u128(low: u64, high: u64) -> String {
|
||||
format!("{:#x}", combine_low_high_bits_to_u128(low, high))
|
||||
}
|
||||
|
||||
impl From<BlockHeader> for crate::misc::BlockHeader {
|
||||
fn from(x: BlockHeader) -> Self {
|
||||
Self {
|
||||
|
@ -54,7 +36,7 @@ impl From<BlockHeader> for crate::misc::BlockHeader {
|
|||
nonce: x.nonce,
|
||||
num_txes: x.num_txes,
|
||||
orphan_status: x.orphan_status,
|
||||
pow_hash: Hex(x.pow_hash),
|
||||
pow_hash: x.pow_hash.map_or_else(String::new, hex::encode),
|
||||
prev_hash: Hex(x.prev_hash),
|
||||
reward: x.reward,
|
||||
timestamp: x.timestamp,
|
||||
|
@ -206,25 +188,3 @@ impl From<TxInfo> for crate::misc::TxInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<AuxPow> for crate::misc::AuxPow {
|
||||
fn from(x: AuxPow) -> Self {
|
||||
Self {
|
||||
id: Hex(x.id),
|
||||
hash: Hex(x.hash),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn hex() {
|
||||
assert_eq!(hex_prefix_u128(0, 0), "0x0");
|
||||
assert_eq!(hex_prefix_u128(0, u64::MAX), "0x0");
|
||||
assert_eq!(hex_prefix_u128(u64::MAX, 0), "0x0");
|
||||
assert_eq!(hex_prefix_u128(u64::MAX, u64::MAX), "0x0");
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -27,6 +27,6 @@ pub use requested_info::RequestedInfo;
|
|||
pub use status::Status;
|
||||
pub use tx_entry::TxEntry;
|
||||
pub use types::{
|
||||
AuxPow, BlockHeader, ChainInfo, ConnectionInfo, GetBan, GetOutputsOut, HistogramEntry,
|
||||
OutKeyBin, SetBan, Span, SpentKeyImageInfo, SyncInfoPeer, TxInfo,
|
||||
BlockHeader, ChainInfo, ConnectionInfo, GetBan, GetOutputsOut, HistogramEntry, OutKeyBin,
|
||||
SetBan, Span, SpentKeyImageInfo, SyncInfoPeer, TxInfo,
|
||||
};
|
||||
|
|
|
@ -90,7 +90,8 @@ define_struct_and_impl_epee! {
|
|||
nonce: u32,
|
||||
num_txes: u64,
|
||||
orphan_status: bool,
|
||||
pow_hash: Hex<32>,
|
||||
/// This is an empty string if the `fill_pow_hash` param is `false`.
|
||||
pow_hash: String,
|
||||
prev_hash: Hex<32>,
|
||||
reward: u64,
|
||||
timestamp: u64,
|
||||
|
@ -309,18 +310,6 @@ define_struct_and_impl_epee! {
|
|||
}
|
||||
}
|
||||
|
||||
define_struct_and_impl_epee! {
|
||||
#[doc = monero_definition_link!(
|
||||
"cc73fe71162d564ffda8e549b79a350bca53c454",
|
||||
"rpc/core_rpc_server_commands_defs.h",
|
||||
1070..=1079
|
||||
)]
|
||||
AuxPow {
|
||||
id: Hex<32>,
|
||||
hash: Hex<32>,
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------- Tests
|
||||
#[cfg(test)]
|
||||
mod test {}
|
||||
|
|
|
@ -18,7 +18,7 @@ json = ["hex", "dep:cuprate-helper"]
|
|||
# We sadly have no choice but to enable serde here as otherwise we will get warnings from the `hex` dep being unused.
|
||||
# This isn't too bad as `Hex` only makes sense with serde anyway.
|
||||
hex = ["serde", "dep:hex"]
|
||||
rpc = ["hex"]
|
||||
rpc = ["hex", "json"]
|
||||
|
||||
[dependencies]
|
||||
cuprate-epee-encoding = { workspace = true, optional = true, features = ["std"] }
|
||||
|
|
|
@ -59,6 +59,7 @@ pub enum HardForkError {
|
|||
)]
|
||||
#[cfg_attr(any(feature = "proptest"), derive(proptest_derive::Arbitrary))]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(try_from = "u8", into = "u8"))]
|
||||
#[repr(u8)]
|
||||
pub enum HardFork {
|
||||
#[default]
|
||||
|
@ -203,6 +204,19 @@ impl HardFork {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<u8> for HardFork {
|
||||
type Error = HardForkError;
|
||||
fn try_from(version: u8) -> Result<Self, Self::Error> {
|
||||
Self::from_version(version)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HardFork> for u8 {
|
||||
fn from(value: HardFork) -> Self {
|
||||
value.as_u8()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "epee")]
|
||||
impl EpeeValue for HardFork {
|
||||
const MARKER: Marker = u8::MARKER;
|
||||
|
|
|
@ -56,6 +56,37 @@ impl<const N: usize> Default for Hex<N> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<Hex<N>> for [u8; N] {
|
||||
fn from(hex: Hex<N>) -> Self {
|
||||
hex.0
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> From<[u8; N]> for Hex<N> {
|
||||
fn from(value: [u8; N]) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> TryFrom<String> for Hex<N> {
|
||||
type Error = hex::FromHexError;
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
let vec = hex::decode(value)?;
|
||||
match <[u8; N]>::try_from(vec) {
|
||||
Ok(s) => Ok(Self(s)),
|
||||
Err(_) => Err(hex::FromHexError::InvalidStringLength),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<const N: usize> TryFrom<&str> for Hex<N> {
|
||||
type Error = hex::FromHexError;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
let mut bytes = [0; N];
|
||||
hex::decode_to_slice(value, &mut bytes).map(|()| Self(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
|
|
|
@ -16,7 +16,7 @@ pub use pool_info::PoolInfo;
|
|||
pub use pool_info_extent::PoolInfoExtent;
|
||||
pub use types::{
|
||||
AddAuxPow, AuxPow, BlockHeader, BlockOutputIndices, ChainInfo, CoinbaseTxSum, ConnectionInfo,
|
||||
FeeEstimate, GetBan, GetMinerDataTxBacklogEntry, GetOutputsOut, HardForkInfo, HardforkEntry,
|
||||
FeeEstimate, GetBan, GetMinerDataTxBacklogEntry, GetOutputsOut, HardForkEntry, HardForkInfo,
|
||||
HistogramEntry, MinerData, MinerDataTxBacklogEntry, OutKey, OutKeyBin, OutputDistributionData,
|
||||
OutputHistogramEntry, OutputHistogramInput, Peer, PoolInfoFull, PoolInfoIncremental,
|
||||
PoolTxInfo, PublicNode, SetBan, Span, SpentKeyImageInfo, SyncInfoPeer, TxBacklogEntry, TxInfo,
|
||||
|
|
|
@ -103,7 +103,8 @@ define_struct_and_impl_epee! {
|
|||
nonce: u32,
|
||||
num_txes: u64,
|
||||
orphan_status: bool,
|
||||
pow_hash: [u8; 32],
|
||||
/// This is [`None`] if the `fill_pow_hash` param is `false`.
|
||||
pow_hash: Option<[u8; 32]>,
|
||||
prev_hash: [u8; 32],
|
||||
reward: u64,
|
||||
timestamp: u64,
|
||||
|
@ -189,7 +190,7 @@ define_struct_and_impl_epee! {
|
|||
2180..=2191
|
||||
)]
|
||||
#[derive(Copy)]
|
||||
HardforkEntry {
|
||||
HardForkEntry {
|
||||
height: u64,
|
||||
hf_version: HardFork,
|
||||
}
|
||||
|
@ -273,8 +274,8 @@ define_struct_and_impl_epee! {
|
|||
1070..=1079
|
||||
)]
|
||||
AuxPow {
|
||||
id: [u8; 32],
|
||||
hash: [u8; 32],
|
||||
id: Hex<32>,
|
||||
hash: Hex<32>,
|
||||
}
|
||||
|
||||
#[doc = monero_definition_link!(
|
||||
|
|
Loading…
Reference in a new issue