From e6b00dda5b829973ea8db089046592cd3e51ff00 Mon Sep 17 00:00:00 2001 From: Mathis Date: Tue, 12 Jul 2022 15:48:36 +0200 Subject: [PATCH] Eqs remove unbounded queries (#1191) * Problem: The size of the events query is unbounded Return at most 100 events. * Problem: unbounded get_all_nullifiers endpoint The endpoint is unused, remove it. --- eqs/api/api.toml | 9 ++++----- eqs/src/routes.rs | 24 ++++++++++-------------- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/eqs/api/api.toml b/eqs/api/api.toml index 0995981f..f86c4edb 100644 --- a/eqs/api/api.toml +++ b/eqs/api/api.toml @@ -35,10 +35,6 @@ HEADING_DESCRIPTION = "Description" PATH = [ "get_cap_state" ] DOC = "Returns the current CAP blockchain state." -[route.get_all_nullifiers] -PATH = [ "get_all_nullifiers" ] -DOC = "Returns the current set of nullifiers." - [route.check_nullifier] PATH = [ "check_nullifier/:nullifier" ] ":nullifier" = "TaggedBase64" @@ -49,7 +45,10 @@ ERROR_nullifier = "A valid nullifier is required. Nullifiers begin with NUL~." PATH = [ "get_events_since/:first", "get_events_since/:first/:max_count" ] ":first" = "Integer" ":max_count" = "Integer" -DOC = "Returns the array of [up to max_count] events since the specified index (inclusive)" +DOC = """Returns the array of [up to max_count] events since the specified index (inclusive) + +If `:max_count` is larger than 100 or omitted at most the first 100 events are returned. +""" ERROR_first = "The index must be a non-negative integer." ERROR_max_count = "The max_count must be a non-negative, non-zero integer." diff --git a/eqs/src/routes.rs b/eqs/src/routes.rs index b893b1a7..e2451ffa 100644 --- a/eqs/src/routes.rs +++ b/eqs/src/routes.rs @@ -16,17 +16,19 @@ use jf_cap::structs::{AssetCode, Nullifier}; use net::server::response; use seahorse::events::LedgerEvent; use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; +use std::collections::HashMap; use std::str::FromStr; use strum::IntoEnumIterator; use strum_macros::{AsRefStr, EnumIter, EnumString}; +/// Maximum number of events to return in a single response. +const EQS_MAX_EVENT_COUNT: usize = 100; + /// Index entries for documentation fragments #[allow(non_camel_case_types)] #[derive(AsRefStr, Copy, Clone, Debug, EnumIter, EnumString)] pub enum ApiRouteKey { get_cap_state, - get_all_nullifiers, check_nullifier, get_events_since, get_transaction, @@ -104,13 +106,6 @@ pub async fn get_cap_state(query_result_state: &QueryResultState) -> Result Result, tide::Error> { - Ok(query_result_state.nullifiers.clone()) -} - /// Check if a nullifier has already been published. pub async fn check_nullifier( bindings: &HashMap, @@ -135,11 +130,13 @@ pub async fn get_events_since( if first >= events_len { return Ok(Vec::new()); } - let last = if let Some(max_count) = bindings.get(":max_count") { - std::cmp::min(first + max_count.value.as_u64()? as usize, events_len) - } else { - events_len + let max_count = match bindings.get(":max_count") { + Some(user_max_count) => { + std::cmp::min(user_max_count.value.as_u64()? as usize, EQS_MAX_EVENT_COUNT) + } + None => EQS_MAX_EVENT_COUNT, }; + let last = std::cmp::min(first + max_count, events_len); Ok(query_result_state.events[first..last].to_vec()) } @@ -229,7 +226,6 @@ pub async fn dispatch_url( let query_state = &*query_state_guard; match key { ApiRouteKey::get_cap_state => response(&req, get_cap_state(query_state).await?), - ApiRouteKey::get_all_nullifiers => response(&req, get_all_nullifiers(query_state).await?), ApiRouteKey::check_nullifier => { response(&req, check_nullifier(bindings, query_state).await?) }