diff --git a/web3_proxy/src/app/mod.rs b/web3_proxy/src/app/mod.rs index 4db00d1b..d882631e 100644 --- a/web3_proxy/src/app/mod.rs +++ b/web3_proxy/src/app/mod.rs @@ -1122,7 +1122,7 @@ impl Web3ProxyApp { /// proxy request with up to 3 tries. async fn proxy_request( self: &Arc, - request: JsonRpcRequest, + mut request: JsonRpcRequest, authorization: Arc, head_block_num: Option, ) -> (StatusCode, JsonRpcForwardedResponse, Vec>) { @@ -1136,16 +1136,15 @@ impl Web3ProxyApp { let response_id = request.id; + // TODO: trace log request.params before we send them to _proxy_request_with_caching which might modify them + let mut tries = 3; - let mut code; - let mut response; + let mut last_code_and_response = None; while tries > 0 { - // TODO: make sure this doesn't retry jsonrpc errors - let response_data; - (code, response_data) = match self + let (code, response_data) = match self ._proxy_request_with_caching( &request.method, - request.params, + &mut request.params, head_block_num, &request_metadata, ) @@ -1155,7 +1154,7 @@ impl Web3ProxyApp { Err(err) => err.as_response_parts(), }; - response = JsonRpcForwardedResponse::from_response_data(response_data, response_id); + last_code_and_response = Some((code, response_data)); if code == StatusCode::OK { break; @@ -1163,11 +1162,14 @@ impl Web3ProxyApp { // TODO: emit a stat? // TODO: only log params in development - warn!(method=%request.method, params=?request.params, ?response, "request failed"); + warn!(method=%request.method, params=?request.params, response=?last_code_and_response, "request failed"); + tries -= 1; } - let response = response.expect("we definitely looped at least once"); + let (code, response) = last_code_and_response.expect("there should always be a response"); + + let response = JsonRpcForwardedResponse::from_response_data(response, response_id); // TODO: this serializes twice :/ request_metadata.add_response(ResponseOrBytes::Response(&response)); @@ -1182,7 +1184,7 @@ impl Web3ProxyApp { async fn _proxy_request_with_caching( self: &Arc, method: &str, - mut params: serde_json::Value, + params: &mut serde_json::Value, head_block_num: Option, request_metadata: &Arc, ) -> Web3ProxyResult>> { @@ -1297,7 +1299,7 @@ impl Web3ProxyApp { let x = bundler_4337_rpcs .try_proxy_connection::<_, Box>( method, - ¶ms, + params, Some(request_metadata), Some(Duration::from_secs(30)), None, @@ -1338,7 +1340,7 @@ impl Web3ProxyApp { .balanced_rpcs .try_proxy_connection::<_, U256>( method, - ¶ms, + params, Some(request_metadata), Some(Duration::from_secs(30)), None, @@ -1371,7 +1373,7 @@ impl Web3ProxyApp { .balanced_rpcs .try_proxy_connection::<_, Box>( method, - ¶ms, + params, Some(request_metadata), Some(Duration::from_secs(30)), None, @@ -1395,7 +1397,7 @@ impl Web3ProxyApp { .balanced_rpcs .try_proxy_connection::<_, Box>( method, - ¶ms, + params, Some(request_metadata), Some(Duration::from_secs(30)), Some(&U64::one()), @@ -1421,7 +1423,7 @@ impl Web3ProxyApp { self .try_send_protected( method, - ¶ms, + params, request_metadata, ) ) @@ -1611,7 +1613,7 @@ impl Web3ProxyApp { let cache_key: Option = match block_needed( &authorization, method, - &mut params, + params, head_block_num, &self.balanced_rpcs, ) @@ -1621,7 +1623,7 @@ impl Web3ProxyApp { None, None, method, - ¶ms, + params, false, )), BlockNeeded::CacheNever => None, @@ -1650,7 +1652,7 @@ impl Web3ProxyApp { Some(request_block), None, method, - ¶ms, + params, cache_errors, )) } @@ -1691,7 +1693,7 @@ impl Web3ProxyApp { Some(from_block), Some(to_block), method, - ¶ms, + params, cache_errors, )) } @@ -1711,11 +1713,11 @@ impl Web3ProxyApp { .jsonrpc_response_cache .try_get_with::<_, Web3ProxyError>(cache_key.hash(), async { let response_data = timeout( - max_wait + Duration::from_millis(10), + max_wait + Duration::from_millis(100), self.balanced_rpcs .try_proxy_connection::<_, Arc>( method, - ¶ms, + params, Some(request_metadata), Some(max_wait), from_block_num.as_ref(), @@ -1741,7 +1743,7 @@ impl Web3ProxyApp { self.balanced_rpcs .try_proxy_connection::<_, Arc>( method, - ¶ms, + params, Some(request_metadata), Some(max_wait), None, diff --git a/web3_proxy/src/errors.rs b/web3_proxy/src/errors.rs index e0241502..a950752f 100644 --- a/web3_proxy/src/errors.rs +++ b/web3_proxy/src/errors.rs @@ -250,17 +250,6 @@ impl Web3ProxyError { }, ) } - Self::Database(err) => { - error!("database err={:#?}", err); - ( - StatusCode::INTERNAL_SERVER_ERROR, - JsonRpcErrorData { - message: "database error!".into(), - code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(), - data: None, - }, - ) - } Self::Contract(err) => { warn!("Contract Error: {:#?}", err); ( @@ -272,6 +261,17 @@ impl Web3ProxyError { }, ) } + Self::Database(err) => { + error!("database err={:#?}", err); + ( + StatusCode::INTERNAL_SERVER_ERROR, + JsonRpcErrorData { + message: "database error!".into(), + code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(), + data: None, + }, + ) + } Self::Decimal(err) => { debug!("Decimal Error: {:#?}", err); ( @@ -283,18 +283,9 @@ impl Web3ProxyError { }, ) } - Self::SiweVerification(err) => { - trace!("Siwe Verification err={:#?}", err,); - ( - StatusCode::UNAUTHORIZED, - JsonRpcErrorData { - message: format!("siwe verification error: {:#?}", err).into(), - code: StatusCode::UNAUTHORIZED.as_u16().into(), - data: None, - }, - ) - } Self::EthersHttpClient(err) => { + todo!("how should we handle this error? needs to try into jsonrpcerrordata"); + warn!("EthersHttpClientError err={:#?}", err); ( StatusCode::INTERNAL_SERVER_ERROR, @@ -306,6 +297,8 @@ impl Web3ProxyError { ) } Self::EthersProvider(err) => { + todo!("how should we handle this error? needs to try into jsonrpcerrordata"); + warn!("EthersProviderError err={:#?}", err); ( StatusCode::INTERNAL_SERVER_ERROR, @@ -317,6 +310,8 @@ impl Web3ProxyError { ) } Self::EthersWsClient(err) => { + todo!("how should we handle this error? needs to try into jsonrpcerrordata"); + warn!("EthersWsClientError err={:#?}", err); ( StatusCode::INTERNAL_SERVER_ERROR, @@ -372,6 +367,17 @@ impl Web3ProxyError { }, ) } + Self::HeaderToString(err) => { + // trace!(?err, "HeaderToString"); + ( + StatusCode::BAD_REQUEST, + JsonRpcErrorData { + message: err.to_string().into(), + code: StatusCode::BAD_REQUEST.as_u16().into(), + data: None, + }, + ) + } Self::HttpUri(err) => { trace!("HttpUri {:#?}", err); ( @@ -489,29 +495,6 @@ impl Web3ProxyError { }, ) } - Self::RedisDeadpool(err) => { - error!("redis deadpool err={:#?}", err); - ( - StatusCode::INTERNAL_SERVER_ERROR, - JsonRpcErrorData { - // TODO: is it safe to expose our io error strings? - message: err.to_string().into(), - code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(), - data: None, - }, - ) - } - Self::UnknownReferralCode => { - trace!("UnknownReferralCode"); - ( - StatusCode::UNAUTHORIZED, - JsonRpcErrorData { - message: "invalid referral code".into(), - code: StatusCode::UNAUTHORIZED.as_u16().into(), - data: None, - }, - ) - } Self::InvalidReferer => { trace!("InvalidReferer"); ( @@ -794,7 +777,7 @@ impl Web3ProxyError { ( StatusCode::PAYMENT_REQUIRED, JsonRpcErrorData { - message: "Payment is required and user is not premium".into(), + message: "Payment is required to activate premium".into(), code: StatusCode::PAYMENT_REQUIRED.as_u16().into(), data: None, }, @@ -843,6 +826,18 @@ impl Web3ProxyError { }, ) } + Self::RedisDeadpool(err) => { + error!("redis deadpool err={:#?}", err); + ( + StatusCode::INTERNAL_SERVER_ERROR, + JsonRpcErrorData { + // TODO: is it safe to expose our io error strings? + message: err.to_string().into(), + code: StatusCode::INTERNAL_SERVER_ERROR.as_u16().into(), + data: None, + }, + ) + } Self::RefererRequired => { trace!("referer required"); ( @@ -899,6 +894,17 @@ impl Web3ProxyError { }, ) } + Self::SiweVerification(err) => { + trace!("Siwe Verification err={:#?}", err,); + ( + StatusCode::UNAUTHORIZED, + JsonRpcErrorData { + message: format!("siwe verification error: {:#?}", err).into(), + code: StatusCode::UNAUTHORIZED.as_u16().into(), + data: None, + }, + ) + } Self::StatusCode(status_code, err_msg, err) => { // different status codes should get different error levels. 500s should warn. 400s should stat let code = status_code.as_u16(); @@ -926,17 +932,6 @@ impl Web3ProxyError { data: None, }, ), - Self::HeaderToString(err) => { - // trace!(?err, "HeaderToString"); - ( - StatusCode::BAD_REQUEST, - JsonRpcErrorData { - message: err.to_string().into(), - code: StatusCode::BAD_REQUEST.as_u16().into(), - data: None, - }, - ) - } Self::UlidDecode(err) => { // trace!(?err, "UlidDecodeError"); ( @@ -959,7 +954,6 @@ impl Web3ProxyError { }, ) } - // TODO: stat? Self::UnknownKey => ( StatusCode::UNAUTHORIZED, JsonRpcErrorData { @@ -968,13 +962,24 @@ impl Web3ProxyError { data: None, }, ), + Self::UnknownReferralCode => { + trace!("UnknownReferralCode"); + ( + StatusCode::UNAUTHORIZED, + JsonRpcErrorData { + message: "invalid referral code".into(), + code: StatusCode::UNAUTHORIZED.as_u16().into(), + data: None, + }, + ) + } Self::UserAgentRequired => { trace!("UserAgentRequired"); ( - StatusCode::BAD_REQUEST, + StatusCode::UNAUTHORIZED, JsonRpcErrorData { message: "User agent required".into(), - code: StatusCode::BAD_REQUEST.as_u16().into(), + code: StatusCode::UNAUTHORIZED.as_u16().into(), data: None, }, ) diff --git a/web3_proxy/src/jsonrpc.rs b/web3_proxy/src/jsonrpc.rs index 1eff1145..c3403738 100644 --- a/web3_proxy/src/jsonrpc.rs +++ b/web3_proxy/src/jsonrpc.rs @@ -1,7 +1,5 @@ -use crate::errors::{Web3ProxyError, Web3ProxyResult}; use crate::response_cache::JsonRpcResponseEnum; use derive_more::From; -use ethers::prelude::ProviderError; use serde::de::{self, Deserializer, MapAccess, SeqAccess, Visitor}; use serde::{Deserialize, Serialize}; use serde_json::json; @@ -10,7 +8,7 @@ use std::borrow::Cow; use std::fmt; use std::sync::Arc; -pub trait JsonRpcParams = Clone + fmt::Debug + serde::Serialize + Send + Sync + 'static; +pub trait JsonRpcParams = fmt::Debug + serde::Serialize + Send + Sync + 'static; pub trait JsonRpcResultData = serde::Serialize + serde::de::DeserializeOwned + fmt::Debug + Send; // TODO: &str here instead of String should save a lot of allocations