Skip to content
This repository was archived by the owner on Aug 3, 2026. It is now read-only.

Commit 336d037

Browse files
authored
feat(proof): enhance aggregation request handling with prover isolation (#682)
- Updated `AggregationRequestKey` to include an optional prover address for isolating aggregate proofs per prover. - Modified `batch_handler` and `shasta_batch_handler` to utilize the new `new_with_image_id_and_prover` method for creating aggregation keys, allowing for more granular proof management based on the prover.
1 parent 6250c6e commit 336d037

3 files changed

Lines changed: 78 additions & 59 deletions

File tree

host/src/server/api/v3/proof/batch_handler.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,11 @@ async fn batch_handler(
120120
let result = if batch_request.aggregate {
121121
prove_aggregation(
122122
&actor,
123-
AggregationRequestKey::new_with_image_id(
123+
AggregationRequestKey::new_with_image_id_and_prover(
124124
batch_request.proof_type,
125125
sub_batch_ids.clone(),
126126
image_id.clone(),
127+
batch_request.prover.to_string(),
127128
)
128129
.into(),
129130
AggregationRequestEntity::new(

host/src/server/api/v3/proof/shasta_handler.rs

Lines changed: 57 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -112,68 +112,67 @@ async fn shasta_batch_handler(
112112
sub_batch_ids,
113113
) = process_shasta_batch(&shasta_request, &image_id);
114114

115-
let result = if shasta_request.aggregate {
116-
prove_aggregation(
117-
&actor,
118-
RequestKey::ShastaAggregation(AggregationRequestKey::new_with_image_id(
119-
shasta_request.proof_type,
120-
sub_batch_ids.clone(),
121-
image_id.clone(),
122-
)),
123-
RequestEntity::ShastaAggregation(AggregationRequestEntity::new(
124-
sub_batch_ids,
125-
vec![],
126-
shasta_request.proof_type,
127-
shasta_request.prover_args.clone(),
128-
)),
129-
sub_request_keys,
130-
sub_request_entities,
131-
)
132-
.await
115+
// Run input step first to reuse cached guest input (both aggregate and non-aggregate)
116+
let statuses =
117+
prove_many(&actor, sub_input_request_keys, sub_input_request_entities).await?;
118+
let is_all_sub_success = statuses
119+
.iter()
120+
.all(|status| matches!(status, raiko_reqpool::Status::Success { .. }));
121+
let result = if !is_all_sub_success {
122+
Ok(raiko_reqpool::Status::Registered)
133123
} else {
134-
let statuses =
135-
prove_many(&actor, sub_input_request_keys, sub_input_request_entities).await?;
136-
let is_all_sub_success = statuses
124+
let guest_inputs: Vec<_> = statuses
137125
.iter()
138-
.all(|status| matches!(status, raiko_reqpool::Status::Success { .. }));
139-
if !is_all_sub_success {
140-
Ok(raiko_reqpool::Status::Registered)
126+
.map(|s| match s {
127+
raiko_reqpool::Status::Success { proof, .. } => proof.proof.clone().unwrap(),
128+
_ => unreachable!(),
129+
})
130+
.collect();
131+
let sub_request_entities_with_input: Vec<_> = sub_request_entities
132+
.iter()
133+
.zip(guest_inputs)
134+
.map(|(entity, guest_input)| match entity {
135+
raiko_reqpool::RequestEntity::ShastaProof(e) => {
136+
let mut prover_args = e.prover_args().clone();
137+
prover_args.insert(
138+
PROVER_ARG_SHASTA_GUEST_INPUT.to_string(),
139+
encode_guest_input_str_to_prover_arg_value(&guest_input).expect("wrap"),
140+
);
141+
ShastaProofRequestEntity::new_with_guest_input_entity(
142+
e.guest_input_entity().clone(),
143+
*e.proof_type(),
144+
prover_args,
145+
)
146+
.into()
147+
}
148+
_ => unreachable!(),
149+
})
150+
.collect();
151+
152+
if shasta_request.aggregate {
153+
prove_aggregation(
154+
&actor,
155+
RequestKey::ShastaAggregation(AggregationRequestKey::new_with_image_id_and_prover(
156+
shasta_request.proof_type,
157+
sub_batch_ids.clone(),
158+
image_id.clone(),
159+
shasta_request.prover.to_string(),
160+
)),
161+
RequestEntity::ShastaAggregation(AggregationRequestEntity::new(
162+
sub_batch_ids,
163+
vec![],
164+
shasta_request.proof_type,
165+
shasta_request.prover_args.clone(),
166+
)),
167+
sub_request_keys,
168+
sub_request_entities_with_input,
169+
)
170+
.await
141171
} else {
142-
let guest_inputs_of_entities = statuses
143-
.iter()
144-
.map(|status| match status {
145-
// get saved guest input and pass down to real prover
146-
raiko_reqpool::Status::Success { proof, .. } => proof.proof.clone().unwrap(),
147-
_ => unreachable!("is_all_sub_success checked"),
148-
})
149-
.collect::<Vec<_>>();
150-
let sub_request_entities = sub_request_entities
151-
.iter()
152-
.zip(guest_inputs_of_entities)
153-
.to_owned()
154-
.map(|(entity, guest_input)| match entity {
155-
raiko_reqpool::RequestEntity::ShastaProof(request_entity) => {
156-
let mut prover_args = request_entity.prover_args().clone();
157-
prover_args.insert(
158-
PROVER_ARG_SHASTA_GUEST_INPUT.to_string(),
159-
encode_guest_input_str_to_prover_arg_value(&guest_input)
160-
.expect("failed to wrap shasta_guest_input string"),
161-
);
162-
ShastaProofRequestEntity::new_with_guest_input_entity(
163-
request_entity.guest_input_entity().clone(),
164-
*request_entity.proof_type(),
165-
prover_args,
166-
)
167-
.into()
168-
}
169-
_ => unreachable!("Invalid request entity"),
170-
})
171-
.collect::<Vec<_>>();
172-
prove_many(&actor, sub_request_keys, sub_request_entities)
172+
prove_many(&actor, sub_request_keys, sub_request_entities_with_input)
173173
.await
174-
.map(|statuses| {
175-
statuses
176-
.into_iter()
174+
.map(|s| {
175+
s.into_iter()
177176
.next()
178177
.unwrap_or_else(|| raiko_reqpool::Status::Failed {
179178
error: "No status returned".to_string(),

reqpool/src/request.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ pub struct AggregationRequestKey {
209209
block_numbers: Vec<u64>,
210210
/// The image ID for zk provers (optional)
211211
image_id: Option<ImageId>,
212+
/// The prover address (optional); when set, isolates aggregate proofs per prover
213+
prover_address: Option<String>,
212214
}
213215

214216
impl AggregationRequestKey {
@@ -217,6 +219,7 @@ impl AggregationRequestKey {
217219
proof_type,
218220
block_numbers,
219221
image_id: None,
222+
prover_address: None,
220223
}
221224
}
222225

@@ -229,6 +232,22 @@ impl AggregationRequestKey {
229232
proof_type,
230233
block_numbers,
231234
image_id: Some(image_id.clone()),
235+
prover_address: None,
236+
}
237+
}
238+
239+
/// Create an aggregation key with image ID and prover address for prover isolation.
240+
pub fn new_with_image_id_and_prover(
241+
proof_type: ProofType,
242+
block_numbers: Vec<u64>,
243+
image_id: ImageId,
244+
prover_address: String,
245+
) -> Self {
246+
Self {
247+
proof_type,
248+
block_numbers,
249+
image_id: Some(image_id.clone()),
250+
prover_address: Some(prover_address),
232251
}
233252
}
234253
}

0 commit comments

Comments
 (0)