Skip to content
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 #355

Open
wants to merge 105 commits into
base: main
Choose a base branch
from
Open

cuprated: RPC handlers #355

wants to merge 105 commits into from

Conversation

hinto-janai
Copy link
Contributor

@hinto-janai hinto-janai commented Dec 5, 2024

What

Implements the {json-rpc, binary, json} handlers in cuprated; adds various types and changes some misc things as needed.

How

See below review.

@github-actions github-actions bot added the A-p2p Related to P2P. label Dec 14, 2024
Copy link
Contributor Author

@hinto-janai hinto-janai left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Boog900 I think this mostly needs review on:

  • general direction and broader changes
  • viability of new tower::Service request/response types

I don't think you have to review each handler fn individually in-depth since there will eventually be the testing harness that proves input/output matches monerod. With that said, here's some info:

RPC code structure

Directory Contains
binaries/cuprated/src/rpc/handlers/ The RPC handler functions, shared functions, and helper functions
binaries/cuprated/src/rpc/service/ fn versions of our tower::Services to reduce noise

RPC handlers

Color Meaning
🟢 Ready
🟡 Ready but could be more efficient
🟣 Ready but callstack depends on other things
🟠 Depends on other things
🔴 Waiting on binary strings
🔵 Unsupported (for now)
Unsupported (probably forever)
I think these could be deprecated or have different behavior
JSON-RPC fn Status Details
get_block_count 🟢
get_last_block_header 🟢
get_block_header_by_hash 🟢
get_block_header_by_height 🟢
get_block 🟢
hard_fork_info 🟢
on_get_block_hash 🟢
get_block_headers_range 🟡 Would benefit from a request that allows retrieving a range of (Block, ExtendedBlockHeader)
get_connections 🟣 Waiting on address book Service impl
set_bans 🟣 ^
get_bans 🟣 ^
banned 🟣 ^
get_version 🟣 Waiting on blockchain context Service impl
get_output_histogram 🟣 ^
get_fee_estimate 🟣 ^
calc_pow 🟣 ^
flush_transaction_pool 🟣 Waiting on txpool manager Service impl
relay_tx 🟣 ^
get_coinbase_tx_sum 🟣 Waiting on blockchain Service impl
get_alternate_chains 🟣 ^
sync_info 🟣 Waiting on multiple Service impls
get_miner_data 🟣 Waiting on txpool Service impl
submit_block 🟣 ^
get_info 🟣 Needs access to unimplemented things from various places
generate_blocks 🟣 Needs access to cuprated's Chain and --regtest
add_aux_pow 🟣 Waiting on crypto functions
get_transaction_pool_backlog 🔴
get_output_distribution 🔴
get_tx_ids_loose 🔵 Not implemented in monerod release branch yet
flush_cache cuprated does not need this
prune_blockchain I don't think an always available RPC method is necessary for something that is done once. This could return if the chain is pruned + the pruning seed but not actually prune if that makes things more complex. Pruning itself should be done with the equivalent of --prune-blockchain.
Other JSON fn Status Details
get_height 🟢
get_outs 🟢
is_key_image_spent 🟣 Waiting on txpool Service impl
get_transaction_pool_hashes 🟣 ^
get_transaction_pool 🟣 ^
get_transaction_pool_stats 🟣 ^
save_bc 🟣 Waiting on blockchain manager Service impl
stop_daemon 🟣 ^
pop_blocks 🟣 ^
get_peer_list 🟣 Waiting on address book Service impl
get_public_nodes 🟣 ^
get_alt_blocks_hashes 🟣 Waiting on blockchain Service impl
send_raw_transaction 🟣 Waiting on txpool manager Service impl
get_transactions 🟣 Waiting on JSON representation of Transaction
get_limit 🟠 Waiting on P2P interface
set_limit 🟠 ^
out_peers 🟠 ^
in_peers 🟠 ^
get_net_stats 🟠 ^
set_log_level 🔵 Will use tracing levels
set_log_categories 🔵 Could be re-purposed to use tracing filters
set_bootstrap_daemon 🔵 Needs bootstrap implementation
start_mining cuprated does not mine
stop_mining ^
mining_status ^
set_log_hash_rate ^
update This could return if an update is available and related info but not actually self-update. Software upgrades should be done by the user and/or a package manager.
Binary fn Status Details
get_blocks_by_height 🟢
get_hashes 🟢
get_output_indexes 🟢
get_outs 🟢
get_blocks 🟣 Waiting on txpool Service impl
get_transaction_pool_hashes 🟣 ^
get_output_distribution 🔴 Although this is binary, the internal fn is shared with JSON-RPC's get_output_distribution

