json-rpc fixes
Some checks are pending
Deny / audit (push) Waiting to run

This commit is contained in:
hinto.janai 2024-12-19 20:41:50 -05:00
parent 114a5db52e
commit b2b7e93e4c
No known key found for this signature in database
GPG key ID: D47CE05FA175A499
4 changed files with 115 additions and 82 deletions

25
Cargo.lock generated
View file

@ -885,6 +885,7 @@ dependencies = [
"bytes",
"cuprate-fixed-bytes",
"cuprate-helper",
"cuprate-hex",
"hex",
"paste",
"ref-cast",
@ -939,6 +940,15 @@ dependencies = [
"windows",
]
[[package]]
name = "cuprate-hex"
version = "0.0.0"
dependencies = [
"hex",
"serde",
"serde_json",
]
[[package]]
name = "cuprate-json-rpc"
version = "0.0.0"
@ -1066,9 +1076,15 @@ version = "0.0.0"
dependencies = [
"cuprate-epee-encoding",
"cuprate-fixed-bytes",
"cuprate-helper",
"cuprate-hex",
"cuprate-p2p-core",
"cuprate-test-utils",
"cuprate-types",
"hex",
"hex-literal",
"paste",
"pretty_assertions",
"serde",
"serde_json",
]
@ -1125,12 +1141,14 @@ dependencies = [
name = "cuprate-types"
version = "0.0.0"
dependencies = [
"bitflags 2.6.0",
"bytes",
"cfg-if",
"cuprate-epee-encoding",
"cuprate-fixed-bytes",
"cuprate-helper",
"cuprate-hex",
"curve25519-dalek",
"hex",
"hex-literal",
"monero-serai",
"pretty_assertions",
@ -1162,7 +1180,7 @@ name = "cuprate-zmq-types"
version = "0.1.0"
dependencies = [
"assert-json-diff",
"cuprate-types",
"cuprate-hex",
"hex",
"serde",
"serde_json",
@ -1190,6 +1208,7 @@ dependencies = [
"cuprate-consensus",
"cuprate-consensus-context",
"cuprate-consensus-rules",
"cuprate-constants",
"cuprate-cryptonight",
"cuprate-dandelion-tower",
"cuprate-database",
@ -1198,6 +1217,7 @@ dependencies = [
"cuprate-fast-sync",
"cuprate-fixed-bytes",
"cuprate-helper",
"cuprate-hex",
"cuprate-json-rpc",
"cuprate-levin",
"cuprate-p2p",
@ -1226,6 +1246,7 @@ dependencies = [
"serde",
"serde_bytes",
"serde_json",
"strum",
"thiserror",
"thread_local",
"tokio",

View file

@ -54,7 +54,7 @@ use cuprate_rpc_types::{
};
use cuprate_types::{
rpc::{AuxPow, CoinbaseTxSum, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry},
BlockTemplate, HardFork,
BlockTemplate, Chain, HardFork,
};
use crate::{
@ -228,12 +228,7 @@ async fn on_get_block_hash(
request: OnGetBlockHashRequest,
) -> Result<OnGetBlockHashResponse, Error> {
let [height] = request.block_height;
let hash = blockchain::block_hash(
&mut state.blockchain_read,
height,
todo!("access to `cuprated`'s Chain"),
)
.await?;
let hash = blockchain::block_hash(&mut state.blockchain_read, height, Chain::Main).await?;
Ok(OnGetBlockHashResponse {
block_hash: Hex(hash),
@ -428,7 +423,7 @@ async fn get_block(
let blob = HexVec(block.serialize());
let miner_tx_hash = Hex(block.miner_transaction.hash());
let tx_hashes = block.transactions.iter().map(|a| Hex(*a)).collect();
let tx_hashes = block.transactions.iter().copied().map(Hex).collect();
let json = {
let block = cuprate_types::json::block::Block::from(block);
serde_json::to_string_pretty(&block)?
@ -467,8 +462,7 @@ async fn get_info(
let c = context.unchecked_blockchain_context();
let cumulative_difficulty = c.cumulative_difficulty;
let adjusted_time = c.current_adjusted_timestamp_for_time_lock(); // TODO: is this correct?
let adjusted_time = c.current_adjusted_timestamp_for_time_lock();
let c = &c.context_to_verify_block;
let alt_blocks_count = if restricted {
@ -476,76 +470,98 @@ async fn get_info(
} else {
blockchain::alt_chain_count(&mut state.blockchain_read).await?
};
let block_weight_limit = usize_to_u64(c.effective_median_weight); // TODO: is this correct?
let block_weight_median = usize_to_u64(c.median_weight_for_block_reward); // TODO: is this correct?
let block_weight_limit = usize_to_u64(c.effective_median_weight);
let block_weight_median = usize_to_u64(c.median_weight_for_block_reward);
let block_size_limit = block_weight_limit;
let block_size_median = block_weight_median;
#[expect(clippy::if_same_then_else, reason = "TODO: support bootstrap")]
let (bootstrap_daemon_address, was_bootstrap_ever_used) = if restricted {
(String::new(), false)
} else {
todo!("support bootstrap daemon")
(String::new(), false)
};
let busy_syncing = blockchain_manager::syncing(&mut state.blockchain_manager).await?;
let (cumulative_difficulty, cumulative_difficulty_top64) =
split_u128_into_low_high_bits(cumulative_difficulty);
let (database_size, free_space) = blockchain::database_size(&mut state.blockchain_read).await?;
let (database_size, free_space) = if restricted {
// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L131-L134>
const fn round_up(value: u64, quantum: u64) -> u64 {
value.div_ceil(quantum)
}
let database_size = round_up(database_size, 5 * 1024 * 1024 * 1024);
(database_size, u64::MAX)
} else {
(database_size, free_space)
};
let (difficulty, difficulty_top64) = split_u128_into_low_high_bits(c.next_difficulty);
let height = usize_to_u64(c.chain_height);
let height_without_bootstrap = if restricted { 0 } else { height };
let (incoming_connections_count, outgoing_connections_count) = if restricted {
(0, 0)
} else {
address_book::connection_count::<ClearNet>(&mut DummyAddressBook).await?
};
let (mainnet, testnet, stagenet) = match todo!("access to `cuprated`'s `Network`") {
// TODO: This should be `cuprated`'s active network.
let network = Network::Mainnet;
let (mainnet, testnet, stagenet) = match network {
Network::Mainnet => (true, false, false),
Network::Testnet => (false, true, false),
Network::Stagenet => (false, false, true),
};
// TODO: make sure this is:
// - the same case as `monerod`
// - untagged (no `Network::`)
let nettype = todo!("access to `cuprated`'s `Network`").to_string();
let offline = todo!("access to CLI/config's `--offline`");
let rpc_connections_count = if restricted {
0
} else {
todo!("implement a connection counter in axum/RPC")
};
let nettype = network.to_string();
// TODO: access to CLI/config's `--offline`
let offline = false;
#[expect(
clippy::if_same_then_else,
reason = "TODO: implement a connection counter in axum/RPC"
)]
let rpc_connections_count = if restricted { 0 } else { 0 };
let start_time = if restricted { 0 } else { *START_INSTANT_UNIX };
let synchronized = blockchain_manager::synced(&mut state.blockchain_manager).await?;
let target_height = blockchain_manager::target_height(&mut state.blockchain_manager).await?;
let target = blockchain_manager::target(&mut state.blockchain_manager)
.await?
.as_secs();
let top_block_hash = Hex(c.top_hash);
let tx_count = blockchain::total_tx_count(&mut state.blockchain_read).await?;
let tx_pool_size = txpool::size(&mut state.txpool_read, !restricted).await?;
let update_available = if restricted {
false
} else {
todo!("implement an update checker for `cuprated`")
};
#[expect(
clippy::if_same_then_else,
clippy::needless_bool,
reason = "TODO: implement an update checker for `cuprated`?"
)]
let update_available = if restricted { false } else { false };
let version = if restricted {
String::new()
} else {
VERSION_BUILD.to_string()
};
let (white_peerlist_size, grey_peerlist_size) = if restricted {
(0, 0)
} else {
address_book::peerlist_size::<ClearNet>(&mut DummyAddressBook).await?
};
let wide_cumulative_difficulty = format!("{cumulative_difficulty:#x}");
let wide_difficulty = format!("{:#x}", c.next_difficulty);
@ -607,18 +623,12 @@ async fn hard_fork_info(
.current_hf
};
let info = blockchain_context::hard_fork_info(&mut state.blockchain_context, hard_fork).await?;
let hard_fork_info =
blockchain_context::hard_fork_info(&mut state.blockchain_context, hard_fork).await?;
Ok(HardForkInfoResponse {
base: helper::access_response_base(false),
earliest_height: info.earliest_height,
enabled: info.enabled,
state: info.state,
threshold: info.threshold,
version: info.version,
votes: info.votes,
voting: info.voting,
window: info.window,
hard_fork_info,
})
}
@ -1036,6 +1046,7 @@ async fn calc_pow(
// }
// TODO: will `CalculatePow` do the above checks?
let pow_hash = blockchain_context::calculate_pow(
&mut state.blockchain_context,
hardfork,
@ -1049,23 +1060,16 @@ async fn calc_pow(
})
}
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551>
async fn flush_cache(
state: CupratedRpcHandler,
request: FlushCacheRequest,
) -> Result<FlushCacheResponse, Error> {
// TODO: cuprated doesn't need this call; decide behavior.
Ok(FlushCacheResponse {
base: helper::response_base(false),
})
}
/// An async-friendly wrapper for [`add_aux_pow_inner`].
async fn add_aux_pow(
state: CupratedRpcHandler,
request: AddAuxPowRequest,
) -> Result<AddAuxPowResponse, Error> {
// This method can be a bit heavy, so rate-limit restricted use.
if state.is_restricted() {
tokio::time::sleep(Duration::from_millis(100)).await;
}
tokio::task::spawn_blocking(|| add_aux_pow_inner(state, request)).await?
}
@ -1261,16 +1265,25 @@ fn add_aux_pow_inner(
})
}
//---------------------------------------------------------------------------------------------------- Unsupported RPC calls (for now)
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3553-L3627>
async fn get_tx_ids_loose(
state: CupratedRpcHandler,
request: GetTxIdsLooseRequest,
) -> Result<GetTxIdsLooseResponse, Error> {
// TODO: this RPC call is not yet in the v0.18 branch.
return Err(anyhow!("Not implemented"));
Ok(GetTxIdsLooseResponse {
base: helper::response_base(false),
txids: todo!(),
txids: todo!("this RPC call is not yet in the v0.18 branch."),
})
}
//---------------------------------------------------------------------------------------------------- Unsupported RPC calls (forever)
/// <https://github.com/monero-project/monero/blob/cc73fe71162d564ffda8e549b79a350bca53c454/src/rpc/core_rpc_server.cpp#L3542-L3551>
async fn flush_cache(
state: CupratedRpcHandler,
request: FlushCacheRequest,
) -> Result<FlushCacheResponse, Error> {
unreachable!()
}

View file

@ -59,7 +59,7 @@ pub async fn size(
Ok(usize_to_u64(size))
}
/// TODO
/// [`TxpoolReadRequest::PoolInfo`]
pub async fn pool_info(
txpool_read: &mut TxpoolReadHandle,
include_sensitive_txs: bool,
@ -84,7 +84,7 @@ pub async fn pool_info(
Ok(pool_info)
}
/// TODO
/// [`TxpoolReadRequest::TxsByHash`]
pub async fn txs_by_hash(
txpool_read: &mut TxpoolReadHandle,
tx_hashes: Vec<[u8; 32]>,
@ -107,7 +107,7 @@ pub async fn txs_by_hash(
Ok(txs_in_pool)
}
/// TODO
/// [`TxpoolReadRequest::KeyImagesSpent`]
pub async fn key_images_spent(
txpool_read: &mut TxpoolReadHandle,
key_images: Vec<[u8; 32]>,
@ -130,7 +130,7 @@ pub async fn key_images_spent(
Ok(status)
}
/// TODO
/// [`TxpoolReadRequest::Pool`]
pub async fn pool(
txpool_read: &mut TxpoolReadHandle,
include_sensitive_txs: bool,
@ -157,7 +157,7 @@ pub async fn pool(
Ok((txs, spent_key_images))
}
/// TODO
/// [`TxpoolReadRequest::PoolStats`]
pub async fn pool_stats(
txpool_read: &mut TxpoolReadHandle,
include_sensitive_txs: bool,
@ -178,7 +178,7 @@ pub async fn pool_stats(
Ok(txpool_stats)
}
/// TODO
/// [`TxpoolReadRequest::AllHashes`]
pub async fn all_hashes(
txpool_read: &mut TxpoolReadHandle,
include_sensitive_txs: bool,
@ -199,19 +199,19 @@ pub async fn all_hashes(
Ok(hashes)
}
/// TODO
/// TODO: impl txpool manager.
pub async fn flush(txpool_manager: &mut Infallible, tx_hashes: Vec<[u8; 32]>) -> Result<(), Error> {
todo!();
Ok(())
}
/// TODO
/// TODO: impl txpool manager.
pub async fn relay(txpool_manager: &mut Infallible, tx_hashes: Vec<[u8; 32]>) -> Result<(), Error> {
todo!();
Ok(())
}
/// TODO
/// TODO: impl txpool manager.
pub async fn check_maybe_relay_local(
txpool_manager: &mut Infallible,
tx: Transaction,

View file

@ -7,7 +7,9 @@
use serde::{Deserialize, Serialize};
use cuprate_hex::{Hex, HexVec};
use cuprate_types::rpc::{AuxPow, GetMinerDataTxBacklogEntry, HardForkEntry, TxBacklogEntry};
use cuprate_types::rpc::{
AuxPow, GetMinerDataTxBacklogEntry, HardForkEntry, HardForkInfo, TxBacklogEntry,
};
use crate::{
base::{AccessResponseBase, ResponseBase},
@ -385,14 +387,9 @@ define_request_and_response! {
},
AccessResponseBase {
earliest_height: u64,
enabled: bool,
state: u32,
threshold: u32,
version: u8,
votes: u32,
voting: u8,
window: u32,
/// This field is [flattened](https://serde.rs/field-attrs.html#flatten).
#[cfg_attr(feature = "serde", serde(flatten))]
hard_fork_info: HardForkInfo,
}
}
@ -1464,6 +1461,7 @@ mod test {
json::HARD_FORK_INFO_RESPONSE,
HardForkInfoResponse {
base: AccessResponseBase::OK,
hard_fork_info: HardForkInfo {
earliest_height: 2689608,
enabled: true,
state: 0,
@ -1473,6 +1471,7 @@ mod test {
voting: 16,
window: 10080,
},
},
);
}