From c342bc0d1ac35eac2dbb170e4fa6b4a20c9d6933 Mon Sep 17 00:00:00 2001 From: mpw Date: Sun, 28 Jan 2024 13:29:40 -0300 Subject: [PATCH] offer validation before submission (#3) --- Cargo.lock | 7 +++++++ Cargo.toml | 1 + src/main.rs | 38 ++++++++++++++++++++++---------------- 3 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6933fcf..974131a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -300,6 +300,12 @@ version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" +[[package]] +name = "bech32" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d86b93f97252c47b41663388e6d155714a9d0c398b99f1005cbc5f978b29f445" + [[package]] name = "bitflags" version = "1.3.2" @@ -2927,6 +2933,7 @@ name = "splash" version = "0.0.5" dependencies = [ "async-trait", + "bech32", "clap", "env_logger", "futures", diff --git a/Cargo.toml b/Cargo.toml index 36d5cc2..1f1ae01 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" reqwest = { version = "0.11.23", default-features = false, features = ["blocking", "json", "rustls-tls"] } warp = "0.3.6" +bech32 = "0.9.1" diff --git a/src/main.rs b/src/main.rs index 0e01424..6f52d19 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,6 +29,8 @@ const BOOTNODES: [&str; 3] = [ "12D3KooWP6QDYTCccwfUQVAc6jQDvzVY1FtU3WVsAxmVratbbC5V", ]; +const MAX_OFFER_SIZE: usize = 300 * 1024; + #[tokio::main] async fn main() -> Result<(), Box> { let _ = tracing_subscriber::fmt() @@ -73,6 +75,7 @@ async fn main() -> Result<(), Box> { let gossipsub_config = gossipsub::ConfigBuilder::default() .heartbeat_interval(Duration::from_secs(5)) // This is set to aid debugging by not cluttering the log space .message_id_fn(unique_offer_fn) // No duplicate offers will be propagated. + .max_transmit_size(MAX_OFFER_SIZE) .build() .map_err(|msg| io::Error::new(io::ErrorKind::Other, msg))?; // Temporary hack because `build` does not return a proper `std::error::Error`. @@ -144,24 +147,27 @@ async fn main() -> Result<(), Box> { let offer_route = warp::post() .and(warp::body::json()) - .map(move |offer: serde_json::Value| { - if let Some(offer_str) = offer.get("offer").and_then(|v| v.as_str()) { - // Convert the offer string to bytes and send - let offer_bytes = offer_str.as_bytes().to_vec(); - let tx = offer_tx_clone.clone(); - tokio::spawn(async move { - if tx.send(offer_bytes).await.is_err() { - eprintln!("Failed to send offer through the channel"); - } - }); - warp::reply::with_status("Offer received", warp::http::StatusCode::OK) - } else { - warp::reply::with_status( + .map( + move |offer: serde_json::Value| match offer.get("offer").and_then(|v| v.as_str()) { + Some(offer_str) if offer_str.as_bytes().len() > MAX_OFFER_SIZE => { + warp::reply::with_status("Offer too large", warp::http::StatusCode::BAD_REQUEST) + } + Some(offer_str) if bech32::decode(offer_str).is_ok() => { + let offer_bytes = offer_str.as_bytes().to_vec(); + let tx = offer_tx_clone.clone(); + tokio::spawn(async move { + if tx.send(offer_bytes).await.is_err() { + eprintln!("Failed to send offer through the channel"); + } + }); + warp::reply::with_status("Offer received", warp::http::StatusCode::OK) + } + _ => warp::reply::with_status( "Invalid offer format", warp::http::StatusCode::BAD_REQUEST, - ) - } - }); + ), + }, + ); // Start the warp server using the address provided in the `listen_offer_submission` option. if let Some(submission_addr_str) = opt.listen_offer_submission {