-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cuprated: RPC handlers (json-rpc) #308
Open
hinto-janai
wants to merge
59
commits into
Cuprate:main
Choose a base branch
from
hinto-janai:json
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
59 commits
Select commit
Hold shift + click to select a range
d170b46
import diffs
hinto-janai 02e950b
small fixes, hardfork changes
hinto-janai c18ba6e
lints
hinto-janai 93be3be
hard_fork
hinto-janai c590bbb
apply diffs
hinto-janai cec746b
review fixes
hinto-janai e57c887
Merge branch 'hf' into json
hinto-janai ac6360a
Merge branch 'main' into json
hinto-janai 2522bb8
binaries/cuprated/src/rpc/request: `pub(super)` -> `pub(crate)`
hinto-janai fd136b2
add `BlockChainContextService`, `on_get_block_hash`
hinto-janai 9459d59
Merge branch 'main' into json
hinto-janai b82ff27
map `tower::BoxError` to `anyhow::Error`
hinto-janai 8a3229b
get_block
hinto-janai 9422c07
connection_info
hinto-janai 50bd576
hard_fork_info
hinto-janai f677b1a
set_bans
hinto-janai 37bcbb5
get_bans
hinto-janai c7ae795
banned
hinto-janai 6af977f
flush_transaction_pool
hinto-janai 1a76934
get_output_histogram
hinto-janai 1d435cc
get_coinbase_tx_sum
hinto-janai d7fef15
get_version
hinto-janai 1e0ab56
get_fee_estimate
hinto-janai 294df3f
get_alternate_chains
hinto-janai 08b5ff2
relay_tx
hinto-janai 2daf255
response_base: `fn` -> `const`
hinto-janai a10ed59
get_transaction_pool_backlog
hinto-janai d7d8b35
prune
hinto-janai 5926f24
calc_pow
hinto-janai 7148ba1
add_aux_pow
hinto-janai d56477c
get_tx_ids_loose
hinto-janai 548639b
generate_blocks
hinto-janai e2f25bd
get_info
hinto-janai 4b1d7bc
sync_info
hinto-janai bd3a844
get_miner_data
hinto-janai bf07f2c
`BlockchainManagerRequest` docs
hinto-janai 98dfaa4
docs, `ConnectionInfo`, `AddressType`
hinto-janai 13eedc6
sig docs, remove `HardForks` request
hinto-janai 79b03e3
Merge branch 'main' into json
hinto-janai 544287d
Merge branch 'main' into json
hinto-janai 0cb6a76
clean imports
hinto-janai e30eeb8
fix `on_get_block_hash`, `generate_blocks`, `get_block_headers_range`
hinto-janai 228a718
fix `get_info`, `banned`
hinto-janai 9374d08
fix `sync_info`
hinto-janai fd84940
fix `get_miner_data`
hinto-janai 46bf198
initial `add_aux_pow` impl
hinto-janai 1f3b5ed
fix `calculate_pow`
hinto-janai e975c42
add_aux_pow
hinto-janai d634bea
`get_output_distribution`
hinto-janai 854b175
checkup
hinto-janai 2d2d493
`find_nonce()` + `add_aux_pow` async wrapper
hinto-janai 86f2dd1
fixes
hinto-janai de7abfc
`helper::block_header`
hinto-janai 1ffa86c
review fixes
hinto-janai 916d593
fixes
hinto-janai ff48fb4
doc fix
hinto-janai 8d5f779
p2p: remove tmp `AddressBookRequest::NextNeededPruningSeed`
hinto-janai 1a079c8
lint/todo fixes
hinto-janai a3fa638
fix bans
hinto-janai File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
mod bin; | ||
mod constants; | ||
mod handler; | ||
mod helper; | ||
mod json; | ||
mod other; | ||
mod request; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
//! RPC request handler functions (binary endpoints). | ||
|
||
use anyhow::Error; | ||
|
||
use cuprate_rpc_types::{ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
//! These are internal helper functions used by the actual RPC handlers. | ||
//! | ||
//! Many of the handlers have bodies with only small differences, | ||
//! the identical code is extracted and reused here in these functions. | ||
//! | ||
//! These build on-top of [`crate::rpc::request`] functions. | ||
|
||
use anyhow::{anyhow, Error}; | ||
|
||
use cuprate_helper::{ | ||
cast::{u64_to_usize, usize_to_u64}, | ||
map::split_u128_into_low_high_bits, | ||
}; | ||
use cuprate_rpc_types::misc::{BlockHeader, KeyImageSpentStatus}; | ||
use cuprate_types::HardFork; | ||
|
||
use crate::{ | ||
rpc::request::{blockchain, blockchain_context}, | ||
rpc::CupratedRpcHandler, | ||
}; | ||
|
||
/// Map some data into a [`BlockHeader`]. | ||
/// | ||
/// Sort of equivalent to: | ||
/// <https://github.com/monero-project/monero/blob/893916ad091a92e765ce3241b94e706ad012b62a/src/rpc/core_rpc_server.cpp#L2361>. | ||
pub(super) async fn block_header( | ||
state: &mut CupratedRpcHandler, | ||
height: u64, | ||
fill_pow_hash: bool, | ||
) -> Result<BlockHeader, Error> { | ||
let block = blockchain::block(&mut state.blockchain_read, height).await?; | ||
let header = blockchain::block_extended_header(&mut state.blockchain_read, height).await?; | ||
let hardfork = HardFork::from_vote(header.vote); | ||
let (top_height, _) = top_height(state).await?; | ||
|
||
// TODO: if the request block is not on the main chain, | ||
// we must get the alt block and this variable will be `true`. | ||
let orphan_status = false; | ||
|
||
// FIXME: is there a cheaper way to get this? | ||
let difficulty = blockchain_context::batch_get_difficulties( | ||
&mut state.blockchain_context, | ||
vec![(height, hardfork)], | ||
) | ||
.await? | ||
.first() | ||
.copied() | ||
.ok_or_else(|| anyhow!("Failed to get block difficulty"))?; | ||
|
||
let pow_hash = if fill_pow_hash { | ||
let seed_height = | ||
cuprate_consensus_rules::blocks::randomx_seed_height(u64_to_usize(height)); | ||
let seed_hash = blockchain::block_hash( | ||
&mut state.blockchain_read, | ||
height, | ||
todo!("access to `cuprated`'s Chain"), | ||
) | ||
.await?; | ||
|
||
let pow_hash = blockchain_context::calculate_pow( | ||
&mut state.blockchain_context, | ||
hardfork, | ||
block, | ||
seed_hash, | ||
) | ||
.await?; | ||
|
||
hex::encode(pow_hash) | ||
} else { | ||
String::new() | ||
}; | ||
|
||
let block_weight = usize_to_u64(header.block_weight); | ||
let depth = top_height.saturating_sub(height); | ||
|
||
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 | ||
.prefix() | ||
.outputs | ||
.iter() | ||
.map(|o| o.amount.expect("coinbase is transparent")) | ||
.sum::<u64>(); | ||
|
||
Ok(BlockHeader { | ||
block_size: block_weight, | ||
block_weight, | ||
cumulative_difficulty_top64, | ||
cumulative_difficulty, | ||
depth, | ||
difficulty_top64, | ||
difficulty, | ||
hash: hex::encode(block.hash()), | ||
height, | ||
long_term_weight: usize_to_u64(header.long_term_weight), | ||
major_version: header.version.as_u8(), | ||
miner_tx_hash: hex::encode(block.miner_transaction.hash()), | ||
minor_version: header.vote, | ||
nonce: block.header.nonce, | ||
num_txes: usize_to_u64(block.transactions.len()), | ||
orphan_status, | ||
pow_hash, | ||
prev_hash: hex::encode(block.header.previous), | ||
reward, | ||
timestamp: block.header.timestamp, | ||
wide_cumulative_difficulty: hex::encode(u128::to_le_bytes(header.cumulative_difficulty)), | ||
wide_difficulty, | ||
}) | ||
} | ||
|
||
/// Same as [`block_header`] but with the block's hash. | ||
pub(super) async fn block_header_by_hash( | ||
state: &mut CupratedRpcHandler, | ||
hash: [u8; 32], | ||
fill_pow_hash: bool, | ||
) -> Result<BlockHeader, Error> { | ||
let (_, height) = blockchain::find_block(&mut state.blockchain_read, hash) | ||
.await? | ||
.ok_or_else(|| anyhow!("Block did not exist."))?; | ||
|
||
let block_header = block_header(state, usize_to_u64(height), fill_pow_hash).await?; | ||
|
||
Ok(block_header) | ||
} | ||
|
||
/// Check if `height` is greater than the [`top_height`]. | ||
/// | ||
/// # Errors | ||
/// This returns the [`top_height`] on [`Ok`] and | ||
/// returns [`Error`] if `height` is greater than [`top_height`]. | ||
pub(super) async fn check_height( | ||
state: &mut CupratedRpcHandler, | ||
height: u64, | ||
) -> Result<u64, Error> { | ||
let (top_height, _) = top_height(state).await?; | ||
|
||
if height > top_height { | ||
return Err(anyhow!( | ||
"Requested block height: {height} greater than top block height: {top_height}", | ||
)); | ||
} | ||
|
||
Ok(top_height) | ||
} | ||
|
||
/// Parse a hexadecimal [`String`] as a 32-byte hash. | ||
#[expect(clippy::needless_pass_by_value)] | ||
pub(super) fn hex_to_hash(hex: String) -> Result<[u8; 32], Error> { | ||
let error = || anyhow!("Failed to parse hex representation of hash. Hex = {hex}."); | ||
|
||
let Ok(bytes) = hex::decode(&hex) else { | ||
return Err(error()); | ||
}; | ||
|
||
let Ok(hash) = bytes.try_into() else { | ||
return Err(error()); | ||
}; | ||
|
||
Ok(hash) | ||
} | ||
|
||
/// [`cuprate_types::blockchain::BlockchainResponse::ChainHeight`] minus 1. | ||
pub(super) async fn top_height(state: &mut CupratedRpcHandler) -> Result<(u64, [u8; 32]), Error> { | ||
let (chain_height, hash) = blockchain::chain_height(&mut state.blockchain_read).await?; | ||
let height = chain_height.saturating_sub(1); | ||
Ok((height, hash)) | ||
} | ||
|
||
/// Check if a key image is spent. | ||
pub(super) async fn key_image_spent( | ||
state: &mut CupratedRpcHandler, | ||
key_image: [u8; 32], | ||
) -> Result<KeyImageSpentStatus, Error> { | ||
todo!("impl key image vec check responding KeyImageSpentStatus") | ||
// if blockchain::key_image_spent(state, key_image).await? { | ||
// Ok(KeyImageSpentStatus::SpentInBlockchain) | ||
// } else if todo!("key image is spent in tx pool") { | ||
// Ok(KeyImageSpentStatus::SpentInPool) | ||
// } else { | ||
// Ok(KeyImageSpentStatus::Unspent) | ||
// } | ||
} | ||
Comment on lines
+174
to
+186
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. TODO: not JSON-RPC but |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alt blocks need to be handled here, is there a cheap way this could be done?