Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,9 @@ agg_mode_gateway_send_sp1_proof:
--vk scripts/test_files/sp1/sp1_fibonacci_5_0_0_vk.bin \
--private-key "0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"

agg_mode_get_quotas:
curl -X GET http://127.0.0.1:8089/quotas/0x70997970C51812dc3A010C7d01b50e0d17dc79C8

__AGGREGATOR__: ## ____

aggregator_start: ## Start the Aggregator. Parameters: ENVIRONMENT=<devnet|testnet|mainnet>, AGG_CONFIG_FILE
Expand Down
16 changes: 16 additions & 0 deletions aggregation_mode/gateway/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::time::{SystemTime, UNIX_EPOCH};

pub(super) fn format_merkle_path(bytes: &[u8]) -> Result<Vec<String>, String> {
if bytes.is_empty() {
return Ok(vec![]);
Expand All @@ -12,3 +14,17 @@ pub(super) fn format_merkle_path(bytes: &[u8]) -> Result<Vec<String>, String> {
.map(|chunk| format!("0x{}", hex::encode(chunk)))
.collect())
}

pub(crate) fn get_time_left_day_formatted() -> String {
let now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Error al obtener el tiempo");

let seconds_remaining = 86400 - (now.as_secs() % 86400);

let hours = seconds_remaining / 3600;
let minutes = (seconds_remaining % 3600) / 60;
let seconds = seconds_remaining % 60;

format!("{hours}:{minutes}:{seconds}")
Comment thread
maximopalopoli marked this conversation as resolved.
Outdated
}
47 changes: 46 additions & 1 deletion aggregation_mode/gateway/src/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use super::{
use crate::{
config::Config,
db::Db,
helpers::get_time_left_day_formatted,
types::{GetReceiptsResponse, SubmitProofRequestRisc0, SubmitProofRequestSP1},
verifiers::{verify_sp1_proof, VerificationError},
};
Expand Down Expand Up @@ -56,6 +57,7 @@ impl GatewayServer {
.route("/receipts", web::get().to(Self::get_receipts))
.route("/proof/sp1", web::post().to(Self::post_proof_sp1))
.route("/proof/risc0", web::post().to(Self::post_proof_risc0))
.route("/quotas/{address}", web::get().to(Self::get_quotas))
})
.bind(("127.0.0.1", port))
.expect("To bind socket correctly")
Expand Down Expand Up @@ -147,8 +149,13 @@ impl GatewayServer {
};

if daily_tasks_by_address >= state.config.max_daily_proofs_per_user {
let formatted_time_left = get_time_left_day_formatted();

return HttpResponse::InternalServerError().json(AppResponse::new_unsucessfull(
"Request denied: Query limit exceeded.",
format!(
"Request denied: Query limit exceeded. Quotas renew in {formatted_time_left}"
)
.as_str(),
400,
));
}
Expand Down Expand Up @@ -322,4 +329,42 @@ impl GatewayServer {
.json(AppResponse::new_unsucessfull("Internal server error", 500)),
}
}

async fn get_quotas(req: HttpRequest) -> impl Responder {
let Some(state) = req.app_data::<Data<GatewayServer>>() else {
return HttpResponse::InternalServerError().json(AppResponse::new_unsucessfull(
"Internal server error: Failed to get app data",
500,
));
};

let state = state.get_ref();

let Some(address_raw) = req.match_info().get("address") else {
return HttpResponse::BadRequest()
.json(AppResponse::new_unsucessfull("Missing address", 400));
};

// Check that the address is a valid ethereum address
if alloy::primitives::Address::from_str(address_raw.trim()).is_err() {
return HttpResponse::BadRequest()
.json(AppResponse::new_unsucessfull("Invalid address", 400));
}

let address = address_raw.to_lowercase();
Comment thread
maximopalopoli marked this conversation as resolved.
Outdated

let Ok(daily_tasks_by_address) = state.db.get_daily_tasks_by_address(&address).await else {
return HttpResponse::InternalServerError()
.json(AppResponse::new_unsucessfull("Internal server error", 500));
};

let formatted_time_left = get_time_left_day_formatted();

HttpResponse::Ok().json(AppResponse::new_sucessfull(serde_json::json!({
"proofs_submitted": daily_tasks_by_address,
"quota_limit": state.config.max_daily_proofs_per_user,
"quota_remaining": (state.config.max_daily_proofs_per_user - daily_tasks_by_address),
"quota_resets_in": formatted_time_left.as_str()
})))
Comment thread
MarcosNicolau marked this conversation as resolved.
Outdated
}
}
Loading