Comment on lines +39 to +42
# Types
"types/types",
"types/hex",
"types/fixed-bytes",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cuprate_types::hex::Hex was moved into a separate crate cuprate_hex such that the types could implement epee without running into cyclic dependency or orphan impl problems.

I moved fixed-bytes as well since that is used in multiple places outside of networking.

@@ -291,6 +291,7 @@ macro_rules! define_response {
}
) => {
$( #[$attr] )*
#[cfg_attr(feature = "serde", serde(default))] // TODO: link epee field not serializing oddity
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the time being, I'm making response types in cuprate-rpc-types have serde(default) since:

  1. monerod will not serialize fields with empty containers
  2. monerod's response types sometimes change depending on branches

serde(default) is a bit of a blunt tool to use but I think it works for now. I will think about this more when integrating RPC into cuprated and with more tests.

//! These are `struct`s that appear in request/response types.
//! For example, [`crate::json::GetConnectionsResponse`] contains
//! the [`crate::misc::ConnectionInfo`] struct defined here.
//! Various types (in)directly used in RPC.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1/2

This is a new module, cuprate_types::rpc. It contains types that are exposed by RPC but are also used internally.

The difference between cuprate_rpc_types and cuprate_types::rpc is that the latter has more canonical types where it makes sense, e.g. [u8; 32] instead of String.

@@ -0,0 +1,190 @@
//! [`From`] implementations from other crate's types into [`crate`] types.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2/2

Since cuprate_types::rpc needs to map to cuprate_rpc_types eventually, instead of doing it adhoc-ly in places, this file defines a bunch of

impl From<cuprate_types::rpc::*> for cuprate_rpc_types::*

plus some other types from other crates.

Comment on lines -187 to -203
#[doc = serde_doc_test!(
GET_BLOCK_TEMPLATE_RESPONSE => GetBlockTemplateResponse {
base: ResponseBase::OK,
blockhashing_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a00000000e0c20372be23d356347091025c5b5e8f2abf83ab618378565cce2b703491523401".into(),
blocktemplate_blob: "1010f4bae0b4069d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a0000000002c681c30101ff8a81c3010180e0a596bb11033b7eedf47baf878f3490cb20b696079c34bd017fe59b0d070e74d73ffabc4bb0e05f011decb630f3148d0163b3bd39690dde4078e4cfb69fecf020d6278a27bad10c58023c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000".into(),
difficulty_top64: 0,
difficulty: 283305047039,
expected_reward: 600000000000,
height: 3195018,
next_seed_hash: "".into(),
prev_hash: "9d648e741d85ca0e7acb4501f051b27e9b107d3cd7a3f03aa7f776089117c81a".into(),
reserved_offset: 131,
seed_hash: "e2aa0b7b55042cd48b02e395d78fa66a29815ccc1584e38db2d1f0e8485cd44f".into(),
seed_height: 3194880,
wide_difficulty: "0x41f64bf3ff".into(),
}
)]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think doing tests like this was a bad tradeoff, it's a bit too noisy and IDE stuff stops working, so a large majority of the changes to rpc/types/src/{json,bin,other}.rs are moving the macro tests into normal #[test] fn() tests at the bottom of the file.

