From f9f77e829b8d0efdd8a191de0ae72a87bf4b1645 Mon Sep 17 00:00:00 2001 From: Erwan <7871622+erwanor@users.noreply.github.com> Date: Mon, 24 Jan 2022 14:38:00 +0100 Subject: [PATCH] fix(ws): propagate deserialization errors upstream + infura quickfix (#827) * fix(ws): propagate error when deserialization fails * fix(ws): tolerate case-insensitive match on the jsonrpc field Infura streams notifications with jsonrpc all capitalized. This fails to deserialize on our end because serde expect a precise match ressembling the Notification jsonrpc field. Fixes #684. * chore(fmt): use nightly rustfmt * chore: fmt * chore: fix failing celo test Co-authored-by: Georgios Konstantopoulos --- ethers-providers/src/transports/common.rs | 1 + ethers-providers/src/transports/ws.rs | 14 ++++++++++++-- ethers-providers/tests/provider.rs | 4 ++-- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/ethers-providers/src/transports/common.rs b/ethers-providers/src/transports/common.rs index 85aec551..29917b76 100644 --- a/ethers-providers/src/transports/common.rs +++ b/ethers-providers/src/transports/common.rs @@ -39,6 +39,7 @@ pub struct Request<'a, T> { #[derive(Serialize, Deserialize, Debug)] /// A JSON-RPC Notifcation pub struct Notification { + #[serde(alias = "JSONRPC")] jsonrpc: String, method: String, pub params: Subscription, diff --git a/ethers-providers/src/transports/ws.rs b/ethers-providers/src/transports/ws.rs index 64ea06fc..44df77d1 100644 --- a/ethers-providers/src/transports/ws.rs +++ b/ethers-providers/src/transports/ws.rs @@ -112,7 +112,6 @@ impl Ws { S: Send + Sync + Stream + Sink + Unpin, { let (sink, stream) = mpsc::unbounded(); - // Spawn the server WsServer::new(ws, stream).spawn(); @@ -310,7 +309,8 @@ where async fn handle_text(&mut self, inner: String) -> Result<(), ClientError> { match serde_json::from_str::(&inner) { - Err(_) => {} + Err(err) => return Err(ClientError::JsonError(err)), + Ok(Incoming::Response(resp)) => { if let Some(request) = self.pending.remove(&resp.id) { if !request.is_canceled() { @@ -491,4 +491,14 @@ mod tests { assert_eq!(sub_id, 1.into()); assert_eq!(blocks, vec![1, 2, 3]) } + + #[tokio::test] + async fn deserialization_fails() { + let ganache = Ganache::new().block_time(1u64).spawn(); + let (ws, _) = tokio_tungstenite::connect_async(ganache.ws_endpoint()).await.unwrap(); + let malformed_data = String::from("not a valid message"); + let (_, stream) = mpsc::unbounded(); + let resp = WsServer::new(ws, stream).handle_text(malformed_data).await; + assert!(resp.is_err(), "Deserialization should not fail silently"); + } } diff --git a/ethers-providers/tests/provider.rs b/ethers-providers/tests/provider.rs index 44a55869..9e8453d0 100644 --- a/ethers-providers/tests/provider.rs +++ b/ethers-providers/tests/provider.rs @@ -117,14 +117,14 @@ mod celo_tests { let provider = Provider::::try_from("https://alfajores-forno.celo-testnet.org").unwrap(); - let tx_hash = "d3d27aa4517124d9ff3ac6f1d8f248e0fe47b6f841b625722546162672ac24c7" + let tx_hash = "a8e1d4b9e245a67fafc7c516ff844c2615cc6419d53560e7f358b124e4ce5e1d" .parse::() .unwrap(); let tx = provider.get_transaction(tx_hash).await.unwrap().unwrap(); assert!(tx.gateway_fee_recipient.is_none()); assert_eq!(tx.gateway_fee.unwrap(), 0.into()); assert_eq!(tx.hash, tx_hash); - assert_eq!(tx.block_number.unwrap(), 9401421.into()) + assert_eq!(tx.block_number.unwrap(), 9534852.into()) } #[tokio::test]