Skip to content

Commit 8c78c41

Browse files
committed
feat: merkle path endpoint
1 parent 770601d commit 8c78c41

File tree

6 files changed

+97
-9
lines changed

6 files changed

+97
-9
lines changed

aggregation_mode/Cargo.lock

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

aggregation_mode/batcher/src/db.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,17 @@ impl Db {
3030

3131
Ok(count)
3232
}
33+
34+
pub async fn get_merkle_path_by_proof_id(
35+
&self,
36+
proof_id: &str,
37+
) -> Result<Option<Vec<u8>>, sqlx::Error> {
38+
sqlx::query_scalar::<_, Option<Vec<u8>>>(
39+
"SELECT merkle_path FROM proofs WHERE proof_id = $1",
40+
)
41+
.bind(proof_id)
42+
.fetch_optional(&self.pool)
43+
.await
44+
.map(|res| res.flatten())
45+
}
3346
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
pub(super) fn format_merkle_path(bytes: &[u8]) -> Result<Vec<String>, String> {
2+
if bytes.is_empty() {
3+
return Ok(vec![]);
4+
}
5+
6+
if bytes.len() % 32 != 0 {
7+
return Err("merkle path length is not a multiple of 32 bytes".into());
8+
}
9+
10+
Ok(bytes
11+
.chunks(32)
12+
.map(|chunk| format!("0x{}", hex::encode(chunk)))
13+
.collect())
14+
}

aggregation_mode/batcher/src/server/http.rs

Lines changed: 59 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use actix_web::{
2-
web::{self, Data},
2+
web::{self, Data, Query},
33
App, HttpRequest, HttpResponse, HttpServer, Responder,
44
};
5+
use serde::Deserialize;
56

6-
use super::types::AppResponse;
7+
use super::{
8+
helpers::format_merkle_path,
9+
types::{AppResponse, ProofMerkleQuery},
10+
};
711

812
use crate::{config::Config, db::Db};
913

@@ -27,10 +31,7 @@ impl BatcherServer {
2731
App::new()
2832
.app_data(Data::new(state.clone()))
2933
.route("/nonce/{address}", web::get().to(Self::get_nonce))
30-
.route(
31-
"/proof/merkle/:receipt",
32-
web::get().to(Self::get_proof_merkle_path),
33-
)
34+
.route("/proof/merkle", web::get().to(Self::get_proof_merkle_path))
3435
.route("/proof", web::post().to(Self::post_proof))
3536
})
3637
.bind(("127.0.0.1", port))?
@@ -70,8 +71,57 @@ impl BatcherServer {
7071
HttpResponse::Ok()
7172
}
7273

73-
// TODO: get the proof merkle path for the receipt id (proof commitment)
74-
async fn get_proof_merkle_path(req: HttpRequest) -> impl Responder {
75-
HttpResponse::Ok()
74+
async fn get_proof_merkle_path(
75+
req: HttpRequest,
76+
params: web::Query<ProofMerkleQuery>,
77+
) -> impl Responder {
78+
let Some(state) = req.app_data::<Data<BatcherServer>>() else {
79+
return HttpResponse::InternalServerError()
80+
.json(AppResponse::new_unsucessfull("Internal server error", 500));
81+
};
82+
83+
let state = state.get_ref();
84+
85+
// TODO: maybe also accept proof commitment in query param
86+
let Some(id) = params.id.clone() else {
87+
return HttpResponse::BadRequest().json(AppResponse::new_unsucessfull(
88+
"Provide proof `id` query param",
89+
400,
90+
));
91+
};
92+
93+
if id.is_empty() {
94+
return HttpResponse::BadRequest().json(AppResponse::new_unsucessfull(
95+
"Proof id cannot be empty",
96+
400,
97+
));
98+
}
99+
100+
let db_result = state.db.get_merkle_path_by_proof_id(&id).await;
101+
let merkle_path = match db_result {
102+
Ok(Some(merkle_path)) => merkle_path,
103+
Ok(None) => {
104+
return HttpResponse::NotFound().json(AppResponse::new_unsucessfull(
105+
"Proof merkle path not found",
106+
404,
107+
))
108+
}
109+
Err(_) => {
110+
return HttpResponse::InternalServerError()
111+
.json(AppResponse::new_unsucessfull("Internal server error", 500))
112+
}
113+
};
114+
115+
match format_merkle_path(&merkle_path) {
116+
Ok(merkle_path) => {
117+
HttpResponse::Ok().json(AppResponse::new_sucessfull(serde_json::json!({
118+
"merkle_path": merkle_path
119+
})))
120+
}
121+
Err(_) => {
122+
return HttpResponse::InternalServerError()
123+
.json(AppResponse::new_unsucessfull("Internal server error", 500))
124+
}
125+
}
76126
}
77127
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
mod helpers;
12
pub mod http;
23
mod types;

aggregation_mode/batcher/src/server/types.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,8 @@ impl AppResponse {
2525
}
2626
}
2727
}
28+
29+
#[derive(Deserialize, Clone)]
30+
pub(super) struct ProofMerkleQuery {
31+
pub id: Option<String>,
32+
}

0 commit comments

Comments
 (0)