Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(host,tasks): complete aggregation api #387

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
11 changes: 11 additions & 0 deletions core/src/interfaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,17 @@ impl TryFrom<u8> for ProofType {
}
}

impl From<ProofType> for u8 {
fn from(val: ProofType) -> Self {
match val {
ProofType::Native => 0,
ProofType::Sp1 => 1,
ProofType::Sgx => 2,
ProofType::Risc0 => 3,
}
}
}

impl From<ProofType> for VerifierType {
fn from(val: ProofType) -> Self {
match val {
Expand Down
75 changes: 75 additions & 0 deletions host/src/server/api/v3/proof/aggregate/cancel.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
use std::str::FromStr;

use axum::{debug_handler, extract::State, routing::post, Json, Router};
use raiko_core::interfaces::{AggregationOnlyRequest, ProofType};
use raiko_tasks::{TaskManager, TaskStatus};
use utoipa::OpenApi;

use crate::{
interfaces::HostResult,
metrics::{inc_guest_req_count, inc_host_req_count},
server::api::v2::CancelStatus,
Message, ProverState,
};

#[utoipa::path(post, path = "/proof/aggregate/cancel",
tag = "Proving",
request_body = AggregationOnlyRequest,
responses (
(status = 200, description = "Successfully cancelled proof aggregation task", body = CancelStatus)
)
)]
#[debug_handler(state = ProverState)]
/// Cancel a proof aggregation task with requested config.
///
/// Accepts a proof aggregation request and cancels a proving task with the specified guest prover.
/// The guest provers currently available are:
/// - native - constructs a block and checks for equality
/// - sgx - uses the sgx environment to construct a block and produce proof of execution
/// - sp1 - uses the sp1 prover
/// - risc0 - uses the risc0 prover
async fn cancel_handler(
State(prover_state): State<ProverState>,
Json(mut aggregation_request): Json<AggregationOnlyRequest>,
) -> HostResult<CancelStatus> {
// Override the existing proof request config from the config file and command line
// options with the request from the client.
aggregation_request.merge(&prover_state.request_config())?;

let proof_type = ProofType::from_str(
aggregation_request
.proof_type
.as_deref()
.unwrap_or_default(),
)?;
inc_host_req_count(0);
inc_guest_req_count(&proof_type, 0);
Comment on lines +39 to +46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To maintain consistency with the 'cancel' API across versions 1 and 2, I recommend removing these two lines of code, as we don't record metrics for 'cancel' API (at least not for now, maybe we can add some metrics for 'cancel' API)


if aggregation_request.proofs.is_empty() {
return Err(anyhow::anyhow!("No proofs provided").into());
}
Comment on lines +48 to +50
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, we don't have to check the proofs.


prover_state
.task_channel
.try_send(Message::CancelAggregate(aggregation_request.clone()))?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The cancelling aggregation request may be non-existing. In order to prevent useless 'cancel' requests, we should check the status of the target aggregation request by get_aggregation_task_status() before sending signal to task_channel.


let mut manager = prover_state.task_manager();

manager
.update_aggregation_task_progress(&aggregation_request, TaskStatus::Cancelled, None)
.await?;

Ok(CancelStatus::Ok)
}

#[derive(OpenApi)]
#[openapi(paths(cancel_handler))]
struct Docs;

pub fn create_docs() -> utoipa::openapi::OpenApi {
Docs::openapi()
}

pub fn create_router() -> Router<ProverState> {
Router::new().route("/", post(cancel_handler))
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ use crate::{
Message, ProverState,
};

pub mod cancel;
pub mod prune;
pub mod report;

#[utoipa::path(post, path = "/proof/aggregate",
tag = "Proving",
request_body = AggregationRequest,
Expand Down Expand Up @@ -106,9 +110,22 @@ async fn aggregation_handler(
struct Docs;

pub fn create_docs() -> utoipa::openapi::OpenApi {
Docs::openapi()
[
cancel::create_docs(),
report::create_docs(),
prune::create_docs(),
]
.into_iter()
.fold(Docs::openapi(), |mut docs, curr| {
docs.merge(curr);
docs
})
}

pub fn create_router() -> Router<ProverState> {
Router::new().route("/", post(aggregation_handler))
Router::new()
.route("/", post(aggregation_handler))
.nest("/cancel", cancel::create_router())
.nest("/prune", prune::create_router())
.nest("/report", report::create_router())
}
33 changes: 33 additions & 0 deletions host/src/server/api/v3/proof/aggregate/prune.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use axum::{debug_handler, extract::State, routing::post, Router};
use raiko_tasks::TaskManager;
use utoipa::OpenApi;

use crate::{interfaces::HostResult, server::api::v2::PruneStatus, ProverState};

#[utoipa::path(post, path = "/proof/aggregate/prune",
tag = "Proving",
responses (
(status = 200, description = "Successfully pruned all aggregation tasks", body = PruneStatus)
)
)]
#[debug_handler(state = ProverState)]
/// Prune all aggregation tasks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Prone API is oriented to normal users?

I'm afraid that the Prune API is too dangerous as it poses significant risks. I propose categorizing such APIs under 'admin' for better control if we really need.

IMO, In practice, operations team members should and can perform these actions manually. So, is this API truly necessary?

async fn prune_handler(State(prover_state): State<ProverState>) -> HostResult<PruneStatus> {
let mut manager = prover_state.task_manager();

manager.prune_aggregation_db().await?;
smtmfft marked this conversation as resolved.
Show resolved Hide resolved

Ok(PruneStatus::Ok)
}

#[derive(OpenApi)]
#[openapi(paths(prune_handler))]
struct Docs;

pub fn create_docs() -> utoipa::openapi::OpenApi {
Docs::openapi()
}

pub fn create_router() -> Router<ProverState> {
Router::new().route("/", post(prune_handler))
}
37 changes: 37 additions & 0 deletions host/src/server/api/v3/proof/aggregate/report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use axum::{debug_handler, extract::State, routing::get, Json, Router};
use raiko_tasks::{AggregationTaskReport, TaskManager};
use utoipa::OpenApi;

use crate::{interfaces::HostResult, ProverState};

#[utoipa::path(post, path = "/proof/aggregate/report",
tag = "Proving",
responses (
(status = 200, description = "Successfully retrieved a report of all aggregation tasks", body = AggregationTaskReport)
)
)]
#[debug_handler(state = ProverState)]
/// List all aggregation tasks.
///
/// Retrieve a list of aggregation task reports.
async fn report_handler(
State(prover_state): State<ProverState>,
) -> HostResult<Json<Vec<AggregationTaskReport>>> {
let mut manager = prover_state.task_manager();

let task_report = manager.list_all_aggregation_tasks().await?;

Ok(Json(task_report))
}

#[derive(OpenApi)]
#[openapi(paths(report_handler))]
struct Docs;

pub fn create_docs() -> utoipa::openapi::OpenApi {
Docs::openapi()
}

pub fn create_router() -> Router<ProverState> {
Router::new().route("/", get(report_handler))
}
Loading
Loading