From f67146aa13677045b08f13baeb235f5a9f307a99 Mon Sep 17 00:00:00 2001 From: Noor Date: Tue, 31 Dec 2024 12:43:12 +0000 Subject: [PATCH] minting state implement 1 minting at a time to prevent ddos enhanced json response --- src/datastore.rs | 18 +++++++++++++++++- src/http_server.rs | 14 +++++++++++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/datastore.rs b/src/datastore.rs index 22c29f7..37c3aaa 100644 --- a/src/datastore.rs +++ b/src/datastore.rs @@ -2,6 +2,7 @@ use crate::persistence::{SealError, SealedFile}; use serde::{Deserialize, Serialize}; use serde_with::{serde_as, TimestampSeconds}; use std::collections::{HashMap, HashSet}; +use std::sync::atomic::{AtomicBool, Ordering}; use std::time::{Duration, SystemTime, UNIX_EPOCH}; use tokio::sync::RwLock; @@ -95,6 +96,7 @@ pub struct State { nodes: RwLock>, conns: RwLock>, timeout: u64, + is_minting: AtomicBool, } impl State { @@ -102,7 +104,13 @@ impl State { let mut nodes = HashMap::new(); let my_info = NodeInfo::load(); nodes.insert(my_ip.clone(), my_info); - Self { my_ip, timeout, nodes: RwLock::new(nodes), conns: RwLock::new(HashSet::new()) } + Self { + my_ip, + timeout, + nodes: RwLock::new(nodes), + conns: RwLock::new(HashSet::new()), + is_minting: AtomicBool::new(false), + } } pub async fn add_conn(&self, ip: &str) { @@ -203,6 +211,14 @@ impl State { Duration::from_secs(self.timeout) } + pub fn is_minting(&self) -> bool { + self.is_minting.compare_exchange(false, true, Ordering::SeqCst, Ordering::SeqCst).is_err() + } + + pub fn release_minting(&self) { + self.is_minting.store(false, Ordering::SeqCst); + } + pub async fn get_my_info(&self) -> NodeInfo { let nodes = self.nodes.read().await; nodes.get(&self.my_ip).cloned().unwrap_or(NodeInfo::new_empty()) diff --git a/src/http_server.rs b/src/http_server.rs index 92b0f9e..dccc585 100644 --- a/src/http_server.rs +++ b/src/http_server.rs @@ -2,6 +2,7 @@ use crate::{datastore, datastore::State, solana::SolClient}; use actix_web::{get, post, web, App, HttpResponse, HttpServer, Responder}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; +use serde_json::json; use std::sync::Arc; const HOMEPAGE: &str = include_str!("HOMEPAGE.md"); @@ -67,12 +68,19 @@ async fn mint( let recipient = req.into_inner().wallet; state.increase_mint_requests().await; - match sol_client.mint(&recipient).await { + if state.is_minting() { + return HttpResponse::TooManyRequests().json(json!({ "error": "already mint processing" })); + } + + let mint_res = sol_client.mint(&recipient).await; + + state.release_minting(); + match mint_res { Ok(s) => { state.increase_mints().await; - HttpResponse::Ok().body(format!(r#"{{" signature": "{s} "}}"#)) + HttpResponse::Ok().json(json!({"signature": s})) } - Err(e) => HttpResponse::InternalServerError().body(format!(r#"{{ "error": "{e}" }}"#)), + Err(e) => HttpResponse::InternalServerError().json(json!({ "error": e.to_string() })), } }