This commit is contained in:
Bryan Stitt 2022-09-22 22:34:43 +00:00
parent 987ed181cd
commit 7f7be6aa69
2 changed files with 39 additions and 28 deletions

View File

@ -61,6 +61,18 @@ pub enum AuthorizedRequest {
User(#[serde(skip)] Option<DatabaseConnection>, AuthorizedKey), User(#[serde(skip)] Option<DatabaseConnection>, AuthorizedKey),
} }
impl AuthorizedRequest {
pub fn has_db(&self) -> bool {
let db_conn = match self {
Self::Internal(db_conn) => db_conn,
Self::Ip(db_conn, _) => db_conn,
Self::User(db_conn, _) => db_conn,
};
db_conn.is_some()
}
}
pub async fn ip_is_authorized( pub async fn ip_is_authorized(
app: &Web3ProxyApp, app: &Web3ProxyApp,
ip: IpAddr, ip: IpAddr,

View File

@ -34,6 +34,7 @@ pub struct OpenRequestHandle {
used: AtomicBool, used: AtomicBool,
} }
/// Depending on the context, RPC errors can require different handling.
pub enum RequestErrorHandler { pub enum RequestErrorHandler {
/// Contains the percent chance to save the revert /// Contains the percent chance to save the revert
SaveReverts(f32), SaveReverts(f32),
@ -57,6 +58,7 @@ impl From<Level> for RequestErrorHandler {
} }
impl AuthorizedRequest { impl AuthorizedRequest {
/// Save a RPC call that return "execution reverted" to the database.
async fn save_revert<T>(self: Arc<Self>, method: String, params: T) -> anyhow::Result<()> async fn save_revert<T>(self: Arc<Self>, method: String, params: T) -> anyhow::Result<()>
where where
T: Clone + fmt::Debug + serde::Serialize + Send + Sync + 'static, T: Clone + fmt::Debug + serde::Serialize + Send + Sync + 'static,
@ -95,6 +97,7 @@ impl OpenRequestHandle {
} }
} }
#[inline]
pub fn clone_connection(&self) -> Arc<Web3Connection> { pub fn clone_connection(&self) -> Arc<Web3Connection> {
self.conn.clone() self.conn.clone()
} }
@ -164,48 +167,44 @@ impl OpenRequestHandle {
// TODO: only set SaveReverts if this is an eth_call or eth_estimateGas? we'll need eth_sendRawTransaction somewhere else // TODO: only set SaveReverts if this is an eth_call or eth_estimateGas? we'll need eth_sendRawTransaction somewhere else
// TODO: logging every one is going to flood the database // TODO: logging every one is going to flood the database
// TODO: have a percent chance to do this. or maybe a "logged reverts per second" // TODO: have a percent chance to do this. or maybe a "logged reverts per second"
if save_chance == 1.0 || rand::thread_rng().gen_range(0.0..=1.0) <= save_chance if self.authorization.has_db()
&& (save_chance == 1.0
|| rand::thread_rng().gen_range(0.0..=1.0) <= save_chance)
{ {
if let ProviderError::JsonRpcClientError(err) = err { if let ProviderError::JsonRpcClientError(err) = err {
match provider { let msg = match provider {
Web3Provider::Http(_) => { Web3Provider::Http(_) => {
if let Some(HttpClientError::JsonRpcError(err)) = if let Some(HttpClientError::JsonRpcError(err)) =
err.downcast_ref::<HttpClientError>() err.downcast_ref::<HttpClientError>()
{ {
if err.message.starts_with("execution reverted") { Some(&err.message)
debug!(%method, ?params, "TODO: save the request"); } else {
None
let f = self
.authorization
.clone()
.save_revert(method.to_string(), params.clone());
tokio::spawn(async move { f.await });
// TODO: don't do this on the hot path. spawn it
} else {
debug!(?err, %method, rpc=%self.conn, "bad response!");
}
} }
} }
Web3Provider::Ws(_) => { Web3Provider::Ws(_) => {
if let Some(WsClientError::JsonRpcError(err)) = if let Some(WsClientError::JsonRpcError(err)) =
err.downcast_ref::<WsClientError>() err.downcast_ref::<WsClientError>()
{ {
if err.message.starts_with("execution reverted") { Some(&err.message)
debug!(%method, ?params, "TODO: save the request"); } else {
None
let f = self
.authorization
.clone()
.save_revert(method.to_string(), params.clone());
tokio::spawn(async move { f.await });
} else {
debug!(?err, %method, rpc=%self.conn, "bad response!");
}
} }
} }
};
if let Some(msg) = msg {
if msg.starts_with("execution reverted") {
// spawn saving to the database so we don't slow down the request (or error if no db)
let f = self
.authorization
.clone()
.save_revert(method.to_string(), params.clone());
tokio::spawn(async move { f.await });
} else {
debug!(?err, %method, rpc=%self.conn, "bad response!");
}
} }
} }
} }