Comment on lines -217 to +131
blockhashing_blob: String,
blocktemplate_blob: String,
blockhashing_blob: HexVec,
blocktemplate_blob: HexVec,
difficulty_top64: u64,
difficulty: u64,
expected_reward: u64,
height: u64,
next_seed_hash: String,
prev_hash: String,
/// This is a [`Hex<32>`] that is sometimes empty.
next_seed_hash: HexVec,
prev_hash: Hex<32>,
reserved_offset: u64,
seed_hash: String,
seed_hash: Hex<32>,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cuprate-rpc-types now uses Hex and HexVec over String where it can.

state: CupratedRpcHandler,
_: GetConnectionsRequest,
) -> Result<GetConnectionsResponse, Error> {
let connections = address_book::connection_info::<ClearNet>(&mut DummyAddressBook).await?;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All RPC calls involving the address book service are hardcoded to ClearNet for now. Can be (easily?) changed later.

Comment on lines +1 to +7
//! String formatting.

/// A type that can be represented in hexadecimal (with a `0x` prefix).
pub trait HexPrefix {
/// Turn `self` into a hexadecimal string prefixed with `0x`.
fn hex_prefix(self) -> String;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lots of fields in RPC are String where it is a hexadecimal encoded u128 with a lowercase prefix, e.g. 0x0

You can use format!("{var:#x}") for this although it's a bit obscure so I made this trait so you can do var.hex_prefix(). Could remove this if wanted.

Comment on lines +177 to 195
let txid = {
let height = u32_to_usize(output.height);
let tx_idx = u64_to_usize(output.tx_idx);
if let Some(hash) = table_block_txs_hashes.get(&height)?.get(tx_idx) {
*hash
} else {
let miner_tx_id = table_block_infos.get(&height)?.mining_tx_index;
let tx_blob = table_tx_blobs.get(&miner_tx_id)?;
Transaction::read(&mut tx_blob.0.as_slice())?.hash()
}
};

Ok(OutputOnChain {
height: output.height as usize,
time_lock,
key,
commitment,
txid,
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function now returns the txid for each output due to https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#get_outs.

This is more expensive, the txid is not required by default as well. Should this be something like txid: Option<[u8; 32]> instead?

Comment on lines -508 to +543
fn key_images_spent(env: &ConcreteEnv, key_images: HashSet<KeyImage>) -> ResponseResult {
fn key_images_spent(env: &ConcreteEnv, key_images: Vec<KeyImage>) -> ResponseResult {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was changed to Vec due to https://www.getmonero.org/resources/developer-guides/daemon-rpc.html#is_key_image_spent behavior.

curl http://127.0.0.1:18081/is_key_image_spent -d '{"key_images":["8d1bd8181bf7d857bdb281e0153d84cd55a3fcaa57c3e570f4a49f935850b5e3","8d1bd8181bf7d857bdb281e0153d84cd55a3fcaa57c3e570f4a49f935850b5e3"]}' -H 'Content-Type: application/json'
{
  "credits": 0,
  "spent_status": [1,1],
  "status": "OK",
  "top_hash": "",
  "untrusted": false
}

If cuprated used HashSet then it would respond with something like "spent_status": [1]. Small detail but I think it could matter with wallets due to indexing code depending on this.

@hinto-janai hinto-janai marked this pull request as ready for review December 25, 2024 23:51
@hinto-janai hinto-janai requested a review from Boog900 December 25, 2024 23:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-binaries Related to binaries. A-book-architecture Related to the Architecture book. A-books Related to Cuprate's books. A-consensus Related to consensus. A-dependency Related to dependencies, or changes to a Cargo.{toml,lock} file. A-docs Related to documentation. A-helper Related to cuprate-helper. A-net Related to networking. A-p2p Related to P2P. A-rpc Related to RPC. A-storage Related to storage. A-types Related to types. A-workspace Changes to a root workspace file or general repo file. A-zmq Related to ZMQ.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant