Skip to content

Commit

Permalink
RPC-456 adding two versions of request handler, one that has json val…
Browse files Browse the repository at this point in the history
…idation and another that does not
  • Loading branch information
dmitriy-helius committed Aug 28, 2024
1 parent ab77949 commit d9f6c6d
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 102 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 1 addition & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use cadence::{BufferedUdpMetricSink, QueuingMetricSink, StatsdClient};
use cadence_macros::set_global_default;
use figment::{providers::Env, Figment};
use grpc_geyser::GrpcGeyserImpl;
use jsonrpsee::server::{RpcServiceBuilder, ServerBuilder};
use jsonrpsee::server::ServerBuilder;
use jsonrpsee::server::middleware::http::ProxyGetRequestLayer;
use priority_fee::PriorityFeeTracker;
use rpc_server::AtlasPriorityFeeEstimator;
Expand All @@ -19,7 +19,6 @@ mod priority_fee;
mod rpc_server;
mod slot_cache;
mod solana;
mod temp_validator;

#[derive(Debug, Deserialize, Clone)]
struct EstimatorEnv {
Expand Down Expand Up @@ -53,7 +52,6 @@ async fn main() {

let port = env.port.unwrap_or(4141);
let server = ServerBuilder::default()
.set_rpc_middleware(RpcServiceBuilder::new().layer(temp_validator::RpcValidatorLayer::new()))
.set_http_middleware(
tower::ServiceBuilder::new()
// Proxy `GET /health` requests to internal `health` method.
Expand Down
4 changes: 2 additions & 2 deletions src/priority_fee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ impl GrpcConsumer for PriorityFeeTracker {

impl PriorityFeeTracker {
pub fn new(slot_cache_length: usize) -> Self {
let (sampling_txn, sampling_rxn) = channel::<(Vec<Pubkey>, bool, Option<u32>)>(1_000);
let (sampling_txn, sampling_rxn) = channel::<(Vec<Pubkey>, bool, Option<u32>)>(100);

let tracker = Self {
priority_fees: Arc::new(DashMap::new()),
Expand Down Expand Up @@ -502,7 +502,7 @@ impl PriorityFeeTracker {
slots_vec.sort();
slots_vec.reverse();

let lookback = calculate_lookback_size(&lookback_period, self.slot_cache.len());
let lookback = calculate_lookback_size(&lookback_period, slots_vec.len());

let mut fees = vec![];
let mut micro_lamport_priority_fee_estimates = MicroLamportPriorityFeeEstimates::default();
Expand Down
112 changes: 96 additions & 16 deletions src/rpc_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,60 @@ impl fmt::Debug for AtlasPriorityFeeEstimator {
#[serde(
rename_all(serialize = "camelCase", deserialize = "camelCase"),
)]
// TODO: DKH - add deny_unknown_fields
// TODO: DKH - delete after all the users were notified
pub struct GetPriorityFeeEstimateRequestLight {
pub transaction: Option<String>, // estimate fee for a txn
pub account_keys: Option<Vec<String>>, // estimate fee for a list of accounts
pub options: Option<GetPriorityFeeEstimateOptionsLight>,
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(
rename_all(serialize = "camelCase", deserialize = "camelCase"),
)]
// TODO: DKH - Delete after all the users were notified
pub struct GetPriorityFeeEstimateOptionsLight {
// controls input txn encoding
pub transaction_encoding: Option<UiTransactionEncoding>,
// controls custom priority fee level response
pub priority_level: Option<PriorityLevel>, // Default to MEDIUM
pub include_all_priority_fee_levels: Option<bool>, // Include all priority level estimates in the response
#[serde()]
pub lookback_slots: Option<u32>, // how many slots to look back on, default 50, min 1, max 300
pub include_vote: Option<bool>, // include vote txns in the estimate
// returns recommended fee, incompatible with custom controls. Currently the recommended fee is the median fee excluding vote txns
pub recommended: Option<bool>, // return the recommended fee (median fee excluding vote txns)
}

impl Into<GetPriorityFeeEstimateRequest> for GetPriorityFeeEstimateRequestLight {
fn into(self) -> GetPriorityFeeEstimateRequest {
let transaction = self.transaction;
let account_keys = self.account_keys;
let options = self.options.map(|o| {
GetPriorityFeeEstimateOptions {
transaction_encoding: o.transaction_encoding,
priority_level: o.priority_level,
include_all_priority_fee_levels: o.include_all_priority_fee_levels,
lookback_slots: o.lookback_slots,
include_vote: o.include_vote,
recommended: o.recommended,
}
});

GetPriorityFeeEstimateRequest
{
transaction,
account_keys,
options,
}
}
}

#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(
rename_all(serialize = "camelCase", deserialize = "camelCase"),
deny_unknown_fields
)]
pub struct GetPriorityFeeEstimateRequest {
pub transaction: Option<String>, // estimate fee for a txn
pub account_keys: Option<Vec<String>>, // estimate fee for a list of accounts
Expand All @@ -55,8 +108,8 @@ pub struct GetPriorityFeeEstimateRequest {
#[derive(Serialize, Deserialize, Clone, Debug, Default)]
#[serde(
rename_all(serialize = "camelCase", deserialize = "camelCase"),
deny_unknown_fields
)]
// TODO: DKH - add deny_unknown_fields
pub struct GetPriorityFeeEstimateOptions {
// controls input txn encoding
pub transaction_encoding: Option<UiTransactionEncoding>,
Expand All @@ -83,13 +136,22 @@ pub struct GetPriorityFeeEstimateResponse {
pub trait AtlasPriorityFeeEstimatorRpc {
#[method(name = "health")]
fn health(&self) -> String;

// TODO: DKH - delete after all the users were notified about moving to strict parsing
#[method(name = "getPriorityFeeEstimate")]
fn get_priority_fee_estimate_light(
&self,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequestLight,
) -> RpcResult<GetPriorityFeeEstimateResponse>;

// TODO: DKH - rename annotation method name to "getPriorityFeeEstimateStrict" to "getPriorityFeeEstimate"
#[method(name = "getPriorityFeeEstimateStrict")]
fn get_priority_fee_estimate(
&self,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequest,
) -> RpcResult<GetPriorityFeeEstimateResponse>;

#[method(name = "getTestPriorityFeeEstimate")]
#[method(name = "getPriorityFeeEstimateTest")]
fn get_test_priority_fee_estimate(
&self,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequest,
Expand Down Expand Up @@ -249,9 +311,27 @@ impl AtlasPriorityFeeEstimatorRpcServer for AtlasPriorityFeeEstimator {
fn health(&self) -> String {
"ok".to_string()
}
fn get_priority_fee_estimate_light(
&self,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequestLight,
) -> RpcResult<GetPriorityFeeEstimateResponse> {
let algo_run_fn = |accounts: Vec<Pubkey>,
include_vote: bool,
lookback_period: Option<u32>|
-> MicroLamportPriorityFeeEstimates {
self.priority_fee_tracker.get_priority_fee_estimates(
accounts,
include_vote,
lookback_period,
true,
)
};
self.execute_priority_fee_estimate_coordinator(get_priority_fee_estimate_request.into(), algo_run_fn)
}

fn get_priority_fee_estimate(
&self,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequest,
get_priority_fee_estimate_request: GetPriorityFeeEstimateRequest
) -> RpcResult<GetPriorityFeeEstimateResponse> {
let algo_run_fn = |accounts: Vec<Pubkey>,
include_vote: bool,
Expand All @@ -265,6 +345,7 @@ impl AtlasPriorityFeeEstimatorRpcServer for AtlasPriorityFeeEstimator {
)
};
self.execute_priority_fee_estimate_coordinator(get_priority_fee_estimate_request, algo_run_fn)

}

fn get_test_priority_fee_estimate(
Expand Down Expand Up @@ -516,8 +597,7 @@ mod tests {
assert_eq!(resp.priority_fee_estimate, Some(10500.0));
}

// #[test]
// TODO: DKH - add the test back after we readd the validation
#[test]
fn test_parsing_wrong_fields() {
for (param, error) in bad_params() {
let json_val = format!("{{\"jsonrpc\": \"2.0\",\"id\": \"1\", \"method\": \"getPriorityFeeEstimate\", \"params\": [{param}] }}");
Expand Down Expand Up @@ -549,16 +629,16 @@ mod tests {

fn bad_params<'a>() -> Vec<(&'a str, &'a str)> {
vec![
(r#"{"transactions": null}"#,"unknown field `transactions`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 15"),
(r#"{"account_keys": null}"#,"unknown field `account_keys`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 15"),
(r#"{"accountkeys": null}"#,"unknown field `accountkeys`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 14"),
(r#"{"accountKeys": [1, 2]}"#, "invalid type: integer `1`, expected a string at line 1 column 18"),
(r#"{"option": null}"#, "unknown field `option`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 9"),
(r#"{"options": {"transaction_encoding":null}}"#, "unknown field `transaction_encoding`, expected one of `transactionEncoding`, `priorityLevel`, `includeAllPriorityFeeLevels`, `lookbackSlots`, `includeVote`, `recommended` at line 1 column 35"),
(r#"{"options": {"priorityLevel":"HIGH"}}"#, "unknown variant `HIGH`, expected one of `Min`, `Low`, `Medium`, `High`, `VeryHigh`, `UnsafeMax`, `Default` at line 1 column 35"),
(r#"{"options": {"includeAllPriorityFeeLevels":"no"}}"#, "invalid type: string \"no\", expected a boolean at line 1 column 47"),
(r#"{"options": {"lookbackSlots":"no"}}"#, "invalid type: string \"no\", expected u32 at line 1 column 33"),
(r#"{"options": {"lookbackSlots":"-1"}}"#, "invalid type: string \"-1\", expected u32 at line 1 column 33"),
(r#"{"transactions": null}"#,"unknown field `transactions`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 16"),
(r#"{"account_keys": null}"#,"unknown field `account_keys`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 16"),
(r#"{"accountkeys": null}"#,"unknown field `accountkeys`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 15"),
(r#"{"accountKeys": [1, 2]}"#, "invalid type: integer `1`, expected a string at line 1 column 19"),
(r#"{"option": null}"#, "unknown field `option`, expected one of `transaction`, `accountKeys`, `options` at line 1 column 10"),
(r#"{"options": {"transaction_encoding":null}}"#, "unknown field `transaction_encoding`, expected one of `transactionEncoding`, `priorityLevel`, `includeAllPriorityFeeLevels`, `lookbackSlots`, `includeVote`, `recommended` at line 1 column 36"),
(r#"{"options": {"priorityLevel":"HIGH"}}"#, "unknown variant `HIGH`, expected one of `Min`, `Low`, `Medium`, `High`, `VeryHigh`, `UnsafeMax`, `Default` at line 1 column 36"),
(r#"{"options": {"includeAllPriorityFeeLevels":"no"}}"#, "invalid type: string \"no\", expected a boolean at line 1 column 48"),
(r#"{"options": {"lookbackSlots":"no"}}"#, "invalid type: string \"no\", expected u32 at line 1 column 34"),
(r#"{"options": {"lookbackSlots":"-1"}}"#, "invalid type: string \"-1\", expected u32 at line 1 column 34"),
]
}
}
5 changes: 5 additions & 0 deletions src/slot_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,11 @@ impl SlotCache {
}
match self.slot_queue.write() {
Ok(mut slot_queue) => {

if self.slot_set.contains(&slot) {
return None;
}

match slot_queue.add(slot) {
Ok(maybe_oldest_slot) => {
if let Some(oldest_slot) = maybe_oldest_slot
Expand Down
80 changes: 0 additions & 80 deletions src/temp_validator.rs

This file was deleted.

0 comments on commit d9f6c6d

Please sign in to comment.