pub mod account;
pub mod chain;
pub mod docs;
pub mod info;
pub mod state;
use std::str;
use futures::{future::BoxFuture, TryFutureExt};
use http::Response;
use hyper::Body;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use warp::{
filters::BoxedFilter,
reject::{self, Reject},
Filter,
};
use warp_json_rpc::{filters, Builder};
use super::{ReactorEventT, RpcRequest};
use crate::effect::EffectBuilder;
use docs::DocExample;
pub const RPC_API_PATH: &str = "rpc";
#[repr(i64)]
enum ErrorCode {
NoSuchDeploy = 32000,
NoSuchBlock = 32001,
ParseQueryKey = 32002,
QueryFailed = 32003,
QueryFailedToExecute = 32004,
ParseGetBalanceURef = 32005,
GetBalanceFailed = 32006,
GetBalanceFailedToExecute = 32007,
InvalidDeploy = 32008,
}
#[derive(Debug)]
pub(super) struct Error(String);
impl Reject for Error {}
impl From<anyhow::Error> for Error {
fn from(error: anyhow::Error) -> Self {
Error(error.to_string())
}
}
pub trait RpcWithParams {
const METHOD: &'static str;
type RequestParams: Serialize
+ for<'de> Deserialize<'de>
+ JsonSchema
+ DocExample
+ Send
+ 'static;
type ResponseResult: Serialize
+ for<'de> Deserialize<'de>
+ JsonSchema
+ DocExample
+ Send
+ 'static;
}
pub(super) trait RpcWithParamsExt: RpcWithParams {
fn create_filter<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
) -> BoxedFilter<(Response<Body>,)> {
warp::path(RPC_API_PATH)
.and(filters::json_rpc())
.and(filters::method(Self::METHOD))
.and(filters::params::<Self::RequestParams>())
.and_then(
move |response_builder: Builder, params: Self::RequestParams| {
Self::handle_request(effect_builder, response_builder, params)
.map_err(reject::custom)
},
)
.boxed()
}
fn handle_request<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
response_builder: Builder,
params: Self::RequestParams,
) -> BoxFuture<'static, Result<Response<Body>, Error>>;
}
pub trait RpcWithoutParams {
const METHOD: &'static str;
type ResponseResult: Serialize
+ for<'de> Deserialize<'de>
+ JsonSchema
+ DocExample
+ Send
+ 'static;
}
pub(super) trait RpcWithoutParamsExt: RpcWithoutParams {
fn create_filter<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
) -> BoxedFilter<(Response<Body>,)> {
warp::path(RPC_API_PATH)
.and(filters::json_rpc())
.and(filters::method(Self::METHOD))
.and_then(move |response_builder: Builder| {
Self::handle_request(effect_builder, response_builder).map_err(reject::custom)
})
.boxed()
}
fn handle_request<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
response_builder: Builder,
) -> BoxFuture<'static, Result<Response<Body>, Error>>;
}
pub trait RpcWithOptionalParams {
const METHOD: &'static str;
type OptionalRequestParams: Serialize
+ for<'de> Deserialize<'de>
+ JsonSchema
+ DocExample
+ Send
+ 'static;
type ResponseResult: Serialize
+ for<'de> Deserialize<'de>
+ JsonSchema
+ DocExample
+ Send
+ 'static;
}
pub(super) trait RpcWithOptionalParamsExt: RpcWithOptionalParams {
fn create_filter<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
) -> BoxedFilter<(Response<Body>,)> {
let with_params = warp::path(RPC_API_PATH)
.and(filters::json_rpc())
.and(filters::method(Self::METHOD))
.and(filters::params::<Self::OptionalRequestParams>())
.and_then(
move |response_builder: Builder, params: Self::OptionalRequestParams| {
Self::handle_request(effect_builder, response_builder, Some(params))
.map_err(reject::custom)
},
);
let without_params = warp::path(RPC_API_PATH)
.and(filters::json_rpc())
.and(filters::method(Self::METHOD))
.and_then(move |response_builder: Builder| {
Self::handle_request(effect_builder, response_builder, None).map_err(reject::custom)
});
with_params.or(without_params).unify().boxed()
}
fn handle_request<REv: ReactorEventT>(
effect_builder: EffectBuilder<REv>,
response_builder: Builder,
maybe_params: Option<Self::OptionalRequestParams>,
) -> BoxFuture<'static, Result<Response<Body>, Error>>;
}
mod common {
use std::convert::TryFrom;
use once_cell::sync::Lazy;
use casper_execution_engine::core::engine_state::{self, QueryResult};
use casper_types::bytesrepr::ToBytes;
use super::ErrorCode;
use crate::types::json_compatibility::StoredValue;
pub(super) static MERKLE_PROOF: Lazy<String> = Lazy::new(|| {
String::from(
"01000000006ef2e0949ac76e55812421f755abe129b6244fe7168b77f47a72536147614625016ef2e0949ac76e\
55812421f755abe129b6244fe7168b77f47a72536147614625000000003529cde5c621f857f75f3810611eb4af3\
f998caaa9d4a3413cf799f99c67db0307010000006ef2e0949ac76e55812421f755abe129b6244fe7168b77f47a\
7253614761462501010102000000006e06000000000074769d28aac597a36a03a932d4b43e4f10bf0403ee5c41d\
d035102553f5773631200b9e173e8f05361b681513c14e25e3138639eb03232581db7557c9e8dbbc83ce9450022\
6a9a7fe4f2b7b88d5103a4fc7400f02bf89c860c9ccdd56951a2afe9be0e0267006d820fb5676eb2960e15722f7\
725f3f8f41030078f8b2e44bf0dc03f71b176d6e800dc5ae9805068c5be6da1a90b2528ee85db0609cc0fb4bd60\
bbd559f497a98b67f500e1e3e846592f4918234647fca39830b7e1e6ad6f5b7a99b39af823d82ba1873d0000030\
00000010186ff500f287e9b53f823ae1582b1fa429dfede28015125fd233a31ca04d5012002015cc42669a55467\
a1fdf49750772bfc1aed59b9b085558eb81510e9b015a7c83b0301e3cf4a34b1db6bfa58808b686cb8fe21ebe0c\
1bcbcee522649d2b135fe510fe3")
});
pub(super) fn extract_query_result(
query_result: Result<QueryResult, engine_state::Error>,
) -> Result<(StoredValue, Vec<u8>), (ErrorCode, String)> {
let (value, proof) = match query_result {
Ok(QueryResult::Success { value, proofs }) => (value, proofs),
Ok(query_result) => {
let error_msg = format!("state query failed: {:?}", query_result);
return Err((ErrorCode::QueryFailed, error_msg));
}
Err(error) => {
let error_msg = format!("state query failed to execute: {:?}", error);
return Err((ErrorCode::QueryFailedToExecute, error_msg));
}
};
let value_compat = match StoredValue::try_from(&*value) {
Ok(value_compat) => value_compat,
Err(error) => {
let error_msg = format!("failed to encode stored value: {:?}", error);
return Err((ErrorCode::QueryFailed, error_msg));
}
};
let proof_bytes = match proof.to_bytes() {
Ok(proof_bytes) => proof_bytes,
Err(error) => {
let error_msg = format!("failed to encode stored value: {:?}", error);
return Err((ErrorCode::QueryFailed, error_msg));
}
};
Ok((value_compat, proof_bytes))
}
}