RPC design proposal
This issue is meant to initiate a discussion on the high-level design of Cuprate's daemon RPC.
The main focus is on defining the interface and  handling parsing methods/params and responses, so I abstracted away all interactions with other Cuprate's parts for now and the actual daemon.

## Overview

[Monerod's daemon RPC](https://www.getmonero.org/resources/developer-guides/daemon-rpc.html)  has three kinds of RPC calls: 

- JSON RPC methods, called at the endpoint `/json_rpc`
- general RPC methods called at their own endpoints (eg. `/get_height`)
- binary (epee format) RPC methods called at their own endpoints ending in .bin (eg.`/get_blocks.bin`)

Given the above it seems natural to split the daemon into three different Services / Layers.

![cuprate](https://github.com/Cuprate/cuprate/assets/30393429/e6204778-a16a-4beb-96ca-b5c09f623dbf)


## (Core) RPC Service
This is the actual service responsible for calling the methods (and interfacing with the necessary Cuprate crates such as the db), it implements `Service<Rpc>` and returns a `method::Response`. 
enum/struct example:
```rust
pub enum Rpc {
    TestMethod(crate::param::TestMethod),
    ...
}
// crate::param
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TestMethod {
    number: u8,
}

epee_object!(
    TestMethod,
    number: u8,
);
```
```rust
//method::Response
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
struct BaseResponse {
    credits: u64,
    status: String,
    top_hash: String,
    untrusted: bool,
}

epee_object!(
    BaseResponse,
    credits: u64,
    status: String,
    top_hash: String,
    untrusted: bool,
);

#[derive(Clone, Serialize, Deserialize)]
pub enum Response {
    TestMethod(TestResponse)
}

#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct TestResponse {
    base: BaseResponse,
    pub test: u8
}

epee_object!(
    TestResponse,
    base: BaseResponse,
    test: u8,
);
```
## Middleware Service
This service is mainly responsible for parsing the parameters of the RPC call so that we can construct the struct related to the specific RPC method and deserializing the response into the proper type (`Value`, `JsonResponse`, `Bytes` in epee format).
Errors regarding method name and parameters are caught and handled before calling the core service.
It has different implementations based on the RPC call type, specifically ` JsonRequest` and `RpcRequest<Bytes>`, `RpcRequest<RawValue>`, where `RpcRequest` is a struct  with the given method by the URI and  the given params, so something like
```rust
pub struct RpcRequest<'a, T> {
    pub method: Cow<'a, str>,
    pub params: T
}
```
Macro example for JSON RPC:
```rust
macro_rules! call_json_rpc {

    ($method:ident, $request:expr, $self:expr, $param:ty) => {{
        let id = $request.id.map(|id| id.into_owned());

        let Some(Ok(param)) = $request.params
            .map(|params| serde_json::from_str::<$param>(params.get())) else {
            return async move { Ok(JsonResponse::invalid_params(id)) }.boxed()
        };

        async move {
            let result = $self.core_rpc.call(crate::method::Rpc::$method(param)).await;
            if let Ok(result) = result {
                let result = serde_json::to_value(&result).unwrap();
                return Ok(JsonResponse::result(Cow::Owned(result), id))
            } else {
                return Ok(JsonResponse::invalid_params(id))
            }
        }.boxed()
    }};
}
```
## HTTP Service
This `hyper::service` (as the name suggests) is responsible for handling all the HTTP related things.
It will parse the body, match the URI so that it knows which Middleware service to call and it wraps the result of those to the body of the hyper::response.



